diff options
Diffstat (limited to 'drivers/spi/spi.c')
-rw-r--r-- | drivers/spi/spi.c | 281 |
1 files changed, 49 insertions, 232 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 349ebba..9e039c6 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -39,9 +39,6 @@ #include <linux/ioport.h> #include <linux/acpi.h> -#define CREATE_TRACE_POINTS -#include <trace/events/spi.h> - static void spidev_release(struct device *dev) { struct spi_device *spi = to_spi_device(dev); @@ -61,13 +58,11 @@ modalias_show(struct device *dev, struct device_attribute *a, char *buf) return sprintf(buf, "%s%s\n", SPI_MODULE_PREFIX, spi->modalias); } -static DEVICE_ATTR_RO(modalias); -static struct attribute *spi_dev_attrs[] = { - &dev_attr_modalias.attr, - NULL, +static struct device_attribute spi_dev_attrs[] = { + __ATTR_RO(modalias), + __ATTR_NULL, }; -ATTRIBUTE_GROUPS(spi_dev); /* modalias support makes "modprobe $MODALIAS" new-style hotplug work, * and the sysfs version makes coldplug work too. @@ -234,7 +229,7 @@ static const struct dev_pm_ops spi_pm = { struct bus_type spi_bus_type = { .name = "spi", - .dev_groups = spi_dev_groups, + .dev_attrs = spi_dev_attrs, .match = spi_match_device, .uevent = spi_uevent, .pm = &spi_pm, @@ -245,27 +240,15 @@ EXPORT_SYMBOL_GPL(spi_bus_type); static int spi_drv_probe(struct device *dev) { const struct spi_driver *sdrv = to_spi_driver(dev->driver); - struct spi_device *spi = to_spi_device(dev); - int ret; - - acpi_dev_pm_attach(&spi->dev, true); - ret = sdrv->probe(spi); - if (ret) - acpi_dev_pm_detach(&spi->dev, true); - return ret; + 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); - struct spi_device *spi = to_spi_device(dev); - int ret; - - ret = sdrv->remove(spi); - acpi_dev_pm_detach(&spi->dev, true); - return ret; + return sdrv->remove(to_spi_device(dev)); } static void spi_drv_shutdown(struct device *dev) @@ -340,7 +323,7 @@ struct spi_device *spi_alloc_device(struct spi_master *master) if (!spi_master_get(master)) return NULL; - spi = kzalloc(sizeof(*spi), GFP_KERNEL); + spi = kzalloc(sizeof *spi, GFP_KERNEL); if (!spi) { dev_err(dev, "cannot alloc spi_device\n"); spi_master_put(master); @@ -357,19 +340,6 @@ struct spi_device *spi_alloc_device(struct spi_master *master) } EXPORT_SYMBOL_GPL(spi_alloc_device); -static void spi_dev_set_name(struct spi_device *spi) -{ - struct acpi_device *adev = ACPI_COMPANION(&spi->dev); - - if (adev) { - dev_set_name(&spi->dev, "spi-%s", acpi_dev_name(adev)); - return; - } - - dev_set_name(&spi->dev, "%s.%u", dev_name(&spi->master->dev), - spi->chip_select); -} - /** * spi_add_device - Add spi_device allocated with spi_alloc_device * @spi: spi_device to register @@ -396,7 +366,9 @@ int spi_add_device(struct spi_device *spi) } /* Set the bus ID string */ - spi_dev_set_name(spi); + dev_set_name(&spi->dev, "%s.%u", dev_name(&spi->master->dev), + spi->chip_select); + /* We need to make sure there's no other device with this * chipselect **BEFORE** we call setup(), else we'll trash @@ -551,95 +523,6 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n) /*-------------------------------------------------------------------------*/ -static void spi_set_cs(struct spi_device *spi, bool enable) -{ - if (spi->mode & SPI_CS_HIGH) - enable = !enable; - - if (spi->cs_gpio >= 0) - gpio_set_value(spi->cs_gpio, !enable); - else if (spi->master->set_cs) - spi->master->set_cs(spi, !enable); -} - -/* - * spi_transfer_one_message - Default implementation of transfer_one_message() - * - * This is a standard implementation of transfer_one_message() for - * drivers which impelment a transfer_one() operation. It provides - * standard handling of delays and chip select management. - */ -static int spi_transfer_one_message(struct spi_master *master, - struct spi_message *msg) -{ - struct spi_transfer *xfer; - bool cur_cs = true; - bool keep_cs = false; - int ret = 0; - - spi_set_cs(msg->spi, true); - - list_for_each_entry(xfer, &msg->transfers, transfer_list) { - trace_spi_transfer_start(msg, xfer); - - reinit_completion(&master->xfer_completion); - - ret = master->transfer_one(master, msg->spi, xfer); - if (ret < 0) { - dev_err(&msg->spi->dev, - "SPI transfer failed: %d\n", ret); - goto out; - } - - if (ret > 0) - wait_for_completion(&master->xfer_completion); - - trace_spi_transfer_stop(msg, xfer); - - if (msg->status != -EINPROGRESS) - goto out; - - if (xfer->delay_usecs) - udelay(xfer->delay_usecs); - - if (xfer->cs_change) { - if (list_is_last(&xfer->transfer_list, - &msg->transfers)) { - keep_cs = true; - } else { - cur_cs = !cur_cs; - spi_set_cs(msg->spi, cur_cs); - } - } - - msg->actual_length += xfer->len; - } - -out: - if (ret != 0 || !keep_cs) - spi_set_cs(msg->spi, false); - - if (msg->status == -EINPROGRESS) - msg->status = ret; - - spi_finalize_current_message(master); - - return ret; -} - -/** - * spi_finalize_current_transfer - report completion of a transfer - * - * Called by SPI drivers using the core transfer_one_message() - * implementation to notify it that the current interrupt driven - * transfer has finised and the next one may be scheduled. - */ -void spi_finalize_current_transfer(struct spi_master *master) -{ - complete(&master->xfer_completion); -} -EXPORT_SYMBOL_GPL(spi_finalize_current_transfer); - /** * spi_pump_messages - kthread work function which processes spi message queue * @work: pointer to kthread work struct contained in the master struct @@ -674,7 +557,6 @@ static void spi_pump_messages(struct kthread_work *work) pm_runtime_mark_last_busy(master->dev.parent); pm_runtime_put_autosuspend(master->dev.parent); } - trace_spi_master_idle(master); return; } @@ -703,9 +585,6 @@ static void spi_pump_messages(struct kthread_work *work) } } - if (!was_busy) - trace_spi_master_busy(master); - if (!was_busy && master->prepare_transfer_hardware) { ret = master->prepare_transfer_hardware(master); if (ret) { @@ -718,20 +597,6 @@ static void spi_pump_messages(struct kthread_work *work) } } - trace_spi_message_start(master->cur_msg); - - if (master->prepare_message) { - ret = master->prepare_message(master, master->cur_msg); - if (ret) { - dev_err(&master->dev, - "failed to prepare message: %d\n", ret); - master->cur_msg->status = ret; - spi_finalize_current_message(master); - return; - } - master->cur_msg_prepared = true; - } - ret = master->transfer_one_message(master, master->cur_msg); if (ret) { dev_err(&master->dev, @@ -813,7 +678,6 @@ void spi_finalize_current_message(struct spi_master *master) { struct spi_message *mesg; unsigned long flags; - int ret; spin_lock_irqsave(&master->queue_lock, flags); mesg = master->cur_msg; @@ -822,20 +686,9 @@ void spi_finalize_current_message(struct spi_master *master) queue_kthread_work(&master->kworker, &master->pump_messages); spin_unlock_irqrestore(&master->queue_lock, flags); - if (master->cur_msg_prepared && master->unprepare_message) { - ret = master->unprepare_message(master, mesg); - if (ret) { - dev_err(&master->dev, - "failed to unprepare message: %d\n", ret); - } - } - master->cur_msg_prepared = false; - mesg->state = NULL; if (mesg->complete) mesg->complete(mesg->context); - - trace_spi_message_done(mesg); } EXPORT_SYMBOL_GPL(spi_finalize_current_message); @@ -950,8 +803,6 @@ static int spi_master_initialize_queue(struct spi_master *master) master->queued = true; master->transfer = spi_queued_transfer; - if (!master->transfer_one_message) - master->transfer_one_message = spi_transfer_one_message; /* Initialize and start queue */ ret = spi_init_queue(master); @@ -987,8 +838,10 @@ static void of_register_spi_devices(struct spi_master *master) { struct spi_device *spi; struct device_node *nc; + const __be32 *prop; + char modalias[SPI_NAME_SIZE + 4]; int rc; - u32 value; + int len; if (!master->dev.of_node) return; @@ -1013,14 +866,14 @@ static void of_register_spi_devices(struct spi_master *master) } /* Device address */ - rc = of_property_read_u32(nc, "reg", &value); - if (rc) { - dev_err(&master->dev, "%s has no valid 'reg' property (%d)\n", - nc->full_name, rc); + prop = of_get_property(nc, "reg", &len); + if (!prop || len < sizeof(*prop)) { + dev_err(&master->dev, "%s has no 'reg' property\n", + nc->full_name); spi_dev_put(spi); continue; } - spi->chip_select = value; + spi->chip_select = be32_to_cpup(prop); /* Mode (clock phase/polarity/etc.) */ if (of_find_property(nc, "spi-cpha", NULL)) @@ -1033,53 +886,55 @@ static void of_register_spi_devices(struct spi_master *master) spi->mode |= SPI_3WIRE; /* Device DUAL/QUAD mode */ - if (!of_property_read_u32(nc, "spi-tx-bus-width", &value)) { - switch (value) { - case 1: + prop = of_get_property(nc, "spi-tx-bus-width", &len); + if (prop && len == sizeof(*prop)) { + switch (be32_to_cpup(prop)) { + case SPI_NBITS_SINGLE: break; - case 2: + case SPI_NBITS_DUAL: spi->mode |= SPI_TX_DUAL; break; - case 4: + case SPI_NBITS_QUAD: spi->mode |= SPI_TX_QUAD; break; default: dev_err(&master->dev, "spi-tx-bus-width %d not supported\n", - value); + be32_to_cpup(prop)); spi_dev_put(spi); continue; } } - if (!of_property_read_u32(nc, "spi-rx-bus-width", &value)) { - switch (value) { - case 1: + prop = of_get_property(nc, "spi-rx-bus-width", &len); + if (prop && len == sizeof(*prop)) { + switch (be32_to_cpup(prop)) { + case SPI_NBITS_SINGLE: break; - case 2: + case SPI_NBITS_DUAL: spi->mode |= SPI_RX_DUAL; break; - case 4: + case SPI_NBITS_QUAD: spi->mode |= SPI_RX_QUAD; break; default: dev_err(&master->dev, "spi-rx-bus-width %d not supported\n", - value); + be32_to_cpup(prop)); spi_dev_put(spi); continue; } } /* Device speed */ - rc = of_property_read_u32(nc, "spi-max-frequency", &value); - if (rc) { - dev_err(&master->dev, "%s has no valid 'spi-max-frequency' property (%d)\n", - nc->full_name, rc); + prop = of_get_property(nc, "spi-max-frequency", &len); + if (!prop || len < sizeof(*prop)) { + dev_err(&master->dev, "%s has no 'spi-max-frequency' property\n", + nc->full_name); spi_dev_put(spi); continue; } - spi->max_speed_hz = value; + spi->max_speed_hz = be32_to_cpup(prop); /* IRQ */ spi->irq = irq_of_parse_and_map(nc, 0); @@ -1089,7 +944,9 @@ static void of_register_spi_devices(struct spi_master *master) spi->dev.of_node = nc; /* Register the new device */ - request_module("%s%s", SPI_MODULE_PREFIX, spi->modalias); + snprintf(modalias, sizeof(modalias), "%s%s", SPI_MODULE_PREFIX, + spi->modalias); + request_module(modalias); rc = spi_add_device(spi); if (rc) { dev_err(&master->dev, "spi_device register error %s\n", @@ -1155,7 +1012,7 @@ static acpi_status acpi_spi_add_device(acpi_handle handle, u32 level, return AE_NO_MEMORY; } - ACPI_COMPANION_SET(&spi->dev, adev); + ACPI_HANDLE_SET(&spi->dev, handle); spi->irq = -1; INIT_LIST_HEAD(&resource_list); @@ -1168,10 +1025,8 @@ static acpi_status acpi_spi_add_device(acpi_handle handle, u32 level, return AE_OK; } - adev->power.flags.ignore_parent = true; - strlcpy(spi->modalias, acpi_device_hid(adev), sizeof(spi->modalias)); + strlcpy(spi->modalias, dev_name(&adev->dev), sizeof(spi->modalias)); if (spi_add_device(spi)) { - adev->power.flags.ignore_parent = false; dev_err(&master->dev, "failed to add SPI device %s from ACPI\n", dev_name(&adev->dev)); spi_dev_put(spi); @@ -1242,7 +1097,7 @@ struct spi_master *spi_alloc_master(struct device *dev, unsigned size) if (!dev) return NULL; - master = kzalloc(size + sizeof(*master), GFP_KERNEL); + master = kzalloc(size + sizeof *master, GFP_KERNEL); if (!master) return NULL; @@ -1267,7 +1122,7 @@ static int of_spi_register_master(struct spi_master *master) return 0; nb = of_gpio_named_count(np, "cs-gpios"); - master->num_chipselect = max_t(int, nb, master->num_chipselect); + master->num_chipselect = max(nb, (int)master->num_chipselect); /* Return error only for an incorrectly formed cs-gpios property */ if (nb == 0 || nb == -ENOENT) @@ -1354,7 +1209,6 @@ int spi_register_master(struct spi_master *master) spin_lock_init(&master->bus_lock_spinlock); mutex_init(&master->bus_lock_mutex); master->bus_lock_flag = 0; - init_completion(&master->xfer_completion); /* register the device, then userspace will see it. * registration fails if the bus ID is in use. @@ -1391,41 +1245,6 @@ done: } EXPORT_SYMBOL_GPL(spi_register_master); -static void devm_spi_unregister(struct device *dev, void *res) -{ - spi_unregister_master(*(struct spi_master **)res); -} - -/** - * dev_spi_register_master - register managed SPI master controller - * @dev: device managing SPI master - * @master: initialized master, originally from spi_alloc_master() - * Context: can sleep - * - * Register a SPI device as with spi_register_master() which will - * automatically be unregister - */ -int devm_spi_register_master(struct device *dev, struct spi_master *master) -{ - struct spi_master **ptr; - int ret; - - ptr = devres_alloc(devm_spi_unregister, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return -ENOMEM; - - ret = spi_register_master(master); - if (!ret) { - *ptr = master; - devres_add(dev, ptr); - } else { - devres_free(ptr); - } - - return ret; -} -EXPORT_SYMBOL_GPL(devm_spi_register_master); - static int __unregister(struct device *dev, void *null) { spi_unregister_device(to_spi_device(dev)); @@ -1583,7 +1402,8 @@ int spi_setup(struct spi_device *spi) if (spi->master->setup) status = spi->master->setup(spi); - dev_dbg(&spi->dev, "setup mode %d, %s%s%s%s%u bits/w, %u Hz max --> %d\n", + dev_dbg(&spi->dev, "setup mode %d, %s%s%s%s" + "%u bits/w, %u Hz max --> %d\n", (int) (spi->mode & (SPI_CPOL | SPI_CPHA)), (spi->mode & SPI_CS_HIGH) ? "cs_high, " : "", (spi->mode & SPI_LSB_FIRST) ? "lsb, " : "", @@ -1601,10 +1421,6 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) struct spi_master *master = spi->master; struct spi_transfer *xfer; - message->spi = spi; - - trace_spi_message_submit(message); - if (list_empty(&message->transfers)) return -EINVAL; if (!message->complete) @@ -1704,6 +1520,7 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) } } + message->spi = spi; message->status = -EINPROGRESS; return master->transfer(spi, message); } @@ -1945,7 +1762,7 @@ int spi_bus_unlock(struct spi_master *master) EXPORT_SYMBOL_GPL(spi_bus_unlock); /* portable code must never pass more than 32 bytes */ -#define SPI_BUFSIZ max(32, SMP_CACHE_BYTES) +#define SPI_BUFSIZ max(32,SMP_CACHE_BYTES) static u8 *buf; @@ -1994,7 +1811,7 @@ int spi_write_then_read(struct spi_device *spi, } spi_message_init(&message); - memset(x, 0, sizeof(x)); + memset(x, 0, sizeof x); if (n_tx) { x[0].len = n_tx; spi_message_add_tail(&x[0], &message); |