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); |
