aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/dw_spi.c
diff options
context:
space:
mode:
authorAlek Du <alek.du@intel.com>2011-03-30 11:09:54 -0400
committerGrant Likely <grant.likely@secretlab.ca>2011-03-30 23:31:48 -0400
commit2ff271bf6505038d8c937e73438ea3c80c387439 (patch)
tree082f4462c98661a6b4da3e924cafe20df9cf9218 /drivers/spi/dw_spi.c
parent8a33a373e5ffb6040c58ff41ea48ba21d5f8b5e9 (diff)
spi/dw_spi: change poll mode transfer from byte ops to batch ops
Current poll transfer will read/write one word, then wait till the hw is non-busy, it's not efficient. This patch will try to read/write as many words as permitted by hardware FIFO depth. Signed-off-by: Alek Du <alek.du@intel.com> Signed-off-by: Feng Tang <feng.tang@intel.com> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/spi/dw_spi.c')
-rw-r--r--drivers/spi/dw_spi.c71
1 files changed, 48 insertions, 23 deletions
diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
index d3aaf8db86cc..7a2a72268f0a 100644
--- a/drivers/spi/dw_spi.c
+++ b/drivers/spi/dw_spi.c
@@ -160,6 +160,37 @@ static inline void mrst_spi_debugfs_remove(struct dw_spi *dws)
160} 160}
161#endif /* CONFIG_DEBUG_FS */ 161#endif /* CONFIG_DEBUG_FS */
162 162
163/* Return the max entries we can fill into tx fifo */
164static inline u32 tx_max(struct dw_spi *dws)
165{
166 u32 tx_left, tx_room, rxtx_gap;
167
168 tx_left = (dws->tx_end - dws->tx) / dws->n_bytes;
169 tx_room = dws->fifo_len - dw_readw(dws, txflr);
170
171 /*
172 * Another concern is about the tx/rx mismatch, we
173 * though to use (dws->fifo_len - rxflr - txflr) as
174 * one maximum value for tx, but it doesn't cover the
175 * data which is out of tx/rx fifo and inside the
176 * shift registers. So a control from sw point of
177 * view is taken.
178 */
179 rxtx_gap = ((dws->rx_end - dws->rx) - (dws->tx_end - dws->tx))
180 / dws->n_bytes;
181
182 return min3(tx_left, tx_room, (u32) (dws->fifo_len - rxtx_gap));
183}
184
185/* Return the max entries we should read out of rx fifo */
186static inline u32 rx_max(struct dw_spi *dws)
187{
188 u32 rx_left = (dws->rx_end - dws->rx) / dws->n_bytes;
189
190 return min(rx_left, (u32)dw_readw(dws, rxflr));
191}
192
193
163static void wait_till_not_busy(struct dw_spi *dws) 194static void wait_till_not_busy(struct dw_spi *dws)
164{ 195{
165 unsigned long end = jiffies + 1 + usecs_to_jiffies(5000); 196 unsigned long end = jiffies + 1 + usecs_to_jiffies(5000);
@@ -175,33 +206,30 @@ static void wait_till_not_busy(struct dw_spi *dws)
175 206
176static int dw_writer(struct dw_spi *dws) 207static int dw_writer(struct dw_spi *dws)
177{ 208{
209 u32 max = tx_max(dws);
178 u16 txw = 0; 210 u16 txw = 0;
179 211
180 if (!(dw_readw(dws, sr) & SR_TF_NOT_FULL) 212 while (max--) {
181 || (dws->tx == dws->tx_end)) 213 /* Set the tx word if the transfer's original "tx" is not null */
182 return 0; 214 if (dws->tx_end - dws->len) {
183 215 if (dws->n_bytes == 1)
184 /* Set the tx word if the transfer's original "tx" is not null */ 216 txw = *(u8 *)(dws->tx);
185 if (dws->tx_end - dws->len) { 217 else
186 if (dws->n_bytes == 1) 218 txw = *(u16 *)(dws->tx);
187 txw = *(u8 *)(dws->tx); 219 }
188 else 220 dw_writew(dws, dr, txw);
189 txw = *(u16 *)(dws->tx); 221 dws->tx += dws->n_bytes;
190 } 222 }
191 223
192 dw_writew(dws, dr, txw);
193 dws->tx += dws->n_bytes;
194
195 wait_till_not_busy(dws);
196 return 1; 224 return 1;
197} 225}
198 226
199static int dw_reader(struct dw_spi *dws) 227static int dw_reader(struct dw_spi *dws)
200{ 228{
229 u32 max = rx_max(dws);
201 u16 rxw; 230 u16 rxw;
202 231
203 while ((dw_readw(dws, sr) & SR_RF_NOT_EMPT) 232 while (max--) {
204 && (dws->rx < dws->rx_end)) {
205 rxw = dw_readw(dws, dr); 233 rxw = dw_readw(dws, dr);
206 /* Care rx only if the transfer's original "rx" is not null */ 234 /* Care rx only if the transfer's original "rx" is not null */
207 if (dws->rx_end - dws->len) { 235 if (dws->rx_end - dws->len) {
@@ -213,7 +241,6 @@ static int dw_reader(struct dw_spi *dws)
213 dws->rx += dws->n_bytes; 241 dws->rx += dws->n_bytes;
214 } 242 }
215 243
216 wait_till_not_busy(dws);
217 return dws->rx == dws->rx_end; 244 return dws->rx == dws->rx_end;
218} 245}
219 246
@@ -368,13 +395,11 @@ static irqreturn_t dw_spi_irq(int irq, void *dev_id)
368/* Must be called inside pump_transfers() */ 395/* Must be called inside pump_transfers() */
369static void poll_transfer(struct dw_spi *dws) 396static void poll_transfer(struct dw_spi *dws)
370{ 397{
371 while (dw_writer(dws)) 398 do {
399 dw_writer(dws);
372 dw_reader(dws); 400 dw_reader(dws);
373 /* 401 cpu_relax();
374 * There is a possibility that the last word of a transaction 402 } while (dws->rx_end > dws->rx);
375 * will be lost if data is not ready. Re-read to solve this issue.
376 */
377 dw_reader(dws);
378 403
379 dw_spi_xfer_done(dws); 404 dw_spi_xfer_done(dws);
380} 405}