[brcm63xx] led and buttons support for board DWV-S0
[openwrt.git] / target / linux / brcm63xx / patches-3.8 / 001-spi-bcm63xx-reject-transfers-unable-to-transfer.patch
1 From 243970ea035623f70431a80ece802f572cd446be Mon Sep 17 00:00:00 2001
2 From: Jonas Gorski <jogo@openwrt.org>
3 Date: Sun, 9 Dec 2012 00:10:00 +0100
4 Subject: [PATCH V2 1/2] spi/bcm63xx: reject transfers unable to transfer
5
6 The hardware does not support keeping CS asserted after sending one
7 FIFO buffer worth of data, so reject transfers requiring CS being kept
8 asserted, either between transers or for a certain time after it,
9 or exceeding the FIFO size.
10
11 Signed-off-by: Jonas Gorski <jogo@openwrt.org>
12 ---
13  drivers/spi/spi-bcm63xx.c |   91 +++++++++++++++++++++------------------------
14  1 file changed, 42 insertions(+), 49 deletions(-)
15
16 --- a/drivers/spi/spi-bcm63xx.c
17 +++ b/drivers/spi/spi-bcm63xx.c
18 @@ -49,16 +49,10 @@ struct bcm63xx_spi {
19         unsigned int            msg_type_shift;
20         unsigned int            msg_ctl_width;
21  
22 -       /* Data buffers */
23 -       const unsigned char     *tx_ptr;
24 -       unsigned char           *rx_ptr;
25 -
26         /* data iomem */
27         u8 __iomem              *tx_io;
28         const u8 __iomem        *rx_io;
29  
30 -       int                     remaining_bytes;
31 -
32         struct clk              *clk;
33         struct platform_device  *pdev;
34  };
35 @@ -175,24 +169,13 @@ static int bcm63xx_spi_setup(struct spi_
36         return 0;
37  }
38  
39 -/* Fill the TX FIFO with as many bytes as possible */
40 -static void bcm63xx_spi_fill_tx_fifo(struct bcm63xx_spi *bs)
41 -{
42 -       u8 size;
43 -
44 -       /* Fill the Tx FIFO with as many bytes as possible */
45 -       size = bs->remaining_bytes < bs->fifo_size ? bs->remaining_bytes :
46 -               bs->fifo_size;
47 -       memcpy_toio(bs->tx_io, bs->tx_ptr, size);
48 -       bs->remaining_bytes -= size;
49 -}
50 -
51 -static unsigned int bcm63xx_txrx_bufs(struct spi_device *spi,
52 -                                       struct spi_transfer *t)
53 +static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
54  {
55         struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
56         u16 msg_ctl;
57         u16 cmd;
58 +       u8 rx_tail;
59 +       unsigned int timeout = 0;
60  
61         /* Disable the CMD_DONE interrupt */
62         bcm_spi_writeb(bs, 0, SPI_INT_MASK);
63 @@ -200,14 +183,8 @@ static unsigned int bcm63xx_txrx_bufs(st
64         dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n",
65                 t->tx_buf, t->rx_buf, t->len);
66  
67 -       /* Transmitter is inhibited */
68 -       bs->tx_ptr = t->tx_buf;
69 -       bs->rx_ptr = t->rx_buf;
70 -
71 -       if (t->tx_buf) {
72 -               bs->remaining_bytes = t->len;
73 -               bcm63xx_spi_fill_tx_fifo(bs);
74 -       }
75 +       if (t->tx_buf)
76 +               memcpy_toio(bs->tx_io, t->tx_buf, t->len);
77  
78         init_completion(&bs->done);
79  
80 @@ -239,7 +216,18 @@ static unsigned int bcm63xx_txrx_bufs(st
81         /* Enable the CMD_DONE interrupt */
82         bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK);
83  
84 -       return t->len - bs->remaining_bytes;
85 +       timeout = wait_for_completion_timeout(&bs->done, HZ);
86 +       if (!timeout)
87 +               return -ETIMEDOUT;
88 +
89 +       /* read out all data */
90 +       rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL);
91 +
92 +       /* Read out all the data */
93 +       if (rx_tail)
94 +               memcpy_fromio(t->rx_ptr, bs->rx_io, rx_tail);
95 +
96 +       return 0;
97  }
98  
99  static int bcm63xx_spi_prepare_transfer(struct spi_master *master)
100 @@ -267,36 +255,41 @@ static int bcm63xx_spi_transfer_one(stru
101         struct spi_transfer *t;
102         struct spi_device *spi = m->spi;
103         int status = 0;
104 -       unsigned int timeout = 0;
105  
106         list_for_each_entry(t, &m->transfers, transfer_list) {
107 -               unsigned int len = t->len;
108 -               u8 rx_tail;
109 -
110                 status = bcm63xx_spi_check_transfer(spi, t);
111                 if (status < 0)
112                         goto exit;
113  
114 +               /* we can only transfer one fifo worth of data */
115 +               if (t->len > bs->fifo_size) {
116 +                       dev_err(&spi->dev, "unable to do transfers larger than FIFO size (%i > %i)\n",
117 +                               t->len, bs->fifo_size);
118 +                       status = -EINVAL;
119 +                       goto exit;
120 +               }
121 +
122 +               /* CS will be deasserted directly after transfer */
123 +               if (t->delay_usecs) {
124 +                       dev_err(&spi->dev, "unable to keep CS asserted after transfer\n");
125 +                       status = -EINVAL;
126 +                       goto exit;
127 +               }
128 +
129 +               if (!t->cs_change &&
130 +                   !list_is_last(&t->transfer_list, &m->transfers)) {
131 +                       dev_err(&spi->dev, "unable to keep CS asserted between transfers\n");
132 +                       status = -EINVAL;
133 +                       goto exit;
134 +               }
135 +
136                 /* configure adapter for a new transfer */
137                 bcm63xx_spi_setup_transfer(spi, t);
138  
139 -               while (len) {
140 -                       /* send the data */
141 -                       len -= bcm63xx_txrx_bufs(spi, t);
142 -
143 -                       timeout = wait_for_completion_timeout(&bs->done, HZ);
144 -                       if (!timeout) {
145 -                               status = -ETIMEDOUT;
146 -                               goto exit;
147 -                       }
148 -
149 -                       /* read out all data */
150 -                       rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL);
151 -
152 -                       /* Read out all the data */
153 -                       if (rx_tail)
154 -                               memcpy_fromio(bs->rx_ptr, bs->rx_io, rx_tail);
155 -               }
156 +               /* send the data */
157 +               status = bcm63xx_txrx_bufs(spi, t);
158 +               if (status)
159 +                       goto exit;
160  
161                 m->actual_length += t->len;
162         }