[PATCH] Add dynamic MMC-over-SPI-GPIO driver - Kernel

This is a discussion on [PATCH] Add dynamic MMC-over-SPI-GPIO driver - Kernel ; This driver provides a sysfs interface to dynamically create and destroy GPIO-based MMC/SD card interfaces. So an MMC or SD card can be connected to generic GPIO pins and be configured dynamically from userspace. Signed-off-by: Michael Buesch --- This driver ...

+ Reply to Thread
Results 1 to 7 of 7

Thread: [PATCH] Add dynamic MMC-over-SPI-GPIO driver

  1. [PATCH] Add dynamic MMC-over-SPI-GPIO driver

    This driver provides a sysfs interface to dynamically create
    and destroy GPIO-based MMC/SD card interfaces.
    So an MMC or SD card can be connected to generic GPIO pins
    and be configured dynamically from userspace.

    Signed-off-by: Michael Buesch

    ---

    This driver is used in OpenWrt since quite some time, so please
    consider for inclusion in mainline.

    See the attached OpenWrt initscript for an example on how to use
    the sysfs interface. Documentation should also be added. I'll submit
    a patch for that, later.


    Index: linux-next/drivers/mmc/host/mmc_over_spigpio.c
    ================================================== =================
    --- /dev/null 1970-01-01 00:00:00.000000000 +0000
    +++ linux-next/drivers/mmc/host/mmc_over_spigpio.c 2008-07-14 21:04:51.000000000 +0200
    @@ -0,0 +1,339 @@
    +/*
    + * Driver for driving an MMC card over a bitbanging GPIO SPI bus.
    + *
    + * Copyright 2008 Michael Buesch
    + *
    + * Licensed under the GNU/GPL. See COPYING for details.
    + */
    +
    +#include
    +#include
    +#include
    +#include
    +
    +
    +/* This is the maximum speed in Hz */
    +#define GPIOMMC_MAXSPEED 5000000 /* Hz */
    +
    +
    +#define DRIVER_NAME "spi-gpio-mmc"
    +#define PFX DRIVER_NAME ": "
    +
    +
    +#define GPIOMMC_MAX_NAMELEN 15
    +#define GPIOMMC_MAX_NAMELEN_STR __stringify(GPIOMMC_MAX_NAMELEN)
    +
    +struct gpiommc_pins {
    + unsigned int gpio_di; /* Card DI pin */
    + unsigned int gpio_do; /* Card DO pin */
    + unsigned int gpio_clk; /* Card CLK pin */
    + unsigned int gpio_cs; /* Card CS pin */
    +};
    +
    +struct gpiommc_device {
    + char name[GPIOMMC_MAX_NAMELEN + 1];
    + struct platform_device *pdev;
    + struct platform_device *spi_pdev;
    + struct gpiommc_pins pins;
    + u8 mode; /* SPI_MODE_X */
    + struct spi_board_info boardinfo;
    +
    + struct list_head list;
    +};
    +
    +
    +static LIST_HEAD(gpiommc_devices_list);
    +static DEFINE_MUTEX(gpiommc_mutex);
    +
    +
    +MODULE_DESCRIPTION("SPI-GPIO based MMC driver");
    +MODULE_AUTHOR("Michael Buesch");
    +MODULE_LICENSE("GPL");
    +
    +
    +static int gpiommc_boardinfo_setup(struct spi_board_info *bi,
    + struct spi_master *master,
    + void *data)
    +{
    + struct gpiommc_device *d = data;
    +
    + /* Bind the SPI master to the MMC-SPI host driver. */
    + strlcpy(bi->modalias, "mmc_spi", sizeof(bi->modalias));
    +
    + bi->max_speed_hz = GPIOMMC_MAXSPEED;
    + bi->bus_num = master->bus_num;
    + bi->mode = d->mode;
    +
    + return 0;
    +}
    +
    +static int gpiommc_probe(struct platform_device *pdev)
    +{
    + static int instance;
    + struct gpiommc_device *d = platform_get_drvdata(pdev);
    + struct spi_gpio_platform_data pdata;
    + int err = -ENOMEM;
    +
    + d->spi_pdev = platform_device_alloc("spi-gpio", instance++);
    + if (!d->spi_pdev)
    + goto out;
    +
    + memset(&pdata, 0, sizeof(pdata));
    + pdata.pin_clk = d->pins.gpio_clk;
    + pdata.pin_miso = d->pins.gpio_do;
    + pdata.pin_mosi = d->pins.gpio_di;
    + pdata.pin_cs = d->pins.gpio_cs;
    + pdata.cs_activelow = 1;
    + pdata.no_spi_delay = 1;
    + pdata.boardinfo_setup = gpiommc_boardinfo_setup;
    + pdata.boardinfo_setup_data = d;
    +
    + err = platform_device_add_data(d->spi_pdev, &pdata, sizeof(pdata));
    + if (err)
    + goto err_free_pdev;
    + err = platform_device_register(d->spi_pdev);
    + if (err)
    + goto err_free_pdata;
    +
    + printk(KERN_INFO PFX "MMC-Card \"%s\" "
    + "attached to GPIO pins %u,%u,%u,%u\n",
    + d->name, d->pins.gpio_di, d->pins.gpio_do,
    + d->pins.gpio_clk, d->pins.gpio_cs);
    +out:
    + return err;
    +
    +err_free_pdata:
    + kfree(d->spi_pdev->dev.platform_data);
    + d->spi_pdev->dev.platform_data = NULL;
    +err_free_pdev:
    + platform_device_put(d->spi_pdev);
    + return err;
    +}
    +
    +static int gpiommc_remove(struct platform_device *pdev)
    +{
    + struct gpiommc_device *d = platform_get_drvdata(pdev);
    +
    + platform_device_unregister(d->spi_pdev);
    + printk(KERN_INFO PFX "MMC-Card \"%s\" removed\n", d->name);
    +
    + return 0;
    +}
    +
    +static void gpiommc_free(struct gpiommc_device *d)
    +{
    + kfree(d);
    +}
    +
    +static struct gpiommc_device *gpiommc_alloc(struct platform_device *pdev,
    + const char *name,
    + const struct gpiommc_pins *pins,
    + u8 mode)
    +{
    + struct gpiommc_device *d;
    +
    + d = kmalloc(sizeof(*d), GFP_KERNEL);
    + if (!d)
    + return NULL;
    +
    + strcpy(d->name, name);
    + memcpy(&d->pins, pins, sizeof(d->pins));
    + d->mode = mode;
    + INIT_LIST_HEAD(&d->list);
    +
    + return d;
    +}
    +
    +/* List must be locked. */
    +static struct gpiommc_device *gpiommc_find_device(const char *name)
    +{
    + struct gpiommc_device *d;
    +
    + list_for_each_entry(d, &gpiommc_devices_list, list) {
    + if (strcmp(d->name, name) == 0)
    + return d;
    + }
    +
    + return NULL;
    +}
    +
    +static void gpiommc_do_destroy_device(struct gpiommc_device *d)
    +{
    + list_del(&d->list);
    + platform_device_unregister(d->pdev);
    + gpiommc_free(d);
    +}
    +
    +static int gpiommc_destroy_device(const char *name)
    +{
    + struct gpiommc_device *d;
    + int err = -ENODEV;
    +
    + mutex_lock(&gpiommc_mutex);
    + d = gpiommc_find_device(name);
    + if (!d)
    + goto out_unlock;
    + gpiommc_do_destroy_device(d);
    + err = 0;
    +out_unlock:
    + mutex_unlock(&gpiommc_mutex);
    +
    + return err;
    +}
    +
    +static int gpiommc_create_device(const char *name,
    + const struct gpiommc_pins *pins,
    + u8 mode)
    +{
    + static int instance;
    + struct platform_device *pdev;
    + struct gpiommc_device *d;
    + int err;
    +
    + mutex_lock(&gpiommc_mutex);
    + err = -EEXIST;
    + if (gpiommc_find_device(name))
    + goto out_unlock;
    + err = -ENOMEM;
    + pdev = platform_device_alloc(DRIVER_NAME, instance++);
    + if (!pdev)
    + goto out_unlock;
    + d = gpiommc_alloc(pdev, name, pins, mode);
    + if (!d)
    + goto err_free_pdev;
    + platform_set_drvdata(pdev, d);
    + d->pdev = pdev;
    + err = platform_device_register(pdev);
    + if (err)
    + goto err_free_mdev;
    + list_add(&d->list, &gpiommc_devices_list);
    +
    + err = 0;
    +out_unlock:
    + mutex_unlock(&gpiommc_mutex);
    +
    + return err;
    +
    +err_free_mdev:
    + gpiommc_free(d);
    +err_free_pdev:
    + platform_device_put(pdev);
    + goto out_unlock;
    +}
    +
    +static ssize_t gpiommc_add_show(struct device_driver *drv,
    + char *buf)
    +{
    + return snprintf(buf, PAGE_SIZE, "NAME DI_pin,DO_pin,CLK_pin,CS_pin [MODE]\n");
    +}
    +
    +static ssize_t gpiommc_add_store(struct device_driver *drv,
    + const char *buf, size_t count)
    +{
    + int res, err;
    + char name[GPIOMMC_MAX_NAMELEN + 1];
    + struct gpiommc_pins pins;
    + unsigned int mode;
    +
    + res = sscanf(buf, "%" GPIOMMC_MAX_NAMELEN_STR "s %u,%u,%u,%u %u",
    + name, &pins.gpio_di, &pins.gpio_do,
    + &pins.gpio_clk, &pins.gpio_cs, &mode);
    + if (res == 5)
    + mode = 0;
    + else if (res != 6)
    + return -EINVAL;
    + switch (mode) {
    + case 0:
    + mode = SPI_MODE_0;
    + break;
    + case 1:
    + mode = SPI_MODE_1;
    + break;
    + case 2:
    + mode = SPI_MODE_2;
    + break;
    + case 3:
    + mode = SPI_MODE_3;
    + break;
    + default:
    + return -EINVAL;
    + }
    + err = gpiommc_create_device(name, &pins, mode);
    +
    + return err ? err : count;
    +}
    +
    +static ssize_t gpiommc_remove_show(struct device_driver *drv,
    + char *buf)
    +{
    + return snprintf(buf, PAGE_SIZE, "write device-name to remove the device\n");
    +}
    +
    +static ssize_t gpiommc_remove_store(struct device_driver *drv,
    + const char *buf, size_t count)
    +{
    + int err;
    +
    + err = gpiommc_destroy_device(buf);
    +
    + return err ? err : count;
    +}
    +
    +static DRIVER_ATTR(add, 0600,
    + gpiommc_add_show, gpiommc_add_store);
    +static DRIVER_ATTR(remove, 0600,
    + gpiommc_remove_show, gpiommc_remove_store);
    +
    +static struct platform_driver gpiommc_plat_driver = {
    + .probe = gpiommc_probe,
    + .remove = gpiommc_remove,
    + .driver = {
    + .name = DRIVER_NAME,
    + .owner = THIS_MODULE,
    + },
    +};
    +
    +static int __init gpiommc_modinit(void)
    +{
    + int err;
    +
    + err = platform_driver_register(&gpiommc_plat_driver);
    + if (err)
    + return err;
    + err = driver_create_file(&gpiommc_plat_driver.driver,
    + &driver_attr_add);
    + if (err)
    + goto err_drv_unreg;
    + err = driver_create_file(&gpiommc_plat_driver.driver,
    + &driver_attr_remove);
    + if (err)
    + goto err_remove_add;
    +
    + return 0;
    +
    +err_remove_add:
    + driver_remove_file(&gpiommc_plat_driver.driver,
    + &driver_attr_add);
    +err_drv_unreg:
    + platform_driver_unregister(&gpiommc_plat_driver);
    + return err;
    +}
    +module_init(gpiommc_modinit);
    +
    +static void __exit gpiommc_modexit(void)
    +{
    + struct gpiommc_device *d, *tmp;
    +
    + driver_remove_file(&gpiommc_plat_driver.driver,
    + &driver_attr_remove);
    + driver_remove_file(&gpiommc_plat_driver.driver,
    + &driver_attr_add);
    +
    + mutex_lock(&gpiommc_mutex);
    + list_for_each_entry_safe(d, tmp, &gpiommc_devices_list, list)
    + gpiommc_do_destroy_device(d);
    + mutex_unlock(&gpiommc_mutex);
    +
    + platform_driver_unregister(&gpiommc_plat_driver);
    +}
    +module_exit(gpiommc_modexit);
    Index: linux-next/drivers/mmc/host/Kconfig
    ================================================== =================
    --- linux-next.orig/drivers/mmc/host/Kconfig 2008-07-14 21:02:13.000000000 +0200
    +++ linux-next/drivers/mmc/host/Kconfig 2008-07-14 21:04:10.000000000 +0200
    @@ -153,6 +153,18 @@ config MMC_SPI

    If unsure, or if your system has no SPI master driver, say N.

    +config MMC_OVER_SPIGPIO
    + tristate "MMC/SD over GPIO-based SPI"
    + depends on MMC && MMC_SPI && SPI_GPIO
    + help
    + This driver provides a sysfs interface to dynamically create
    + and destroy GPIO-based MMC/SD card interfaces.
    + So an MMC or SD card can be connected to generic GPIO pins
    + and be configured dynamically from userspace.
    + The module will be called mmc_over_spigpio.
    +
    + If unsure, say N.
    +
    config MMC_S3C
    tristate "Samsung S3C SD/MMC Card Interface support"
    depends on ARCH_S3C2410 && MMC
    Index: linux-next/drivers/mmc/host/Makefile
    ================================================== =================
    --- linux-next.orig/drivers/mmc/host/Makefile 2008-07-14 21:02:13.000000000 +0200
    +++ linux-next/drivers/mmc/host/Makefile 2008-07-14 21:04:10.000000000 +0200
    @@ -20,3 +20,4 @@ obj-$(CONFIG_MMC_ATMELMCI) += atmel-mci.
    obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o
    obj-$(CONFIG_MMC_SPI) += mmc_spi.o
    obj-$(CONFIG_MMC_S3C) += s3cmci.o
    +obj-$(CONFIG_MMC_OVER_SPIGPIO) += mmc_over_spigpio.o

    --
    Greetings Michael.


  2. Re: [PATCH] Add dynamic MMC-over-SPI-GPIO driver

    On Mon, 14 Jul 2008 21:09:18 +0200
    Michael Buesch wrote:

    > This driver provides a sysfs interface to dynamically create
    > and destroy GPIO-based MMC/SD card interfaces.
    > So an MMC or SD card can be connected to generic GPIO pins
    > and be configured dynamically from userspace.
    >
    > Signed-off-by: Michael Buesch
    >
    > ---
    >
    > This driver is used in OpenWrt since quite some time, so please
    > consider for inclusion in mainline.
    >
    > See the attached OpenWrt initscript for an example on how to use
    > the sysfs interface. Documentation should also be added. I'll submit
    > a patch for that, later.
    >
    > ...
    >
    > +static int gpiommc_probe(struct platform_device *pdev)
    > +{
    > + static int instance;
    > + struct gpiommc_device *d = platform_get_drvdata(pdev);
    > + struct spi_gpio_platform_data pdata;
    > + int err = -ENOMEM;
    > +
    > + d->spi_pdev = platform_device_alloc("spi-gpio", instance++);
    > + if (!d->spi_pdev)
    > + goto out;


    I guess that incrementing `instance' even if the allocation failed is
    somewhat wrong.

    > + memset(&pdata, 0, sizeof(pdata));
    > + pdata.pin_clk = d->pins.gpio_clk;
    > + pdata.pin_miso = d->pins.gpio_do;
    > + pdata.pin_mosi = d->pins.gpio_di;
    > + pdata.pin_cs = d->pins.gpio_cs;
    > + pdata.cs_activelow = 1;
    > + pdata.no_spi_delay = 1;
    > + pdata.boardinfo_setup = gpiommc_boardinfo_setup;
    > + pdata.boardinfo_setup_data = d;
    > +
    > + err = platform_device_add_data(d->spi_pdev, &pdata, sizeof(pdata));
    > + if (err)
    > + goto err_free_pdev;
    > + err = platform_device_register(d->spi_pdev);
    > + if (err)
    > + goto err_free_pdata;
    > +
    > + printk(KERN_INFO PFX "MMC-Card \"%s\" "
    > + "attached to GPIO pins %u,%u,%u,%u\n",
    > + d->name, d->pins.gpio_di, d->pins.gpio_do,
    > + d->pins.gpio_clk, d->pins.gpio_cs);
    > +out:
    > + return err;
    > +
    > +err_free_pdata:
    > + kfree(d->spi_pdev->dev.platform_data);
    > + d->spi_pdev->dev.platform_data = NULL;
    > +err_free_pdev:
    > + platform_device_put(d->spi_pdev);
    > + return err;
    > +}
    > +
    >
    > ...
    >
    > +static struct gpiommc_device *gpiommc_alloc(struct platform_device *pdev,
    > + const char *name,
    > + const struct gpiommc_pins *pins,
    > + u8 mode)
    > +{
    > + struct gpiommc_device *d;
    > +
    > + d = kmalloc(sizeof(*d), GFP_KERNEL);
    > + if (!d)
    > + return NULL;
    > +
    > + strcpy(d->name, name);


    No check for overruns?

    > + memcpy(&d->pins, pins, sizeof(d->pins));


    If this had used the typesafe

    d->pins = *pins;

    I wouldn't have needed to run all around the place working out if
    overflow/underflow checks were needed here.

    > + d->mode = mode;
    > + INIT_LIST_HEAD(&d->list);
    > +
    > + return d;
    > +}
    > +
    >
    > ...
    >
    > +static ssize_t gpiommc_add_store(struct device_driver *drv,
    > + const char *buf, size_t count)
    > +{
    > + int res, err;
    > + char name[GPIOMMC_MAX_NAMELEN + 1];
    > + struct gpiommc_pins pins;
    > + unsigned int mode;
    > +
    > + res = sscanf(buf, "%" GPIOMMC_MAX_NAMELEN_STR "s %u,%u,%u,%u %u",
    > + name, &pins.gpio_di, &pins.gpio_do,
    > + &pins.gpio_clk, &pins.gpio_cs, &mode);


    What's going on here? So new kernel/userspace ABI. Not documented in
    changelog, not documented in code comments, not documented in
    Documentation/ABI. This forces reviewers to reverse-engineer the
    interface design from the implementation and then attempt to review
    that design. Reviewers not happy!

    Userspace interfaces are the things which we care about most, because
    they are the things which we can never change. Please document them
    prominently.

    > + if (res == 5)
    > + mode = 0;
    > + else if (res != 6)
    > + return -EINVAL;
    > + switch (mode) {
    > + case 0:
    > + mode = SPI_MODE_0;
    > + break;
    > + case 1:
    > + mode = SPI_MODE_1;
    > + break;
    > + case 2:
    > + mode = SPI_MODE_2;
    > + break;
    > + case 3:
    > + mode = SPI_MODE_3;
    > + break;
    > + default:
    > + return -EINVAL;
    > + }
    > + err = gpiommc_create_device(name, &pins, mode);
    > +
    > + return err ? err : count;
    > +}
    > +
    > +static ssize_t gpiommc_remove_show(struct device_driver *drv,
    > + char *buf)
    > +{
    > + return snprintf(buf, PAGE_SIZE, "write device-name to remove the device\n");
    > +}


    Now that is one weird way in which to document the interface! What a
    waste of kernel text

    > +static ssize_t gpiommc_remove_store(struct device_driver *drv,
    > + const char *buf, size_t count)
    > +{
    > + int err;
    > +
    > + err = gpiommc_destroy_device(buf);
    > +
    > + return err ? err : count;
    > +}
    > +
    > +static DRIVER_ATTR(add, 0600,
    > + gpiommc_add_show, gpiommc_add_store);
    > +static DRIVER_ATTR(remove, 0600,
    > + gpiommc_remove_show, gpiommc_remove_store);
    > +
    > +static struct platform_driver gpiommc_plat_driver = {
    > + .probe = gpiommc_probe,
    > + .remove = gpiommc_remove,
    > + .driver = {
    > + .name = DRIVER_NAME,
    > + .owner = THIS_MODULE,
    > + },
    > +};
    > +


    I'll skip this, pending suitable documentation of the proposed
    interface design, and review of that design.

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  3. Re: [PATCH] Add dynamic MMC-over-SPI-GPIO driver


    On Mon, 2008-07-14 at 21:09 +0200, Michael Buesch wrote:
    > This driver provides a sysfs interface to dynamically create
    > and destroy GPIO-based MMC/SD card interfaces.
    > So an MMC or SD card can be connected to generic GPIO pins
    > and be configured dynamically from userspace.


    Can you use mmc-spi attached to spi-gpio and be done with it? Sure you
    won't have the dynamic alloc capability but you won't be reinventing the
    wheel either. You don't have dynamic creation for any other platform
    device and if you need it then, IMO, it'd be better solved in a more
    generic way.

    btw, what's this spi-gpio thing? I can't see it in mainline except in a
    s3c24xx specific way. My domestic blindness??

    --Ben.


    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  4. Re: [PATCH] Add dynamic MMC-over-SPI-GPIO driver

    On Monday 14 July 2008 22:54:41 Andrew Morton wrote:
    > > +static int gpiommc_probe(struct platform_device *pdev)
    > > +{
    > > + static int instance;
    > > + struct gpiommc_device *d = platform_get_drvdata(pdev);
    > > + struct spi_gpio_platform_data pdata;
    > > + int err = -ENOMEM;
    > > +
    > > + d->spi_pdev = platform_device_alloc("spi-gpio", instance++);
    > > + if (!d->spi_pdev)
    > > + goto out;

    >
    > I guess that incrementing `instance' even if the allocation failed is
    > somewhat wrong.


    Well, I guess it doesn't matter much. The number is pretty random anyway.

    > > +static struct gpiommc_device *gpiommc_alloc(struct platform_device *pdev,
    > > + const char *name,
    > > + const struct gpiommc_pins *pins,
    > > + u8 mode)
    > > +{
    > > + struct gpiommc_device *d;
    > > +
    > > + d = kmalloc(sizeof(*d), GFP_KERNEL);
    > > + if (!d)
    > > + return NULL;
    > > +
    > > + strcpy(d->name, name);

    >
    > No check for overruns?


    The caller checks the length, but it is a good idea to double-check here.
    Good catch.

    > > + memcpy(&d->pins, pins, sizeof(d->pins));

    >
    > If this had used the typesafe
    >
    > d->pins = *pins;
    >
    > I wouldn't have needed to run all around the place working out if
    > overflow/underflow checks were needed here.


    Yeah well, can use this.

    > > +static ssize_t gpiommc_add_store(struct device_driver *drv,
    > > + const char *buf, size_t count)
    > > +{
    > > + int res, err;
    > > + char name[GPIOMMC_MAX_NAMELEN + 1];
    > > + struct gpiommc_pins pins;
    > > + unsigned int mode;
    > > +
    > > + res = sscanf(buf, "%" GPIOMMC_MAX_NAMELEN_STR "s %u,%u,%u,%u %u",
    > > + name, &pins.gpio_di, &pins.gpio_do,
    > > + &pins.gpio_clk, &pins.gpio_cs, &mode);

    >
    > What's going on here? So new kernel/userspace ABI.


    The whole point of the module is to create a new userspace interface for
    creating the device. The module does just glue several modules together
    and create an actual device.

    > Not documented in
    > changelog, not documented in code comments, not documented in
    > Documentation/ABI. This forces reviewers to reverse-engineer the
    > interface design from the implementation and then attempt to review
    > that design. Reviewers not happy!


    Yeah well, as I said, I will do docs later. I didn't have any time
    to write documentation, yet.
    by.

    > > +static ssize_t gpiommc_remove_show(struct device_driver *drv,
    > > + char *buf)
    > > +{
    > > + return snprintf(buf, PAGE_SIZE, "write device-name to remove the device\n");
    > > +}

    >
    > Now that is one weird way in which to document the interface! What a
    > waste of kernel text


    Yeah, well. Better than nothing
    As I already said in the original patch announcement. This is by no way the
    final version of the patch. Docs will be moved to Documentation/

    --
    Greetings Michael.
    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  5. Re: [PATCH] Add dynamic MMC-over-SPI-GPIO driver

    On Tuesday 15 July 2008 07:06:49 Ben Nizette wrote:
    >
    > On Mon, 2008-07-14 at 21:09 +0200, Michael Buesch wrote:
    > > This driver provides a sysfs interface to dynamically create
    > > and destroy GPIO-based MMC/SD card interfaces.
    > > So an MMC or SD card can be connected to generic GPIO pins
    > > and be configured dynamically from userspace.

    >
    > Can you use mmc-spi attached to spi-gpio and be done with it?


    This is _exactly_ what this module does. It combines mmc-spi and
    spi-gpio and creates an actual device for them.

    > Sure you
    > won't have the dynamic alloc capability but you won't be reinventing the
    > wheel either.


    This does not reinvent anything. It just wires up the two modules.

    --
    Greetings Michael.
    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  6. Re: [PATCH] Add dynamic MMC-over-SPI-GPIO driver

    On Monday 14 July 2008 21:09:18 Michael Buesch wrote:
    > This driver provides a sysfs interface to dynamically create
    > and destroy GPIO-based MMC/SD card interfaces.
    > So an MMC or SD card can be connected to generic GPIO pins
    > and be configured dynamically from userspace.


    Ok, I had requests in private to also allow registering the platform
    device from outside of the module (and use platform data). This is
    used for certain embedded hardware from the arch
    code to statically create a GPIO-based MMC device.
    I'll add that and resend along with the proposed fixes.
    Thanks for the review!


    --
    Greetings Michael.
    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  7. Re: [PATCH] Add dynamic MMC-over-SPI-GPIO driver

    On Monday 14 July 2008, Ben Nizette wrote:
    >
    > On Mon, 2008-07-14 at 21:09 +0200, Michael Buesch wrote:
    > > This driver provides a sysfs interface to dynamically create
    > > and destroy GPIO-based MMC/SD card interfaces.
    > > So an MMC or SD card can be connected to generic GPIO pins
    > > and be configured dynamically from userspace.

    >
    > Can you use mmc-spi attached to spi-gpio and be done with it?


    Yes, that's how some of the early mmc-spi work was done.


    > Sure you
    > won't have the dynamic alloc capability but you won't be reinventing the
    > wheel either. You don't have dynamic creation for any other platform
    > device and if you need it then, IMO, it'd be better solved in a more
    > generic way.
    >
    > btw, what's this spi-gpio thing? I can't see it in mainline except in a
    > s3c24xx specific way. My domestic blindness??


    ISTR a patch for that, sitting somewhere in my mailbox waiting
    for review cycles. I've sent examples of such stuff around
    before too.

    I've held back submitting a spi-gpio driver until I could come
    up with a way to configure it which would let the GPIO calls
    get inlined ... because otherwise, there's a nasty speed penalty.

    It's the difference between a function call per GPIO operation
    and an instruction per GPIO operation. Consider that each SPI
    clock cycle requires four such operations, and GPIO function
    calls often take 30 instructions ... there's a big penalty to
    the non-inlined bitbangers, which is only partly addressed by
    having those function calls sitting in I-cache.

    - Dave
    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

+ Reply to Thread