diff options
Diffstat (limited to 'drivers/spi/spi_bitbang.c')
-rw-r--r-- | drivers/spi/spi_bitbang.c | 86 |
1 files changed, 49 insertions, 37 deletions
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c index 44aff198eb96..f037e5593269 100644 --- a/drivers/spi/spi_bitbang.c +++ b/drivers/spi/spi_bitbang.c | |||
@@ -146,6 +146,9 @@ int spi_bitbang_setup(struct spi_device *spi) | |||
146 | struct spi_bitbang_cs *cs = spi->controller_state; | 146 | struct spi_bitbang_cs *cs = spi->controller_state; |
147 | struct spi_bitbang *bitbang; | 147 | struct spi_bitbang *bitbang; |
148 | 148 | ||
149 | if (!spi->max_speed_hz) | ||
150 | return -EINVAL; | ||
151 | |||
149 | if (!cs) { | 152 | if (!cs) { |
150 | cs = kzalloc(sizeof *cs, SLAB_KERNEL); | 153 | cs = kzalloc(sizeof *cs, SLAB_KERNEL); |
151 | if (!cs) | 154 | if (!cs) |
@@ -172,13 +175,8 @@ int spi_bitbang_setup(struct spi_device *spi) | |||
172 | if (!cs->txrx_word) | 175 | if (!cs->txrx_word) |
173 | return -EINVAL; | 176 | return -EINVAL; |
174 | 177 | ||
175 | if (!spi->max_speed_hz) | 178 | /* nsecs = (clock period)/2 */ |
176 | spi->max_speed_hz = 500 * 1000; | ||
177 | |||
178 | /* nsecs = max(50, (clock period)/2), be optimistic */ | ||
179 | cs->nsecs = (1000000000/2) / (spi->max_speed_hz); | 179 | cs->nsecs = (1000000000/2) / (spi->max_speed_hz); |
180 | if (cs->nsecs < 50) | ||
181 | cs->nsecs = 50; | ||
182 | if (cs->nsecs > MAX_UDELAY_MS * 1000) | 180 | if (cs->nsecs > MAX_UDELAY_MS * 1000) |
183 | return -EINVAL; | 181 | return -EINVAL; |
184 | 182 | ||
@@ -194,7 +192,7 @@ int spi_bitbang_setup(struct spi_device *spi) | |||
194 | /* deselect chip (low or high) */ | 192 | /* deselect chip (low or high) */ |
195 | spin_lock(&bitbang->lock); | 193 | spin_lock(&bitbang->lock); |
196 | if (!bitbang->busy) { | 194 | if (!bitbang->busy) { |
197 | bitbang->chipselect(spi, 0); | 195 | bitbang->chipselect(spi, BITBANG_CS_INACTIVE); |
198 | ndelay(cs->nsecs); | 196 | ndelay(cs->nsecs); |
199 | } | 197 | } |
200 | spin_unlock(&bitbang->lock); | 198 | spin_unlock(&bitbang->lock); |
@@ -244,9 +242,9 @@ static void bitbang_work(void *_bitbang) | |||
244 | struct spi_message *m; | 242 | struct spi_message *m; |
245 | struct spi_device *spi; | 243 | struct spi_device *spi; |
246 | unsigned nsecs; | 244 | unsigned nsecs; |
247 | struct spi_transfer *t; | 245 | struct spi_transfer *t = NULL; |
248 | unsigned tmp; | 246 | unsigned tmp; |
249 | unsigned chipselect; | 247 | unsigned cs_change; |
250 | int status; | 248 | int status; |
251 | 249 | ||
252 | m = container_of(bitbang->queue.next, struct spi_message, | 250 | m = container_of(bitbang->queue.next, struct spi_message, |
@@ -254,37 +252,49 @@ static void bitbang_work(void *_bitbang) | |||
254 | list_del_init(&m->queue); | 252 | list_del_init(&m->queue); |
255 | spin_unlock_irqrestore(&bitbang->lock, flags); | 253 | spin_unlock_irqrestore(&bitbang->lock, flags); |
256 | 254 | ||
257 | // FIXME this is made-up | 255 | /* FIXME this is made-up ... the correct value is known to |
258 | nsecs = 100; | 256 | * word-at-a-time bitbang code, and presumably chipselect() |
257 | * should enforce these requirements too? | ||
258 | */ | ||
259 | nsecs = 100; | ||
259 | 260 | ||
260 | spi = m->spi; | 261 | spi = m->spi; |
261 | t = m->transfers; | ||
262 | tmp = 0; | 262 | tmp = 0; |
263 | chipselect = 0; | 263 | cs_change = 1; |
264 | status = 0; | 264 | status = 0; |
265 | 265 | ||
266 | for (;;t++) { | 266 | list_for_each_entry (t, &m->transfers, transfer_list) { |
267 | if (bitbang->shutdown) { | 267 | if (bitbang->shutdown) { |
268 | status = -ESHUTDOWN; | 268 | status = -ESHUTDOWN; |
269 | break; | 269 | break; |
270 | } | 270 | } |
271 | 271 | ||
272 | /* set up default clock polarity, and activate chip */ | 272 | /* set up default clock polarity, and activate chip; |
273 | if (!chipselect) { | 273 | * this implicitly updates clock and spi modes as |
274 | bitbang->chipselect(spi, 1); | 274 | * previously recorded for this device via setup(). |
275 | * (and also deselects any other chip that might be | ||
276 | * selected ...) | ||
277 | */ | ||
278 | if (cs_change) { | ||
279 | bitbang->chipselect(spi, BITBANG_CS_ACTIVE); | ||
275 | ndelay(nsecs); | 280 | ndelay(nsecs); |
276 | } | 281 | } |
282 | cs_change = t->cs_change; | ||
277 | if (!t->tx_buf && !t->rx_buf && t->len) { | 283 | if (!t->tx_buf && !t->rx_buf && t->len) { |
278 | status = -EINVAL; | 284 | status = -EINVAL; |
279 | break; | 285 | break; |
280 | } | 286 | } |
281 | 287 | ||
282 | /* transfer data */ | 288 | /* transfer data. the lower level code handles any |
289 | * new dma mappings it needs. our caller always gave | ||
290 | * us dma-safe buffers. | ||
291 | */ | ||
283 | if (t->len) { | 292 | if (t->len) { |
284 | /* FIXME if bitbang->use_dma, dma_map_single() | 293 | /* REVISIT dma API still needs a designated |
285 | * before the transfer, and dma_unmap_single() | 294 | * DMA_ADDR_INVALID; ~0 might be better. |
286 | * afterwards, for either or both buffers... | ||
287 | */ | 295 | */ |
296 | if (!m->is_dma_mapped) | ||
297 | t->rx_dma = t->tx_dma = 0; | ||
288 | status = bitbang->txrx_bufs(spi, t); | 298 | status = bitbang->txrx_bufs(spi, t); |
289 | } | 299 | } |
290 | if (status != t->len) { | 300 | if (status != t->len) { |
@@ -299,29 +309,31 @@ nsecs = 100; | |||
299 | if (t->delay_usecs) | 309 | if (t->delay_usecs) |
300 | udelay(t->delay_usecs); | 310 | udelay(t->delay_usecs); |
301 | 311 | ||
302 | tmp++; | 312 | if (!cs_change) |
303 | if (tmp >= m->n_transfer) | ||
304 | break; | ||
305 | |||
306 | chipselect = !t->cs_change; | ||
307 | if (chipselect); | ||
308 | continue; | 313 | continue; |
314 | if (t->transfer_list.next == &m->transfers) | ||
315 | break; | ||
309 | 316 | ||
310 | bitbang->chipselect(spi, 0); | 317 | /* sometimes a short mid-message deselect of the chip |
311 | 318 | * may be needed to terminate a mode or command | |
312 | /* REVISIT do we want the udelay here instead? */ | 319 | */ |
313 | msleep(1); | 320 | ndelay(nsecs); |
321 | bitbang->chipselect(spi, BITBANG_CS_INACTIVE); | ||
322 | ndelay(nsecs); | ||
314 | } | 323 | } |
315 | 324 | ||
316 | tmp = m->n_transfer - 1; | ||
317 | tmp = m->transfers[tmp].cs_change; | ||
318 | |||
319 | m->status = status; | 325 | m->status = status; |
320 | m->complete(m->context); | 326 | m->complete(m->context); |
321 | 327 | ||
322 | ndelay(2 * nsecs); | 328 | /* normally deactivate chipselect ... unless no error and |
323 | bitbang->chipselect(spi, status == 0 && tmp); | 329 | * cs_change has hinted that the next message will probably |
324 | ndelay(nsecs); | 330 | * be for this chip too. |
331 | */ | ||
332 | if (!(status == 0 && cs_change)) { | ||
333 | ndelay(nsecs); | ||
334 | bitbang->chipselect(spi, BITBANG_CS_INACTIVE); | ||
335 | ndelay(nsecs); | ||
336 | } | ||
325 | 337 | ||
326 | spin_lock_irqsave(&bitbang->lock, flags); | 338 | spin_lock_irqsave(&bitbang->lock, flags); |
327 | } | 339 | } |