]> err.no Git - linux-2.6/blobdiff - drivers/spi/spi.c
[PATCH] i2c: Use module_param in i2c-algo-sibyte
[linux-2.6] / drivers / spi / spi.c
index 7cd356b1764422a2f3a095de6234a3922fa7fdf6..791c4dc550aee0e7df764270282ef977edf6a151 100644 (file)
 #include <linux/spi/spi.h>
 
 
-/* SPI bustype and spi_master class are registered during early boot,
- * usually before board init code provides the SPI device tables, and
- * are available later when driver init code needs them.
- *
- * Drivers for SPI devices started out like those for platform bus
- * devices.  But both have changed in 2.6.15; maybe this should get
- * an "spi_driver" structure at some point (not currently needed)
+/* SPI bustype and spi_master class are registered after board init code
+ * provides the SPI device tables, ensuring that both are present by the
+ * time controller driver registration causes spi_devices to "enumerate".
  */
 static void spidev_release(struct device *dev)
 {
@@ -42,7 +38,7 @@ static void spidev_release(struct device *dev)
        if (spi->master->cleanup)
                spi->master->cleanup(spi);
 
-       class_device_put(&spi->master->cdev);
+       spi_master_put(spi->master);
        kfree(dev);
 }
 
@@ -83,10 +79,7 @@ static int spi_uevent(struct device *dev, char **envp, int num_envp,
 
 #ifdef CONFIG_PM
 
-/* Suspend/resume in "struct device_driver" don't really need that
- * strange third parameter, so we just make it a constant and expect
- * SPI drivers to ignore it just like most platform drivers do.
- *
+/*
  * NOTE:  the suspend() method for an spi_master controller driver
  * should verify that all its child devices are marked as suspended;
  * suspend requests delivered through sysfs power/state files don't
@@ -94,13 +87,14 @@ static int spi_uevent(struct device *dev, char **envp, int num_envp,
  */
 static int spi_suspend(struct device *dev, pm_message_t message)
 {
-       int     value;
+       int                     value;
+       struct spi_driver       *drv = to_spi_driver(dev->driver);
 
-       if (!dev->driver || !dev->driver->suspend)
+       if (!drv->suspend)
                return 0;
 
        /* suspend will stop irqs and dma; no more i/o */
-       value = dev->driver->suspend(dev, message);
+       value = drv->suspend(to_spi_device(dev), message);
        if (value == 0)
                dev->power.power_state = message;
        return value;
@@ -108,13 +102,14 @@ static int spi_suspend(struct device *dev, pm_message_t message)
 
 static int spi_resume(struct device *dev)
 {
-       int     value;
+       int                     value;
+       struct spi_driver       *drv = to_spi_driver(dev->driver);
 
-       if (!dev->driver || !dev->driver->resume)
+       if (!drv->resume)
                return 0;
 
        /* resume may restart the i/o queue */
-       value = dev->driver->resume(dev);
+       value = drv->resume(to_spi_device(dev));
        if (value == 0)
                dev->power.power_state = PMSG_ON;
        return value;
@@ -135,6 +130,41 @@ struct bus_type spi_bus_type = {
 };
 EXPORT_SYMBOL_GPL(spi_bus_type);
 
+
+static int spi_drv_probe(struct device *dev)
+{
+       const struct spi_driver         *sdrv = to_spi_driver(dev->driver);
+
+       return sdrv->probe(to_spi_device(dev));
+}
+
+static int spi_drv_remove(struct device *dev)
+{
+       const struct spi_driver         *sdrv = to_spi_driver(dev->driver);
+
+       return sdrv->remove(to_spi_device(dev));
+}
+
+static void spi_drv_shutdown(struct device *dev)
+{
+       const struct spi_driver         *sdrv = to_spi_driver(dev->driver);
+
+       sdrv->shutdown(to_spi_device(dev));
+}
+
+int spi_register_driver(struct spi_driver *sdrv)
+{
+       sdrv->driver.bus = &spi_bus_type;
+       if (sdrv->probe)
+               sdrv->driver.probe = spi_drv_probe;
+       if (sdrv->remove)
+               sdrv->driver.remove = spi_drv_remove;
+       if (sdrv->shutdown)
+               sdrv->driver.shutdown = spi_drv_shutdown;
+       return driver_register(&sdrv->driver);
+}
+EXPORT_SYMBOL_GPL(spi_register_driver);
+
 /*-------------------------------------------------------------------------*/
 
 /* SPI devices should normally not be created by SPI device drivers; that
@@ -168,7 +198,7 @@ spi_new_device(struct spi_master *master, struct spi_board_info *chip)
 
        /* NOTE:  caller did any chip->bus_num checks necessary */
 
-       if (!class_device_get(&master->cdev))
+       if (!spi_master_get(master))
                return NULL;
 
        proxy = kzalloc(sizeof *proxy, GFP_KERNEL);
@@ -208,13 +238,15 @@ spi_new_device(struct spi_master *master, struct spi_board_info *chip)
        if (status < 0) {
                dev_dbg(dev, "can't %s %s, status %d\n",
                                "add", proxy->dev.bus_id, status);
-fail:
-               class_device_put(&master->cdev);
-               kfree(proxy);
-               return NULL;
+               goto fail;
        }
        dev_dbg(dev, "registered child %s\n", proxy->dev.bus_id);
        return proxy;
+
+fail:
+       spi_master_put(master);
+       kfree(proxy);
+       return NULL;
 }
 EXPORT_SYMBOL_GPL(spi_new_device);
 
@@ -237,11 +269,11 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n)
 {
        struct boardinfo        *bi;
 
-       bi = kmalloc (sizeof (*bi) + n * sizeof (*info), GFP_KERNEL);
+       bi = kmalloc(sizeof(*bi) + n * sizeof *info, GFP_KERNEL);
        if (!bi)
                return -ENOMEM;
        bi->n_board_info = n;
-       memcpy(bi->board_info, info, n * sizeof (*info));
+       memcpy(bi->board_info, info, n * sizeof *info);
 
        down(&board_lock);
        list_add_tail(&bi->list, &board_list);
@@ -292,8 +324,6 @@ static void spi_master_release(struct class_device *cdev)
        struct spi_master *master;
 
        master = container_of(cdev, struct spi_master, cdev);
-       put_device(master->cdev.dev);
-       master->cdev.dev = NULL;
        kfree(master);
 }
 
@@ -307,8 +337,9 @@ static struct class spi_master_class = {
 /**
  * spi_alloc_master - allocate SPI master controller
  * @dev: the controller, possibly using the platform_bus
- * @size: how much driver-private data to preallocate; a pointer to this
- *     memory in the class_data field of the returned class_device
+ * @size: how much driver-private data to preallocate; the pointer to this
+ *     memory is in the class_data field of the returned class_device,
+ *     accessible with spi_master_get_devdata().
  *
  * This call is used only by SPI master controller drivers, which are the
  * only ones directly touching chip registers.  It's how they allocate
@@ -318,21 +349,25 @@ static struct class spi_master_class = {
  * master structure on success, else NULL.
  *
  * The caller is responsible for assigning the bus number and initializing
- * the master's methods before calling spi_add_master(), or else (on error)
- * calling class_device_put() to prevent a memory leak.
+ * the master's methods before calling spi_add_master(); and (after errors
+ * adding the device) calling spi_master_put() to prevent a memory leak.
  */
 struct spi_master * __init_or_module
 spi_alloc_master(struct device *dev, unsigned size)
 {
        struct spi_master       *master;
 
+       if (!dev)
+               return NULL;
+
        master = kzalloc(size + sizeof *master, SLAB_KERNEL);
        if (!master)
                return NULL;
 
+       class_device_initialize(&master->cdev);
        master->cdev.class = &spi_master_class;
        master->cdev.dev = get_device(dev);
-       class_set_devdata(&master->cdev, &master[1]);
+       spi_master_set_devdata(master, &master[1]);
 
        return master;
 }
@@ -354,6 +389,8 @@ EXPORT_SYMBOL_GPL(spi_alloc_master);
  *
  * This must be called from context that can sleep.  It returns zero on
  * success, else a negative error code (dropping the master's refcount).
+ * After a successful return, the caller is responsible for calling
+ * spi_unregister_master().
  */
 int __init_or_module
 spi_register_master(struct spi_master *master)
@@ -363,10 +400,13 @@ spi_register_master(struct spi_master *master)
        int                     status = -ENODEV;
        int                     dynamic = 0;
 
+       if (!dev)
+               return -ENODEV;
+
        /* convention:  dynamically assigned bus IDs count down from the max */
        if (master->bus_num == 0) {
                master->bus_num = atomic_dec_return(&dyn_bus_id);
-               dynamic = 0;
+               dynamic = 1;
        }
 
        /* register the device, then userspace will see it.
@@ -374,11 +414,9 @@ spi_register_master(struct spi_master *master)
         */
        snprintf(master->cdev.class_id, sizeof master->cdev.class_id,
                "spi%u", master->bus_num);
-       status = class_device_register(&master->cdev);
-       if (status < 0) {
-               class_device_put(&master->cdev);
+       status = class_device_add(&master->cdev);
+       if (status < 0)
                goto done;
-       }
        dev_dbg(dev, "registered master %s%s\n", master->cdev.class_id,
                        dynamic ? " (dynamic)" : "");
 
@@ -394,7 +432,7 @@ EXPORT_SYMBOL_GPL(spi_register_master);
 static int __unregister(struct device *dev, void *unused)
 {
        /* note: before about 2.6.14-rc1 this would corrupt memory: */
-       device_unregister(dev);
+       spi_unregister_device(to_spi_device(dev));
        return 0;
 }
 
@@ -409,8 +447,9 @@ static int __unregister(struct device *dev, void *unused)
  */
 void spi_unregister_master(struct spi_master *master)
 {
-       class_device_unregister(&master->cdev);
        (void) device_for_each_child(master->cdev.dev, NULL, __unregister);
+       class_device_unregister(&master->cdev);
+       master->cdev.dev = NULL;
 }
 EXPORT_SYMBOL_GPL(spi_unregister_master);
 
@@ -441,6 +480,11 @@ EXPORT_SYMBOL_GPL(spi_busnum_to_master);
 
 /*-------------------------------------------------------------------------*/
 
+static void spi_complete(void *arg)
+{
+       complete(arg);
+}
+
 /**
  * spi_sync - blocking/synchronous SPI data transfers
  * @spi: device with which data will be exchanged
@@ -456,6 +500,9 @@ EXPORT_SYMBOL_GPL(spi_busnum_to_master);
  * by leaving it selected in anticipation that the next message will go
  * to the same chip.  (That may increase power usage.)
  *
+ * Also, the caller is guaranteeing that the memory associated with the
+ * message will not be freed before this call returns.
+ *
  * The return value is a negative error code if the message could not be
  * submitted, else zero.  When the value is zero, then message->status is
  * also defined:  it's the completion code for the transfer, either zero
@@ -466,7 +513,7 @@ int spi_sync(struct spi_device *spi, struct spi_message *message)
        DECLARE_COMPLETION(done);
        int status;
 
-       message->complete = (void (*)(void *)) complete;
+       message->complete = spi_complete;
        message->context = &done;
        status = spi_async(spi, message);
        if (status == 0)
@@ -491,10 +538,11 @@ static u8 *buf;
  * This performs a half duplex MicroWire style transaction with the
  * device, sending txbuf and then reading rxbuf.  The return value
  * is zero for success, else a negative errno status code.
+ * This call may only be used from a context that may sleep.
  *
- * Parameters to this routine are always copied using a small buffer,
- * large transfers should use use spi_{async,sync}() calls with
- * dma-safe buffers.
+ * Parameters to this routine are always copied using a small buffer;
+ * performance-sensitive or bulk transfer code should instead use
+ * spi_{async,sync}() calls with dma-safe buffers.
  */
 int spi_write_then_read(struct spi_device *spi,
                const u8 *txbuf, unsigned n_tx,
@@ -514,6 +562,17 @@ int spi_write_then_read(struct spi_device *spi,
        if ((n_tx + n_rx) > SPI_BUFSIZ)
                return -EINVAL;
 
+       spi_message_init(&message);
+       memset(x, 0, sizeof x);
+       if (n_tx) {
+               x[0].len = n_tx;
+               spi_message_add_tail(&x[0], &message);
+       }
+       if (n_rx) {
+               x[1].len = n_rx;
+               spi_message_add_tail(&x[1], &message);
+       }
+
        /* ... unless someone else is using the pre-allocated buffer */
        if (down_trylock(&lock)) {
                local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
@@ -522,18 +581,11 @@ int spi_write_then_read(struct spi_device *spi,
        } else
                local_buf = buf;
 
-       memset(x, 0, sizeof x);
-
        memcpy(local_buf, txbuf, n_tx);
        x[0].tx_buf = local_buf;
-       x[0].len = n_tx;
-
        x[1].rx_buf = local_buf + n_tx;
-       x[1].len = n_rx;
 
        /* do the i/o */
-       message.transfers = x;
-       message.n_transfer = ARRAY_SIZE(x);
        status = spi_sync(spi, &message);
        if (status == 0) {
                memcpy(rxbuf, x[1].rx_buf, n_rx);
@@ -553,16 +605,38 @@ EXPORT_SYMBOL_GPL(spi_write_then_read);
 
 static int __init spi_init(void)
 {
+       int     status;
+
        buf = kmalloc(SPI_BUFSIZ, SLAB_KERNEL);
-       if (!buf)
-               return -ENOMEM;
+       if (!buf) {
+               status = -ENOMEM;
+               goto err0;
+       }
+
+       status = bus_register(&spi_bus_type);
+       if (status < 0)
+               goto err1;
 
-       bus_register(&spi_bus_type);
-       class_register(&spi_master_class);
+       status = class_register(&spi_master_class);
+       if (status < 0)
+               goto err2;
        return 0;
+
+err2:
+       bus_unregister(&spi_bus_type);
+err1:
+       kfree(buf);
+       buf = NULL;
+err0:
+       return status;
 }
+
 /* board_info is normally registered in arch_initcall(),
  * but even essential drivers wait till later
+ *
+ * REVISIT only boardinfo really needs static linking. the rest (device and
+ * driver registration) _could_ be dynamically linked (modular) ... costs
+ * include needing to have boardinfo data structures be much more public.
  */
 subsys_initcall(spi_init);