diff options
-rw-r--r-- | drivers/spi/spi-fsl-lib.h | 1 | ||||
-rw-r--r-- | drivers/spi/spi-fsl-spi.c | 50 |
2 files changed, 46 insertions, 5 deletions
diff --git a/drivers/spi/spi-fsl-lib.h b/drivers/spi/spi-fsl-lib.h index d5c788b584df..52db6936778e 100644 --- a/drivers/spi/spi-fsl-lib.h +++ b/drivers/spi/spi-fsl-lib.h | |||
@@ -71,6 +71,7 @@ struct mpc8xxx_spi { | |||
71 | 71 | ||
72 | #ifdef CONFIG_SPI_FSL_SPI | 72 | #ifdef CONFIG_SPI_FSL_SPI |
73 | int type; | 73 | int type; |
74 | int native_chipselects; | ||
74 | u8 max_bits_per_word; | 75 | u8 max_bits_per_word; |
75 | 76 | ||
76 | void (*set_shifts)(u32 *rx_shift, u32 *tx_shift, | 77 | void (*set_shifts)(u32 *rx_shift, u32 *tx_shift, |
diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c index 6846459e5c9d..14e202ee7036 100644 --- a/drivers/spi/spi-fsl-spi.c +++ b/drivers/spi/spi-fsl-spi.c | |||
@@ -456,12 +456,46 @@ static int fsl_spi_setup(struct spi_device *spi) | |||
456 | return retval; | 456 | return retval; |
457 | } | 457 | } |
458 | 458 | ||
459 | if (mpc8xxx_spi->type == TYPE_GRLIB) { | ||
460 | if (gpio_is_valid(spi->cs_gpio)) { | ||
461 | int desel; | ||
462 | |||
463 | retval = gpio_request(spi->cs_gpio, | ||
464 | dev_name(&spi->dev)); | ||
465 | if (retval) | ||
466 | return retval; | ||
467 | |||
468 | desel = !(spi->mode & SPI_CS_HIGH); | ||
469 | retval = gpio_direction_output(spi->cs_gpio, desel); | ||
470 | if (retval) { | ||
471 | gpio_free(spi->cs_gpio); | ||
472 | return retval; | ||
473 | } | ||
474 | } else if (spi->cs_gpio != -ENOENT) { | ||
475 | if (spi->cs_gpio < 0) | ||
476 | return spi->cs_gpio; | ||
477 | return -EINVAL; | ||
478 | } | ||
479 | /* When spi->cs_gpio == -ENOENT, a hole in the phandle list | ||
480 | * indicates to use native chipselect if present, or allow for | ||
481 | * an always selected chip | ||
482 | */ | ||
483 | } | ||
484 | |||
459 | /* Initialize chipselect - might be active for SPI_CS_HIGH mode */ | 485 | /* Initialize chipselect - might be active for SPI_CS_HIGH mode */ |
460 | fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE); | 486 | fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE); |
461 | 487 | ||
462 | return 0; | 488 | return 0; |
463 | } | 489 | } |
464 | 490 | ||
491 | static void fsl_spi_cleanup(struct spi_device *spi) | ||
492 | { | ||
493 | struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); | ||
494 | |||
495 | if (mpc8xxx_spi->type == TYPE_GRLIB && gpio_is_valid(spi->cs_gpio)) | ||
496 | gpio_free(spi->cs_gpio); | ||
497 | } | ||
498 | |||
465 | static void fsl_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) | 499 | static void fsl_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) |
466 | { | 500 | { |
467 | struct fsl_spi_reg *reg_base = mspi->reg_base; | 501 | struct fsl_spi_reg *reg_base = mspi->reg_base; |
@@ -529,9 +563,13 @@ static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on) | |||
529 | u32 slvsel; | 563 | u32 slvsel; |
530 | u16 cs = spi->chip_select; | 564 | u16 cs = spi->chip_select; |
531 | 565 | ||
532 | slvsel = mpc8xxx_spi_read_reg(®_base->slvsel); | 566 | if (gpio_is_valid(spi->cs_gpio)) { |
533 | slvsel = on ? (slvsel | (1 << cs)) : (slvsel & ~(1 << cs)); | 567 | gpio_set_value(spi->cs_gpio, on); |
534 | mpc8xxx_spi_write_reg(®_base->slvsel, slvsel); | 568 | } else if (cs < mpc8xxx_spi->native_chipselects) { |
569 | slvsel = mpc8xxx_spi_read_reg(®_base->slvsel); | ||
570 | slvsel = on ? (slvsel | (1 << cs)) : (slvsel & ~(1 << cs)); | ||
571 | mpc8xxx_spi_write_reg(®_base->slvsel, slvsel); | ||
572 | } | ||
535 | } | 573 | } |
536 | 574 | ||
537 | static void fsl_spi_grlib_probe(struct device *dev) | 575 | static void fsl_spi_grlib_probe(struct device *dev) |
@@ -550,11 +588,12 @@ static void fsl_spi_grlib_probe(struct device *dev) | |||
550 | if (mbits) | 588 | if (mbits) |
551 | mpc8xxx_spi->max_bits_per_word = mbits + 1; | 589 | mpc8xxx_spi->max_bits_per_word = mbits + 1; |
552 | 590 | ||
553 | master->num_chipselect = 1; /* Allow for an always selected chip */ | 591 | mpc8xxx_spi->native_chipselects = 0; |
554 | if (SPCAP_SSEN(capabilities)) { | 592 | if (SPCAP_SSEN(capabilities)) { |
555 | master->num_chipselect = SPCAP_SSSZ(capabilities); | 593 | mpc8xxx_spi->native_chipselects = SPCAP_SSSZ(capabilities); |
556 | mpc8xxx_spi_write_reg(®_base->slvsel, 0xffffffff); | 594 | mpc8xxx_spi_write_reg(®_base->slvsel, 0xffffffff); |
557 | } | 595 | } |
596 | master->num_chipselect = mpc8xxx_spi->native_chipselects; | ||
558 | pdata->cs_control = fsl_spi_grlib_cs_control; | 597 | pdata->cs_control = fsl_spi_grlib_cs_control; |
559 | } | 598 | } |
560 | 599 | ||
@@ -581,6 +620,7 @@ static struct spi_master * fsl_spi_probe(struct device *dev, | |||
581 | goto err_probe; | 620 | goto err_probe; |
582 | 621 | ||
583 | master->setup = fsl_spi_setup; | 622 | master->setup = fsl_spi_setup; |
623 | master->cleanup = fsl_spi_cleanup; | ||
584 | 624 | ||
585 | mpc8xxx_spi = spi_master_get_devdata(master); | 625 | mpc8xxx_spi = spi_master_get_devdata(master); |
586 | mpc8xxx_spi->spi_do_one_msg = fsl_spi_do_one_msg; | 626 | mpc8xxx_spi->spi_do_one_msg = fsl_spi_do_one_msg; |