diff options
author | Qipan Li <Qipan.Li@csr.com> | 2014-09-02 05:01:01 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2014-09-04 15:20:15 -0400 |
commit | 7850cdfc8028cc7d522c032f64c62c1c01e85875 (patch) | |
tree | fe03078fee1cc8700136b73f46a4abd71c823efd | |
parent | 7d1311b93e58ed55f3a31cc8f94c4b8fe988a2b9 (diff) |
spi: sirf: correct spi gpio and hardware chipselect behaviour
the old codes check the cs-gpios, if the gpio number is 0 like:
<&gpio, 0, 0>, the driver will use the only hardware chipselect.
this is wrong because of_spi_register_master() can read property
cs-gpios from device node and set the spi master's cs number and
gpio cs automatically based on whether the cs-gpios is valid.
this patch fixes the beviour of CSR spi driver and move to a core
level supported way.
Signed-off-by: Qipan Li <Qipan.Li@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | drivers/spi/spi-sirf.c | 86 |
1 files changed, 33 insertions, 53 deletions
diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c index 95ac276eaafe..44ec3bbbf5a4 100644 --- a/drivers/spi/spi-sirf.c +++ b/drivers/spi/spi-sirf.c | |||
@@ -170,8 +170,7 @@ struct sirfsoc_spi { | |||
170 | * command model | 170 | * command model |
171 | */ | 171 | */ |
172 | bool tx_by_cmd; | 172 | bool tx_by_cmd; |
173 | 173 | bool hw_cs; | |
174 | int chipselect[0]; | ||
175 | }; | 174 | }; |
176 | 175 | ||
177 | static void spi_sirfsoc_rx_word_u8(struct sirfsoc_spi *sspi) | 176 | static void spi_sirfsoc_rx_word_u8(struct sirfsoc_spi *sspi) |
@@ -484,7 +483,7 @@ static void spi_sirfsoc_chipselect(struct spi_device *spi, int value) | |||
484 | { | 483 | { |
485 | struct sirfsoc_spi *sspi = spi_master_get_devdata(spi->master); | 484 | struct sirfsoc_spi *sspi = spi_master_get_devdata(spi->master); |
486 | 485 | ||
487 | if (sspi->chipselect[spi->chip_select] == 0) { | 486 | if (sspi->hw_cs) { |
488 | u32 regval = readl(sspi->base + SIRFSOC_SPI_CTRL); | 487 | u32 regval = readl(sspi->base + SIRFSOC_SPI_CTRL); |
489 | switch (value) { | 488 | switch (value) { |
490 | case BITBANG_CS_ACTIVE: | 489 | case BITBANG_CS_ACTIVE: |
@@ -502,14 +501,13 @@ static void spi_sirfsoc_chipselect(struct spi_device *spi, int value) | |||
502 | } | 501 | } |
503 | writel(regval, sspi->base + SIRFSOC_SPI_CTRL); | 502 | writel(regval, sspi->base + SIRFSOC_SPI_CTRL); |
504 | } else { | 503 | } else { |
505 | int gpio = sspi->chipselect[spi->chip_select]; | ||
506 | switch (value) { | 504 | switch (value) { |
507 | case BITBANG_CS_ACTIVE: | 505 | case BITBANG_CS_ACTIVE: |
508 | gpio_direction_output(gpio, | 506 | gpio_direction_output(spi->cs_gpio, |
509 | spi->mode & SPI_CS_HIGH ? 1 : 0); | 507 | spi->mode & SPI_CS_HIGH ? 1 : 0); |
510 | break; | 508 | break; |
511 | case BITBANG_CS_INACTIVE: | 509 | case BITBANG_CS_INACTIVE: |
512 | gpio_direction_output(gpio, | 510 | gpio_direction_output(spi->cs_gpio, |
513 | spi->mode & SPI_CS_HIGH ? 0 : 1); | 511 | spi->mode & SPI_CS_HIGH ? 0 : 1); |
514 | break; | 512 | break; |
515 | } | 513 | } |
@@ -603,8 +601,8 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) | |||
603 | sspi->tx_by_cmd = false; | 601 | sspi->tx_by_cmd = false; |
604 | } | 602 | } |
605 | /* | 603 | /* |
606 | * set spi controller in RISC chipselect mode, we are controlling CS by | 604 | * it should never set to hardware cs mode because in hardware cs mode, |
607 | * software BITBANG_CS_ACTIVE and BITBANG_CS_INACTIVE. | 605 | * cs signal can't controlled by driver. |
608 | */ | 606 | */ |
609 | regval |= SIRFSOC_SPI_CS_IO_MODE; | 607 | regval |= SIRFSOC_SPI_CS_IO_MODE; |
610 | writel(regval, sspi->base + SIRFSOC_SPI_CTRL); | 608 | writel(regval, sspi->base + SIRFSOC_SPI_CTRL); |
@@ -627,9 +625,17 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) | |||
627 | 625 | ||
628 | static int spi_sirfsoc_setup(struct spi_device *spi) | 626 | static int spi_sirfsoc_setup(struct spi_device *spi) |
629 | { | 627 | { |
628 | struct sirfsoc_spi *sspi; | ||
629 | |||
630 | if (!spi->max_speed_hz) | 630 | if (!spi->max_speed_hz) |
631 | return -EINVAL; | 631 | return -EINVAL; |
632 | 632 | ||
633 | sspi = spi_master_get_devdata(spi->master); | ||
634 | |||
635 | if (spi->cs_gpio == -ENOENT) | ||
636 | sspi->hw_cs = true; | ||
637 | else | ||
638 | sspi->hw_cs = false; | ||
633 | return spi_sirfsoc_setup_transfer(spi, NULL); | 639 | return spi_sirfsoc_setup_transfer(spi, NULL); |
634 | } | 640 | } |
635 | 641 | ||
@@ -638,19 +644,10 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) | |||
638 | struct sirfsoc_spi *sspi; | 644 | struct sirfsoc_spi *sspi; |
639 | struct spi_master *master; | 645 | struct spi_master *master; |
640 | struct resource *mem_res; | 646 | struct resource *mem_res; |
641 | int num_cs, cs_gpio, irq; | 647 | int irq; |
642 | int i; | 648 | int i, ret; |
643 | int ret; | ||
644 | |||
645 | ret = of_property_read_u32(pdev->dev.of_node, | ||
646 | "sirf,spi-num-chipselects", &num_cs); | ||
647 | if (ret < 0) { | ||
648 | dev_err(&pdev->dev, "Unable to get chip select number\n"); | ||
649 | goto err_cs; | ||
650 | } | ||
651 | 649 | ||
652 | master = spi_alloc_master(&pdev->dev, | 650 | master = spi_alloc_master(&pdev->dev, sizeof(*sspi)); |
653 | sizeof(*sspi) + sizeof(int) * num_cs); | ||
654 | if (!master) { | 651 | if (!master) { |
655 | dev_err(&pdev->dev, "Unable to allocate SPI master\n"); | 652 | dev_err(&pdev->dev, "Unable to allocate SPI master\n"); |
656 | return -ENOMEM; | 653 | return -ENOMEM; |
@@ -658,32 +655,6 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) | |||
658 | platform_set_drvdata(pdev, master); | 655 | platform_set_drvdata(pdev, master); |
659 | sspi = spi_master_get_devdata(master); | 656 | sspi = spi_master_get_devdata(master); |
660 | 657 | ||
661 | master->num_chipselect = num_cs; | ||
662 | |||
663 | for (i = 0; i < master->num_chipselect; i++) { | ||
664 | cs_gpio = of_get_named_gpio(pdev->dev.of_node, "cs-gpios", i); | ||
665 | if (cs_gpio < 0) { | ||
666 | dev_err(&pdev->dev, "can't get cs gpio from DT\n"); | ||
667 | ret = -ENODEV; | ||
668 | goto free_master; | ||
669 | } | ||
670 | |||
671 | sspi->chipselect[i] = cs_gpio; | ||
672 | if (cs_gpio == 0) | ||
673 | continue; /* use cs from spi controller */ | ||
674 | |||
675 | ret = gpio_request(cs_gpio, DRIVER_NAME); | ||
676 | if (ret) { | ||
677 | while (i > 0) { | ||
678 | i--; | ||
679 | if (sspi->chipselect[i] > 0) | ||
680 | gpio_free(sspi->chipselect[i]); | ||
681 | } | ||
682 | dev_err(&pdev->dev, "fail to request cs gpios\n"); | ||
683 | goto free_master; | ||
684 | } | ||
685 | } | ||
686 | |||
687 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 658 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
688 | sspi->base = devm_ioremap_resource(&pdev->dev, mem_res); | 659 | sspi->base = devm_ioremap_resource(&pdev->dev, mem_res); |
689 | if (IS_ERR(sspi->base)) { | 660 | if (IS_ERR(sspi->base)) { |
@@ -753,7 +724,21 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) | |||
753 | ret = spi_bitbang_start(&sspi->bitbang); | 724 | ret = spi_bitbang_start(&sspi->bitbang); |
754 | if (ret) | 725 | if (ret) |
755 | goto free_dummypage; | 726 | goto free_dummypage; |
756 | 727 | for (i = 0; master->cs_gpios && i < master->num_chipselect; i++) { | |
728 | if (master->cs_gpios[i] == -ENOENT) | ||
729 | continue; | ||
730 | if (!gpio_is_valid(master->cs_gpios[i])) { | ||
731 | dev_err(&pdev->dev, "no valid gpio\n"); | ||
732 | ret = -EINVAL; | ||
733 | goto free_dummypage; | ||
734 | } | ||
735 | ret = devm_gpio_request(&pdev->dev, | ||
736 | master->cs_gpios[i], DRIVER_NAME); | ||
737 | if (ret) { | ||
738 | dev_err(&pdev->dev, "failed to request gpio\n"); | ||
739 | goto free_dummypage; | ||
740 | } | ||
741 | } | ||
757 | dev_info(&pdev->dev, "registerred, bus number = %d\n", master->bus_num); | 742 | dev_info(&pdev->dev, "registerred, bus number = %d\n", master->bus_num); |
758 | 743 | ||
759 | return 0; | 744 | return 0; |
@@ -768,7 +753,7 @@ free_rx_dma: | |||
768 | dma_release_channel(sspi->rx_chan); | 753 | dma_release_channel(sspi->rx_chan); |
769 | free_master: | 754 | free_master: |
770 | spi_master_put(master); | 755 | spi_master_put(master); |
771 | err_cs: | 756 | |
772 | return ret; | 757 | return ret; |
773 | } | 758 | } |
774 | 759 | ||
@@ -776,16 +761,11 @@ static int spi_sirfsoc_remove(struct platform_device *pdev) | |||
776 | { | 761 | { |
777 | struct spi_master *master; | 762 | struct spi_master *master; |
778 | struct sirfsoc_spi *sspi; | 763 | struct sirfsoc_spi *sspi; |
779 | int i; | ||
780 | 764 | ||
781 | master = platform_get_drvdata(pdev); | 765 | master = platform_get_drvdata(pdev); |
782 | sspi = spi_master_get_devdata(master); | 766 | sspi = spi_master_get_devdata(master); |
783 | 767 | ||
784 | spi_bitbang_stop(&sspi->bitbang); | 768 | spi_bitbang_stop(&sspi->bitbang); |
785 | for (i = 0; i < master->num_chipselect; i++) { | ||
786 | if (sspi->chipselect[i] > 0) | ||
787 | gpio_free(sspi->chipselect[i]); | ||
788 | } | ||
789 | kfree(sspi->dummypage); | 769 | kfree(sspi->dummypage); |
790 | clk_disable_unprepare(sspi->clk); | 770 | clk_disable_unprepare(sspi->clk); |
791 | clk_put(sspi->clk); | 771 | clk_put(sspi->clk); |