diff options
Diffstat (limited to 'drivers/spi/spi_bitbang.c')
| -rw-r--r-- | drivers/spi/spi_bitbang.c | 104 |
1 files changed, 84 insertions, 20 deletions
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c index f037e5593269..dd2f950b21a7 100644 --- a/drivers/spi/spi_bitbang.c +++ b/drivers/spi/spi_bitbang.c | |||
| @@ -138,6 +138,45 @@ static unsigned bitbang_txrx_32( | |||
| 138 | return t->len - count; | 138 | return t->len - count; |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | int spi_bitbang_setup_transfer(struct spi_device *spi, struct spi_transfer *t) | ||
| 142 | { | ||
| 143 | struct spi_bitbang_cs *cs = spi->controller_state; | ||
| 144 | u8 bits_per_word; | ||
| 145 | u32 hz; | ||
| 146 | |||
| 147 | if (t) { | ||
| 148 | bits_per_word = t->bits_per_word; | ||
| 149 | hz = t->speed_hz; | ||
| 150 | } else { | ||
| 151 | bits_per_word = 0; | ||
| 152 | hz = 0; | ||
| 153 | } | ||
| 154 | |||
| 155 | /* spi_transfer level calls that work per-word */ | ||
| 156 | if (!bits_per_word) | ||
| 157 | bits_per_word = spi->bits_per_word; | ||
| 158 | if (bits_per_word <= 8) | ||
| 159 | cs->txrx_bufs = bitbang_txrx_8; | ||
| 160 | else if (bits_per_word <= 16) | ||
| 161 | cs->txrx_bufs = bitbang_txrx_16; | ||
| 162 | else if (bits_per_word <= 32) | ||
| 163 | cs->txrx_bufs = bitbang_txrx_32; | ||
| 164 | else | ||
| 165 | return -EINVAL; | ||
| 166 | |||
| 167 | /* nsecs = (clock period)/2 */ | ||
| 168 | if (!hz) | ||
| 169 | hz = spi->max_speed_hz; | ||
| 170 | if (hz) { | ||
| 171 | cs->nsecs = (1000000000/2) / hz; | ||
| 172 | if (cs->nsecs > (MAX_UDELAY_MS * 1000 * 1000)) | ||
| 173 | return -EINVAL; | ||
| 174 | } | ||
| 175 | |||
| 176 | return 0; | ||
| 177 | } | ||
| 178 | EXPORT_SYMBOL_GPL(spi_bitbang_setup_transfer); | ||
| 179 | |||
| 141 | /** | 180 | /** |
| 142 | * spi_bitbang_setup - default setup for per-word I/O loops | 181 | * spi_bitbang_setup - default setup for per-word I/O loops |
| 143 | */ | 182 | */ |
| @@ -145,8 +184,16 @@ int spi_bitbang_setup(struct spi_device *spi) | |||
| 145 | { | 184 | { |
| 146 | struct spi_bitbang_cs *cs = spi->controller_state; | 185 | struct spi_bitbang_cs *cs = spi->controller_state; |
| 147 | struct spi_bitbang *bitbang; | 186 | struct spi_bitbang *bitbang; |
| 187 | int retval; | ||
| 148 | 188 | ||
| 149 | if (!spi->max_speed_hz) | 189 | bitbang = spi_master_get_devdata(spi->master); |
| 190 | |||
| 191 | /* REVISIT: some systems will want to support devices using lsb-first | ||
| 192 | * bit encodings on the wire. In pure software that would be trivial, | ||
| 193 | * just bitbang_txrx_le_cphaX() routines shifting the other way, and | ||
| 194 | * some hardware controllers also have this support. | ||
| 195 | */ | ||
| 196 | if ((spi->mode & SPI_LSB_FIRST) != 0) | ||
| 150 | return -EINVAL; | 197 | return -EINVAL; |
| 151 | 198 | ||
| 152 | if (!cs) { | 199 | if (!cs) { |
| @@ -155,32 +202,20 @@ int spi_bitbang_setup(struct spi_device *spi) | |||
| 155 | return -ENOMEM; | 202 | return -ENOMEM; |
| 156 | spi->controller_state = cs; | 203 | spi->controller_state = cs; |
| 157 | } | 204 | } |
| 158 | bitbang = spi_master_get_devdata(spi->master); | ||
| 159 | 205 | ||
| 160 | if (!spi->bits_per_word) | 206 | if (!spi->bits_per_word) |
| 161 | spi->bits_per_word = 8; | 207 | spi->bits_per_word = 8; |
| 162 | 208 | ||
| 163 | /* spi_transfer level calls that work per-word */ | ||
| 164 | if (spi->bits_per_word <= 8) | ||
| 165 | cs->txrx_bufs = bitbang_txrx_8; | ||
| 166 | else if (spi->bits_per_word <= 16) | ||
| 167 | cs->txrx_bufs = bitbang_txrx_16; | ||
| 168 | else if (spi->bits_per_word <= 32) | ||
| 169 | cs->txrx_bufs = bitbang_txrx_32; | ||
| 170 | else | ||
| 171 | return -EINVAL; | ||
| 172 | |||
| 173 | /* per-word shift register access, in hardware or bitbanging */ | 209 | /* per-word shift register access, in hardware or bitbanging */ |
| 174 | cs->txrx_word = bitbang->txrx_word[spi->mode & (SPI_CPOL|SPI_CPHA)]; | 210 | cs->txrx_word = bitbang->txrx_word[spi->mode & (SPI_CPOL|SPI_CPHA)]; |
| 175 | if (!cs->txrx_word) | 211 | if (!cs->txrx_word) |
| 176 | return -EINVAL; | 212 | return -EINVAL; |
| 177 | 213 | ||
| 178 | /* nsecs = (clock period)/2 */ | 214 | retval = spi_bitbang_setup_transfer(spi, NULL); |
| 179 | cs->nsecs = (1000000000/2) / (spi->max_speed_hz); | 215 | if (retval < 0) |
| 180 | if (cs->nsecs > MAX_UDELAY_MS * 1000) | 216 | return retval; |
| 181 | return -EINVAL; | ||
| 182 | 217 | ||
| 183 | dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec\n", | 218 | dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec/bit\n", |
| 184 | __FUNCTION__, spi->mode & (SPI_CPOL | SPI_CPHA), | 219 | __FUNCTION__, spi->mode & (SPI_CPOL | SPI_CPHA), |
| 185 | spi->bits_per_word, 2 * cs->nsecs); | 220 | spi->bits_per_word, 2 * cs->nsecs); |
| 186 | 221 | ||
| @@ -246,6 +281,8 @@ static void bitbang_work(void *_bitbang) | |||
| 246 | unsigned tmp; | 281 | unsigned tmp; |
| 247 | unsigned cs_change; | 282 | unsigned cs_change; |
| 248 | int status; | 283 | int status; |
| 284 | int (*setup_transfer)(struct spi_device *, | ||
| 285 | struct spi_transfer *); | ||
| 249 | 286 | ||
| 250 | m = container_of(bitbang->queue.next, struct spi_message, | 287 | m = container_of(bitbang->queue.next, struct spi_message, |
| 251 | queue); | 288 | queue); |
| @@ -262,6 +299,7 @@ static void bitbang_work(void *_bitbang) | |||
| 262 | tmp = 0; | 299 | tmp = 0; |
| 263 | cs_change = 1; | 300 | cs_change = 1; |
| 264 | status = 0; | 301 | status = 0; |
| 302 | setup_transfer = NULL; | ||
| 265 | 303 | ||
| 266 | list_for_each_entry (t, &m->transfers, transfer_list) { | 304 | list_for_each_entry (t, &m->transfers, transfer_list) { |
| 267 | if (bitbang->shutdown) { | 305 | if (bitbang->shutdown) { |
| @@ -269,6 +307,20 @@ static void bitbang_work(void *_bitbang) | |||
| 269 | break; | 307 | break; |
| 270 | } | 308 | } |
| 271 | 309 | ||
| 310 | /* override or restore speed and wordsize */ | ||
| 311 | if (t->speed_hz || t->bits_per_word) { | ||
| 312 | setup_transfer = bitbang->setup_transfer; | ||
| 313 | if (!setup_transfer) { | ||
| 314 | status = -ENOPROTOOPT; | ||
| 315 | break; | ||
| 316 | } | ||
| 317 | } | ||
| 318 | if (setup_transfer) { | ||
| 319 | status = setup_transfer(spi, t); | ||
| 320 | if (status < 0) | ||
| 321 | break; | ||
| 322 | } | ||
| 323 | |||
| 272 | /* set up default clock polarity, and activate chip; | 324 | /* set up default clock polarity, and activate chip; |
| 273 | * this implicitly updates clock and spi modes as | 325 | * this implicitly updates clock and spi modes as |
| 274 | * previously recorded for this device via setup(). | 326 | * previously recorded for this device via setup(). |
| @@ -325,6 +377,10 @@ static void bitbang_work(void *_bitbang) | |||
| 325 | m->status = status; | 377 | m->status = status; |
| 326 | m->complete(m->context); | 378 | m->complete(m->context); |
| 327 | 379 | ||
| 380 | /* restore speed and wordsize */ | ||
| 381 | if (setup_transfer) | ||
| 382 | setup_transfer(spi, NULL); | ||
| 383 | |||
| 328 | /* normally deactivate chipselect ... unless no error and | 384 | /* normally deactivate chipselect ... unless no error and |
| 329 | * cs_change has hinted that the next message will probably | 385 | * cs_change has hinted that the next message will probably |
| 330 | * be for this chip too. | 386 | * be for this chip too. |
| @@ -348,6 +404,7 @@ int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m) | |||
| 348 | { | 404 | { |
| 349 | struct spi_bitbang *bitbang; | 405 | struct spi_bitbang *bitbang; |
| 350 | unsigned long flags; | 406 | unsigned long flags; |
| 407 | int status = 0; | ||
| 351 | 408 | ||
| 352 | m->actual_length = 0; | 409 | m->actual_length = 0; |
| 353 | m->status = -EINPROGRESS; | 410 | m->status = -EINPROGRESS; |
| @@ -357,11 +414,15 @@ int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m) | |||
| 357 | return -ESHUTDOWN; | 414 | return -ESHUTDOWN; |
| 358 | 415 | ||
| 359 | spin_lock_irqsave(&bitbang->lock, flags); | 416 | spin_lock_irqsave(&bitbang->lock, flags); |
| 360 | list_add_tail(&m->queue, &bitbang->queue); | 417 | if (!spi->max_speed_hz) |
| 361 | queue_work(bitbang->workqueue, &bitbang->work); | 418 | status = -ENETDOWN; |
| 419 | else { | ||
| 420 | list_add_tail(&m->queue, &bitbang->queue); | ||
| 421 | queue_work(bitbang->workqueue, &bitbang->work); | ||
| 422 | } | ||
| 362 | spin_unlock_irqrestore(&bitbang->lock, flags); | 423 | spin_unlock_irqrestore(&bitbang->lock, flags); |
| 363 | 424 | ||
| 364 | return 0; | 425 | return status; |
| 365 | } | 426 | } |
| 366 | EXPORT_SYMBOL_GPL(spi_bitbang_transfer); | 427 | EXPORT_SYMBOL_GPL(spi_bitbang_transfer); |
| 367 | 428 | ||
| @@ -406,6 +467,9 @@ int spi_bitbang_start(struct spi_bitbang *bitbang) | |||
| 406 | bitbang->use_dma = 0; | 467 | bitbang->use_dma = 0; |
| 407 | bitbang->txrx_bufs = spi_bitbang_bufs; | 468 | bitbang->txrx_bufs = spi_bitbang_bufs; |
| 408 | if (!bitbang->master->setup) { | 469 | if (!bitbang->master->setup) { |
| 470 | if (!bitbang->setup_transfer) | ||
| 471 | bitbang->setup_transfer = | ||
| 472 | spi_bitbang_setup_transfer; | ||
| 409 | bitbang->master->setup = spi_bitbang_setup; | 473 | bitbang->master->setup = spi_bitbang_setup; |
| 410 | bitbang->master->cleanup = spi_bitbang_cleanup; | 474 | bitbang->master->cleanup = spi_bitbang_cleanup; |
| 411 | } | 475 | } |
