diff options
Diffstat (limited to 'drivers/spi/spi-bitbang.c')
-rw-r--r-- | drivers/spi/spi-bitbang.c | 152 |
1 files changed, 43 insertions, 109 deletions
diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index 840a4984d365..3aa9e6e3dac8 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c | |||
@@ -24,6 +24,8 @@ | |||
24 | #include <linux/spi/spi.h> | 24 | #include <linux/spi/spi.h> |
25 | #include <linux/spi/spi_bitbang.h> | 25 | #include <linux/spi/spi_bitbang.h> |
26 | 26 | ||
27 | #define SPI_BITBANG_CS_DELAY 100 | ||
28 | |||
27 | 29 | ||
28 | /*----------------------------------------------------------------------*/ | 30 | /*----------------------------------------------------------------------*/ |
29 | 31 | ||
@@ -180,7 +182,6 @@ int spi_bitbang_setup(struct spi_device *spi) | |||
180 | { | 182 | { |
181 | struct spi_bitbang_cs *cs = spi->controller_state; | 183 | struct spi_bitbang_cs *cs = spi->controller_state; |
182 | struct spi_bitbang *bitbang; | 184 | struct spi_bitbang *bitbang; |
183 | unsigned long flags; | ||
184 | 185 | ||
185 | bitbang = spi_master_get_devdata(spi->master); | 186 | bitbang = spi_master_get_devdata(spi->master); |
186 | 187 | ||
@@ -210,12 +211,12 @@ int spi_bitbang_setup(struct spi_device *spi) | |||
210 | */ | 211 | */ |
211 | 212 | ||
212 | /* deselect chip (low or high) */ | 213 | /* deselect chip (low or high) */ |
213 | spin_lock_irqsave(&bitbang->lock, flags); | 214 | mutex_lock(&bitbang->lock); |
214 | if (!bitbang->busy) { | 215 | if (!bitbang->busy) { |
215 | bitbang->chipselect(spi, BITBANG_CS_INACTIVE); | 216 | bitbang->chipselect(spi, BITBANG_CS_INACTIVE); |
216 | ndelay(cs->nsecs); | 217 | ndelay(cs->nsecs); |
217 | } | 218 | } |
218 | spin_unlock_irqrestore(&bitbang->lock, flags); | 219 | mutex_unlock(&bitbang->lock); |
219 | 220 | ||
220 | return 0; | 221 | return 0; |
221 | } | 222 | } |
@@ -255,122 +256,39 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t) | |||
255 | static int spi_bitbang_prepare_hardware(struct spi_master *spi) | 256 | static int spi_bitbang_prepare_hardware(struct spi_master *spi) |
256 | { | 257 | { |
257 | struct spi_bitbang *bitbang; | 258 | struct spi_bitbang *bitbang; |
258 | unsigned long flags; | ||
259 | 259 | ||
260 | bitbang = spi_master_get_devdata(spi); | 260 | bitbang = spi_master_get_devdata(spi); |
261 | 261 | ||
262 | spin_lock_irqsave(&bitbang->lock, flags); | 262 | mutex_lock(&bitbang->lock); |
263 | bitbang->busy = 1; | 263 | bitbang->busy = 1; |
264 | spin_unlock_irqrestore(&bitbang->lock, flags); | 264 | mutex_unlock(&bitbang->lock); |
265 | 265 | ||
266 | return 0; | 266 | return 0; |
267 | } | 267 | } |
268 | 268 | ||
269 | static int spi_bitbang_transfer_one(struct spi_master *master, | 269 | static int spi_bitbang_transfer_one(struct spi_master *master, |
270 | struct spi_message *m) | 270 | struct spi_device *spi, |
271 | struct spi_transfer *transfer) | ||
271 | { | 272 | { |
272 | struct spi_bitbang *bitbang; | 273 | struct spi_bitbang *bitbang = spi_master_get_devdata(master); |
273 | unsigned nsecs; | 274 | int status = 0; |
274 | struct spi_transfer *t = NULL; | ||
275 | unsigned cs_change; | ||
276 | int status; | ||
277 | int do_setup = -1; | ||
278 | struct spi_device *spi = m->spi; | ||
279 | |||
280 | bitbang = spi_master_get_devdata(master); | ||
281 | |||
282 | /* FIXME this is made-up ... the correct value is known to | ||
283 | * word-at-a-time bitbang code, and presumably chipselect() | ||
284 | * should enforce these requirements too? | ||
285 | */ | ||
286 | nsecs = 100; | ||
287 | |||
288 | cs_change = 1; | ||
289 | status = 0; | ||
290 | |||
291 | list_for_each_entry(t, &m->transfers, transfer_list) { | ||
292 | |||
293 | /* override speed or wordsize? */ | ||
294 | if (t->speed_hz || t->bits_per_word) | ||
295 | do_setup = 1; | ||
296 | |||
297 | /* init (-1) or override (1) transfer params */ | ||
298 | if (do_setup != 0) { | ||
299 | if (bitbang->setup_transfer) { | ||
300 | status = bitbang->setup_transfer(spi, t); | ||
301 | if (status < 0) | ||
302 | break; | ||
303 | } | ||
304 | if (do_setup == -1) | ||
305 | do_setup = 0; | ||
306 | } | ||
307 | |||
308 | /* set up default clock polarity, and activate chip; | ||
309 | * this implicitly updates clock and spi modes as | ||
310 | * previously recorded for this device via setup(). | ||
311 | * (and also deselects any other chip that might be | ||
312 | * selected ...) | ||
313 | */ | ||
314 | if (cs_change) { | ||
315 | bitbang->chipselect(spi, BITBANG_CS_ACTIVE); | ||
316 | ndelay(nsecs); | ||
317 | } | ||
318 | cs_change = t->cs_change; | ||
319 | if (!t->tx_buf && !t->rx_buf && t->len) { | ||
320 | status = -EINVAL; | ||
321 | break; | ||
322 | } | ||
323 | |||
324 | /* transfer data. the lower level code handles any | ||
325 | * new dma mappings it needs. our caller always gave | ||
326 | * us dma-safe buffers. | ||
327 | */ | ||
328 | if (t->len) { | ||
329 | /* REVISIT dma API still needs a designated | ||
330 | * DMA_ADDR_INVALID; ~0 might be better. | ||
331 | */ | ||
332 | if (!m->is_dma_mapped) | ||
333 | t->rx_dma = t->tx_dma = 0; | ||
334 | status = bitbang->txrx_bufs(spi, t); | ||
335 | } | ||
336 | if (status > 0) | ||
337 | m->actual_length += status; | ||
338 | if (status != t->len) { | ||
339 | /* always report some kind of error */ | ||
340 | if (status >= 0) | ||
341 | status = -EREMOTEIO; | ||
342 | break; | ||
343 | } | ||
344 | status = 0; | ||
345 | 275 | ||
346 | /* protocol tweaks before next transfer */ | 276 | if (bitbang->setup_transfer) { |
347 | if (t->delay_usecs) | 277 | status = bitbang->setup_transfer(spi, transfer); |
348 | udelay(t->delay_usecs); | 278 | if (status < 0) |
349 | 279 | goto out; | |
350 | if (cs_change && | ||
351 | !list_is_last(&t->transfer_list, &m->transfers)) { | ||
352 | /* sometimes a short mid-message deselect of the chip | ||
353 | * may be needed to terminate a mode or command | ||
354 | */ | ||
355 | ndelay(nsecs); | ||
356 | bitbang->chipselect(spi, BITBANG_CS_INACTIVE); | ||
357 | ndelay(nsecs); | ||
358 | } | ||
359 | } | 280 | } |
360 | 281 | ||
361 | m->status = status; | 282 | if (transfer->len) |
283 | status = bitbang->txrx_bufs(spi, transfer); | ||
362 | 284 | ||
363 | /* normally deactivate chipselect ... unless no error and | 285 | if (status == transfer->len) |
364 | * cs_change has hinted that the next message will probably | 286 | status = 0; |
365 | * be for this chip too. | 287 | else if (status >= 0) |
366 | */ | 288 | status = -EREMOTEIO; |
367 | if (!(status == 0 && cs_change)) { | ||
368 | ndelay(nsecs); | ||
369 | bitbang->chipselect(spi, BITBANG_CS_INACTIVE); | ||
370 | ndelay(nsecs); | ||
371 | } | ||
372 | 289 | ||
373 | spi_finalize_current_message(master); | 290 | out: |
291 | spi_finalize_current_transfer(master); | ||
374 | 292 | ||
375 | return status; | 293 | return status; |
376 | } | 294 | } |
@@ -378,17 +296,32 @@ static int spi_bitbang_transfer_one(struct spi_master *master, | |||
378 | static int spi_bitbang_unprepare_hardware(struct spi_master *spi) | 296 | static int spi_bitbang_unprepare_hardware(struct spi_master *spi) |
379 | { | 297 | { |
380 | struct spi_bitbang *bitbang; | 298 | struct spi_bitbang *bitbang; |
381 | unsigned long flags; | ||
382 | 299 | ||
383 | bitbang = spi_master_get_devdata(spi); | 300 | bitbang = spi_master_get_devdata(spi); |
384 | 301 | ||
385 | spin_lock_irqsave(&bitbang->lock, flags); | 302 | mutex_lock(&bitbang->lock); |
386 | bitbang->busy = 0; | 303 | bitbang->busy = 0; |
387 | spin_unlock_irqrestore(&bitbang->lock, flags); | 304 | mutex_unlock(&bitbang->lock); |
388 | 305 | ||
389 | return 0; | 306 | return 0; |
390 | } | 307 | } |
391 | 308 | ||
309 | static void spi_bitbang_set_cs(struct spi_device *spi, bool enable) | ||
310 | { | ||
311 | struct spi_bitbang *bitbang = spi_master_get_devdata(spi->master); | ||
312 | |||
313 | /* SPI core provides CS high / low, but bitbang driver | ||
314 | * expects CS active | ||
315 | * spi device driver takes care of handling SPI_CS_HIGH | ||
316 | */ | ||
317 | enable = (!!(spi->mode & SPI_CS_HIGH) == enable); | ||
318 | |||
319 | ndelay(SPI_BITBANG_CS_DELAY); | ||
320 | bitbang->chipselect(spi, enable ? BITBANG_CS_ACTIVE : | ||
321 | BITBANG_CS_INACTIVE); | ||
322 | ndelay(SPI_BITBANG_CS_DELAY); | ||
323 | } | ||
324 | |||
392 | /*----------------------------------------------------------------------*/ | 325 | /*----------------------------------------------------------------------*/ |
393 | 326 | ||
394 | /** | 327 | /** |
@@ -427,7 +360,7 @@ int spi_bitbang_start(struct spi_bitbang *bitbang) | |||
427 | if (!master || !bitbang->chipselect) | 360 | if (!master || !bitbang->chipselect) |
428 | return -EINVAL; | 361 | return -EINVAL; |
429 | 362 | ||
430 | spin_lock_init(&bitbang->lock); | 363 | mutex_init(&bitbang->lock); |
431 | 364 | ||
432 | if (!master->mode_bits) | 365 | if (!master->mode_bits) |
433 | master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags; | 366 | master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags; |
@@ -437,7 +370,8 @@ int spi_bitbang_start(struct spi_bitbang *bitbang) | |||
437 | 370 | ||
438 | master->prepare_transfer_hardware = spi_bitbang_prepare_hardware; | 371 | master->prepare_transfer_hardware = spi_bitbang_prepare_hardware; |
439 | master->unprepare_transfer_hardware = spi_bitbang_unprepare_hardware; | 372 | master->unprepare_transfer_hardware = spi_bitbang_unprepare_hardware; |
440 | master->transfer_one_message = spi_bitbang_transfer_one; | 373 | master->transfer_one = spi_bitbang_transfer_one; |
374 | master->set_cs = spi_bitbang_set_cs; | ||
441 | 375 | ||
442 | if (!bitbang->txrx_bufs) { | 376 | if (!bitbang->txrx_bufs) { |
443 | bitbang->use_dma = 0; | 377 | bitbang->use_dma = 0; |