aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-mpc512x-psc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi-mpc512x-psc.c')
-rw-r--r--drivers/spi/spi-mpc512x-psc.c141
1 files changed, 107 insertions, 34 deletions
diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 759a937d5fa7..53c7899a8aba 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -137,6 +137,7 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi,
137 struct mpc52xx_psc __iomem *psc = mps->psc; 137 struct mpc52xx_psc __iomem *psc = mps->psc;
138 struct mpc512x_psc_fifo __iomem *fifo = mps->fifo; 138 struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
139 size_t tx_len = t->len; 139 size_t tx_len = t->len;
140 size_t rx_len = t->len;
140 u8 *tx_buf = (u8 *)t->tx_buf; 141 u8 *tx_buf = (u8 *)t->tx_buf;
141 u8 *rx_buf = (u8 *)t->rx_buf; 142 u8 *rx_buf = (u8 *)t->rx_buf;
142 143
@@ -150,57 +151,129 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi,
150 /* enable transmiter/receiver */ 151 /* enable transmiter/receiver */
151 out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE); 152 out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
152 153
153 while (tx_len) { 154 while (rx_len || tx_len) {
154 size_t txcount; 155 size_t txcount;
155 int i;
156 u8 data; 156 u8 data;
157 size_t fifosz; 157 size_t fifosz;
158 size_t rxcount; 158 size_t rxcount;
159 int rxtries;
159 160
160 /* 161 /*
161 * The number of bytes that can be sent at a time 162 * send the TX bytes in as large a chunk as possible
162 * depends on the fifo size. 163 * but neither exceed the TX nor the RX FIFOs
163 */ 164 */
164 fifosz = MPC512x_PSC_FIFO_SZ(in_be32(&fifo->txsz)); 165 fifosz = MPC512x_PSC_FIFO_SZ(in_be32(&fifo->txsz));
165 txcount = min(fifosz, tx_len); 166 txcount = min(fifosz, tx_len);
167 fifosz = MPC512x_PSC_FIFO_SZ(in_be32(&fifo->rxsz));
168 fifosz -= in_be32(&fifo->rxcnt) + 1;
169 txcount = min(fifosz, txcount);
170 if (txcount) {
171
172 /* fill the TX FIFO */
173 while (txcount-- > 0) {
174 data = tx_buf ? *tx_buf++ : 0;
175 if (tx_len == EOFBYTE && t->cs_change)
176 setbits32(&fifo->txcmd,
177 MPC512x_PSC_FIFO_EOF);
178 out_8(&fifo->txdata_8, data);
179 tx_len--;
180 }
166 181
167 for (i = txcount; i > 0; i--) { 182 /* have the ISR trigger when the TX FIFO is empty */
168 data = tx_buf ? *tx_buf++ : 0; 183 INIT_COMPLETION(mps->txisrdone);
169 if (tx_len == EOFBYTE && t->cs_change) 184 out_be32(&fifo->txisr, MPC512x_PSC_FIFO_EMPTY);
170 setbits32(&fifo->txcmd, MPC512x_PSC_FIFO_EOF); 185 out_be32(&fifo->tximr, MPC512x_PSC_FIFO_EMPTY);
171 out_8(&fifo->txdata_8, data); 186 wait_for_completion(&mps->txisrdone);
172 tx_len--;
173 } 187 }
174 188
175 INIT_COMPLETION(mps->txisrdone); 189 /*
176 190 * consume as much RX data as the FIFO holds, while we
177 /* interrupt on tx fifo empty */ 191 * iterate over the transfer's TX data length
178 out_be32(&fifo->txisr, MPC512x_PSC_FIFO_EMPTY); 192 *
179 out_be32(&fifo->tximr, MPC512x_PSC_FIFO_EMPTY); 193 * only insist in draining all the remaining RX bytes
180 194 * when the TX bytes were exhausted (that's at the very
181 wait_for_completion(&mps->txisrdone); 195 * end of this transfer, not when still iterating over
182 196 * the transfer's chunks)
183 mdelay(1); 197 */
198 rxtries = 50;
199 do {
200
201 /*
202 * grab whatever was in the FIFO when we started
203 * looking, don't bother fetching what was added to
204 * the FIFO while we read from it -- we'll return
205 * here eventually and prefer sending out remaining
206 * TX data
207 */
208 fifosz = in_be32(&fifo->rxcnt);
209 rxcount = min(fifosz, rx_len);
210 while (rxcount-- > 0) {
211 data = in_8(&fifo->rxdata_8);
212 if (rx_buf)
213 *rx_buf++ = data;
214 rx_len--;
215 }
184 216
185 /* rx fifo should have txcount bytes in it */ 217 /*
186 rxcount = in_be32(&fifo->rxcnt); 218 * come back later if there still is TX data to send,
187 if (rxcount != txcount) 219 * bail out of the RX drain loop if all of the TX data
188 mdelay(1); 220 * was sent and all of the RX data was received (i.e.
221 * when the transmission has completed)
222 */
223 if (tx_len)
224 break;
225 if (!rx_len)
226 break;
189 227
190 rxcount = in_be32(&fifo->rxcnt); 228 /*
191 if (rxcount != txcount) { 229 * TX data transmission has completed while RX data
192 dev_warn(&spi->dev, "expected %d bytes in rx fifo " 230 * is still pending -- that's a transient situation
193 "but got %d\n", txcount, rxcount); 231 * which depends on wire speed and specific
232 * hardware implementation details (buffering) yet
233 * should resolve very quickly
234 *
235 * just yield for a moment to not hog the CPU for
236 * too long when running SPI at low speed
237 *
238 * the timeout range is rather arbitrary and tries
239 * to balance throughput against system load; the
240 * chosen values result in a minimal timeout of 50
241 * times 10us and thus work at speeds as low as
242 * some 20kbps, while the maximum timeout at the
243 * transfer's end could be 5ms _if_ nothing else
244 * ticks in the system _and_ RX data still wasn't
245 * received, which only occurs in situations that
246 * are exceptional; removing the unpredictability
247 * of the timeout either decreases throughput
248 * (longer timeouts), or puts more load on the
249 * system (fixed short timeouts) or requires the
250 * use of a timeout API instead of a counter and an
251 * unknown inner delay
252 */
253 usleep_range(10, 100);
254
255 } while (--rxtries > 0);
256 if (!tx_len && rx_len && !rxtries) {
257 /*
258 * not enough RX bytes even after several retries
259 * and the resulting rather long timeout?
260 */
261 rxcount = in_be32(&fifo->rxcnt);
262 dev_warn(&spi->dev,
263 "short xfer, missing %zd RX bytes, FIFO level %zd\n",
264 rx_len, rxcount);
194 } 265 }
195 266
196 rxcount = min(rxcount, txcount); 267 /*
197 for (i = rxcount; i > 0; i--) { 268 * drain and drop RX data which "should not be there" in
198 data = in_8(&fifo->rxdata_8); 269 * the first place, for undisturbed transmission this turns
199 if (rx_buf) 270 * into a NOP (except for the FIFO level fetch)
200 *rx_buf++ = data; 271 */
272 if (!tx_len && !rx_len) {
273 while (in_be32(&fifo->rxcnt))
274 in_8(&fifo->rxdata_8);
201 } 275 }
202 while (in_be32(&fifo->rxcnt)) 276
203 in_8(&fifo->rxdata_8);
204 } 277 }
205 /* disable transmiter/receiver and fifo interrupt */ 278 /* disable transmiter/receiver and fifo interrupt */
206 out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE); 279 out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);