summaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2017-07-03 16:21:05 +0100
committerMark Brown <broonie@kernel.org>2017-07-03 16:21:05 +0100
commit9d540b0d4964603798efdccae90cab8ac06c8bf4 (patch)
tree3ecf8c3779f1c99578cd64068121478895b05408 /drivers/spi
parent096bf6b7f4fcc2fe486f61526b888034a7059342 (diff)
parent8caab75fd2c2a92667cbb1cd315720bede3feaa9 (diff)
Merge remote-tracking branch 'spi/topic/master' into spi-next
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/Kconfig26
-rw-r--r--drivers/spi/Makefile4
-rw-r--r--drivers/spi/spi-slave-system-control.c154
-rw-r--r--drivers/spi/spi-slave-time.c129
-rw-r--r--drivers/spi/spi.c1216
5 files changed, 987 insertions, 542 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 097883362036..82cd818aa062 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -785,6 +785,30 @@ config SPI_TLE62X0
endif # SPI_MASTER
-# (slave support would go here)
+#
+# SLAVE side ... listening to other SPI masters
+#
+
+config SPI_SLAVE
+ bool "SPI slave protocol handlers"
+ help
+ If your system has a slave-capable SPI controller, you can enable
+ slave protocol handlers.
+
+if SPI_SLAVE
+
+config SPI_SLAVE_TIME
+ tristate "SPI slave handler reporting boot up time"
+ help
+ SPI slave handler responding with the time of reception of the last
+ SPI message.
+
+config SPI_SLAVE_SYSTEM_CONTROL
+ tristate "SPI slave handler controlling system state"
+ help
+ SPI slave handler to allow remote control of system reboot, power
+ off, halt, and suspend.
+
+endif # SPI_SLAVE
endif # SPI
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index b375a7a89216..1d7923e8c63b 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -105,3 +105,7 @@ obj-$(CONFIG_SPI_XILINX) += spi-xilinx.o
obj-$(CONFIG_SPI_XLP) += spi-xlp.o
obj-$(CONFIG_SPI_XTENSA_XTFPGA) += spi-xtensa-xtfpga.o
obj-$(CONFIG_SPI_ZYNQMP_GQSPI) += spi-zynqmp-gqspi.o
+
+# SPI slave protocol handlers
+obj-$(CONFIG_SPI_SLAVE_TIME) += spi-slave-time.o
+obj-$(CONFIG_SPI_SLAVE_SYSTEM_CONTROL) += spi-slave-system-control.o
diff --git a/drivers/spi/spi-slave-system-control.c b/drivers/spi/spi-slave-system-control.c
new file mode 100644
index 000000000000..c0257e937995
--- /dev/null
+++ b/drivers/spi/spi-slave-system-control.c
@@ -0,0 +1,154 @@
+/*
+ * SPI slave handler controlling system state
+ *
+ * This SPI slave handler allows remote control of system reboot, power off,
+ * halt, and suspend.
+ *
+ * Copyright (C) 2016-2017 Glider bvba
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Usage (assuming /dev/spidev2.0 corresponds to the SPI master on the remote
+ * system):
+ *
+ * # reboot='\x7c\x50'
+ * # poweroff='\x71\x3f'
+ * # halt='\x38\x76'
+ * # suspend='\x1b\x1b'
+ * # spidev_test -D /dev/spidev2.0 -p $suspend # or $reboot, $poweroff, $halt
+ */
+
+#include <linux/completion.h>
+#include <linux/module.h>
+#include <linux/reboot.h>
+#include <linux/suspend.h>
+#include <linux/spi/spi.h>
+
+/*
+ * The numbers are chosen to display something human-readable on two 7-segment
+ * displays connected to two 74HC595 shift registers
+ */
+#define CMD_REBOOT 0x7c50 /* rb */
+#define CMD_POWEROFF 0x713f /* OF */
+#define CMD_HALT 0x3876 /* HL */
+#define CMD_SUSPEND 0x1b1b /* ZZ */
+
+struct spi_slave_system_control_priv {
+ struct spi_device *spi;
+ struct completion finished;
+ struct spi_transfer xfer;
+ struct spi_message msg;
+ __be16 cmd;
+};
+
+static
+int spi_slave_system_control_submit(struct spi_slave_system_control_priv *priv);
+
+static void spi_slave_system_control_complete(void *arg)
+{
+ struct spi_slave_system_control_priv *priv = arg;
+ u16 cmd;
+ int ret;
+
+ if (priv->msg.status)
+ goto terminate;
+
+ cmd = be16_to_cpu(priv->cmd);
+ switch (cmd) {
+ case CMD_REBOOT:
+ dev_info(&priv->spi->dev, "Rebooting system...\n");
+ kernel_restart(NULL);
+
+ case CMD_POWEROFF:
+ dev_info(&priv->spi->dev, "Powering off system...\n");
+ kernel_power_off();
+ break;
+
+ case CMD_HALT:
+ dev_info(&priv->spi->dev, "Halting system...\n");
+ kernel_halt();
+ break;
+
+ case CMD_SUSPEND:
+ dev_info(&priv->spi->dev, "Suspending system...\n");
+ pm_suspend(PM_SUSPEND_MEM);
+ break;
+
+ default:
+ dev_warn(&priv->spi->dev, "Unknown command 0x%x\n", cmd);
+ break;
+ }
+
+ ret = spi_slave_system_control_submit(priv);
+ if (ret)
+ goto terminate;
+
+ return;
+
+terminate:
+ dev_info(&priv->spi->dev, "Terminating\n");
+ complete(&priv->finished);
+}
+
+static
+int spi_slave_system_control_submit(struct spi_slave_system_control_priv *priv)
+{
+ int ret;
+
+ spi_message_init_with_transfers(&priv->msg, &priv->xfer, 1);
+
+ priv->msg.complete = spi_slave_system_control_complete;
+ priv->msg.context = priv;
+
+ ret = spi_async(priv->spi, &priv->msg);
+ if (ret)
+ dev_err(&priv->spi->dev, "spi_async() failed %d\n", ret);
+
+ return ret;
+}
+
+static int spi_slave_system_control_probe(struct spi_device *spi)
+{
+ struct spi_slave_system_control_priv *priv;
+ int ret;
+
+ priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->spi = spi;
+ init_completion(&priv->finished);
+ priv->xfer.rx_buf = &priv->cmd;
+ priv->xfer.len = sizeof(priv->cmd);
+
+ ret = spi_slave_system_control_submit(priv);
+ if (ret)
+ return ret;
+
+ spi_set_drvdata(spi, priv);
+ return 0;
+}
+
+static int spi_slave_system_control_remove(struct spi_device *spi)
+{
+ struct spi_slave_system_control_priv *priv = spi_get_drvdata(spi);
+
+ spi_slave_abort(spi);
+ wait_for_completion(&priv->finished);
+ return 0;
+}
+
+static struct spi_driver spi_slave_system_control_driver = {
+ .driver = {
+ .name = "spi-slave-system-control",
+ },
+ .probe = spi_slave_system_control_probe,
+ .remove = spi_slave_system_control_remove,
+};
+module_spi_driver(spi_slave_system_control_driver);
+
+MODULE_AUTHOR("Geert Uytterhoeven <geert+renesas@glider.be>");
+MODULE_DESCRIPTION("SPI slave handler controlling system state");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/spi-slave-time.c b/drivers/spi/spi-slave-time.c
new file mode 100644
index 000000000000..f2e07a392d68
--- /dev/null
+++ b/drivers/spi/spi-slave-time.c
@@ -0,0 +1,129 @@
+/*
+ * SPI slave handler reporting uptime at reception of previous SPI message
+ *
+ * This SPI slave handler sends the time of reception of the last SPI message
+ * as two 32-bit unsigned integers in binary format and in network byte order,
+ * representing the number of seconds and fractional seconds (in microseconds)
+ * since boot up.
+ *
+ * Copyright (C) 2016-2017 Glider bvba
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Usage (assuming /dev/spidev2.0 corresponds to the SPI master on the remote
+ * system):
+ *
+ * # spidev_test -D /dev/spidev2.0 -p dummy-8B
+ * spi mode: 0x0
+ * bits per word: 8
+ * max speed: 500000 Hz (500 KHz)
+ * RX | 00 00 04 6D 00 09 5B BB ...
+ * ^^^^^ ^^^^^^^^
+ * seconds microseconds
+ */
+
+#include <linux/completion.h>
+#include <linux/module.h>
+#include <linux/sched/clock.h>
+#include <linux/spi/spi.h>
+
+
+struct spi_slave_time_priv {
+ struct spi_device *spi;
+ struct completion finished;
+ struct spi_transfer xfer;
+ struct spi_message msg;
+ __be32 buf[2];
+};
+
+static int spi_slave_time_submit(struct spi_slave_time_priv *priv);
+
+static void spi_slave_time_complete(void *arg)
+{
+ struct spi_slave_time_priv *priv = arg;
+ int ret;
+
+ ret = priv->msg.status;
+ if (ret)
+ goto terminate;
+
+ ret = spi_slave_time_submit(priv);
+ if (ret)
+ goto terminate;
+
+ return;
+
+terminate:
+ dev_info(&priv->spi->dev, "Terminating\n");
+ complete(&priv->finished);
+}
+
+static int spi_slave_time_submit(struct spi_slave_time_priv *priv)
+{
+ u32 rem_us;
+ int ret;
+ u64 ts;
+
+ ts = local_clock();
+ rem_us = do_div(ts, 1000000000) / 1000;
+
+ priv->buf[0] = cpu_to_be32(ts);
+ priv->buf[1] = cpu_to_be32(rem_us);
+
+ spi_message_init_with_transfers(&priv->msg, &priv->xfer, 1);
+
+ priv->msg.complete = spi_slave_time_complete;
+ priv->msg.context = priv;
+
+ ret = spi_async(priv->spi, &priv->msg);
+ if (ret)
+ dev_err(&priv->spi->dev, "spi_async() failed %d\n", ret);
+
+ return ret;
+}
+
+static int spi_slave_time_probe(struct spi_device *spi)
+{
+ struct spi_slave_time_priv *priv;
+ int ret;
+
+ priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->spi = spi;
+ init_completion(&priv->finished);
+ priv->xfer.tx_buf = priv->buf;
+ priv->xfer.len = sizeof(priv->buf);
+
+ ret = spi_slave_time_submit(priv);
+ if (ret)
+ return ret;
+
+ spi_set_drvdata(spi, priv);
+ return 0;
+}
+
+static int spi_slave_time_remove(struct spi_device *spi)
+{
+ struct spi_slave_time_priv *priv = spi_get_drvdata(spi);
+
+ spi_slave_abort(spi);
+ wait_for_completion(&priv->finished);
+ return 0;
+}
+
+static struct spi_driver spi_slave_time_driver = {
+ .driver = {
+ .name = "spi-slave-time",
+ },
+ .probe = spi_slave_time_probe,
+ .remove = spi_slave_time_remove,
+};
+module_spi_driver(spi_slave_time_driver);
+
+MODULE_AUTHOR("Geert Uytterhoeven <geert+renesas@glider.be>");
+MODULE_DESCRIPTION("SPI slave reporting uptime at previous SPI message");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 6f87fec409b5..4fcbb0aa71d3 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -48,11 +48,11 @@ static void spidev_release(struct device *dev)
{
struct spi_device *spi = to_spi_device(dev);
- /* spi masters may cleanup for released devices */
- if (spi->master->cleanup)
- spi->master->cleanup(spi);
+ /* spi controllers may cleanup for released devices */
+ if (spi->controller->cleanup)
+ spi->controller->cleanup(spi);
- spi_master_put(spi->master);
+ spi_controller_put(spi->controller);
kfree(spi);
}
@@ -71,17 +71,17 @@ modalias_show(struct device *dev, struct device_attribute *a, char *buf)
static DEVICE_ATTR_RO(modalias);
#define SPI_STATISTICS_ATTRS(field, file) \
-static ssize_t spi_master_##field##_show(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
+static ssize_t spi_controller_##field##_show(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
{ \
- struct spi_master *master = container_of(dev, \
- struct spi_master, dev); \
- return spi_statistics_##field##_show(&master->statistics, buf); \
+ struct spi_controller *ctlr = container_of(dev, \
+ struct spi_controller, dev); \
+ return spi_statistics_##field##_show(&ctlr->statistics, buf); \
} \
-static struct device_attribute dev_attr_spi_master_##field = { \
+static struct device_attribute dev_attr_spi_controller_##field = { \
.attr = { .name = file, .mode = 0444 }, \
- .show = spi_master_##field##_show, \
+ .show = spi_controller_##field##_show, \
}; \
static ssize_t spi_device_##field##_show(struct device *dev, \
struct device_attribute *attr, \
@@ -201,51 +201,51 @@ static const struct attribute_group *spi_dev_groups[] = {
NULL,
};
-static struct attribute *spi_master_statistics_attrs[] = {
- &dev_attr_spi_master_messages.attr,
- &dev_attr_spi_master_transfers.attr,
- &dev_attr_spi_master_errors.attr,
- &dev_attr_spi_master_timedout.attr,
- &dev_attr_spi_master_spi_sync.attr,
- &dev_attr_spi_master_spi_sync_immediate.attr,
- &dev_attr_spi_master_spi_async.attr,
- &dev_attr_spi_master_bytes.attr,
- &dev_attr_spi_master_bytes_rx.attr,
- &dev_attr_spi_master_bytes_tx.attr,
- &dev_attr_spi_master_transfer_bytes_histo0.attr,
- &dev_attr_spi_master_transfer_bytes_histo1.attr,
- &dev_attr_spi_master_transfer_bytes_histo2.attr,
- &dev_attr_spi_master_transfer_bytes_histo3.attr,
- &dev_attr_spi_master_transfer_bytes_histo4.attr,
- &dev_attr_spi_master_transfer_bytes_histo5.attr,
- &dev_attr_spi_master_transfer_bytes_histo6.attr,
- &dev_attr_spi_master_transfer_bytes_histo7.attr,
- &dev_attr_spi_master_transfer_bytes_histo8.attr,
- &dev_attr_spi_master_transfer_bytes_histo9.attr,
- &dev_attr_spi_master_transfer_bytes_histo10.attr,
- &dev_attr_spi_master_transfer_bytes_histo11.attr,
- &dev_attr_spi_master_transfer_bytes_histo12.attr,
- &dev_attr_spi_master_transfer_bytes_histo13.attr,
- &dev_attr_spi_master_transfer_bytes_histo14.attr,
- &dev_attr_spi_master_transfer_bytes_histo15.attr,
- &dev_attr_spi_master_transfer_bytes_histo16.attr,
- &dev_attr_spi_master_transfers_split_maxsize.attr,
+static struct attribute *spi_controller_statistics_attrs[] = {
+ &dev_attr_spi_controller_messages.attr,
+ &dev_attr_spi_controller_transfers.attr,
+ &dev_attr_spi_controller_errors.attr,
+ &dev_attr_spi_controller_timedout.attr,
+ &dev_attr_spi_controller_spi_sync.attr,
+ &dev_attr_spi_controller_spi_sync_immediate.attr,
+ &dev_attr_spi_controller_spi_async.attr,
+ &dev_attr_spi_controller_bytes.attr,
+ &dev_attr_spi_controller_bytes_rx.attr,
+ &dev_attr_spi_controller_bytes_tx.attr,
+ &dev_attr_spi_controller_transfer_bytes_histo0.attr,
+ &dev_attr_spi_controller_transfer_bytes_histo1.attr,
+ &dev_attr_spi_controller_transfer_bytes_histo2.attr,
+ &dev_attr_spi_controller_transfer_bytes_histo3.attr,
+ &dev_attr_spi_controller_transfer_bytes_histo4.attr,
+ &dev_attr_spi_controller_transfer_bytes_histo5.attr,
+ &dev_attr_spi_controller_transfer_bytes_histo6.attr,
+ &dev_attr_spi_controller_transfer_bytes_histo7.attr,
+ &dev_attr_spi_controller_transfer_bytes_histo8.attr,
+ &dev_attr_spi_controller_transfer_bytes_histo9.attr,
+ &dev_attr_spi_controller_transfer_bytes_histo10.attr,
+ &dev_attr_spi_controller_transfer_bytes_histo11.attr,
+ &dev_attr_spi_controller_transfer_bytes_histo12.attr,
+ &dev_attr_spi_controller_transfer_bytes_histo13.attr,
+ &dev_attr_spi_controller_transfer_bytes_histo14.attr,
+ &dev_attr_spi_controller_transfer_bytes_histo15.attr,
+ &dev_attr_spi_controller_transfer_bytes_histo16.attr,
+ &dev_attr_spi_controller_transfers_split_maxsize.attr,
NULL,
};
-static const struct attribute_group spi_master_statistics_group = {
+static const struct attribute_group spi_controller_statistics_group = {
.name = "statistics",
- .attrs = spi_master_statistics_attrs,
+ .attrs = spi_controller_statistics_attrs,
};
static const struct attribute_group *spi_master_groups[] = {
- &spi_master_statistics_group,
+ &spi_controller_statistics_group,
NULL,
};
void spi_statistics_add_transfer_stats(struct spi_statistics *stats,
struct spi_transfer *xfer,
- struct spi_master *master)
+ struct spi_controller *ctlr)
{
unsigned long flags;
int l2len = min(fls(xfer->len), SPI_STATISTICS_HISTO_SIZE) - 1;
@@ -260,10 +260,10 @@ void spi_statistics_add_transfer_stats(struct spi_statistics *stats,
stats->bytes += xfer->len;
if ((xfer->tx_buf) &&
- (xfer->tx_buf != master->dummy_tx))
+ (xfer->tx_buf != ctlr->dummy_tx))
stats->bytes_tx += xfer->len;
if ((xfer->rx_buf) &&
- (xfer->rx_buf != master->dummy_rx))
+ (xfer->rx_buf != ctlr->dummy_rx))
stats->bytes_rx += xfer->len;
spin_unlock_irqrestore(&stats->lock, flags);
@@ -405,7 +405,7 @@ EXPORT_SYMBOL_GPL(__spi_register_driver);
/*-------------------------------------------------------------------------*/
/* SPI devices should normally not be created by SPI device drivers; that
- * would make them board-specific. Similarly with SPI master drivers.
+ * would make them board-specific. Similarly with SPI controller drivers.
* Device registration normally goes into like arch/.../mach.../board-YYY.c
* with other readonly (flashable) information about mainboard devices.
*/
@@ -416,17 +416,17 @@ struct boardinfo {
};
static LIST_HEAD(board_list);
-static LIST_HEAD(spi_master_list);
+static LIST_HEAD(spi_controller_list);
/*
* Used to protect add/del opertion for board_info list and
- * spi_master list, and their matching process
+ * spi_controller list, and their matching process
*/
static DEFINE_MUTEX(board_lock);
/**
* spi_alloc_device - Allocate a new SPI device
- * @master: Controller to which device is connected
+ * @ctlr: Controller to which device is connected
* Context: can sleep
*
* Allows a driver to allocate and initialize a spi_device without
@@ -435,27 +435,27 @@ static DEFINE_MUTEX(board_lock);
* spi_add_device() on it.
*
* Caller is responsible to call spi_add_device() on the returned
- * spi_device structure to add it to the SPI master. If the caller
+ * spi_device structure to add it to the SPI controller. If the caller
* needs to discard the spi_device without adding it, then it should
* call spi_dev_put() on it.
*
* Return: a pointer to the new device, or NULL.
*/
-struct spi_device *spi_alloc_device(struct spi_master *master)
+struct spi_device *spi_alloc_device(struct spi_controller *ctlr)
{
struct spi_device *spi;
- if (!spi_master_get(master))
+ if (!spi_controller_get(ctlr))
return NULL;
spi = kzalloc(sizeof(*spi), GFP_KERNEL);
if (!spi) {
- spi_master_put(master);
+ spi_controller_put(ctlr);
return NULL;
}
- spi->master = master;
- spi->dev.parent = &master->dev;
+ spi->master = spi->controller = ctlr;
+ spi->dev.parent = &ctlr->dev;
spi->dev.bus = &spi_bus_type;
spi->dev.release = spidev_release;
spi->cs_gpio = -ENOENT;
@@ -476,7 +476,7 @@ static void spi_dev_set_name(struct spi_device *spi)
return;
}
- dev_set_name(&spi->dev, "%s.%u", dev_name(&spi->master->dev),
+ dev_set_name(&spi->dev, "%s.%u", dev_name(&spi->controller->dev),
spi->chip_select);
}
@@ -485,7 +485,7 @@ static int spi_dev_check(struct device *dev, void *data)
struct spi_device *spi = to_spi_device(dev);
struct spi_device *new_spi = data;
- if (spi->master == new_spi->master &&
+ if (spi->controller == new_spi->controller &&
spi->chip_select == new_spi->chip_select)
return -EBUSY;
return 0;
@@ -503,15 +503,14 @@ static int spi_dev_check(struct device *dev, void *data)
int spi_add_device(struct spi_device *spi)
{
static DEFINE_MUTEX(spi_add_lock);
- struct spi_master *master = spi->master;
- struct device *dev = master->dev.parent;
+ struct spi_controller *ctlr = spi->controller;
+ struct device *dev = ctlr->dev.parent;
int status;
/* Chipselects are numbered 0..max; validate. */
- if (spi->chip_select >= master->num_chipselect) {
- dev_err(dev, "cs%d >= max %d\n",
- spi->chip_select,
- master->num_chipselect);
+ if (spi->chip_select >= ctlr->num_chipselect) {
+ dev_err(dev, "cs%d >= max %d\n", spi->chip_select,
+ ctlr->num_chipselect);
return -EINVAL;
}
@@ -531,8 +530,8 @@ int spi_add_device(struct spi_device *spi)
goto done;
}
- if (master->cs_gpios)
- spi->cs_gpio = master->cs_gpios[spi->chip_select];
+ if (ctlr->cs_gpios)
+ spi->cs_gpio = ctlr->cs_gpios[spi->chip_select];
/* Drivers may modify this initial i/o setup, but will
* normally rely on the device being setup. Devices
@@ -561,7 +560,7 @@ EXPORT_SYMBOL_GPL(spi_add_device);
/**
* spi_new_device - instantiate one new SPI device
- * @master: Controller to which device is connected
+ * @ctlr: Controller to which device is connected
* @chip: Describes the SPI device
* Context: can sleep
*
@@ -573,7 +572,7 @@ EXPORT_SYMBOL_GPL(spi_add_device);
*
* Return: the new device, or NULL.
*/
-struct spi_device *spi_new_device(struct spi_master *master,
+struct spi_device *spi_new_device(struct spi_controller *ctlr,
struct spi_board_info *chip)
{
struct spi_device *proxy;
@@ -586,7 +585,7 @@ struct spi_device *spi_new_device(struct spi_master *master,
* suggests syslogged diagnostics are best here (ugh).
*/
- proxy = spi_alloc_device(master);
+ proxy = spi_alloc_device(ctlr);
if (!proxy)
return NULL;
@@ -604,7 +603,7 @@ struct spi_device *spi_new_device(struct spi_master *master,
if (chip->properties) {
status = device_add_properties(&proxy->dev, chip->properties);
if (status) {
- dev_err(&master->dev,
+ dev_err(&ctlr->dev,
"failed to add properties to '%s': %d\n",
chip->modalias, status);
goto err_dev_put;
@@ -631,7 +630,7 @@ EXPORT_SYMBOL_GPL(spi_new_device);
* @spi: spi_device to unregister
*
* Start making the passed SPI device vanish. Normally this would be handled
- * by spi_unregister_master().
+ * by spi_unregister_controller().
*/
void spi_unregister_device(struct spi_device *spi)
{
@@ -648,17 +647,17 @@ void spi_unregister_device(struct spi_device *spi)
}
EXPORT_SYMBOL_GPL(spi_unregister_device);
-static void spi_match_master_to_boardinfo(struct spi_master *master,
- struct spi_board_info *bi)
+static void spi_match_controller_to_boardinfo(struct spi_controller *ctlr,
+ struct spi_board_info *bi)
{
struct spi_device *dev;
- if (master->bus_num != bi->bus_num)
+ if (ctlr->bus_num != bi->bus_num)
return;
- dev = spi_new_device(master, bi);
+ dev = spi_new_device(ctlr, bi);
if (!dev)
- dev_err(master->dev.parent, "can't create new device for %s\n",
+ dev_err(ctlr->dev.parent, "can't create new device for %s\n",
bi->modalias);
}
@@ -697,7 +696,7 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n)
return -ENOMEM;
for (i = 0; i < n; i++, bi++, info++) {
- struct spi_master *master;
+ struct spi_controller *ctlr;
memcpy(&bi->board_info, info, sizeof(*info));
if (info->properties) {
@@ -709,8 +708,9 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n)
mutex_lock(&board_lock);
list_add_tail(&bi->list, &board_list);
- list_for_each_entry(master, &spi_master_list, list)
- spi_match_master_to_boardinfo(master, &bi->board_info);
+ list_for_each_entry(ctlr, &spi_controller_list, list)
+ spi_match_controller_to_boardinfo(ctlr,
+ &bi->board_info);
mutex_unlock(&board_lock);
}
@@ -727,16 +727,16 @@ static void spi_set_cs(struct spi_device *spi, bool enable)
if (gpio_is_valid(spi->cs_gpio)) {
gpio_set_value(spi->cs_gpio, !enable);
/* Some SPI masters need both GPIO CS & slave_select */
- if ((spi->master->flags & SPI_MASTER_GPIO_SS) &&
- spi->master->set_cs)
- spi->master->set_cs(spi, !enable);
- } else if (spi->master->set_cs) {
- spi->master->set_cs(spi, !enable);
+ if ((spi->controller->flags & SPI_MASTER_GPIO_SS) &&
+ spi->controller->set_cs)
+ spi->controller->set_cs(spi, !enable);
+ } else if (spi->controller->set_cs) {
+ spi->controller->set_cs(spi, !enable);
}
}
#ifdef CONFIG_HAS_DMA
-static int spi_map_buf(struct spi_master *master, struct device *dev,
+static int spi_map_buf(struct spi_controller *ctlr, struct device *dev,
struct sg_table *sgt, void *buf, size_t len,
enum dma_data_direction dir)
{
@@ -761,7 +761,7 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
desc_len = min_t(int, max_seg_size, PAGE_SIZE);
sgs = DIV_ROUND_UP(len + offset_in_page(buf), desc_len);
} else if (virt_addr_valid(buf)) {
- desc_len = min_t(int, max_seg_size, master->max_dma_len);
+ desc_len = min_t(int, max_seg_size, ctlr->max_dma_len);
sgs = DIV_ROUND_UP(len, desc_len);
} else {
return -EINVAL;
@@ -811,7 +811,7 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
return 0;
}
-static void spi_unmap_buf(struct spi_master *master, struct device *dev,
+static void spi_unmap_buf(struct spi_controller *ctlr, struct device *dev,
struct sg_table *sgt, enum dma_data_direction dir)
{
if (sgt->orig_nents) {
@@ -820,31 +820,31 @@ static void spi_unmap_buf(struct spi_master *master, struct device *dev,
}
}
-static int __spi_map_msg(struct spi_master *master, struct spi_message *msg)
+static int __spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg)
{
struct device *tx_dev, *rx_dev;
struct spi_transfer *xfer;
int ret;
- if (!master->can_dma)
+ if (!ctlr->can_dma)
return 0;
- if (master->dma_tx)
- tx_dev = master->dma_tx->device->dev;
+ if (ctlr->dma_tx)
+ tx_dev = ctlr->dma_tx->device->dev;
else
- tx_dev = master->dev.parent;
+ tx_dev = ctlr->dev.parent;
- if (master->dma_rx)
- rx_dev = master->dma_rx->device->dev;
+ if (ctlr->dma_rx)
+ rx_dev = ctlr->dma_rx->device->dev;
else
- rx_dev = master->dev.parent;
+ rx_dev = ctlr->dev.parent;
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
- if (!master->can_dma(master, msg->spi, xfer))
+ if (!ctlr->can_dma(ctlr, msg->spi, xfer))
continue;
if (xfer->tx_buf != NULL) {
- ret = spi_map_buf(master, tx_dev, &xfer->tx_sg,
+ ret = spi_map_buf(ctlr, tx_dev, &xfer->tx_sg,
(void *)xfer->tx_buf, xfer->len,
DMA_TO_DEVICE);
if (ret != 0)
@@ -852,79 +852,78 @@ static int __spi_map_msg(struct spi_master *master, struct spi_message *msg)
}
if (xfer->rx_buf != NULL) {
- ret = spi_map_buf(master, rx_dev, &xfer->rx_sg,
+ ret = spi_map_buf(ctlr, rx_dev, &xfer->rx_sg,
xfer->rx_buf, xfer->len,
DMA_FROM_DEVICE);
if (ret != 0) {
- spi_unmap_buf(master, tx_dev, &xfer->tx_sg,
+ spi_unmap_buf(ctlr, tx_dev, &xfer->tx_sg,
DMA_TO_DEVICE);
return ret;
}
}
}
- master->cur_msg_mapped = true;
+ ctlr->cur_msg_mapped = true;
return 0;
}
-static int __spi_unmap_msg(struct spi_master *master, struct spi_message *msg)
+static int __spi_unmap_msg(struct spi_controller *ctlr, struct spi_message *msg)
{
struct spi_transfer *xfer;
struct device *tx_dev, *rx_dev;
- if (!master->cur_msg_mapped || !master->can_dma)
+ if (!ctlr->cur_msg_mapped || !ctlr->can_dma)
return 0;
- if (master->dma_tx)
- tx_dev = master->dma_tx->device->dev;
+ if (ctlr->dma_tx)
+ tx_dev = ctlr->dma_tx->device->dev;
else
- tx_dev = master->dev.parent;
+ tx_dev = ctlr->dev.parent;
- if (master->dma_rx)
- rx_dev = master->dma_rx->device->dev;
+ if (ctlr->dma_rx)
+ rx_dev = ctlr->dma_rx->device->dev;
else
- rx_dev = master->dev.parent;
+ rx_dev = ctlr->dev.parent;
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
- if (!master->can_dma(master, msg->spi, xfer))
+ if (!ctlr->can_dma(ctlr, msg->spi, xfer))
continue;
- spi_unmap_buf(master, rx_dev, &xfer->rx_sg, DMA_FROM_DEVICE);
- spi_unmap_buf(master, tx_dev, &xfer->tx_sg, DMA_TO_DEVICE);
+ spi_unmap_buf(ctlr, rx_dev, &xfer->rx_sg, DMA_FROM_DEVICE);
+ spi_unmap_buf(ctlr, tx_dev, &xfer->tx_sg, DMA_TO_DEVICE);
}
return 0;
}
#else /* !CONFIG_HAS_DMA */
-static inline int spi_map_buf(struct spi_master *master,
- struct device *dev, struct sg_table *sgt,
- void *buf, size_t len,
+static inline int spi_map_buf(struct spi_controller *ctlr, struct device *dev,
+ struct sg_table *sgt, void *buf, size_t len,
enum dma_data_direction dir)
{
return -EINVAL;
}
-static inline void spi_unmap_buf(struct spi_master *master,
+static inline void spi_unmap_buf(struct spi_controller *ctlr,
struct device *dev, struct sg_table *sgt,
enum dma_data_direction dir)
{
}
-static inline int __spi_map_msg(struct spi_master *master,
+static inline int __spi_map_msg(struct spi_controller *ctlr,
struct spi_message *msg)
{
return 0;
}
-static inline int __spi_unmap_msg(struct spi_master *master,
+static inline int __spi_unmap_msg(struct spi_controller *ctlr,
struct spi_message *msg)
{
return 0;
}
#endif /* !CONFIG_HAS_DMA */
-static inline int spi_unmap_msg(struct spi_master *master,
+static inline int spi_unmap_msg(struct spi_controller *ctlr,
struct spi_message *msg)
{
struct spi_transfer *xfer;
@@ -934,63 +933,63 @@ static inline int spi_unmap_msg(struct spi_master *master,
* Restore the original value of tx_buf or rx_buf if they are
* NULL.
*/
- if (xfer->tx_buf == master->dummy_tx)
+ if (xfer->tx_buf == ctlr->dummy_tx)
xfer->tx_buf = NULL;
- if (xfer->rx_buf == master->dummy_rx)
+ if (xfer->rx_buf == ctlr->dummy_rx)
xfer->rx_buf = NULL;
}
- return __spi_unmap_msg(master, msg);
+ return __spi_unmap_msg(ctlr, msg);
}
-static int spi_map_msg(struct spi_master *master, struct spi_message *msg)
+static int spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg)
{
struct spi_transfer *xfer;
void *tmp;
unsigned int max_tx, max_rx;
- if (master->flags & (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX)) {
+ if (ctlr->flags & (SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX)) {
max_tx = 0;
max_rx = 0;
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
- if ((master->flags & SPI_MASTER_MUST_TX) &&
+ if ((ctlr->flags & SPI_CONTROLLER_MUST_TX) &&
!xfer->tx_buf)
max_tx = max(xfer->len, max_tx);
- if ((master->flags & SPI_MASTER_MUST_RX) &&
+ if ((ctlr->flags & SPI_CONTROLLER_MUST_RX) &&
!xfer->rx_buf)
max_rx = max(xfer->len, max_rx);
}
if (max_tx) {
- tmp = krealloc(master->dummy_tx, max_tx,
+ tmp = krealloc(ctlr->dummy_tx, max_tx,
GFP_KERNEL | GFP_DMA);
if (!tmp)
return -ENOMEM;
- master->dummy_tx = tmp;
+ ctlr->dummy_tx = tmp;
memset(tmp, 0, max_tx);
}
if (max_rx) {
- tmp = krealloc(master->dummy_rx, max_rx,
+ tmp = krealloc(ctlr->dummy_rx, max_rx,
GFP_KERNEL | GFP_DMA);
if (!tmp)
return -ENOMEM;
- master->dummy_rx = tmp;
+ ctlr->dummy_rx = tmp;
}
if (max_tx || max_rx) {
list_for_each_entry(xfer, &msg->transfers,
transfer_list) {
if (!xfer->tx_buf)
- xfer->tx_buf = master->dummy_tx;
+ xfer->tx_buf = ctlr->dummy_tx;
if (!xfer->rx_buf)
- xfer->rx_buf = master->dummy_rx;
+ xfer->rx_buf = ctlr->dummy_rx;
}
}
}
- return __spi_map_msg(master, msg);
+ return __spi_map_msg(ctlr, msg);
}
/*
@@ -1000,14 +999,14 @@ static int spi_map_msg(struct spi_master *master, struct spi_message *msg)
* drivers which implement a transfer_one() operation. It provides
* standard handling of delays and chip select management.
*/
-static int spi_transfer_one_message(struct spi_master *master,
+static int spi_transfer_one_message(struct spi_controller *ctlr,
struct spi_message *msg)
{
struct spi_transfer *xfer;
bool keep_cs = false;
int ret = 0;
unsigned long long ms = 1;
- struct spi_statistics *statm = &master->statistics;
+ struct spi_statistics *statm = &ctlr->statistics;
struct spi_statistics *stats = &msg->spi->statistics;
spi_set_cs(msg->spi, true);
@@ -1018,13 +1017,13 @@ static int spi_transfer_one_message(struct spi_master *master,
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
trace_spi_transfer_start(msg, xfer);
- spi_statistics_add_transfer_stats(statm, xfer, master);
- spi_statistics_add_transfer_stats(stats, xfer, master);
+ spi_statistics_add_transfer_stats(statm, xfer, ctlr);
+ spi_statistics_add_transfer_stats(stats, xfer, ctlr);
if (xfer->tx_buf || xfer->rx_buf) {
- reinit_completion(&master->xfer_completion);
+ reinit_completion(&ctlr->xfer_completion);
- ret = master->transfer_one(master, msg->spi, xfer);
+ ret = ctlr->transfer_one(ctlr, msg->spi, xfer);
if (ret < 0) {
SPI_STATISTICS_INCREMENT_FIELD(statm,
errors);
@@ -1044,7 +1043,7 @@ static int spi_transfer_one_message(struct spi_master *master,
if (ms > UINT_MAX)
ms = UINT_MAX;
- ms = wait_for_completion_timeout(&master->xfer_completion,
+ ms = wait_for_completion_timeout(&ctlr->xfer_completion,
msecs_to_jiffies(ms));
}
@@ -1099,33 +1098,33 @@ out:
if (msg->status == -EINPROGRESS)
msg->status = ret;
- if (msg->status && master->handle_err)
- master->handle_err(master, msg);
+ if (msg->status && ctlr->handle_err)
+ ctlr->handle_err(ctlr, msg);
- spi_res_release(master, msg);
+ spi_res_release(ctlr, msg);
- spi_finalize_current_message(master);
+ spi_finalize_current_message(ctlr);
return ret;
}
/**
* spi_finalize_current_transfer - report completion of a transfer
- * @master: the master reporting completion
+ * @ctlr: the controller reporting completion
*
* Called by SPI drivers using the core transfer_one_message()
* implementation to notify it that the current interrupt driven
* transfer has finished and the next one may be scheduled.
*/
-void spi_finalize_current_transfer(struct spi_master *master)
+void spi_finalize_current_transfer(struct spi_controller *ctlr)
{
- complete(&master->xfer_completion);
+ complete(&ctlr->xfer_completion);
}
EXPORT_SYMBOL_GPL(spi_finalize_current_transfer);
/**
* __spi_pump_messages - function which processes spi message queue
- * @master: master to process queue for
+ * @ctlr: controller to process queue for
* @in_kthread: true if we are in the context of the message pump thread
*
* This function checks if there is any spi message in the queue that