diff options
| -rw-r--r-- | drivers/spi/spi-bcm2835aux.c | 57 |
1 files changed, 41 insertions, 16 deletions
diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c index e1b2fec1db63..a6e25c6c66ca 100644 --- a/drivers/spi/spi-bcm2835aux.c +++ b/drivers/spi/spi-bcm2835aux.c | |||
| @@ -218,9 +218,9 @@ static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id) | |||
| 218 | BCM2835_AUX_SPI_CNTL1_IDLE); | 218 | BCM2835_AUX_SPI_CNTL1_IDLE); |
| 219 | } | 219 | } |
| 220 | 220 | ||
| 221 | /* and if rx_len is 0 then wake up completion and disable spi */ | 221 | /* and if rx_len is 0 then disable interrupts and wake up completion */ |
| 222 | if (!bs->rx_len) { | 222 | if (!bs->rx_len) { |
| 223 | bcm2835aux_spi_reset_hw(bs); | 223 | bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]); |
| 224 | complete(&master->xfer_completion); | 224 | complete(&master->xfer_completion); |
| 225 | } | 225 | } |
| 226 | 226 | ||
| @@ -313,9 +313,6 @@ static int bcm2835aux_spi_transfer_one_poll(struct spi_master *master, | |||
| 313 | } | 313 | } |
| 314 | } | 314 | } |
| 315 | 315 | ||
| 316 | /* Transfer complete - reset SPI HW */ | ||
| 317 | bcm2835aux_spi_reset_hw(bs); | ||
| 318 | |||
| 319 | /* and return without waiting for completion */ | 316 | /* and return without waiting for completion */ |
| 320 | return 0; | 317 | return 0; |
| 321 | } | 318 | } |
| @@ -336,10 +333,6 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master, | |||
| 336 | * resulting (potentially) in more interrupts when transferring | 333 | * resulting (potentially) in more interrupts when transferring |
| 337 | * more than 12 bytes | 334 | * more than 12 bytes |
| 338 | */ | 335 | */ |
| 339 | bs->cntl[0] = BCM2835_AUX_SPI_CNTL0_ENABLE | | ||
| 340 | BCM2835_AUX_SPI_CNTL0_VAR_WIDTH | | ||
| 341 | BCM2835_AUX_SPI_CNTL0_MSBF_OUT; | ||
| 342 | bs->cntl[1] = BCM2835_AUX_SPI_CNTL1_MSBF_IN; | ||
| 343 | 336 | ||
| 344 | /* set clock */ | 337 | /* set clock */ |
| 345 | spi_hz = tfr->speed_hz; | 338 | spi_hz = tfr->speed_hz; |
| @@ -354,17 +347,13 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master, | |||
| 354 | } else { /* the slowest we can go */ | 347 | } else { /* the slowest we can go */ |
| 355 | speed = BCM2835_AUX_SPI_CNTL0_SPEED_MAX; | 348 | speed = BCM2835_AUX_SPI_CNTL0_SPEED_MAX; |
| 356 | } | 349 | } |
| 350 | /* mask out old speed from previous spi_transfer */ | ||
| 351 | bs->cntl[0] &= ~(BCM2835_AUX_SPI_CNTL0_SPEED); | ||
| 352 | /* set the new speed */ | ||
| 357 | bs->cntl[0] |= speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT; | 353 | bs->cntl[0] |= speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT; |
| 358 | 354 | ||
| 359 | spi_used_hz = clk_hz / (2 * (speed + 1)); | 355 | spi_used_hz = clk_hz / (2 * (speed + 1)); |
| 360 | 356 | ||
| 361 | /* handle all the modes */ | ||
| 362 | if (spi->mode & SPI_CPOL) | ||
| 363 | bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPOL; | ||
| 364 | if (spi->mode & SPI_CPHA) | ||
| 365 | bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPHA_OUT | | ||
| 366 | BCM2835_AUX_SPI_CNTL0_CPHA_IN; | ||
| 367 | |||
| 368 | /* set transmit buffers and length */ | 357 | /* set transmit buffers and length */ |
| 369 | bs->tx_buf = tfr->tx_buf; | 358 | bs->tx_buf = tfr->tx_buf; |
| 370 | bs->rx_buf = tfr->rx_buf; | 359 | bs->rx_buf = tfr->rx_buf; |
| @@ -388,6 +377,40 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master, | |||
| 388 | return bcm2835aux_spi_transfer_one_irq(master, spi, tfr); | 377 | return bcm2835aux_spi_transfer_one_irq(master, spi, tfr); |
| 389 | } | 378 | } |
| 390 | 379 | ||
| 380 | static int bcm2835aux_spi_prepare_message(struct spi_master *master, | ||
| 381 | struct spi_message *msg) | ||
| 382 | { | ||
| 383 | struct spi_device *spi = msg->spi; | ||
| 384 | struct bcm2835aux_spi *bs = spi_master_get_devdata(master); | ||
| 385 | |||
| 386 | bs->cntl[0] = BCM2835_AUX_SPI_CNTL0_ENABLE | | ||
| 387 | BCM2835_AUX_SPI_CNTL0_VAR_WIDTH | | ||
| 388 | BCM2835_AUX_SPI_CNTL0_MSBF_OUT; | ||
| 389 | bs->cntl[1] = BCM2835_AUX_SPI_CNTL1_MSBF_IN; | ||
| 390 | |||
| 391 | /* handle all the modes */ | ||
| 392 | if (spi->mode & SPI_CPOL) | ||
| 393 | bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPOL; | ||
| 394 | if (spi->mode & SPI_CPHA) | ||
| 395 | bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPHA_OUT | | ||
| 396 | BCM2835_AUX_SPI_CNTL0_CPHA_IN; | ||
| 397 | |||
| 398 | bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]); | ||
| 399 | bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]); | ||
| 400 | |||
| 401 | return 0; | ||
| 402 | } | ||
| 403 | |||
| 404 | static int bcm2835aux_spi_unprepare_message(struct spi_master *master, | ||
| 405 | struct spi_message *msg) | ||
| 406 | { | ||
| 407 | struct bcm2835aux_spi *bs = spi_master_get_devdata(master); | ||
| 408 | |||
| 409 | bcm2835aux_spi_reset_hw(bs); | ||
| 410 | |||
| 411 | return 0; | ||
| 412 | } | ||
| 413 | |||
| 391 | static void bcm2835aux_spi_handle_err(struct spi_master *master, | 414 | static void bcm2835aux_spi_handle_err(struct spi_master *master, |
| 392 | struct spi_message *msg) | 415 | struct spi_message *msg) |
| 393 | { | 416 | { |
| @@ -416,6 +439,8 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) | |||
| 416 | master->num_chipselect = -1; | 439 | master->num_chipselect = -1; |
| 417 | master->transfer_one = bcm2835aux_spi_transfer_one; | 440 | master->transfer_one = bcm2835aux_spi_transfer_one; |
| 418 | master->handle_err = bcm2835aux_spi_handle_err; | 441 | master->handle_err = bcm2835aux_spi_handle_err; |
| 442 | master->prepare_message = bcm2835aux_spi_prepare_message; | ||
| 443 | master->unprepare_message = bcm2835aux_spi_unprepare_message; | ||
| 419 | master->dev.of_node = pdev->dev.of_node; | 444 | master->dev.of_node = pdev->dev.of_node; |
| 420 | 445 | ||
| 421 | bs = spi_master_get_devdata(master); | 446 | bs = spi_master_get_devdata(master); |
