From b3e7766bc459af941c311a3cb03f2082b2fe60ba Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Sun, 8 Feb 2015 10:11:05 -0500 Subject: [PATCH 01/13] spi: bcm53xx: use msecs_to_jiffies for conversion Converting milliseconds to jiffies by "val * HZ / 1000" is technically ok but msecs_to_jiffies(val) is the cleaner solution and handles all corner cases correctly. This is only an API consolidation and should make things more readable Signed-off-by: Nicholas Mc Guire Signed-off-by: Mark Brown --- drivers/spi/spi-bcm53xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-bcm53xx.c b/drivers/spi/spi-bcm53xx.c index 17b34cbadc03..1933ef332bbb 100644 --- a/drivers/spi/spi-bcm53xx.c +++ b/drivers/spi/spi-bcm53xx.c @@ -44,7 +44,7 @@ static int bcm53xxspi_wait(struct bcm53xxspi *b53spi, unsigned int timeout_ms) u32 tmp; /* SPE bit has to be 0 before we read MSPI STATUS */ - deadline = jiffies + BCM53XXSPI_SPE_TIMEOUT_MS * HZ / 1000; + deadline = jiffies + msecs_to_jiffies(BCM53XXSPI_SPE_TIMEOUT_MS); do { tmp = bcm53xxspi_read(b53spi, B53SPI_MSPI_SPCR2); if (!(tmp & B53SPI_MSPI_SPCR2_SPE)) @@ -56,7 +56,7 @@ static int bcm53xxspi_wait(struct bcm53xxspi *b53spi, unsigned int timeout_ms) goto spi_timeout; /* Check status */ - deadline = jiffies + timeout_ms * HZ / 1000; + deadline = jiffies + msecs_to_jiffies(timeout_ms); do { tmp = bcm53xxspi_read(b53spi, B53SPI_MSPI_MSPI_STATUS); if (tmp & B53SPI_MSPI_MSPI_STATUS_SPIF) { From b716c4ffc6a2b0bfbcf9619880f335be11b65708 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 27 Feb 2015 17:34:15 +0200 Subject: [PATCH 02/13] spi: introduce master->handle_err() callback This callback would be useful to handle an error that occurs in the generic implementation of transfer_one_message(). The good candidate for this is to drain FIFO and / or to terminate DMA transfers when timeout happened. Signed-off-by: Andy Shevchenko Signed-off-by: Mark Brown --- drivers/spi/spi.c | 3 +++ include/linux/spi/spi.h | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index c64a3e59fce3..31d4d9d997e2 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -851,6 +851,9 @@ out: if (msg->status == -EINPROGRESS) msg->status = ret; + if (msg->status) + master->handle_err(master, msg); + spi_finalize_current_message(master); return ret; diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index ed9489d893a4..4eaac3a5227b 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -294,6 +294,8 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) * transfer_one_message are mutually exclusive; when both * are set, the generic subsystem does not call your * transfer_one callback. + * @handle_err: the subsystem calls the driver to handle and error that occurs + * in the generic implementation of transfer_one_message(). * @unprepare_message: undo any work done by prepare_message(). * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS * number. Any individual value may be -ENOENT for CS lines that @@ -448,6 +450,8 @@ struct spi_master { void (*set_cs)(struct spi_device *spi, bool enable); int (*transfer_one)(struct spi_master *master, struct spi_device *spi, struct spi_transfer *transfer); + void (*handle_err)(struct spi_master *master, + struct spi_message *message); /* gpio chip select */ int *cs_gpios; From 342f948a166c2a17b0e187e3fc2618dc561842f3 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Fri, 20 Mar 2015 15:26:11 +0100 Subject: [PATCH 03/13] spi: bcm2835: fix all checkpath --strict messages The following errors/warnings issued by checkpatch.pl --strict have been fixed: drivers/spi/spi-bcm2835.c:182: CHECK: Alignment should match open parenthesis drivers/spi/spi-bcm2835.c:191: CHECK: braces {} should be used on all arms of this statement drivers/spi/spi-bcm2835.c:234: CHECK: Alignment should match open parenthesis drivers/spi/spi-bcm2835.c:256: CHECK: Alignment should match open parenthesis drivers/spi/spi-bcm2835.c:271: CHECK: Alignment should match open parenthesis drivers/spi/spi-bcm2835.c:346: CHECK: Alignment should match open parenthesis total: 0 errors, 0 warnings, 6 checks, 403 lines checked In 2 locations the arguments had to get split/moved to the next line so that the line width stays below 80 chars. Signed-off-by: Martin Sperl Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 419a782ab6d5..779d3a86c3cb 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -179,7 +179,7 @@ static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id) } static int bcm2835_spi_start_transfer(struct spi_device *spi, - struct spi_transfer *tfr) + struct spi_transfer *tfr) { struct bcm2835_spi *bs = spi_master_get_devdata(spi->master); unsigned long spi_hz, clk_hz, cdiv; @@ -196,8 +196,9 @@ static int bcm2835_spi_start_transfer(struct spi_device *spi, if (cdiv >= 65536) cdiv = 0; /* 0 is the slowest we can go */ - } else + } else { cdiv = 0; /* 0 is the slowest we can go */ + } if (spi->mode & SPI_CPOL) cs |= BCM2835_SPI_CS_CPOL; @@ -231,7 +232,8 @@ static int bcm2835_spi_start_transfer(struct spi_device *spi, } static int bcm2835_spi_finish_transfer(struct spi_device *spi, - struct spi_transfer *tfr, bool cs_change) + struct spi_transfer *tfr, + bool cs_change) { struct bcm2835_spi *bs = spi_master_get_devdata(spi->master); u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); @@ -253,7 +255,7 @@ static int bcm2835_spi_finish_transfer(struct spi_device *spi, } static int bcm2835_spi_transfer_one(struct spi_master *master, - struct spi_message *mesg) + struct spi_message *mesg) { struct bcm2835_spi *bs = spi_master_get_devdata(master); struct spi_transfer *tfr; @@ -267,8 +269,10 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, if (err) goto out; - timeout = wait_for_completion_timeout(&bs->done, - msecs_to_jiffies(BCM2835_SPI_TIMEOUT_MS)); + timeout = wait_for_completion_timeout( + &bs->done, + msecs_to_jiffies(BCM2835_SPI_TIMEOUT_MS) + ); if (!timeout) { err = -ETIMEDOUT; goto out; @@ -343,7 +347,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev) clk_prepare_enable(bs->clk); err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt, 0, - dev_name(&pdev->dev), master); + dev_name(&pdev->dev), master); if (err) { dev_err(&pdev->dev, "could not request IRQ: %d\n", err); goto out_clk_disable; From ea467326e36b496a92c677cbbed1dfd03b707aaf Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 18 Mar 2015 15:53:08 +0000 Subject: [PATCH 04/13] spi: atmel: use endian agnostic IO Use the endian agnositc IO functions instead of the __raw ones for when the driver is in use on big-endian systems. Signed-off-by: Ben Dooks Acked-by: Nicolas Ferre Signed-off-by: Mark Brown --- drivers/spi/spi-atmel.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 9af7841f2e8c..75757aa531f2 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -180,11 +180,17 @@ | SPI_BF(name, value)) /* Register access macros */ +#ifdef CONFIG_AVR32 #define spi_readl(port, reg) \ __raw_readl((port)->regs + SPI_##reg) #define spi_writel(port, reg, value) \ __raw_writel((value), (port)->regs + SPI_##reg) - +#else +#define spi_readl(port, reg) \ + readl_relaxed((port)->regs + SPI_##reg) +#define spi_writel(port, reg, value) \ + writel_relaxed((value), (port)->regs + SPI_##reg) +#endif /* use PIO for small transfers, avoiding DMA setup/teardown overhead and * cache operations; better heuristics consider wordsize and bitrate. */ From 4adf312976ef2b72830b83f212fef3f6a36513a6 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Mon, 23 Mar 2015 15:11:53 +0100 Subject: [PATCH 05/13] spi: bcm2835: fill/drain SPI-fifo as much as possible during interrupt Implement the recommendation from the BCM2835 data-sheet with regards to polling drivers to fill/drain the FIFO as much data as possible also for the interrupt-driven case (which this driver is making use of). This means that for long transfers (>64bytes) we need one interrupt every 64 bytes instead of every 12 bytes, as the FIFO is 16 words (not bytes) wide. Tested with mcp251x (can bus), fb_st7735 (TFT framebuffer device) and enc28j60 (ethernet) drivers. Signed-off-by: Martin Sperl Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835.c | 78 +++++++++------------------------------ 1 file changed, 17 insertions(+), 61 deletions(-) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 779d3a86c3cb..960dcce607c2 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -91,25 +91,23 @@ static inline void bcm2835_wr(struct bcm2835_spi *bs, unsigned reg, u32 val) writel(val, bs->regs + reg); } -static inline void bcm2835_rd_fifo(struct bcm2835_spi *bs, int len) +static inline void bcm2835_rd_fifo(struct bcm2835_spi *bs) { u8 byte; - while (len--) { + while (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_RXD) { byte = bcm2835_rd(bs, BCM2835_SPI_FIFO); if (bs->rx_buf) *bs->rx_buf++ = byte; } } -static inline void bcm2835_wr_fifo(struct bcm2835_spi *bs, int len) +static inline void bcm2835_wr_fifo(struct bcm2835_spi *bs) { u8 byte; - if (len > bs->len) - len = bs->len; - - while (len--) { + while ((bs->len) && + (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_TXD)) { byte = bs->tx_buf ? *bs->tx_buf++ : 0; bcm2835_wr(bs, BCM2835_SPI_FIFO, byte); bs->len--; @@ -122,60 +120,24 @@ static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id) struct bcm2835_spi *bs = spi_master_get_devdata(master); u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); - /* - * RXR - RX needs Reading. This means 12 (or more) bytes have been - * transmitted and hence 12 (or more) bytes have been received. - * - * The FIFO is 16-bytes deep. We check for this interrupt to keep the - * FIFO full; we have a 4-byte-time buffer for IRQ latency. We check - * this before DONE (TX empty) just in case we delayed processing this - * interrupt for some reason. - * - * We only check for this case if we have more bytes to TX; at the end - * of the transfer, we ignore this pipelining optimization, and let - * bcm2835_spi_finish_transfer() drain the RX FIFO. - */ - if (bs->len && (cs & BCM2835_SPI_CS_RXR)) { - /* Read 12 bytes of data */ - bcm2835_rd_fifo(bs, 12); + /* Read as many bytes as possible from FIFO */ + bcm2835_rd_fifo(bs); - /* Write up to 12 bytes */ - bcm2835_wr_fifo(bs, 12); + if (bs->len) { /* there is more data to transmit */ + bcm2835_wr_fifo(bs); + } else { /* Transfer complete */ + /* Disable SPI interrupts */ + cs &= ~(BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD); + bcm2835_wr(bs, BCM2835_SPI_CS, cs); /* - * We must have written something to the TX FIFO due to the - * bs->len check above, so cannot be DONE. Hence, return - * early. Note that DONE could also be set if we serviced an - * RXR interrupt really late. + * Wake up bcm2835_spi_transfer_one(), which will call + * bcm2835_spi_finish_transfer(), to drain the RX FIFO. */ - return IRQ_HANDLED; + complete(&bs->done); } - /* - * DONE - TX empty. This occurs when we first enable the transfer - * since we do not pre-fill the TX FIFO. At any other time, given that - * we refill the TX FIFO above based on RXR, and hence ignore DONE if - * RXR is set, DONE really does mean end-of-transfer. - */ - if (cs & BCM2835_SPI_CS_DONE) { - if (bs->len) { /* First interrupt in a transfer */ - bcm2835_wr_fifo(bs, 16); - } else { /* Transfer complete */ - /* Disable SPI interrupts */ - cs &= ~(BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD); - bcm2835_wr(bs, BCM2835_SPI_CS, cs); - - /* - * Wake up bcm2835_spi_transfer_one(), which will call - * bcm2835_spi_finish_transfer(), to drain the RX FIFO. - */ - complete(&bs->done); - } - - return IRQ_HANDLED; - } - - return IRQ_NONE; + return IRQ_HANDLED; } static int bcm2835_spi_start_transfer(struct spi_device *spi, @@ -238,12 +200,6 @@ static int bcm2835_spi_finish_transfer(struct spi_device *spi, struct bcm2835_spi *bs = spi_master_get_devdata(spi->master); u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); - /* Drain RX FIFO */ - while (cs & BCM2835_SPI_CS_RXD) { - bcm2835_rd_fifo(bs, 1); - cs = bcm2835_rd(bs, BCM2835_SPI_CS); - } - if (tfr->delay_usecs) udelay(tfr->delay_usecs); From 210b49231af6a3ede5de3c90850dbf1134a855c2 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Thu, 19 Mar 2015 09:01:52 +0000 Subject: [PATCH 06/13] spi: bcm2835: clock divider can be a multiple of 2 The official documentation is wrong in this respect. Has been tested empirically for dividers 2-1024 Signed-off-by: Martin Sperl Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 960dcce607c2..8de1925fe554 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -153,8 +153,9 @@ static int bcm2835_spi_start_transfer(struct spi_device *spi, if (spi_hz >= clk_hz / 2) { cdiv = 2; /* clk_hz/2 is the fastest we can go */ } else if (spi_hz) { - /* CDIV must be a power of two */ - cdiv = roundup_pow_of_two(DIV_ROUND_UP(clk_hz, spi_hz)); + /* CDIV must be a multiple of two */ + cdiv = DIV_ROUND_UP(clk_hz, spi_hz); + cdiv += (cdiv % 2); if (cdiv >= 65536) cdiv = 0; /* 0 is the slowest we can go */ From 6935224da2482a261c786501fbccb1dc4a675225 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Thu, 19 Mar 2015 09:01:53 +0000 Subject: [PATCH 07/13] spi: bcm2835: enable support of 3-wire mode Signed-off-by: Martin Sperl Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 8de1925fe554..3f93718aad3f 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -67,7 +67,8 @@ #define BCM2835_SPI_CS_CS_01 0x00000001 #define BCM2835_SPI_TIMEOUT_MS 30000 -#define BCM2835_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS) +#define BCM2835_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \ + | SPI_NO_CS | SPI_3WIRE) #define DRV_NAME "spi-bcm2835" @@ -163,6 +164,9 @@ static int bcm2835_spi_start_transfer(struct spi_device *spi, cdiv = 0; /* 0 is the slowest we can go */ } + if ((spi->mode & SPI_3WIRE) && (tfr->rx_buf)) + cs |= BCM2835_SPI_CS_REN; + if (spi->mode & SPI_CPOL) cs |= BCM2835_SPI_CS_CPOL; if (spi->mode & SPI_CPHA) From e34ff011c70e5f4ef219141711142d5111ae6ebb Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Thu, 26 Mar 2015 11:08:36 +0100 Subject: [PATCH 08/13] spi: bcm2835: move to the transfer_one driver model This also allows for GPIO-CS to get used removing the limitation of 2/3 SPI devises on the SPI bus. Fixes: spi-cs-high with native CS with multiple devices on the spi-bus resetting the chip selects to "normal" polarity after a finished transfer. No other functionality/improvements added. Tested with the following 4 devices on the spi-bus: * mcp2515 with native CS * mcp2515 with gpio CS * fb_st7735r with native CS (plus spi-cs-high via transistor inverting polarity) * enc28j60 with gpio-CS Tested-by: Martin Sperl Signed-off-by: Martin Sperl Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835.c | 212 ++++++++++++++++++++++---------------- 1 file changed, 124 insertions(+), 88 deletions(-) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 3f93718aad3f..0dbe544e8be4 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -3,6 +3,7 @@ * * Copyright (C) 2012 Chris Boot * Copyright (C) 2013 Stephen Warren + * Copyright (C) 2015 Martin Sperl * * This driver is inspired by: * spi-ath79.c, Copyright (C) 2009-2011 Gabor Juhos @@ -29,6 +30,7 @@ #include #include #include +#include #include #include @@ -76,10 +78,10 @@ struct bcm2835_spi { void __iomem *regs; struct clk *clk; int irq; - struct completion done; const u8 *tx_buf; u8 *rx_buf; - int len; + int tx_len; + int rx_len; }; static inline u32 bcm2835_rd(struct bcm2835_spi *bs, unsigned reg) @@ -96,10 +98,12 @@ static inline void bcm2835_rd_fifo(struct bcm2835_spi *bs) { u8 byte; - while (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_RXD) { + while ((bs->rx_len) && + (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_RXD)) { byte = bcm2835_rd(bs, BCM2835_SPI_FIFO); if (bs->rx_buf) *bs->rx_buf++ = byte; + bs->rx_len--; } } @@ -107,47 +111,60 @@ static inline void bcm2835_wr_fifo(struct bcm2835_spi *bs) { u8 byte; - while ((bs->len) && + while ((bs->tx_len) && (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_TXD)) { byte = bs->tx_buf ? *bs->tx_buf++ : 0; bcm2835_wr(bs, BCM2835_SPI_FIFO, byte); - bs->len--; + bs->tx_len--; } } +static void bcm2835_spi_reset_hw(struct spi_master *master) +{ + struct bcm2835_spi *bs = spi_master_get_devdata(master); + u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); + + /* Disable SPI interrupts and transfer */ + cs &= ~(BCM2835_SPI_CS_INTR | + BCM2835_SPI_CS_INTD | + BCM2835_SPI_CS_TA); + /* and reset RX/TX FIFOS */ + cs |= BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX; + + /* and reset the SPI_HW */ + bcm2835_wr(bs, BCM2835_SPI_CS, cs); +} + static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id) { struct spi_master *master = dev_id; struct bcm2835_spi *bs = spi_master_get_devdata(master); - u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); /* Read as many bytes as possible from FIFO */ bcm2835_rd_fifo(bs); + /* Write as many bytes as possible to FIFO */ + bcm2835_wr_fifo(bs); - if (bs->len) { /* there is more data to transmit */ - bcm2835_wr_fifo(bs); - } else { /* Transfer complete */ - /* Disable SPI interrupts */ - cs &= ~(BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD); - bcm2835_wr(bs, BCM2835_SPI_CS, cs); - - /* - * Wake up bcm2835_spi_transfer_one(), which will call - * bcm2835_spi_finish_transfer(), to drain the RX FIFO. - */ - complete(&bs->done); + /* based on flags decide if we can finish the transfer */ + if (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_DONE) { + /* Transfer complete - reset SPI HW */ + bcm2835_spi_reset_hw(master); + /* wake up the framework */ + complete(&master->xfer_completion); } return IRQ_HANDLED; } -static int bcm2835_spi_start_transfer(struct spi_device *spi, - struct spi_transfer *tfr) +static int bcm2835_spi_transfer_one(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *tfr) { - struct bcm2835_spi *bs = spi_master_get_devdata(spi->master); + struct bcm2835_spi *bs = spi_master_get_devdata(master); unsigned long spi_hz, clk_hz, cdiv; - u32 cs = BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD | BCM2835_SPI_CS_TA; + u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); + /* set clock */ spi_hz = tfr->speed_hz; clk_hz = clk_get_rate(bs->clk); @@ -163,100 +180,118 @@ static int bcm2835_spi_start_transfer(struct spi_device *spi, } else { cdiv = 0; /* 0 is the slowest we can go */ } + bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv); + /* handle all the modes */ if ((spi->mode & SPI_3WIRE) && (tfr->rx_buf)) cs |= BCM2835_SPI_CS_REN; - if (spi->mode & SPI_CPOL) cs |= BCM2835_SPI_CS_CPOL; if (spi->mode & SPI_CPHA) cs |= BCM2835_SPI_CS_CPHA; - if (!(spi->mode & SPI_NO_CS)) { - if (spi->mode & SPI_CS_HIGH) { - cs |= BCM2835_SPI_CS_CSPOL; - cs |= BCM2835_SPI_CS_CSPOL0 << spi->chip_select; - } + /* for gpio_cs set dummy CS so that no HW-CS get changed + * we can not run this in bcm2835_spi_set_cs, as it does + * not get called for cs_gpio cases, so we need to do it here + */ + if (gpio_is_valid(spi->cs_gpio) || (spi->mode & SPI_NO_CS)) + cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01; - cs |= spi->chip_select; - } - - reinit_completion(&bs->done); + /* set transmit buffers and length */ bs->tx_buf = tfr->tx_buf; bs->rx_buf = tfr->rx_buf; - bs->len = tfr->len; + bs->tx_len = tfr->len; + bs->rx_len = tfr->len; - bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv); /* * Enable the HW block. This will immediately trigger a DONE (TX * empty) interrupt, upon which we will fill the TX FIFO with the * first TX bytes. Pre-filling the TX FIFO here to avoid the * interrupt doesn't work:-( */ + cs |= BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD | BCM2835_SPI_CS_TA; bcm2835_wr(bs, BCM2835_SPI_CS, cs); - return 0; + /* signal that we need to wait for completion */ + return 1; } -static int bcm2835_spi_finish_transfer(struct spi_device *spi, - struct spi_transfer *tfr, - bool cs_change) +static void bcm2835_spi_handle_err(struct spi_master *master, + struct spi_message *msg) { - struct bcm2835_spi *bs = spi_master_get_devdata(spi->master); - u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); - - if (tfr->delay_usecs) - udelay(tfr->delay_usecs); - - if (cs_change) - /* Clear TA flag */ - bcm2835_wr(bs, BCM2835_SPI_CS, cs & ~BCM2835_SPI_CS_TA); - - return 0; + bcm2835_spi_reset_hw(master); } -static int bcm2835_spi_transfer_one(struct spi_master *master, - struct spi_message *mesg) +static void bcm2835_spi_set_cs(struct spi_device *spi, bool gpio_level) { + /* + * we can assume that we are "native" as per spi_set_cs + * calling us ONLY when cs_gpio is not set + * we can also assume that we are CS < 3 as per bcm2835_spi_setup + * we would not get called because of error handling there. + * the level passed is the electrical level not enabled/disabled + * so it has to get translated back to enable/disable + * see spi_set_cs in spi.c for the implementation + */ + + struct spi_master *master = spi->master; struct bcm2835_spi *bs = spi_master_get_devdata(master); - struct spi_transfer *tfr; - struct spi_device *spi = mesg->spi; - int err = 0; - unsigned int timeout; - bool cs_change; + u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); + bool enable; - list_for_each_entry(tfr, &mesg->transfers, transfer_list) { - err = bcm2835_spi_start_transfer(spi, tfr); - if (err) - goto out; + /* calculate the enable flag from the passed gpio_level */ + enable = (spi->mode & SPI_CS_HIGH) ? gpio_level : !gpio_level; - timeout = wait_for_completion_timeout( - &bs->done, - msecs_to_jiffies(BCM2835_SPI_TIMEOUT_MS) - ); - if (!timeout) { - err = -ETIMEDOUT; - goto out; - } - - cs_change = tfr->cs_change || - list_is_last(&tfr->transfer_list, &mesg->transfers); - - err = bcm2835_spi_finish_transfer(spi, tfr, cs_change); - if (err) - goto out; - - mesg->actual_length += (tfr->len - bs->len); + /* set flags for "reverse" polarity in the registers */ + if (spi->mode & SPI_CS_HIGH) { + /* set the correct CS-bits */ + cs |= BCM2835_SPI_CS_CSPOL; + cs |= BCM2835_SPI_CS_CSPOL0 << spi->chip_select; + } else { + /* clean the CS-bits */ + cs &= ~BCM2835_SPI_CS_CSPOL; + cs &= ~(BCM2835_SPI_CS_CSPOL0 << spi->chip_select); } -out: - /* Clear FIFOs, and disable the HW block */ - bcm2835_wr(bs, BCM2835_SPI_CS, - BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX); - mesg->status = err; - spi_finalize_current_message(master); + /* select the correct chip_select depending on disabled/enabled */ + if (enable) { + /* set cs correctly */ + if (spi->mode & SPI_NO_CS) { + /* use the "undefined" chip-select */ + cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01; + } else { + /* set the chip select */ + cs &= ~(BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01); + cs |= spi->chip_select; + } + } else { + /* disable CSPOL which puts HW-CS into deselected state */ + cs &= ~BCM2835_SPI_CS_CSPOL; + /* use the "undefined" chip-select as precaution */ + cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01; + } - return 0; + /* finally set the calculated flags in SPI_CS */ + bcm2835_wr(bs, BCM2835_SPI_CS, cs); +} + +static int bcm2835_spi_setup(struct spi_device *spi) +{ + /* + * sanity checking the native-chipselects + */ + if (spi->mode & SPI_NO_CS) + return 0; + if (gpio_is_valid(spi->cs_gpio)) + return 0; + if (spi->chip_select < 3) + return 0; + + /* error in the case of native CS requested with CS-id > 2 */ + dev_err(&spi->dev, + "setup: only three native chip-selects are supported\n" + ); + return -EINVAL; } static int bcm2835_spi_probe(struct platform_device *pdev) @@ -277,13 +312,14 @@ static int bcm2835_spi_probe(struct platform_device *pdev) master->mode_bits = BCM2835_SPI_MODE_BITS; master->bits_per_word_mask = SPI_BPW_MASK(8); master->num_chipselect = 3; - master->transfer_one_message = bcm2835_spi_transfer_one; + master->setup = bcm2835_spi_setup; + master->set_cs = bcm2835_spi_set_cs; + master->transfer_one = bcm2835_spi_transfer_one; + master->handle_err = bcm2835_spi_handle_err; master->dev.of_node = pdev->dev.of_node; bs = spi_master_get_devdata(master); - init_completion(&bs->done); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); bs->regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(bs->regs)) { @@ -314,7 +350,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev) goto out_clk_disable; } - /* initialise the hardware */ + /* initialise the hardware with the default polarities */ bcm2835_wr(bs, BCM2835_SPI_CS, BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX); From 1e4df62d46fa45109123f2b265b2d8146031db16 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Sun, 29 Mar 2015 16:03:23 +0200 Subject: [PATCH 09/13] spi: bcm2835: fix code formatting issue Signed-off-by: Martin Sperl Tested-by: Martin Sperl Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 0dbe544e8be4..2e6533e34b19 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -289,8 +289,7 @@ static int bcm2835_spi_setup(struct spi_device *spi) /* error in the case of native CS requested with CS-id > 2 */ dev_err(&spi->dev, - "setup: only three native chip-selects are supported\n" - ); + "setup: only three native chip-selects are supported\n"); return -EINVAL; } From e3a2be3030e2fec27a2577d3c52203da090a4366 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Sun, 29 Mar 2015 16:03:25 +0200 Subject: [PATCH 10/13] spi: bcm2835: fill FIFO before enabling interrupts to reduce interrupts/message To reduce the number of interrupts/message we fill the FIFO before enabling interrupts - for short messages this reduces the interrupt count from 2 to 1 interrupt. There have been rare cases where short (<200ns) chip-select switches with native CS have been observed during such operation, this is why this optimization is only enabled for GPIO-CS. Signed-off-by: Martin Sperl Tested-by: Martin Sperl Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 2e6533e34b19..08e5406c5029 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -203,6 +203,22 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, bs->tx_len = tfr->len; bs->rx_len = tfr->len; + /* fill in fifo if we have gpio-cs + * note that there have been rare events where the native-CS + * flapped for <1us which may change the behaviour + * with gpio-cs this does not happen, so it is implemented + * only for this case + */ + if (gpio_is_valid(spi->cs_gpio)) { + /* enable HW block, but without interrupts enabled + * this would triggern an immediate interrupt + */ + bcm2835_wr(bs, BCM2835_SPI_CS, + cs | BCM2835_SPI_CS_TA); + /* fill in tx fifo as much as possible */ + bcm2835_wr_fifo(bs); + } + /* * Enable the HW block. This will immediately trigger a DONE (TX * empty) interrupt, upon which we will fill the TX FIFO with the From 232a5adc5199891efde6c844fd15b8d4d18245e6 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Tue, 31 Mar 2015 16:35:01 +0200 Subject: [PATCH 11/13] spi: bitbang: only toggle bitchanges The current implementation of bitbang_txrx_be_cpha0 and bitbang_txrx_be_cpha1 always call setmosi. That runs into several unnecessary calls into the gpiolib when the level of the GPIO actually has not to be changed. This patch changes the routines to remember the last GPIO level and only calls setmosi if an change has to be made. This way it improves the transfer throughput. Signed-off-by: Michael Grzeschik Signed-off-by: Mark Brown --- drivers/spi/spi-bitbang-txrx.h | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-bitbang-txrx.h b/drivers/spi/spi-bitbang-txrx.h index c616e41521be..06b34e5bcfa3 100644 --- a/drivers/spi/spi-bitbang-txrx.h +++ b/drivers/spi/spi-bitbang-txrx.h @@ -49,12 +49,17 @@ bitbang_txrx_be_cpha0(struct spi_device *spi, { /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */ + bool oldbit = !(word & 1); /* clock starts at inactive polarity */ for (word <<= (32 - bits); likely(bits); bits--) { /* setup MSB (to slave) on trailing edge */ - if ((flags & SPI_MASTER_NO_TX) == 0) - setmosi(spi, word & (1 << 31)); + if ((flags & SPI_MASTER_NO_TX) == 0) { + if ((word & (1 << 31)) != oldbit) { + setmosi(spi, word & (1 << 31)); + oldbit = word & (1 << 31); + } + } spidelay(nsecs); /* T(setup) */ setsck(spi, !cpol); @@ -76,13 +81,18 @@ bitbang_txrx_be_cpha1(struct spi_device *spi, { /* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */ + bool oldbit = !(word & (1 << 31)); /* clock starts at inactive polarity */ for (word <<= (32 - bits); likely(bits); bits--) { /* setup MSB (to slave) on leading edge */ setsck(spi, !cpol); - if ((flags & SPI_MASTER_NO_TX) == 0) - setmosi(spi, word & (1 << 31)); + if ((flags & SPI_MASTER_NO_TX) == 0) { + if ((word & (1 << 31)) != oldbit) { + setmosi(spi, word & (1 << 31)); + oldbit = word & (1 << 31); + } + } spidelay(nsecs); /* T(setup) */ setsck(spi, cpol); From a30a555d7435a440fab06fe5960cf3448d8cedd3 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Mon, 6 Apr 2015 17:16:31 +0000 Subject: [PATCH 12/13] spi: bcm2835: transform native-cs to gpio-cs on first spi_setup Transforms the bcm-2835 native SPI-chip select to their gpio-cs equivalent. This allows for some support of some optimizations that are not possible due to HW-gliches on the CS line - especially filling the FIFO before enabling SPI interrupts (by writing to CS register) while the transfer is already in progress (See commit: e3a2be3030e2) This patch also works arround some issues in bcm2835-pinctrl which does not set the value when setting the GPIO as output - it just sets up output and (typically) leaves the GPIO as low. When a fix for this is merged then this gpio_set_value can get removed from bcm2835_spi_setup. Signed-off-by: Martin Sperl Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835.c | 49 +++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 08e5406c5029..90064494e828 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -291,8 +291,15 @@ static void bcm2835_spi_set_cs(struct spi_device *spi, bool gpio_level) bcm2835_wr(bs, BCM2835_SPI_CS, cs); } +static int chip_match_name(struct gpio_chip *chip, void *data) +{ + return !strcmp(chip->label, data); +} + static int bcm2835_spi_setup(struct spi_device *spi) { + int err; + struct gpio_chip *chip; /* * sanity checking the native-chipselects */ @@ -300,13 +307,45 @@ static int bcm2835_spi_setup(struct spi_device *spi) return 0; if (gpio_is_valid(spi->cs_gpio)) return 0; - if (spi->chip_select < 3) + if (spi->chip_select > 1) { + /* error in the case of native CS requested with CS > 1 + * officially there is a CS2, but it is not documented + * which GPIO is connected with that... + */ + dev_err(&spi->dev, + "setup: only two native chip-selects are supported\n"); + return -EINVAL; + } + /* now translate native cs to GPIO */ + + /* get the gpio chip for the base */ + chip = gpiochip_find("pinctrl-bcm2835", chip_match_name); + if (!chip) return 0; - /* error in the case of native CS requested with CS-id > 2 */ - dev_err(&spi->dev, - "setup: only three native chip-selects are supported\n"); - return -EINVAL; + /* and calculate the real CS */ + spi->cs_gpio = chip->base + 8 - spi->chip_select; + + /* and set up the "mode" and level */ + dev_info(&spi->dev, "setting up native-CS%i as GPIO %i\n", + spi->chip_select, spi->cs_gpio); + + /* set up GPIO as output and pull to the correct level */ + err = gpio_direction_output(spi->cs_gpio, + (spi->mode & SPI_CS_HIGH) ? 0 : 1); + if (err) { + dev_err(&spi->dev, + "could not set CS%i gpio %i as output: %i", + spi->chip_select, spi->cs_gpio, err); + return err; + } + /* the implementation of pinctrl-bcm2835 currently does not + * set the GPIO value when using gpio_direction_output + * so we are setting it here explicitly + */ + gpio_set_value(spi->cs_gpio, (spi->mode & SPI_CS_HIGH) ? 0 : 1); + + return 0; } static int bcm2835_spi_probe(struct platform_device *pdev) From 704f32d48af221fd6d6ffcafe679f04ddcf5e7f6 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Mon, 6 Apr 2015 17:16:30 +0000 Subject: [PATCH 13/13] spi: bcm2835: enabling polling mode for transfers shorter than 30us In cases of short transfer times the CPU is spending lots of time in the interrupt handler and scheduler to reschedule the worker thread. Measurements show that we have times where it takes 29.32us to between the last clock change and the time that the worker-thread is running again returning from wait_for_completion_timeout(). During this time the interrupt-handler is running calling complete() and then also the scheduler is rescheduling the worker thread. This time can vary depending on how much of the code is still in CPU-caches, when there is a burst of spi transfers the subsequent delays are in the order of 25us, so the value of 30us seems reasonable. With polling the whole transfer of 4 bytes at 10MHz finishes after 6.16us (CS down to up) with the real transfer (clock running) taking 3.56us. So the efficiency has much improved and is also freeing CPU cycles, reducing interrupts and context switches. Because of the above 30us seems to be a reasonable limit for polling. Signed-off-by: Martin Sperl Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835.c | 140 +++++++++++++++++++++++++++----------- 1 file changed, 100 insertions(+), 40 deletions(-) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 90064494e828..f63864a893c5 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -68,7 +68,8 @@ #define BCM2835_SPI_CS_CS_10 0x00000002 #define BCM2835_SPI_CS_CS_01 0x00000001 -#define BCM2835_SPI_TIMEOUT_MS 30000 +#define BCM2835_SPI_POLLING_LIMIT_US 30 +#define BCM2835_SPI_TIMEOUT_MS 30000 #define BCM2835_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \ | SPI_NO_CS | SPI_3WIRE) @@ -156,52 +157,49 @@ static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static int bcm2835_spi_transfer_one(struct spi_master *master, - struct spi_device *spi, - struct spi_transfer *tfr) +static int bcm2835_spi_transfer_one_poll(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *tfr, + u32 cs, + unsigned long xfer_time_us) { struct bcm2835_spi *bs = spi_master_get_devdata(master); - unsigned long spi_hz, clk_hz, cdiv; - u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); + unsigned long timeout = jiffies + + max(4 * xfer_time_us * HZ / 1000000, 2uL); - /* set clock */ - spi_hz = tfr->speed_hz; - clk_hz = clk_get_rate(bs->clk); + /* enable HW block without interrupts */ + bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_TA); - if (spi_hz >= clk_hz / 2) { - cdiv = 2; /* clk_hz/2 is the fastest we can go */ - } else if (spi_hz) { - /* CDIV must be a multiple of two */ - cdiv = DIV_ROUND_UP(clk_hz, spi_hz); - cdiv += (cdiv % 2); - - if (cdiv >= 65536) - cdiv = 0; /* 0 is the slowest we can go */ - } else { - cdiv = 0; /* 0 is the slowest we can go */ + /* set timeout to 4x the expected time, or 2 jiffies */ + /* loop until finished the transfer */ + while (bs->rx_len) { + /* read from fifo as much as possible */ + bcm2835_rd_fifo(bs); + /* fill in tx fifo as much as possible */ + bcm2835_wr_fifo(bs); + /* if we still expect some data after the read, + * check for a possible timeout + */ + if (bs->rx_len && time_after(jiffies, timeout)) { + /* Transfer complete - reset SPI HW */ + bcm2835_spi_reset_hw(master); + /* and return timeout */ + return -ETIMEDOUT; + } } - bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv); - /* handle all the modes */ - if ((spi->mode & SPI_3WIRE) && (tfr->rx_buf)) - cs |= BCM2835_SPI_CS_REN; - if (spi->mode & SPI_CPOL) - cs |= BCM2835_SPI_CS_CPOL; - if (spi->mode & SPI_CPHA) - cs |= BCM2835_SPI_CS_CPHA; + /* Transfer complete - reset SPI HW */ + bcm2835_spi_reset_hw(master); + /* and return without waiting for completion */ + return 0; +} - /* for gpio_cs set dummy CS so that no HW-CS get changed - * we can not run this in bcm2835_spi_set_cs, as it does - * not get called for cs_gpio cases, so we need to do it here - */ - if (gpio_is_valid(spi->cs_gpio) || (spi->mode & SPI_NO_CS)) - cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01; - - /* set transmit buffers and length */ - bs->tx_buf = tfr->tx_buf; - bs->rx_buf = tfr->rx_buf; - bs->tx_len = tfr->len; - bs->rx_len = tfr->len; +static int bcm2835_spi_transfer_one_irq(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *tfr, + u32 cs) +{ + struct bcm2835_spi *bs = spi_master_get_devdata(master); /* fill in fifo if we have gpio-cs * note that there have been rare events where the native-CS @@ -232,6 +230,68 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, return 1; } +static int bcm2835_spi_transfer_one(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *tfr) +{ + struct bcm2835_spi *bs = spi_master_get_devdata(master); + unsigned long spi_hz, clk_hz, cdiv; + unsigned long spi_used_hz, xfer_time_us; + u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); + + /* set clock */ + spi_hz = tfr->speed_hz; + clk_hz = clk_get_rate(bs->clk); + + if (spi_hz >= clk_hz / 2) { + cdiv = 2; /* clk_hz/2 is the fastest we can go */ + } else if (spi_hz) { + /* CDIV must be a multiple of two */ + cdiv = DIV_ROUND_UP(clk_hz, spi_hz); + cdiv += (cdiv % 2); + + if (cdiv >= 65536) + cdiv = 0; /* 0 is the slowest we can go */ + } else { + cdiv = 0; /* 0 is the slowest we can go */ + } + spi_used_hz = cdiv ? (clk_hz / cdiv) : (clk_hz / 65536); + bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv); + + /* handle all the modes */ + if ((spi->mode & SPI_3WIRE) && (tfr->rx_buf)) + cs |= BCM2835_SPI_CS_REN; + if (spi->mode & SPI_CPOL) + cs |= BCM2835_SPI_CS_CPOL; + if (spi->mode & SPI_CPHA) + cs |= BCM2835_SPI_CS_CPHA; + + /* for gpio_cs set dummy CS so that no HW-CS get changed + * we can not run this in bcm2835_spi_set_cs, as it does + * not get called for cs_gpio cases, so we need to do it here + */ + if (gpio_is_valid(spi->cs_gpio) || (spi->mode & SPI_NO_CS)) + cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01; + + /* set transmit buffers and length */ + bs->tx_buf = tfr->tx_buf; + bs->rx_buf = tfr->rx_buf; + bs->tx_len = tfr->len; + bs->rx_len = tfr->len; + + /* calculate the estimated time in us the transfer runs */ + xfer_time_us = tfr->len + * 9 /* clocks/byte - SPI-HW waits 1 clock after each byte */ + * 1000000 / spi_used_hz; + + /* for short requests run polling*/ + if (xfer_time_us <= BCM2835_SPI_POLLING_LIMIT_US) + return bcm2835_spi_transfer_one_poll(master, spi, tfr, + cs, xfer_time_us); + + return bcm2835_spi_transfer_one_irq(master, spi, tfr, cs); +} + static void bcm2835_spi_handle_err(struct spi_master *master, struct spi_message *msg) {