X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=drivers%2Fspi%2Fspi-bcm2835.c;h=8de1925fe5548f9ea58579e26268f6fafe391d4b;hb=210b49231af6a3ede5de3c90850dbf1134a855c2;hp=419a782ab6d50541809f0c8b10b3d8eaeeb1ae89;hpb=12df4289ee8e4dccf932b7186b391bb6d2b915fa;p=firefly-linux-kernel-4.4.55.git diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 419a782ab6d5..8de1925fe554 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,64 +120,28 @@ 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; - } - - /* - * 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; + complete(&bs->done); } - return IRQ_NONE; + return IRQ_HANDLED; } 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; @@ -191,13 +153,15 @@ 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 */ - } else + } else { cdiv = 0; /* 0 is the slowest we can go */ + } if (spi->mode & SPI_CPOL) cs |= BCM2835_SPI_CS_CPOL; @@ -231,17 +195,12 @@ 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); - /* 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); @@ -253,7 +212,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 +226,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 +304,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;