summaryrefslogtreecommitdiff
path: root/drivers/spi/spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi.c')
-rw-r--r--drivers/spi/spi.c281
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);