summaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi.c')
-rw-r--r--drivers/spi/spi.c136
1 files changed, 114 insertions, 22 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index a5f53de813d3..e2415be209d5 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -123,6 +123,28 @@ SPI_STATISTICS_SHOW(bytes, "%llu");
SPI_STATISTICS_SHOW(bytes_rx, "%llu");
SPI_STATISTICS_SHOW(bytes_tx, "%llu");
+#define SPI_STATISTICS_TRANSFER_BYTES_HISTO(index, number) \
+ SPI_STATISTICS_SHOW_NAME(transfer_bytes_histo##index, \
+ "transfer_bytes_histo_" number, \
+ transfer_bytes_histo[index], "%lu")
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(0, "0-1");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(1, "2-3");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(2, "4-7");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(3, "8-15");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(4, "16-31");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(5, "32-63");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(6, "64-127");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(7, "128-255");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(8, "256-511");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(9, "512-1023");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(10, "1024-2047");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(11, "2048-4095");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(12, "4096-8191");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(13, "8192-16383");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(14, "16384-32767");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(15, "32768-65535");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(16, "65536+");
+
static struct attribute *spi_dev_attrs[] = {
&dev_attr_modalias.attr,
NULL,
@@ -143,6 +165,23 @@ static struct attribute *spi_device_statistics_attrs[] = {
&dev_attr_spi_device_bytes.attr,
&dev_attr_spi_device_bytes_rx.attr,
&dev_attr_spi_device_bytes_tx.attr,
+ &dev_attr_spi_device_transfer_bytes_histo0.attr,
+ &dev_attr_spi_device_transfer_bytes_histo1.attr,
+ &dev_attr_spi_device_transfer_bytes_histo2.attr,
+ &dev_attr_spi_device_transfer_bytes_histo3.attr,
+ &dev_attr_spi_device_transfer_bytes_histo4.attr,
+ &dev_attr_spi_device_transfer_bytes_histo5.attr,
+ &dev_attr_spi_device_transfer_bytes_histo6.attr,
+ &dev_attr_spi_device_transfer_bytes_histo7.attr,
+ &dev_attr_spi_device_transfer_bytes_histo8.attr,
+ &dev_attr_spi_device_transfer_bytes_histo9.attr,
+ &dev_attr_spi_device_transfer_bytes_histo10.attr,
+ &dev_attr_spi_device_transfer_bytes_histo11.attr,
+ &dev_attr_spi_device_transfer_bytes_histo12.attr,
+ &dev_attr_spi_device_transfer_bytes_histo13.attr,
+ &dev_attr_spi_device_transfer_bytes_histo14.attr,
+ &dev_attr_spi_device_transfer_bytes_histo15.attr,
+ &dev_attr_spi_device_transfer_bytes_histo16.attr,
NULL,
};
@@ -168,6 +207,23 @@ static struct attribute *spi_master_statistics_attrs[] = {
&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,
NULL,
};
@@ -186,10 +242,15 @@ void spi_statistics_add_transfer_stats(struct spi_statistics *stats,
struct spi_master *master)
{
unsigned long flags;
+ int l2len = min(fls(xfer->len), SPI_STATISTICS_HISTO_SIZE) - 1;
+
+ if (l2len < 0)
+ l2len = 0;
spin_lock_irqsave(&stats->lock, flags);
stats->transfers++;
+ stats->transfer_bytes_histo[l2len]++;
stats->bytes += xfer->len;
if ((xfer->tx_buf) &&
@@ -270,15 +331,24 @@ 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;
ret = of_clk_set_defaults(dev->of_node, false);
if (ret)
return ret;
+ if (dev->of_node) {
+ spi->irq = of_irq_get(dev->of_node, 0);
+ if (spi->irq == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ if (spi->irq < 0)
+ spi->irq = 0;
+ }
+
ret = dev_pm_domain_attach(dev, true);
if (ret != -EPROBE_DEFER) {
- ret = sdrv->probe(to_spi_device(dev));
+ ret = sdrv->probe(spi);
if (ret)
dev_pm_domain_detach(dev, true);
}
@@ -305,12 +375,15 @@ static void spi_drv_shutdown(struct device *dev)
}
/**
- * spi_register_driver - register a SPI driver
+ * __spi_register_driver - register a SPI driver
* @sdrv: the driver to register
* Context: can sleep
+ *
+ * Return: zero on success, else a negative error code.
*/
-int spi_register_driver(struct spi_driver *sdrv)
+int __spi_register_driver(struct module *owner, struct spi_driver *sdrv)
{
+ sdrv->driver.owner = owner;
sdrv->driver.bus = &spi_bus_type;
if (sdrv->probe)
sdrv->driver.probe = spi_drv_probe;
@@ -320,7 +393,7 @@ int spi_register_driver(struct spi_driver *sdrv)
sdrv->driver.shutdown = spi_drv_shutdown;
return driver_register(&sdrv->driver);
}
-EXPORT_SYMBOL_GPL(spi_register_driver);
+EXPORT_SYMBOL_GPL(__spi_register_driver);
/*-------------------------------------------------------------------------*/
@@ -359,7 +432,7 @@ static DEFINE_MUTEX(board_lock);
* needs to discard the spi_device without adding it, then it should
* call spi_dev_put() on it.
*
- * Returns a pointer to the new device, or NULL.
+ * Return: a pointer to the new device, or NULL.
*/
struct spi_device *spi_alloc_device(struct spi_master *master)
{
@@ -418,7 +491,7 @@ static int spi_dev_check(struct device *dev, void *data)
* Companion function to spi_alloc_device. Devices allocated with
* spi_alloc_device can be added onto the spi bus with this function.
*
- * Returns 0 on success; negative errno on failure
+ * Return: 0 on success; negative errno on failure
*/
int spi_add_device(struct spi_device *spi)
{
@@ -491,7 +564,7 @@ EXPORT_SYMBOL_GPL(spi_add_device);
* 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).
*
- * Returns the new device, or NULL.
+ * Return: the new device, or NULL.
*/
struct spi_device *spi_new_device(struct spi_master *master,
struct spi_board_info *chip)
@@ -563,6 +636,8 @@ static void spi_match_master_to_boardinfo(struct spi_master *master,
*
* The board info passed can safely be __initdata ... but be careful of
* any embedded pointers (platform_data, etc), they're copied as-is.
+ *
+ * Return: zero on success, else a negative error code.
*/
int spi_register_board_info(struct spi_board_info const *info, unsigned n)
{
@@ -597,7 +672,7 @@ static void spi_set_cs(struct spi_device *spi, bool enable)
if (spi->mode & SPI_CS_HIGH)
enable = !enable;
- if (spi->cs_gpio >= 0)
+ if (gpio_is_valid(spi->cs_gpio))
gpio_set_value(spi->cs_gpio, !enable);
else if (spi->master->set_cs)
spi->master->set_cs(spi, !enable);
@@ -1140,6 +1215,8 @@ static int spi_init_queue(struct spi_master *master)
*
* If there are more messages in the queue, the next message is returned from
* this call.
+ *
+ * Return: the next message in the queue, else NULL if the queue is empty.
*/
struct spi_message *spi_get_next_queued_message(struct spi_master *master)
{
@@ -1303,6 +1380,8 @@ static int __spi_queued_transfer(struct spi_device *spi,
* spi_queued_transfer - transfer function for queued transfers
* @spi: spi device which is requesting transfer
* @msg: spi message which is to handled is queued to driver queue
+ *
+ * Return: zero on success, else a negative error code.
*/
static int spi_queued_transfer(struct spi_device *spi, struct spi_message *msg)
{
@@ -1433,9 +1512,6 @@ of_register_spi_device(struct spi_master *master, struct device_node *nc)
}
spi->max_speed_hz = value;
- /* IRQ */
- spi->irq = irq_of_parse_and_map(nc, 0);
-
/* Store a pointer to the node in the device structure */
of_node_get(nc);
spi->dev.of_node = nc;
@@ -1605,12 +1681,13 @@ static struct class spi_master_class = {
* only ones directly touching chip registers. It's how they allocate
* an spi_master structure, prior to calling spi_register_master().
*
- * This must be called from context that can sleep. It returns the SPI
- * master structure on success, else NULL.
+ * This must be called from context that can sleep.
*
* The caller is responsible for assigning the bus number and initializing
* the master's methods before calling spi_register_master(); and (after errors
* adding the device) calling spi_master_put() to prevent a memory leak.
+ *
+ * Return: the SPI master structure on success, else NULL.
*/
struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
{
@@ -1694,6 +1771,8 @@ static int of_spi_register_master(struct spi_master *master)
* success, else a negative error code (dropping the master's refcount).
* After a successful return, the caller is responsible for calling
* spi_unregister_master().
+ *
+ * Return: zero on success, else a negative error code.
*/
int spi_register_master(struct spi_master *master)
{
@@ -1787,6 +1866,8 @@ static void devm_spi_unregister(struct device *dev, void *res)
*
* Register a SPI device as with spi_register_master() which will
* automatically be unregister
+ *
+ * Return: zero on success, else a negative error code.
*/
int devm_spi_register_master(struct device *dev, struct spi_master *master)
{
@@ -1892,6 +1973,8 @@ static int __spi_master_match(struct device *dev, const void *data)
* 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.
+ *
+ * Return: the SPI master structure on success, else NULL.
*/
struct spi_master *spi_busnum_to_master(u16 bus_num)
{
@@ -1945,11 +2028,13 @@ static int __spi_validate_bits_per_word(struct spi_master *master, u8 bits_per_w
* that the underlying controller or its driver does not support. For
* example, not all hardware supports wire transfers using nine bit words,
* LSB-first wire encoding, or active-high chipselects.
+ *
+ * Return: zero on success, else a negative error code.
*/
int spi_setup(struct spi_device *spi)
{
unsigned bad_bits, ugly_bits;
- int status = 0;
+ int status;
/* check mode to prevent that DUAL and QUAD set at the same time
*/
@@ -1986,17 +2071,18 @@ int spi_setup(struct spi_device *spi)
if (!spi->bits_per_word)
spi->bits_per_word = 8;
- if (__spi_validate_bits_per_word(spi->master, spi->bits_per_word))
- return -EINVAL;
+ status = __spi_validate_bits_per_word(spi->master, spi->bits_per_word);
+ if (status)
+ return status;
if (!spi->max_speed_hz)
spi->max_speed_hz = spi->master->max_speed_hz;
- spi_set_cs(spi, false);
-
if (spi->master->setup)
status = spi->master->setup(spi);
+ spi_set_cs(spi, false);
+
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, " : "",
@@ -2162,6 +2248,8 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
* 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.)
+ *
+ * Return: zero on success, else a negative error code.
*/
int spi_async(struct spi_device *spi, struct spi_message *message)
{
@@ -2214,6 +2302,8 @@ EXPORT_SYMBOL_GPL(spi_async);
* 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.)
+ *
+ * Return: zero on success, else a negative error code.
*/
int spi_async_locked(struct spi_device *spi, struct spi_message *message)
{
@@ -2329,7 +2419,7 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message,
* Also, the caller is guaranteeing that the memory associated with the
* message will not be freed before this call returns.
*
- * It returns zero on success, else a negative error code.
+ * Return: zero on success, else a negative error code.
*/
int spi_sync(struct spi_device *spi, struct spi_message *message)
{
@@ -2351,7 +2441,7 @@ EXPORT_SYMBOL_GPL(spi_sync);
* SPI bus. It has to be preceded by a spi_bus_lock call. The SPI bus must
* be released by a spi_bus_unlock call when the exclusive access is over.
*
- * It returns zero on success, else a negative error code.
+ * Return: zero on success, else a negative error code.
*/
int spi_sync_locked(struct spi_device *spi, struct spi_message *message)
{
@@ -2372,7 +2462,7 @@ EXPORT_SYMBOL_GPL(spi_sync_locked);
* exclusive access is over. Data transfer must be done by spi_sync_locked
* and spi_async_locked calls when the SPI bus lock is held.
*
- * It returns zero on success, else a negative error code.
+ * Return: always zero.
*/
int spi_bus_lock(struct spi_master *master)
{
@@ -2401,7 +2491,7 @@ EXPORT_SYMBOL_GPL(spi_bus_lock);
* This call releases an SPI bus lock previously obtained by an spi_bus_lock
* call.
*
- * It returns zero on success, else a negative error code.
+ * Return: always zero.
*/
int spi_bus_unlock(struct spi_master *master)
{
@@ -2436,6 +2526,8 @@ static u8 *buf;
* portable code should never use this for more than 32 bytes.
* Performance-sensitive or bulk transfer code should instead use
* spi_{async,sync}() calls with dma-safe buffers.
+ *
+ * Return: zero on success, else a negative error code.
*/
int spi_write_then_read(struct spi_device *spi,
const void *txbuf, unsigned n_tx,
OpenPOWER on IntegriCloud