From 8ae12a0d85987dc138f8c944cb78a92bf466cea0 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 8 Jan 2006 13:34:19 -0800 Subject: [PATCH] spi: simple SPI framework This is the core of a small SPI framework, implementing the model of a queue of messages which complete asynchronously (with thin synchronous wrappers on top). - It's still less than 2KB of ".text" (ARM). If there's got to be a mid-layer for something so simple, that's the right size budget. :) - The guts use board-specific SPI device tables to build the driver model tree. (Hardware probing is rarely an option.) - This version of Kconfig includes no drivers. At this writing there are two known master controller drivers (PXA/SSP, OMAP MicroWire) and three protocol drivers (CS8415a, ADS7846, DataFlash) with LKML mentions of other drivers in development. - No userspace API. There are several implementations to compare. Implement them like any other driver, and bind them with sysfs. The changes from last version posted to LKML (on 11-Nov-2005) are minor, and include: - One bugfix (removes a FIXME), with the visible effect of making device names be "spiB.C" where B is the bus number and C is the chipselect. - The "caller provides DMA mappings" mechanism now has kerneldoc, for DMA drivers that want to be fancy. - Hey, the framework init can be subsys_init. Even though board init logic fires earlier, at arch_init ... since the framework init is for driver support, and the board init support uses static init. - Various additional spec/doc clarifications based on discussions with other folk. It adds a brief "thank you" at the end, for folk who've helped nudge this framework into existence. As I've said before, I think that "protocol tweaking" is the main support that this driver framework will need to evolve. From: Mark Underwood Update the SPI framework to remove a potential priority inversion case by reverting to kmalloc if the pre-allocated DMA-safe buffer isn't available. Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/spi/spi.c | 568 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 568 insertions(+) create mode 100644 drivers/spi/spi.c (limited to 'drivers/spi/spi.c') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c new file mode 100644 index 00000000000..7cd356b1764 --- /dev/null +++ b/drivers/spi/spi.c @@ -0,0 +1,568 @@ +/* + * spi.c - SPI init/core code + * + * Copyright (C) 2005 David Brownell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + + +/* 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) + */ +static void spidev_release(struct device *dev) +{ + const struct spi_device *spi = to_spi_device(dev); + + /* spi masters may cleanup for released devices */ + if (spi->master->cleanup) + spi->master->cleanup(spi); + + class_device_put(&spi->master->cdev); + kfree(dev); +} + +static ssize_t +modalias_show(struct device *dev, struct device_attribute *a, char *buf) +{ + const struct spi_device *spi = to_spi_device(dev); + + return snprintf(buf, BUS_ID_SIZE + 1, "%s\n", spi->modalias); +} + +static struct device_attribute spi_dev_attrs[] = { + __ATTR_RO(modalias), + __ATTR_NULL, +}; + +/* modalias support makes "modprobe $MODALIAS" new-style hotplug work, + * and the sysfs version makes coldplug work too. + */ + +static int spi_match_device(struct device *dev, struct device_driver *drv) +{ + const struct spi_device *spi = to_spi_device(dev); + + return strncmp(spi->modalias, drv->name, BUS_ID_SIZE) == 0; +} + +static int spi_uevent(struct device *dev, char **envp, int num_envp, + char *buffer, int buffer_size) +{ + const struct spi_device *spi = to_spi_device(dev); + + envp[0] = buffer; + snprintf(buffer, buffer_size, "MODALIAS=%s", spi->modalias); + envp[1] = NULL; + return 0; +} + +#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 + * enforce such constraints. + */ +static int spi_suspend(struct device *dev, pm_message_t message) +{ + int value; + + if (!dev->driver || !dev->driver->suspend) + return 0; + + /* suspend will stop irqs and dma; no more i/o */ + value = dev->driver->suspend(dev, message); + if (value == 0) + dev->power.power_state = message; + return value; +} + +static int spi_resume(struct device *dev) +{ + int value; + + if (!dev->driver || !dev->driver->resume) + return 0; + + /* resume may restart the i/o queue */ + value = dev->driver->resume(dev); + if (value == 0) + dev->power.power_state = PMSG_ON; + return value; +} + +#else +#define spi_suspend NULL +#define spi_resume NULL +#endif + +struct bus_type spi_bus_type = { + .name = "spi", + .dev_attrs = spi_dev_attrs, + .match = spi_match_device, + .uevent = spi_uevent, + .suspend = spi_suspend, + .resume = spi_resume, +}; +EXPORT_SYMBOL_GPL(spi_bus_type); + +/*-------------------------------------------------------------------------*/ + +/* SPI devices should normally not be created by SPI device drivers; that + * would make them board-specific. Similarly with SPI master drivers. + * Device registration normally goes into like arch/.../mach.../board-YYY.c + * with other readonly (flashable) information about mainboard devices. + */ + +struct boardinfo { + struct list_head list; + unsigned n_board_info; + struct spi_board_info board_info[0]; +}; + +static LIST_HEAD(board_list); +static DECLARE_MUTEX(board_lock); + + +/* On typical mainboards, this is purely internal; and it's not needed + * after board init creates the hard-wired devices. Some development + * platforms may not be able to use spi_register_board_info though, and + * this is exported so that for example a USB or parport based adapter + * driver could add devices (which it would learn about out-of-band). + */ +struct spi_device *__init_or_module +spi_new_device(struct spi_master *master, struct spi_board_info *chip) +{ + struct spi_device *proxy; + struct device *dev = master->cdev.dev; + int status; + + /* NOTE: caller did any chip->bus_num checks necessary */ + + if (!class_device_get(&master->cdev)) + return NULL; + + proxy = kzalloc(sizeof *proxy, GFP_KERNEL); + if (!proxy) { + dev_err(dev, "can't alloc dev for cs%d\n", + chip->chip_select); + goto fail; + } + proxy->master = master; + proxy->chip_select = chip->chip_select; + proxy->max_speed_hz = chip->max_speed_hz; + proxy->irq = chip->irq; + proxy->modalias = chip->modalias; + + snprintf(proxy->dev.bus_id, sizeof proxy->dev.bus_id, + "%s.%u", master->cdev.class_id, + chip->chip_select); + proxy->dev.parent = dev; + proxy->dev.bus = &spi_bus_type; + proxy->dev.platform_data = (void *) chip->platform_data; + proxy->controller_data = chip->controller_data; + proxy->controller_state = NULL; + proxy->dev.release = spidev_release; + + /* drivers may modify this default i/o setup */ + status = master->setup(proxy); + if (status < 0) { + dev_dbg(dev, "can't %s %s, status %d\n", + "setup", proxy->dev.bus_id, status); + goto fail; + } + + /* driver core catches callers that misbehave by defining + * devices that already exist. + */ + status = device_register(&proxy->dev); + 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; + } + dev_dbg(dev, "registered child %s\n", proxy->dev.bus_id); + return proxy; +} +EXPORT_SYMBOL_GPL(spi_new_device); + +/* + * Board-specific early init code calls this (probably during arch_initcall) + * with segments of the SPI device table. Any device nodes are created later, + * after the relevant parent SPI controller (bus_num) is defined. We keep + * this table of devices forever, so that reloading a controller driver will + * not make Linux forget about these hard-wired devices. + * + * Other code can also call this, e.g. a particular add-on board might provide + * SPI devices through its expansion connector, so code initializing that board + * would naturally declare its SPI devices. + * + * The board info passed can safely be __initdata ... but be careful of + * any embedded pointers (platform_data, etc), they're copied as-is. + */ +int __init +spi_register_board_info(struct spi_board_info const *info, unsigned n) +{ + struct boardinfo *bi; + + 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)); + + down(&board_lock); + list_add_tail(&bi->list, &board_list); + up(&board_lock); + return 0; +} +EXPORT_SYMBOL_GPL(spi_register_board_info); + +/* FIXME someone should add support for a __setup("spi", ...) that + * creates board info from kernel command lines + */ + +static void __init_or_module +scan_boardinfo(struct spi_master *master) +{ + struct boardinfo *bi; + struct device *dev = master->cdev.dev; + + down(&board_lock); + list_for_each_entry(bi, &board_list, list) { + struct spi_board_info *chip = bi->board_info; + unsigned n; + + for (n = bi->n_board_info; n > 0; n--, chip++) { + if (chip->bus_num != master->bus_num) + continue; + /* some controllers only have one chip, so they + * might not use chipselects. otherwise, the + * chipselects are numbered 0..max. + */ + if (chip->chip_select >= master->num_chipselect + && master->num_chipselect) { + dev_dbg(dev, "cs%d > max %d\n", + chip->chip_select, + master->num_chipselect); + continue; + } + (void) spi_new_device(master, chip); + } + } + up(&board_lock); +} + +/*-------------------------------------------------------------------------*/ + +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); +} + +static struct class spi_master_class = { + .name = "spi_master", + .owner = THIS_MODULE, + .release = spi_master_release, +}; + + +/** + * 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 + * + * This call is used only by SPI master controller drivers, which are the + * only ones directly touching chip registers. It's how they allocate + * an spi_master structure, prior to calling spi_add_master(). + * + * This must be called from context that can sleep. It returns the SPI + * 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. + */ +struct spi_master * __init_or_module +spi_alloc_master(struct device *dev, unsigned size) +{ + struct spi_master *master; + + master = kzalloc(size + sizeof *master, SLAB_KERNEL); + if (!master) + return NULL; + + master->cdev.class = &spi_master_class; + master->cdev.dev = get_device(dev); + class_set_devdata(&master->cdev, &master[1]); + + return master; +} +EXPORT_SYMBOL_GPL(spi_alloc_master); + +/** + * spi_register_master - register SPI master controller + * @master: initialized master, originally from spi_alloc_master() + * + * SPI master controllers connect to their drivers using some non-SPI bus, + * such as the platform bus. The final stage of probe() in that code + * includes calling spi_register_master() to hook up to this SPI bus glue. + * + * SPI controllers use board specific (often SOC specific) bus numbers, + * and board-specific addressing for SPI devices combines those numbers + * with chip select numbers. Since SPI does not directly support dynamic + * device identification, boards need configuration tables telling which + * chip is at which address. + * + * This must be called from context that can sleep. It returns zero on + * success, else a negative error code (dropping the master's refcount). + */ +int __init_or_module +spi_register_master(struct spi_master *master) +{ + static atomic_t dyn_bus_id = ATOMIC_INIT(0); + struct device *dev = master->cdev.dev; + int status = -ENODEV; + int dynamic = 0; + + /* 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; + } + + /* register the device, then userspace will see it. + * registration fails if the bus ID is in use. + */ + 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); + goto done; + } + dev_dbg(dev, "registered master %s%s\n", master->cdev.class_id, + dynamic ? " (dynamic)" : ""); + + /* populate children from any spi device tables */ + scan_boardinfo(master); + status = 0; +done: + return status; +} +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); + return 0; +} + +/** + * spi_unregister_master - unregister SPI master controller + * @master: the master being unregistered + * + * This call is used only by SPI master controller drivers, which are the + * only ones directly touching chip registers. + * + * This must be called from context that can sleep. + */ +void spi_unregister_master(struct spi_master *master) +{ + class_device_unregister(&master->cdev); + (void) device_for_each_child(master->cdev.dev, NULL, __unregister); +} +EXPORT_SYMBOL_GPL(spi_unregister_master); + +/** + * spi_busnum_to_master - look up master associated with bus_num + * @bus_num: the master's bus number + * + * This call may be used with devices that are registered after + * arch init time. It returns a refcounted pointer to the relevant + * spi_master (which the caller must release), or NULL if there is + * no such master registered. + */ +struct spi_master *spi_busnum_to_master(u16 bus_num) +{ + if (bus_num) { + char name[8]; + struct kobject *bus; + + snprintf(name, sizeof name, "spi%u", bus_num); + bus = kset_find_obj(&spi_master_class.subsys.kset, name); + if (bus) + return container_of(bus, struct spi_master, cdev.kobj); + } + return NULL; +} +EXPORT_SYMBOL_GPL(spi_busnum_to_master); + + +/*-------------------------------------------------------------------------*/ + +/** + * spi_sync - blocking/synchronous SPI data transfers + * @spi: device with which data will be exchanged + * @message: describes the data transfers + * + * This call may only be used from a context that may sleep. The sleep + * is non-interruptible, and has no timeout. Low-overhead controller + * drivers may DMA directly into and out of the message buffers. + * + * Note that the SPI device's chip select is active during the message, + * and then is normally disabled between messages. Drivers for some + * frequently-used devices may want to minimize costs of selecting a chip, + * by leaving it selected in anticipation that the next message will go + * to the same chip. (That may increase power usage.) + * + * 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 + * or a negative error code from the controller driver. + */ +int spi_sync(struct spi_device *spi, struct spi_message *message) +{ + DECLARE_COMPLETION(done); + int status; + + message->complete = (void (*)(void *)) complete; + message->context = &done; + status = spi_async(spi, message); + if (status == 0) + wait_for_completion(&done); + message->context = NULL; + return status; +} +EXPORT_SYMBOL_GPL(spi_sync); + +#define SPI_BUFSIZ (SMP_CACHE_BYTES) + +static u8 *buf; + +/** + * spi_write_then_read - SPI synchronous write followed by read + * @spi: device with which data will be exchanged + * @txbuf: data to be written (need not be dma-safe) + * @n_tx: size of txbuf, in bytes + * @rxbuf: buffer into which data will be read + * @n_rx: size of rxbuf, in bytes (need not be dma-safe) + * + * 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. + * + * Parameters to this routine are always copied using a small buffer, + * large transfers should use use spi_{async,sync}() calls with + * dma-safe buffers. + */ +int spi_write_then_read(struct spi_device *spi, + const u8 *txbuf, unsigned n_tx, + u8 *rxbuf, unsigned n_rx) +{ + static DECLARE_MUTEX(lock); + + int status; + struct spi_message message; + struct spi_transfer x[2]; + u8 *local_buf; + + /* Use preallocated DMA-safe buffer. We can't avoid copying here, + * (as a pure convenience thing), but we can keep heap costs + * out of the hot path ... + */ + if ((n_tx + n_rx) > SPI_BUFSIZ) + return -EINVAL; + + /* ... unless someone else is using the pre-allocated buffer */ + if (down_trylock(&lock)) { + local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL); + if (!local_buf) + return -ENOMEM; + } 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); + status = message.status; + } + + if (x[0].tx_buf == buf) + up(&lock); + else + kfree(local_buf); + + return status; +} +EXPORT_SYMBOL_GPL(spi_write_then_read); + +/*-------------------------------------------------------------------------*/ + +static int __init spi_init(void) +{ + buf = kmalloc(SPI_BUFSIZ, SLAB_KERNEL); + if (!buf) + return -ENOMEM; + + bus_register(&spi_bus_type); + class_register(&spi_master_class); + return 0; +} +/* board_info is normally registered in arch_initcall(), + * but even essential drivers wait till later + */ +subsys_initcall(spi_init); + -- cgit v1.2.3 From b885244eb2628e0b8206e7edaaa6a314da78e9a4 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 8 Jan 2006 13:34:23 -0800 Subject: [PATCH] spi: add spi_driver to SPI framework This is a refresh of the "Simple SPI Framework" found in 2.6.15-rc3-mm1 which makes the following changes: * There's now a "struct spi_driver". This increase the footprint of the core a bit, since it now includes code to do what the driver core was previously handling directly. Documentation and comments were updated to match. * spi_alloc_master() now does class_device_initialize(), so it can at least be refcounted before spi_register_master(). To match, spi_register_master() switched over to class_device_add(). * States explicitly that after transfer errors, spi_devices will be deselected. We want fault recovery procedures to work the same for all controller drivers. * Minor tweaks: controller_data no longer points to readonly data; prevent some potential cast-from-null bugs with container_of calls; clarifies some existing kerneldoc, And a few small cleanups. Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- Documentation/spi/spi-summary | 52 ++++++++++++------- drivers/spi/spi.c | 118 ++++++++++++++++++++++++++++++------------ include/linux/spi/spi.h | 75 +++++++++++++++++++-------- 3 files changed, 170 insertions(+), 75 deletions(-) (limited to 'drivers/spi/spi.c') diff --git a/Documentation/spi/spi-summary b/Documentation/spi/spi-summary index 00497f95ca4..c6152d1ff2b 100644 --- a/Documentation/spi/spi-summary +++ b/Documentation/spi/spi-summary @@ -1,18 +1,19 @@ Overview of Linux kernel SPI support ==================================== -22-Nov-2005 +02-Dec-2005 What is SPI? ------------ -The "Serial Peripheral Interface" (SPI) is a four-wire point-to-point -serial link used to connect microcontrollers to sensors and memory. +The "Serial Peripheral Interface" (SPI) is a synchronous four wire serial +link used to connect microcontrollers to sensors, memory, and peripherals. The three signal wires hold a clock (SCLK, often on the order of 10 MHz), and parallel data lines with "Master Out, Slave In" (MOSI) or "Master In, Slave Out" (MISO) signals. (Other names are also used.) There are four clocking modes through which data is exchanged; mode-0 and mode-3 are most -commonly used. +commonly used. Each clock cycle shifts data out and data in; the clock +doesn't cycle except when there is data to shift. SPI masters may use a "chip select" line to activate a given SPI slave device, so those three signal wires may be connected to several chips @@ -79,11 +80,18 @@ The header file includes kerneldoc, as does the main source code, and you should certainly read that. This is just an overview, so you get the big picture before the details. +SPI requests always go into I/O queues. Requests for a given SPI device +are always executed in FIFO order, and complete asynchronously through +completion callbacks. There are also some simple synchronous wrappers +for those calls, including ones for common transaction types like writing +a command and then reading its response. + There are two types of SPI driver, here called: Controller drivers ... these are often built in to System-On-Chip processors, and often support both Master and Slave roles. These drivers touch hardware registers and may use DMA. + Or they can be PIO bitbangers, needing just GPIO pins. Protocol drivers ... these pass messages through the controller driver to communicate with a Slave or Master device on the @@ -116,11 +124,6 @@ shows up in sysfs in several locations: managing bus "B". All the spiB.* devices share the same physical SPI bus segment, with SCLK, MOSI, and MISO. -The basic I/O primitive submits an asynchronous message to an I/O queue -maintained by the controller driver. A completion callback is issued -asynchronously when the data transfer(s) in that message completes. -There are also some simple synchronous wrappers for those calls. - How does board-specific init code declare SPI devices? ------------------------------------------------------ @@ -263,33 +266,40 @@ would just be another kernel driver, probably offering some lowlevel access through aio_read(), aio_write(), and ioctl() calls and using the standard userspace sysfs mechanisms to bind to a given SPI device. -SPI protocol drivers are normal device drivers, with no more wrapper -than needed by platform devices: +SPI protocol drivers somewhat resemble platform device drivers: + + static struct spi_driver CHIP_driver = { + .driver = { + .name = "CHIP", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, - static struct device_driver CHIP_driver = { - .name = "CHIP", - .bus = &spi_bus_type, .probe = CHIP_probe, - .remove = __exit_p(CHIP_remove), + .remove = __devexit_p(CHIP_remove), .suspend = CHIP_suspend, .resume = CHIP_resume, }; -The SPI core will autmatically attempt to bind this driver to any SPI +The driver core will autmatically attempt to bind this driver to any SPI device whose board_info gave a modalias of "CHIP". Your probe() code might look like this unless you're creating a class_device: - static int __init CHIP_probe(struct device *dev) + static int __devinit CHIP_probe(struct spi_device *spi) { - struct spi_device *spi = to_spi_device(dev); struct CHIP *chip; - struct CHIP_platform_data *pdata = dev->platform_data; + struct CHIP_platform_data *pdata; + + /* assuming the driver requires board-specific data: */ + pdata = &spi->dev.platform_data; + if (!pdata) + return -ENODEV; /* get memory for driver's per-chip state */ chip = kzalloc(sizeof *chip, GFP_KERNEL); if (!chip) return -ENOMEM; - dev_set_drvdata(dev, chip); + dev_set_drvdata(&spi->dev, chip); ... etc return 0; @@ -328,6 +338,8 @@ the driver guarantees that it won't submit any more such messages. - The basic I/O primitive is spi_async(). Async requests may be issued in any context (irq handler, task, etc) and completion is reported using a callback provided with the message. + After any detected error, the chip is deselected and processing + of that spi_message is aborted. - There are also synchronous wrappers like spi_sync(), and wrappers like spi_read(), spi_write(), and spi_write_then_read(). These diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 7cd356b1764..2ecb86cb368 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -26,13 +26,9 @@ #include -/* 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) { @@ -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 || !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 || !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 @@ -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: + class_device_put(&master->cdev); + 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); @@ -330,6 +362,7 @@ spi_alloc_master(struct device *dev, unsigned size) 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]); @@ -366,7 +399,7 @@ spi_register_master(struct spi_master *master) /* 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 +407,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)" : ""); @@ -491,6 +522,7 @@ 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 @@ -553,16 +585,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); diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 51a6769114d..c851b3d1320 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -20,13 +20,8 @@ #define __LINUX_SPI_H /* - * INTERFACES between SPI master drivers and infrastructure + * INTERFACES between SPI master-side drivers and SPI infrastructure. * (There's no SPI slave support for Linux yet...) - * - * A "struct device_driver" for an spi_device uses "spi_bus_type" and - * needs no special API wrappers (much like platform_bus). These drivers - * are bound to devices based on their names (much like platform_bus), - * and are available in dev->driver. */ extern struct bus_type spi_bus_type; @@ -46,8 +41,8 @@ extern struct bus_type spi_bus_type; * @irq: Negative, or the number passed to request_irq() to receive * interrupts from this device. * @controller_state: Controller's runtime state - * @controller_data: Static board-specific definitions for controller, such - * as FIFO initialization parameters; from board_info.controller_data + * @controller_data: Board-specific definitions for controller, such as + * FIFO initialization parameters; from board_info.controller_data * * An spi_device is used to interchange data between an SPI slave * (usually a discrete chip) and CPU memory. @@ -63,31 +58,32 @@ struct spi_device { u32 max_speed_hz; u8 chip_select; u8 mode; -#define SPI_CPHA 0x01 /* clock phase */ -#define SPI_CPOL 0x02 /* clock polarity */ +#define SPI_CPHA 0x01 /* clock phase */ +#define SPI_CPOL 0x02 /* clock polarity */ #define SPI_MODE_0 (0|0) -#define SPI_MODE_1 (0|SPI_CPHA) +#define SPI_MODE_1 (0|SPI_CPHA) /* (original MicroWire) */ #define SPI_MODE_2 (SPI_CPOL|0) #define SPI_MODE_3 (SPI_CPOL|SPI_CPHA) -#define SPI_CS_HIGH 0x04 /* chipselect active high? */ +#define SPI_CS_HIGH 0x04 /* chipselect active high? */ u8 bits_per_word; int irq; void *controller_state; - const void *controller_data; + void *controller_data; const char *modalias; // likely need more hooks for more protocol options affecting how - // the controller talks to its chips, like: + // the controller talks to each chip, like: // - bit order (default is wordwise msb-first) // - memory packing (12 bit samples into low bits, others zeroed) // - priority + // - drop chipselect after each word // - chipselect delays // - ... }; static inline struct spi_device *to_spi_device(struct device *dev) { - return container_of(dev, struct spi_device, dev); + return dev ? container_of(dev, struct spi_device, dev) : NULL; } /* most drivers won't need to care about device refcounting */ @@ -117,12 +113,38 @@ static inline void spi_set_ctldata(struct spi_device *spi, void *state) struct spi_message; + +struct spi_driver { + int (*probe)(struct spi_device *spi); + int (*remove)(struct spi_device *spi); + void (*shutdown)(struct spi_device *spi); + int (*suspend)(struct spi_device *spi, pm_message_t mesg); + int (*resume)(struct spi_device *spi); + struct device_driver driver; +}; + +static inline struct spi_driver *to_spi_driver(struct device_driver *drv) +{ + return drv ? container_of(drv, struct spi_driver, driver) : NULL; +} + +extern int spi_register_driver(struct spi_driver *sdrv); + +static inline void spi_unregister_driver(struct spi_driver *sdrv) +{ + if (!sdrv) + return; + driver_unregister(&sdrv->driver); +} + + + /** * struct spi_master - interface to SPI master controller * @cdev: class interface to this driver * @bus_num: board-specific (and often SOC-specific) identifier for a * given SPI controller. - * @num_chipselects: chipselects are used to distinguish individual + * @num_chipselect: chipselects are used to distinguish individual * SPI slaves, and are numbered from zero to num_chipselects. * each slave has a chipselect signal, but it's common that not * every chipselect is connected to a slave. @@ -275,7 +297,8 @@ struct spi_transfer { * addresses for each transfer buffer * @complete: called to report transaction completions * @context: the argument to complete() when it's called - * @actual_length: how many bytes were transferd + * @actual_length: the total number of bytes that were transferred in all + * successful segments * @status: zero for success, else negative errno * @queue: for use by whichever driver currently owns the message * @state: for use by whichever driver currently owns the message @@ -295,7 +318,7 @@ struct spi_message { * * Some controller drivers (message-at-a-time queue processing) * could provide that as their default scheduling algorithm. But - * others (with multi-message pipelines) would need a flag to + * others (with multi-message pipelines) could need a flag to * tell them about such special cases. */ @@ -346,6 +369,13 @@ spi_setup(struct spi_device *spi) * FIFO order, messages may go to different devices in other orders. * Some device might be higher priority, or have various "hard" access * time requirements, for example. + * + * On detection of any fault during the transfer, processing of + * the entire message is aborted, and the device is deselected. + * Until returning from the associated message completion callback, + * no other spi_message queued to that device will be processed. + * (This rule applies equally to all the synchronous transfer calls, + * which are wrappers around this core asynchronous primitive.) */ static inline int spi_async(struct spi_device *spi, struct spi_message *message) @@ -484,12 +514,12 @@ struct spi_board_info { * "modalias" is normally the driver name. * * platform_data goes to spi_device.dev.platform_data, - * controller_data goes to spi_device.platform_data, + * controller_data goes to spi_device.controller_data, * irq is copied too */ char modalias[KOBJ_NAME_LEN]; const void *platform_data; - const void *controller_data; + void *controller_data; int irq; /* slower signaling on noisy or low voltage boards */ @@ -525,9 +555,8 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n) /* If you're hotplugging an adapter with devices (parport, usb, etc) - * use spi_new_device() to describe each device. You can also call - * spi_unregister_device() to get start making that device vanish, - * but normally that would be handled by spi_unregister_master(). + * use spi_new_device() to describe each device. You would then call + * spi_unregister_device() to start making that device vanish. */ extern struct spi_device * spi_new_device(struct spi_master *, struct spi_board_info *); -- cgit v1.2.3 From 0c868461fcb8413cb9f691d68e5b99b0fd3c0737 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 8 Jan 2006 13:34:25 -0800 Subject: [PATCH] SPI core tweaks, bugfix This includes various updates to the SPI core: - Fixes a driver model refcount bug in spi_unregister_master() paths. - The spi_master structures now have wrappers which help keep drivers from needing class-level get/put for device data or for refcounts. - Check for a few setup errors that would cause oopsing later. - Docs say more about memory management. Highlights the use of DMA-safe i/o buffers, and zero-initializing spi_message and such metadata. - Provide a simple alloc/free for spi_message and its spi_transfer; this is only one of the possible memory management policies. Nothing to break code that already works. Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- Documentation/spi/spi-summary | 16 +++++++++ drivers/spi/spi.c | 45 ++++++++++++++++---------- include/linux/spi/spi.h | 75 +++++++++++++++++++++++++++++++++++++++---- 3 files changed, 113 insertions(+), 23 deletions(-) (limited to 'drivers/spi/spi.c') diff --git a/Documentation/spi/spi-summary b/Documentation/spi/spi-summary index c6152d1ff2b..761debf748e 100644 --- a/Documentation/spi/spi-summary +++ b/Documentation/spi/spi-summary @@ -363,6 +363,22 @@ upper boundaries might include sysfs (especially for sensor readings), the input layer, ALSA, networking, MTD, the character device framework, or other Linux subsystems. +Note that there are two types of memory your driver must manage as part +of interacting with SPI devices. + + - I/O buffers use the usual Linux rules, and must be DMA-safe. + You'd normally allocate them from the heap or free page pool. + Don't use the stack, or anything that's declared "static". + + - The spi_message and spi_transfer metadata used to glue those + I/O buffers into a group of protocol transactions. These can + be allocated anywhere it's convenient, including as part of + other allocate-once driver data structures. Zero-init these. + +If you like, spi_message_alloc() and spi_message_free() convenience +routines are available to allocate and zero-initialize an spi_message +with several transfers. + How do I write an "SPI Master Controller Driver"? ------------------------------------------------- diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 2ecb86cb368..3ecedccdb96 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -38,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); } @@ -90,7 +90,7 @@ static int spi_suspend(struct device *dev, pm_message_t message) int value; struct spi_driver *drv = to_spi_driver(dev->driver); - if (!drv || !drv->suspend) + if (!drv->suspend) return 0; /* suspend will stop irqs and dma; no more i/o */ @@ -105,7 +105,7 @@ static int spi_resume(struct device *dev) int value; struct spi_driver *drv = to_spi_driver(dev->driver); - if (!drv || !drv->resume) + if (!drv->resume) return 0; /* resume may restart the i/o queue */ @@ -198,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); @@ -244,7 +244,7 @@ spi_new_device(struct spi_master *master, struct spi_board_info *chip) return proxy; fail: - class_device_put(&master->cdev); + spi_master_put(master); kfree(proxy); return NULL; } @@ -324,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); } @@ -339,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 @@ -350,14 +349,17 @@ 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; @@ -365,7 +367,7 @@ spi_alloc_master(struct device *dev, unsigned size) 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; } @@ -387,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) @@ -396,6 +400,9 @@ 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); @@ -425,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; } @@ -440,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); @@ -487,6 +495,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 @@ -524,9 +535,9 @@ static u8 *buf; * 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, diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index c851b3d1320..6a41e2650b2 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -60,8 +60,8 @@ struct spi_device { u8 mode; #define SPI_CPHA 0x01 /* clock phase */ #define SPI_CPOL 0x02 /* clock polarity */ -#define SPI_MODE_0 (0|0) -#define SPI_MODE_1 (0|SPI_CPHA) /* (original MicroWire) */ +#define SPI_MODE_0 (0|0) /* (original MicroWire) */ +#define SPI_MODE_1 (0|SPI_CPHA) #define SPI_MODE_2 (SPI_CPOL|0) #define SPI_MODE_3 (SPI_CPOL|SPI_CPHA) #define SPI_CS_HIGH 0x04 /* chipselect active high? */ @@ -209,6 +209,30 @@ struct spi_master { void (*cleanup)(const struct spi_device *spi); }; +static inline void *spi_master_get_devdata(struct spi_master *master) +{ + return class_get_devdata(&master->cdev); +} + +static inline void spi_master_set_devdata(struct spi_master *master, void *data) +{ + class_set_devdata(&master->cdev, data); +} + +static inline struct spi_master *spi_master_get(struct spi_master *master) +{ + if (!master || !class_device_get(&master->cdev)) + return NULL; + return master; +} + +static inline void spi_master_put(struct spi_master *master) +{ + if (master) + class_device_put(&master->cdev); +} + + /* the spi driver core manages memory for the spi_master classdev */ extern struct spi_master * spi_alloc_master(struct device *host, unsigned size); @@ -271,11 +295,17 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum); * stay selected until the next transfer. This is purely a performance * hint; the controller driver may need to select a different device * for the next message. + * + * The code that submits an spi_message (and its spi_transfers) + * to the lower layers is responsible for managing its memory. + * Zero-initialize every field you don't set up explicitly, to + * insulate against future API updates. */ struct spi_transfer { /* it's ok if tx_buf == rx_buf (right?) * for MicroWire, one buffer must be null - * buffers must work with dma_*map_single() calls + * buffers must work with dma_*map_single() calls, unless + * spi_message.is_dma_mapped reports a pre-existing mapping */ const void *tx_buf; void *rx_buf; @@ -302,6 +332,11 @@ struct spi_transfer { * @status: zero for success, else negative errno * @queue: for use by whichever driver currently owns the message * @state: for use by whichever driver currently owns the message + * + * The code that submits an spi_message (and its spi_transfers) + * to the lower layers is responsible for managing its memory. + * Zero-initialize every field you don't set up explicitly, to + * insulate against future API updates. */ struct spi_message { struct spi_transfer *transfers; @@ -336,6 +371,29 @@ struct spi_message { void *state; }; +/* It's fine to embed message and transaction structures in other data + * structures so long as you don't free them while they're in use. + */ + +static inline struct spi_message *spi_message_alloc(unsigned ntrans, gfp_t flags) +{ + struct spi_message *m; + + m = kzalloc(sizeof(struct spi_message) + + ntrans * sizeof(struct spi_transfer), + flags); + if (m) { + m->transfers = (void *)(m + 1); + m->n_transfer = ntrans; + } + return m; +} + +static inline void spi_message_free(struct spi_message *m) +{ + kfree(m); +} + /** * spi_setup -- setup SPI mode and clock rate * @spi: the device whose settings are being modified @@ -363,7 +421,10 @@ spi_setup(struct spi_device *spi) * The completion callback is invoked in a context which can't sleep. * Before that invocation, the value of message->status is undefined. * When the callback is issued, message->status holds either zero (to - * indicate complete success) or a negative error code. + * indicate complete success) or a negative error code. After that + * callback returns, the driver which issued the transfer request may + * deallocate the associated memory; it's no longer in use by any SPI + * core or controller driver code. * * Note that although all messages to a spi_device are handled in * FIFO order, messages may go to different devices in other orders. @@ -445,6 +506,7 @@ spi_read(struct spi_device *spi, u8 *buf, size_t len) return spi_sync(spi, &m); } +/* this copies txbuf and rxbuf data; for small transfers only! */ extern int spi_write_then_read(struct spi_device *spi, const u8 *txbuf, unsigned n_tx, u8 *rxbuf, unsigned n_rx); @@ -555,8 +617,9 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n) /* If you're hotplugging an adapter with devices (parport, usb, etc) - * use spi_new_device() to describe each device. You would then call - * spi_unregister_device() to start making that device vanish. + * use spi_new_device() to describe each device. You can also call + * spi_unregister_device() to start making that device vanish, but + * normally that would be handled by spi_unregister_master(). */ extern struct spi_device * spi_new_device(struct spi_master *, struct spi_board_info *); -- cgit v1.2.3 From 8275c642ccdce09a2146d0a9eb022e3698ee927e Mon Sep 17 00:00:00 2001 From: Vitaly Wool Date: Sun, 8 Jan 2006 13:34:28 -0800 Subject: [PATCH] spi: use linked lists rather than an array This makes the SPI core and its users access transfers in the SPI message structure as linked list not as an array, as discussed on LKML. From: David Brownell Updates including doc, bugfixes to the list code, add spi_message_add_tail(). Plus, initialize things _before_ grabbing the locks in some cases (in case it grows more expensive). This also merges some bitbang updates of mine that didn't yet make it into the mm tree. Signed-off-by: Vitaly Wool Signed-off-by: Dmitry Pervushin Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/input/touchscreen/ads7846.c | 12 +++-- drivers/mtd/devices/m25p80.c | 50 ++++++++++---------- drivers/mtd/devices/mtd_dataflash.c | 28 ++++++----- drivers/spi/spi.c | 18 +++++--- drivers/spi/spi_bitbang.c | 86 +++++++++++++++++++--------------- include/linux/spi/spi.h | 92 +++++++++++++++++++++++++------------ include/linux/spi/spi_bitbang.h | 7 +++ 7 files changed, 180 insertions(+), 113 deletions(-) (limited to 'drivers/spi/spi.c') diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index c741776ef3b..dd8c6a9ffc7 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -155,10 +155,13 @@ static int ads7846_read12_ser(struct device *dev, unsigned command) struct ser_req *req = kzalloc(sizeof *req, SLAB_KERNEL); int status; int sample; + int i; if (!req) return -ENOMEM; + INIT_LIST_HEAD(&req->msg.transfers); + /* activate reference, so it has time to settle; */ req->xfer[0].tx_buf = &ref_on; req->xfer[0].len = 1; @@ -192,8 +195,8 @@ static int ads7846_read12_ser(struct device *dev, unsigned command) /* group all the transfers together, so we can't interfere with * reading touchscreen state; disable penirq while sampling */ - req->msg.transfers = req->xfer; - req->msg.n_transfer = 6; + for (i = 0; i < 6; i++) + spi_message_add_tail(&req->xfer[i], &req->msg); disable_irq(spi->irq); status = spi_sync(spi, &req->msg); @@ -398,6 +401,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) struct ads7846 *ts; struct ads7846_platform_data *pdata = spi->dev.platform_data; struct spi_transfer *x; + int i; if (!spi->irq) { dev_dbg(&spi->dev, "no IRQ?\n"); @@ -500,8 +504,8 @@ static int __devinit ads7846_probe(struct spi_device *spi) CS_CHANGE(x[-1]); - ts->msg.transfers = ts->xfer; - ts->msg.n_transfer = x - ts->xfer; + for (i = 0; i < x - ts->xfer; i++) + spi_message_add_tail(&ts->xfer[i], &ts->msg); ts->msg.complete = ads7846_rx; ts->msg.context = ts; diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 71a072103a7..45108ed8558 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -245,6 +245,21 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, if (from + len > flash->mtd.size) return -EINVAL; + spi_message_init(&m); + memset(t, 0, (sizeof t)); + + t[0].tx_buf = flash->command; + t[0].len = sizeof(flash->command); + spi_message_add_tail(&t[0], &m); + + t[1].rx_buf = buf; + t[1].len = len; + spi_message_add_tail(&t[1], &m); + + /* Byte count starts at zero. */ + if (retlen) + *retlen = 0; + down(&flash->lock); /* Wait till previous write/erase is done. */ @@ -254,8 +269,6 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, return 1; } - memset(t, 0, (sizeof t)); - /* NOTE: OPCODE_FAST_READ (if available) is faster... */ /* Set up the write data buffer. */ @@ -264,19 +277,6 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, flash->command[2] = from >> 8; flash->command[3] = from; - /* Byte count starts at zero. */ - if (retlen) - *retlen = 0; - - t[0].tx_buf = flash->command; - t[0].len = sizeof(flash->command); - - t[1].rx_buf = buf; - t[1].len = len; - - m.transfers = t; - m.n_transfer = 2; - spi_sync(flash->spi, &m); *retlen = m.actual_length - sizeof(flash->command); @@ -313,6 +313,16 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, if (to + len > flash->mtd.size) return -EINVAL; + spi_message_init(&m); + memset(t, 0, (sizeof t)); + + t[0].tx_buf = flash->command; + t[0].len = sizeof(flash->command); + spi_message_add_tail(&t[0], &m); + + t[1].tx_buf = buf; + spi_message_add_tail(&t[1], &m); + down(&flash->lock); /* Wait until finished previous write command. */ @@ -321,26 +331,17 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, write_enable(flash); - memset(t, 0, (sizeof t)); - /* Set up the opcode in the write buffer. */ flash->command[0] = OPCODE_PP; flash->command[1] = to >> 16; flash->command[2] = to >> 8; flash->command[3] = to; - t[0].tx_buf = flash->command; - t[0].len = sizeof(flash->command); - - m.transfers = t; - m.n_transfer = 2; - /* what page do we start with? */ page_offset = to % FLASH_PAGESIZE; /* do all the bytes fit onto one page? */ if (page_offset + len <= FLASH_PAGESIZE) { - t[1].tx_buf = buf; t[1].len = len; spi_sync(flash->spi, &m); @@ -352,7 +353,6 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, /* the size of data remaining on the first page */ page_size = FLASH_PAGESIZE - page_offset; - t[1].tx_buf = buf; t[1].len = page_size; spi_sync(flash->spi, &m); diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index a39b3b6b266..99d3a0320fc 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c @@ -147,7 +147,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) { struct dataflash *priv = (struct dataflash *)mtd->priv; struct spi_device *spi = priv->spi; - struct spi_transfer x[1] = { { .tx_dma = 0, }, }; + struct spi_transfer x = { .tx_dma = 0, }; struct spi_message msg; unsigned blocksize = priv->page_size << 3; u8 *command; @@ -162,10 +162,11 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) || (instr->addr % priv->page_size) != 0) return -EINVAL; - x[0].tx_buf = command = priv->command; - x[0].len = 4; - msg.transfers = x; - msg.n_transfer = 1; + spi_message_init(&msg); + + x.tx_buf = command = priv->command; + x.len = 4; + spi_message_add_tail(&x, &msg); down(&priv->lock); while (instr->len > 0) { @@ -256,12 +257,15 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, DEBUG(MTD_DEBUG_LEVEL3, "READ: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]); + spi_message_init(&msg); + x[0].tx_buf = command; x[0].len = 8; + spi_message_add_tail(&x[0], &msg); + x[1].rx_buf = buf; x[1].len = len; - msg.transfers = x; - msg.n_transfer = 2; + spi_message_add_tail(&x[1], &msg); down(&priv->lock); @@ -320,9 +324,11 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, if ((to + len) > mtd->size) return -EINVAL; + spi_message_init(&msg); + x[0].tx_buf = command = priv->command; x[0].len = 4; - msg.transfers = x; + spi_message_add_tail(&x[0], &msg); pageaddr = ((unsigned)to / priv->page_size); offset = ((unsigned)to % priv->page_size); @@ -364,7 +370,6 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, DEBUG(MTD_DEBUG_LEVEL3, "TRANSFER: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]); - msg.n_transfer = 1; status = spi_sync(spi, &msg); if (status < 0) DEBUG(MTD_DEBUG_LEVEL1, "%s: xfer %u -> %d \n", @@ -385,14 +390,16 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, x[1].tx_buf = writebuf; x[1].len = writelen; - msg.n_transfer = 2; + spi_message_add_tail(x + 1, &msg); status = spi_sync(spi, &msg); + spi_transfer_del(x + 1); if (status < 0) DEBUG(MTD_DEBUG_LEVEL1, "%s: pgm %u/%u -> %d \n", spi->dev.bus_id, addr, writelen, status); (void) dataflash_waitready(priv->spi); + #ifdef CONFIG_DATAFLASH_WRITE_VERIFY /* (3) Compare to Buffer1 */ @@ -405,7 +412,6 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, DEBUG(MTD_DEBUG_LEVEL3, "COMPARE: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]); - msg.n_transfer = 1; status = spi_sync(spi, &msg); if (status < 0) DEBUG(MTD_DEBUG_LEVEL1, "%s: compare %u -> %d \n", diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 3ecedccdb96..cdb242de901 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -557,6 +557,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); @@ -565,18 +576,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); diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c index 44aff198eb9..f037e559326 100644 --- a/drivers/spi/spi_bitbang.c +++ b/drivers/spi/spi_bitbang.c @@ -146,6 +146,9 @@ int spi_bitbang_setup(struct spi_device *spi) struct spi_bitbang_cs *cs = spi->controller_state; struct spi_bitbang *bitbang; + if (!spi->max_speed_hz) + return -EINVAL; + if (!cs) { cs = kzalloc(sizeof *cs, SLAB_KERNEL); if (!cs) @@ -172,13 +175,8 @@ int spi_bitbang_setup(struct spi_device *spi) if (!cs->txrx_word) return -EINVAL; - if (!spi->max_speed_hz) - spi->max_speed_hz = 500 * 1000; - - /* nsecs = max(50, (clock period)/2), be optimistic */ + /* nsecs = (clock period)/2 */ cs->nsecs = (1000000000/2) / (spi->max_speed_hz); - if (cs->nsecs < 50) - cs->nsecs = 50; if (cs->nsecs > MAX_UDELAY_MS * 1000) return -EINVAL; @@ -194,7 +192,7 @@ int spi_bitbang_setup(struct spi_device *spi) /* deselect chip (low or high) */ spin_lock(&bitbang->lock); if (!bitbang->busy) { - bitbang->chipselect(spi, 0); + bitbang->chipselect(spi, BITBANG_CS_INACTIVE); ndelay(cs->nsecs); } spin_unlock(&bitbang->lock); @@ -244,9 +242,9 @@ static void bitbang_work(void *_bitbang) struct spi_message *m; struct spi_device *spi; unsigned nsecs; - struct spi_transfer *t; + struct spi_transfer *t = NULL; unsigned tmp; - unsigned chipselect; + unsigned cs_change; int status; m = container_of(bitbang->queue.next, struct spi_message, @@ -254,37 +252,49 @@ static void bitbang_work(void *_bitbang) list_del_init(&m->queue); spin_unlock_irqrestore(&bitbang->lock, flags); -// FIXME this is made-up -nsecs = 100; + /* FIXME this is made-up ... the correct value is known to + * word-at-a-time bitbang code, and presumably chipselect() + * should enforce these requirements too? + */ + nsecs = 100; spi = m->spi; - t = m->transfers; tmp = 0; - chipselect = 0; + cs_change = 1; status = 0; - for (;;t++) { + list_for_each_entry (t, &m->transfers, transfer_list) { if (bitbang->shutdown) { status = -ESHUTDOWN; break; } - /* set up default clock polarity, and activate chip */ - if (!chipselect) { - bitbang->chipselect(spi, 1); + /* set up default clock polarity, and activate chip; + * this implicitly updates clock and spi modes as + * previously recorded for this device via setup(). + * (and also deselects any other chip that might be + * selected ...) + */ + if (cs_change) { + bitbang->chipselect(spi, BITBANG_CS_ACTIVE); ndelay(nsecs); } + cs_change = t->cs_change; if (!t->tx_buf && !t->rx_buf && t->len) { status = -EINVAL; break; } - /* transfer data */ + /* transfer data. the lower level code handles any + * new dma mappings it needs. our caller always gave + * us dma-safe buffers. + */ if (t->len) { - /* FIXME if bitbang->use_dma, dma_map_single() - * before the transfer, and dma_unmap_single() - * afterwards, for either or both buffers... + /* REVISIT dma API still needs a designated + * DMA_ADDR_INVALID; ~0 might be better. */ + if (!m->is_dma_mapped) + t->rx_dma = t->tx_dma = 0; status = bitbang->txrx_bufs(spi, t); } if (status != t->len) { @@ -299,29 +309,31 @@ nsecs = 100; if (t->delay_usecs) udelay(t->delay_usecs); - tmp++; - if (tmp >= m->n_transfer) - break; - - chipselect = !t->cs_change; - if (chipselect); + if (!cs_change) continue; + if (t->transfer_list.next == &m->transfers) + break; - bitbang->chipselect(spi, 0); - - /* REVISIT do we want the udelay here instead? */ - msleep(1); + /* sometimes a short mid-message deselect of the chip + * may be needed to terminate a mode or command + */ + ndelay(nsecs); + bitbang->chipselect(spi, BITBANG_CS_INACTIVE); + ndelay(nsecs); } - tmp = m->n_transfer - 1; - tmp = m->transfers[tmp].cs_change; - m->status = status; m->complete(m->context); - ndelay(2 * nsecs); - bitbang->chipselect(spi, status == 0 && tmp); - ndelay(nsecs); + /* normally deactivate chipselect ... unless no error and + * cs_change has hinted that the next message will probably + * be for this chip too. + */ + if (!(status == 0 && cs_change)) { + ndelay(nsecs); + bitbang->chipselect(spi, BITBANG_CS_INACTIVE); + ndelay(nsecs); + } spin_lock_irqsave(&bitbang->lock, flags); } diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 6a41e2650b2..939afd3a2e7 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -263,15 +263,16 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum); /** * struct spi_transfer - a read/write buffer pair - * @tx_buf: data to be written (dma-safe address), or NULL - * @rx_buf: data to be read (dma-safe address), or NULL - * @tx_dma: DMA address of buffer, if spi_message.is_dma_mapped - * @rx_dma: DMA address of buffer, if spi_message.is_dma_mapped + * @tx_buf: data to be written (dma-safe memory), or NULL + * @rx_buf: data to be read (dma-safe memory), or NULL + * @tx_dma: DMA address of tx_buf, if spi_message.is_dma_mapped + * @rx_dma: DMA address of rx_buf, if spi_message.is_dma_mapped * @len: size of rx and tx buffers (in bytes) * @cs_change: affects chipselect after this transfer completes * @delay_usecs: microseconds to delay after this transfer before * (optionally) changing the chipselect status, then starting * the next transfer or completing this spi_message. + * @transfer_list: transfers are sequenced through spi_message.transfers * * SPI transfers always write the same number of bytes as they read. * Protocol drivers should always provide rx_buf and/or tx_buf. @@ -279,11 +280,16 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum); * the data being transferred; that may reduce overhead, when the * underlying driver uses dma. * - * All SPI transfers start with the relevant chipselect active. Drivers - * can change behavior of the chipselect after the transfer finishes - * (including any mandatory delay). The normal behavior is to leave it - * selected, except for the last transfer in a message. Setting cs_change - * allows two additional behavior options: + * If the transmit buffer is null, undefined data will be shifted out + * while filling rx_buf. If the receive buffer is null, the data + * shifted in will be discarded. Only "len" bytes shift out (or in). + * It's an error to try to shift out a partial word. (For example, by + * shifting out three bytes with word size of sixteen or twenty bits; + * the former uses two bytes per word, the latter uses four bytes.) + * + * All SPI transfers start with the relevant chipselect active. Normally + * it stays selected until after the last transfer in a message. Drivers + * can affect the chipselect signal using cs_change: * * (i) If the transfer isn't the last one in the message, this flag is * used to make the chipselect briefly go inactive in the middle of the @@ -299,7 +305,8 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum); * The code that submits an spi_message (and its spi_transfers) * to the lower layers is responsible for managing its memory. * Zero-initialize every field you don't set up explicitly, to - * insulate against future API updates. + * insulate against future API updates. After you submit a message + * and its transfers, ignore them until its completion callback. */ struct spi_transfer { /* it's ok if tx_buf == rx_buf (right?) @@ -316,12 +323,13 @@ struct spi_transfer { unsigned cs_change:1; u16 delay_usecs; + + struct list_head transfer_list; }; /** * struct spi_message - one multi-segment SPI transaction - * @transfers: the segements of the transaction - * @n_transfer: how many segments + * @transfers: list of transfer segments in this transaction * @spi: SPI device to which the transaction is queued * @is_dma_mapped: if true, the caller provided both dma and cpu virtual * addresses for each transfer buffer @@ -333,14 +341,22 @@ struct spi_transfer { * @queue: for use by whichever driver currently owns the message * @state: for use by whichever driver currently owns the message * + * An spi_message is used to execute an atomic sequence of data transfers, + * each represented by a struct spi_transfer. The sequence is "atomic" + * in the sense that no other spi_message may use that SPI bus until that + * sequence completes. On some systems, many such sequences can execute as + * as single programmed DMA transfer. On all systems, these messages are + * queued, and might complete after transactions to other devices. Messages + * sent to a given spi_device are alway executed in FIFO order. + * * The code that submits an spi_message (and its spi_transfers) * to the lower layers is responsible for managing its memory. * Zero-initialize every field you don't set up explicitly, to - * insulate against future API updates. + * insulate against future API updates. After you submit a message + * and its transfers, ignore them until its completion callback. */ struct spi_message { - struct spi_transfer *transfers; - unsigned n_transfer; + struct list_head transfers; struct spi_device *spi; @@ -371,6 +387,24 @@ struct spi_message { void *state; }; +static inline void spi_message_init(struct spi_message *m) +{ + memset(m, 0, sizeof *m); + INIT_LIST_HEAD(&m->transfers); +} + +static inline void +spi_message_add_tail(struct spi_transfer *t, struct spi_message *m) +{ + list_add_tail(&t->transfer_list, &m->transfers); +} + +static inline void +spi_transfer_del(struct spi_transfer *t) +{ + list_del(&t->transfer_list); +} + /* It's fine to embed message and transaction structures in other data * structures so long as you don't free them while they're in use. */ @@ -383,8 +417,12 @@ static inline struct spi_message *spi_message_alloc(unsigned ntrans, gfp_t flags + ntrans * sizeof(struct spi_transfer), flags); if (m) { - m->transfers = (void *)(m + 1); - m->n_transfer = ntrans; + int i; + struct spi_transfer *t = (struct spi_transfer *)(m + 1); + + INIT_LIST_HEAD(&m->transfers); + for (i = 0; i < ntrans; i++, t++) + spi_message_add_tail(t, m); } return m; } @@ -402,6 +440,8 @@ static inline void spi_message_free(struct spi_message *m) * device doesn't work with the mode 0 default. They may likewise need * to update clock rates or word sizes from initial values. This function * changes those settings, and must be called from a context that can sleep. + * The changes take effect the next time the device is selected and data + * is transferred to or from it. */ static inline int spi_setup(struct spi_device *spi) @@ -468,15 +508,12 @@ spi_write(struct spi_device *spi, const u8 *buf, size_t len) { struct spi_transfer t = { .tx_buf = buf, - .rx_buf = NULL, .len = len, - .cs_change = 0, - }; - struct spi_message m = { - .transfers = &t, - .n_transfer = 1, }; + struct spi_message m; + spi_message_init(&m); + spi_message_add_tail(&t, &m); return spi_sync(spi, &m); } @@ -493,16 +530,13 @@ static inline int spi_read(struct spi_device *spi, u8 *buf, size_t len) { struct spi_transfer t = { - .tx_buf = NULL, .rx_buf = buf, .len = len, - .cs_change = 0, - }; - struct spi_message m = { - .transfers = &t, - .n_transfer = 1, }; + struct spi_message m; + spi_message_init(&m); + spi_message_add_tail(&t, &m); return spi_sync(spi, &m); } diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h index 8dfe61a445f..c961fe9bf3e 100644 --- a/include/linux/spi/spi_bitbang.h +++ b/include/linux/spi/spi_bitbang.h @@ -31,8 +31,15 @@ struct spi_bitbang { struct spi_master *master; void (*chipselect)(struct spi_device *spi, int is_on); +#define BITBANG_CS_ACTIVE 1 /* normally nCS, active low */ +#define BITBANG_CS_INACTIVE 0 + /* txrx_bufs() may handle dma mapping for transfers that don't + * already have one (transfer.{tx,rx}_dma is zero), or use PIO + */ int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t); + + /* txrx_word[SPI_MODE_*]() just looks like a shift register */ u32 (*txrx_word[4])(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits); -- cgit v1.2.3 From 5d870c8e216f121307445c71caa72e7e10a20061 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 11 Jan 2006 11:23:49 -0800 Subject: [PATCH] spi: remove fastcall crap gcc4 generates warnings when a non-FASTCALL function pointer is assigned to a FASTCALL one. Perhaps it has taste. Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/spi/spi.c | 7 ++++++- include/linux/spi/spi.h | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/spi/spi.c') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index cdb242de901..791c4dc550a 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -480,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 @@ -508,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) diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 939afd3a2e7..b05f1463a26 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -374,7 +374,7 @@ struct spi_message { */ /* completion is reported through a callback */ - void FASTCALL((*complete)(void *context)); + void (*complete)(void *context); void *context; unsigned actual_length; int status; -- cgit v1.2.3