diff options
Diffstat (limited to 'drivers/spi/spi-fsl-dspi.c')
| -rw-r--r-- | drivers/spi/spi-fsl-dspi.c | 163 |
1 files changed, 86 insertions, 77 deletions
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 4cda994d3f40..d1a39249704a 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c | |||
| @@ -106,7 +106,7 @@ struct chip_data { | |||
| 106 | }; | 106 | }; |
| 107 | 107 | ||
| 108 | struct fsl_dspi { | 108 | struct fsl_dspi { |
| 109 | struct spi_bitbang bitbang; | 109 | struct spi_master *master; |
| 110 | struct platform_device *pdev; | 110 | struct platform_device *pdev; |
| 111 | 111 | ||
| 112 | struct regmap *regmap; | 112 | struct regmap *regmap; |
| @@ -114,6 +114,7 @@ struct fsl_dspi { | |||
| 114 | struct clk *clk; | 114 | struct clk *clk; |
| 115 | 115 | ||
| 116 | struct spi_transfer *cur_transfer; | 116 | struct spi_transfer *cur_transfer; |
| 117 | struct spi_message *cur_msg; | ||
| 117 | struct chip_data *cur_chip; | 118 | struct chip_data *cur_chip; |
| 118 | size_t len; | 119 | size_t len; |
| 119 | void *tx; | 120 | void *tx; |
| @@ -123,6 +124,7 @@ struct fsl_dspi { | |||
| 123 | char dataflags; | 124 | char dataflags; |
| 124 | u8 cs; | 125 | u8 cs; |
| 125 | u16 void_write_data; | 126 | u16 void_write_data; |
| 127 | u32 cs_change; | ||
| 126 | 128 | ||
| 127 | wait_queue_head_t waitq; | 129 | wait_queue_head_t waitq; |
| 128 | u32 waitflags; | 130 | u32 waitflags; |
| @@ -225,6 +227,8 @@ static int dspi_transfer_write(struct fsl_dspi *dspi) | |||
| 225 | if (dspi->len == 0 || tx_count == DSPI_FIFO_SIZE - 1) { | 227 | if (dspi->len == 0 || tx_count == DSPI_FIFO_SIZE - 1) { |
| 226 | /* last transfer in the transfer */ | 228 | /* last transfer in the transfer */ |
| 227 | dspi_pushr |= SPI_PUSHR_EOQ; | 229 | dspi_pushr |= SPI_PUSHR_EOQ; |
| 230 | if ((dspi->cs_change) && (!dspi->len)) | ||
| 231 | dspi_pushr &= ~SPI_PUSHR_CONT; | ||
| 228 | } else if (tx_word && (dspi->len == 1)) | 232 | } else if (tx_word && (dspi->len == 1)) |
| 229 | dspi_pushr |= SPI_PUSHR_EOQ; | 233 | dspi_pushr |= SPI_PUSHR_EOQ; |
| 230 | 234 | ||
| @@ -246,6 +250,7 @@ static int dspi_transfer_read(struct fsl_dspi *dspi) | |||
| 246 | int rx_count = 0; | 250 | int rx_count = 0; |
| 247 | int rx_word = is_double_byte_mode(dspi); | 251 | int rx_word = is_double_byte_mode(dspi); |
| 248 | u16 d; | 252 | u16 d; |
| 253 | |||
| 249 | while ((dspi->rx < dspi->rx_end) | 254 | while ((dspi->rx < dspi->rx_end) |
| 250 | && (rx_count < DSPI_FIFO_SIZE)) { | 255 | && (rx_count < DSPI_FIFO_SIZE)) { |
| 251 | if (rx_word) { | 256 | if (rx_word) { |
| @@ -276,86 +281,89 @@ static int dspi_transfer_read(struct fsl_dspi *dspi) | |||
| 276 | return rx_count; | 281 | return rx_count; |
| 277 | } | 282 | } |
| 278 | 283 | ||
| 279 | static int dspi_txrx_transfer(struct spi_device *spi, struct spi_transfer *t) | 284 | static int dspi_transfer_one_message(struct spi_master *master, |
| 285 | struct spi_message *message) | ||
| 280 | { | 286 | { |
| 281 | struct fsl_dspi *dspi = spi_master_get_devdata(spi->master); | 287 | struct fsl_dspi *dspi = spi_master_get_devdata(master); |
| 282 | dspi->cur_transfer = t; | 288 | struct spi_device *spi = message->spi; |
| 283 | dspi->cur_chip = spi_get_ctldata(spi); | 289 | struct spi_transfer *transfer; |
| 284 | dspi->cs = spi->chip_select; | 290 | int status = 0; |
| 285 | dspi->void_write_data = dspi->cur_chip->void_write_data; | 291 | message->actual_length = 0; |
| 286 | 292 | ||
| 287 | dspi->dataflags = 0; | 293 | list_for_each_entry(transfer, &message->transfers, transfer_list) { |
| 288 | dspi->tx = (void *)t->tx_buf; | 294 | dspi->cur_transfer = transfer; |
| 289 | dspi->tx_end = dspi->tx + t->len; | 295 | dspi->cur_msg = message; |
| 290 | dspi->rx = t->rx_buf; | 296 | dspi->cur_chip = spi_get_ctldata(spi); |
| 291 | dspi->rx_end = dspi->rx + t->len; | 297 | dspi->cs = spi->chip_select; |
| 292 | dspi->len = t->len; | 298 | if (dspi->cur_transfer->transfer_list.next |
| 293 | 299 | == &dspi->cur_msg->transfers) | |
| 294 | if (!dspi->rx) | 300 | transfer->cs_change = 1; |
| 295 | dspi->dataflags |= TRAN_STATE_RX_VOID; | 301 | dspi->cs_change = transfer->cs_change; |
| 296 | 302 | dspi->void_write_data = dspi->cur_chip->void_write_data; | |
| 297 | if (!dspi->tx) | 303 | |
| 298 | dspi->dataflags |= TRAN_STATE_TX_VOID; | 304 | dspi->dataflags = 0; |
| 299 | 305 | dspi->tx = (void *)transfer->tx_buf; | |
| 300 | regmap_write(dspi->regmap, SPI_MCR, dspi->cur_chip->mcr_val); | 306 | dspi->tx_end = dspi->tx + transfer->len; |
| 301 | regmap_write(dspi->regmap, SPI_CTAR(dspi->cs), dspi->cur_chip->ctar_val); | 307 | dspi->rx = transfer->rx_buf; |
| 302 | regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_EOQFE); | 308 | dspi->rx_end = dspi->rx + transfer->len; |
| 303 | 309 | dspi->len = transfer->len; | |
| 304 | if (t->speed_hz) | 310 | |
| 311 | if (!dspi->rx) | ||
| 312 | dspi->dataflags |= TRAN_STATE_RX_VOID; | ||
| 313 | |||
| 314 | if (!dspi->tx) | ||
| 315 | dspi->dataflags |= TRAN_STATE_TX_VOID; | ||
| 316 | |||
| 317 | regmap_write(dspi->regmap, SPI_MCR, dspi->cur_chip->mcr_val); | ||
| 318 | regmap_update_bits(dspi->regmap, SPI_MCR, | ||
| 319 | SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF, | ||
| 320 | SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF); | ||
| 305 | regmap_write(dspi->regmap, SPI_CTAR(dspi->cs), | 321 | regmap_write(dspi->regmap, SPI_CTAR(dspi->cs), |
| 306 | dspi->cur_chip->ctar_val); | 322 | dspi->cur_chip->ctar_val); |
| 323 | if (transfer->speed_hz) | ||
| 324 | regmap_write(dspi->regmap, SPI_CTAR(dspi->cs), | ||
| 325 | dspi->cur_chip->ctar_val); | ||
| 307 | 326 | ||
| 308 | dspi_transfer_write(dspi); | 327 | regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_EOQFE); |
| 328 | message->actual_length += dspi_transfer_write(dspi); | ||
| 309 | 329 | ||
| 310 | if (wait_event_interruptible(dspi->waitq, dspi->waitflags)) | 330 | if (wait_event_interruptible(dspi->waitq, dspi->waitflags)) |
| 311 | dev_err(&dspi->pdev->dev, "wait transfer complete fail!\n"); | 331 | dev_err(&dspi->pdev->dev, "wait transfer complete fail!\n"); |
| 312 | dspi->waitflags = 0; | 332 | dspi->waitflags = 0; |
| 313 | |||
| 314 | return t->len - dspi->len; | ||
| 315 | } | ||
| 316 | 333 | ||
| 317 | static void dspi_chipselect(struct spi_device *spi, int value) | 334 | if (transfer->delay_usecs) |
| 318 | { | 335 | udelay(transfer->delay_usecs); |
| 319 | struct fsl_dspi *dspi = spi_master_get_devdata(spi->master); | ||
| 320 | unsigned int pushr; | ||
| 321 | |||
| 322 | regmap_read(dspi->regmap, SPI_PUSHR, &pushr); | ||
| 323 | |||
| 324 | switch (value) { | ||
| 325 | case BITBANG_CS_ACTIVE: | ||
| 326 | pushr |= SPI_PUSHR_CONT; | ||
| 327 | break; | ||
| 328 | case BITBANG_CS_INACTIVE: | ||
| 329 | pushr &= ~SPI_PUSHR_CONT; | ||
| 330 | break; | ||
| 331 | } | 336 | } |
| 332 | 337 | ||
| 333 | regmap_write(dspi->regmap, SPI_PUSHR, pushr); | 338 | message->status = status; |
| 339 | spi_finalize_current_message(master); | ||
| 340 | |||
| 341 | return status; | ||
| 334 | } | 342 | } |
| 335 | 343 | ||
| 336 | static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) | 344 | static int dspi_setup(struct spi_device *spi) |
| 337 | { | 345 | { |
| 338 | struct chip_data *chip; | 346 | struct chip_data *chip; |
| 339 | struct fsl_dspi *dspi = spi_master_get_devdata(spi->master); | 347 | struct fsl_dspi *dspi = spi_master_get_devdata(spi->master); |
| 340 | unsigned char br = 0, pbr = 0, fmsz = 0; | 348 | unsigned char br = 0, pbr = 0, fmsz = 0; |
| 341 | 349 | ||
| 350 | if ((spi->bits_per_word >= 4) && (spi->bits_per_word <= 16)) { | ||
| 351 | fmsz = spi->bits_per_word - 1; | ||
| 352 | } else { | ||
| 353 | pr_err("Invalid wordsize\n"); | ||
| 354 | return -ENODEV; | ||
| 355 | } | ||
| 356 | |||
| 342 | /* Only alloc on first setup */ | 357 | /* Only alloc on first setup */ |
| 343 | chip = spi_get_ctldata(spi); | 358 | chip = spi_get_ctldata(spi); |
| 344 | if (chip == NULL) { | 359 | if (chip == NULL) { |
| 345 | chip = devm_kzalloc(&spi->dev, sizeof(struct chip_data), | 360 | chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); |
| 346 | GFP_KERNEL); | ||
| 347 | if (!chip) | 361 | if (!chip) |
| 348 | return -ENOMEM; | 362 | return -ENOMEM; |
| 349 | } | 363 | } |
| 350 | 364 | ||
| 351 | chip->mcr_val = SPI_MCR_MASTER | SPI_MCR_PCSIS | | 365 | chip->mcr_val = SPI_MCR_MASTER | SPI_MCR_PCSIS | |
| 352 | SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF; | 366 | SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF; |
| 353 | if ((spi->bits_per_word >= 4) && (spi->bits_per_word <= 16)) { | ||
| 354 | fmsz = spi->bits_per_word - 1; | ||
| 355 | } else { | ||
| 356 | pr_err("Invalid wordsize\n"); | ||
| 357 | return -ENODEV; | ||
| 358 | } | ||
| 359 | 367 | ||
| 360 | chip->void_write_data = 0; | 368 | chip->void_write_data = 0; |
| 361 | 369 | ||
| @@ -374,34 +382,34 @@ static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) | |||
| 374 | return 0; | 382 | return 0; |
| 375 | } | 383 | } |
| 376 | 384 | ||
| 377 | static int dspi_setup(struct spi_device *spi) | 385 | static void dspi_cleanup(struct spi_device *spi) |
| 378 | { | 386 | { |
| 379 | if (!spi->max_speed_hz) | 387 | struct chip_data *chip = spi_get_ctldata((struct spi_device *)spi); |
| 380 | return -EINVAL; | 388 | |
| 389 | dev_dbg(&spi->dev, "spi_device %u.%u cleanup\n", | ||
| 390 | spi->master->bus_num, spi->chip_select); | ||
| 381 | 391 | ||
| 382 | return dspi_setup_transfer(spi, NULL); | 392 | kfree(chip); |
| 383 | } | 393 | } |
| 384 | 394 | ||
| 385 | static irqreturn_t dspi_interrupt(int irq, void *dev_id) | 395 | static irqreturn_t dspi_interrupt(int irq, void *dev_id) |
| 386 | { | 396 | { |
| 387 | struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id; | 397 | struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id; |
| 388 | 398 | ||
| 389 | regmap_write(dspi->regmap, SPI_SR, SPI_SR_EOQF); | 399 | struct spi_message *msg = dspi->cur_msg; |
| 390 | 400 | ||
| 401 | regmap_write(dspi->regmap, SPI_SR, SPI_SR_EOQF); | ||
| 391 | dspi_transfer_read(dspi); | 402 | dspi_transfer_read(dspi); |
| 392 | 403 | ||
| 393 | if (!dspi->len) { | 404 | if (!dspi->len) { |
| 394 | if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM) | 405 | if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM) |
| 395 | regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs), | 406 | regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs), |
| 396 | SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(16)); | 407 | SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(16)); |
| 397 | 408 | ||
| 398 | dspi->waitflags = 1; | 409 | dspi->waitflags = 1; |
| 399 | wake_up_interruptible(&dspi->waitq); | 410 | wake_up_interruptible(&dspi->waitq); |
| 400 | } else { | 411 | } else |
| 401 | dspi_transfer_write(dspi); | 412 | msg->actual_length += dspi_transfer_write(dspi); |
| 402 | |||
| 403 | return IRQ_HANDLED; | ||
| 404 | } | ||
| 405 | 413 | ||
| 406 | return IRQ_HANDLED; | 414 | return IRQ_HANDLED; |
| 407 | } | 415 | } |
| @@ -460,13 +468,14 @@ static int dspi_probe(struct platform_device *pdev) | |||
| 460 | 468 | ||
| 461 | dspi = spi_master_get_devdata(master); | 469 | dspi = spi_master_get_devdata(master); |
| 462 | dspi->pdev = pdev; | 470 | dspi->pdev = pdev; |
| 463 | dspi->bitbang.master = master; | 471 | dspi->master = master; |
| 464 | dspi->bitbang.chipselect = dspi_chipselect; | 472 | |
| 465 | dspi->bitbang.setup_transfer = dspi_setup_transfer; | 473 | master->transfer = NULL; |
| 466 | dspi->bitbang.txrx_bufs = dspi_txrx_transfer; | 474 | master->setup = dspi_setup; |
| 467 | dspi->bitbang.master->setup = dspi_setup; | 475 | master->transfer_one_message = dspi_transfer_one_message; |
| 468 | dspi->bitbang.master->dev.of_node = pdev->dev.of_node; | 476 | master->dev.of_node = pdev->dev.of_node; |
| 469 | 477 | ||
| 478 | master->cleanup = dspi_cleanup; | ||
| 470 | master->mode_bits = SPI_CPOL | SPI_CPHA; | 479 | master->mode_bits = SPI_CPOL | SPI_CPHA; |
| 471 | master->bits_per_word_mask = SPI_BPW_MASK(4) | SPI_BPW_MASK(8) | | 480 | master->bits_per_word_mask = SPI_BPW_MASK(4) | SPI_BPW_MASK(8) | |
| 472 | SPI_BPW_MASK(16); | 481 | SPI_BPW_MASK(16); |
| @@ -525,7 +534,7 @@ static int dspi_probe(struct platform_device *pdev) | |||
| 525 | init_waitqueue_head(&dspi->waitq); | 534 | init_waitqueue_head(&dspi->waitq); |
| 526 | platform_set_drvdata(pdev, master); | 535 | platform_set_drvdata(pdev, master); |
| 527 | 536 | ||
| 528 | ret = spi_bitbang_start(&dspi->bitbang); | 537 | ret = spi_register_master(master); |
| 529 | if (ret != 0) { | 538 | if (ret != 0) { |
| 530 | dev_err(&pdev->dev, "Problem registering DSPI master\n"); | 539 | dev_err(&pdev->dev, "Problem registering DSPI master\n"); |
| 531 | goto out_clk_put; | 540 | goto out_clk_put; |
| @@ -547,9 +556,9 @@ static int dspi_remove(struct platform_device *pdev) | |||
| 547 | struct fsl_dspi *dspi = spi_master_get_devdata(master); | 556 | struct fsl_dspi *dspi = spi_master_get_devdata(master); |
| 548 | 557 | ||
| 549 | /* Disconnect from the SPI framework */ | 558 | /* Disconnect from the SPI framework */ |
| 550 | spi_bitbang_stop(&dspi->bitbang); | ||
| 551 | clk_disable_unprepare(dspi->clk); | 559 | clk_disable_unprepare(dspi->clk); |
| 552 | spi_master_put(dspi->bitbang.master); | 560 | spi_unregister_master(dspi->master); |
| 561 | spi_master_put(dspi->master); | ||
| 553 | 562 | ||
| 554 | return 0; | 563 | return 0; |
| 555 | } | 564 | } |
