diff options
author | Shawn Guo <shawn.guo@linaro.org> | 2011-07-09 13:16:41 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2011-07-14 15:47:18 -0400 |
commit | 22a85e4cd51b49ec99703ddfdff8686d5442a093 (patch) | |
tree | ef8ba67b86bd74f67a5f14752a0edb7b72254291 | |
parent | c2387cb9e55f9c85ed33a5bf086f348312158133 (diff) |
spi/imx: add device tree probe support
It adds device tree probe support for spi-imx driver.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-rw-r--r-- | Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt | 22 | ||||
-rw-r--r-- | drivers/spi/spi-imx.c | 38 |
2 files changed, 53 insertions, 7 deletions
diff --git a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt new file mode 100644 index 000000000000..9841057d112b --- /dev/null +++ b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt | |||
@@ -0,0 +1,22 @@ | |||
1 | * Freescale (Enhanced) Configurable Serial Peripheral Interface | ||
2 | (CSPI/eCSPI) for i.MX | ||
3 | |||
4 | Required properties: | ||
5 | - compatible : Should be "fsl,<soc>-cspi" or "fsl,<soc>-ecspi" | ||
6 | - reg : Offset and length of the register set for the device | ||
7 | - interrupts : Should contain CSPI/eCSPI interrupt | ||
8 | - fsl,spi-num-chipselects : Contains the number of the chipselect | ||
9 | - cs-gpios : Specifies the gpio pins to be used for chipselects. | ||
10 | |||
11 | Example: | ||
12 | |||
13 | ecspi@70010000 { | ||
14 | #address-cells = <1>; | ||
15 | #size-cells = <0>; | ||
16 | compatible = "fsl,imx51-ecspi"; | ||
17 | reg = <0x70010000 0x4000>; | ||
18 | interrupts = <36>; | ||
19 | fsl,spi-num-chipselects = <2>; | ||
20 | cs-gpios = <&gpio3 24 0>, /* GPIO4_24 */ | ||
21 | <&gpio3 25 0>; /* GPIO4_25 */ | ||
22 | }; | ||
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 591ebc3546d6..8ac6542aedcd 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c | |||
@@ -34,6 +34,9 @@ | |||
34 | #include <linux/spi/spi.h> | 34 | #include <linux/spi/spi.h> |
35 | #include <linux/spi/spi_bitbang.h> | 35 | #include <linux/spi/spi_bitbang.h> |
36 | #include <linux/types.h> | 36 | #include <linux/types.h> |
37 | #include <linux/of.h> | ||
38 | #include <linux/of_device.h> | ||
39 | #include <linux/of_gpio.h> | ||
37 | 40 | ||
38 | #include <mach/spi.h> | 41 | #include <mach/spi.h> |
39 | 42 | ||
@@ -604,6 +607,16 @@ static struct platform_device_id spi_imx_devtype[] = { | |||
604 | } | 607 | } |
605 | }; | 608 | }; |
606 | 609 | ||
610 | static const struct of_device_id spi_imx_dt_ids[] = { | ||
611 | { .compatible = "fsl,imx1-cspi", .data = &imx1_cspi_devtype_data, }, | ||
612 | { .compatible = "fsl,imx21-cspi", .data = &imx21_cspi_devtype_data, }, | ||
613 | { .compatible = "fsl,imx27-cspi", .data = &imx27_cspi_devtype_data, }, | ||
614 | { .compatible = "fsl,imx31-cspi", .data = &imx31_cspi_devtype_data, }, | ||
615 | { .compatible = "fsl,imx35-cspi", .data = &imx35_cspi_devtype_data, }, | ||
616 | { .compatible = "fsl,imx51-ecspi", .data = &imx51_ecspi_devtype_data, }, | ||
617 | { /* sentinel */ } | ||
618 | }; | ||
619 | |||
607 | static void spi_imx_chipselect(struct spi_device *spi, int is_active) | 620 | static void spi_imx_chipselect(struct spi_device *spi, int is_active) |
608 | { | 621 | { |
609 | struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); | 622 | struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); |
@@ -737,19 +750,25 @@ static void spi_imx_cleanup(struct spi_device *spi) | |||
737 | 750 | ||
738 | static int __devinit spi_imx_probe(struct platform_device *pdev) | 751 | static int __devinit spi_imx_probe(struct platform_device *pdev) |
739 | { | 752 | { |
740 | struct spi_imx_master *mxc_platform_info; | 753 | struct device_node *np = pdev->dev.of_node; |
754 | const struct of_device_id *of_id = | ||
755 | of_match_device(spi_imx_dt_ids, &pdev->dev); | ||
756 | struct spi_imx_master *mxc_platform_info = | ||
757 | dev_get_platdata(&pdev->dev); | ||
741 | struct spi_master *master; | 758 | struct spi_master *master; |
742 | struct spi_imx_data *spi_imx; | 759 | struct spi_imx_data *spi_imx; |
743 | struct resource *res; | 760 | struct resource *res; |
744 | int i, ret, num_cs; | 761 | int i, ret, num_cs; |
745 | 762 | ||
746 | mxc_platform_info = dev_get_platdata(&pdev->dev); | 763 | if (!np && !mxc_platform_info) { |
747 | if (!mxc_platform_info) { | ||
748 | dev_err(&pdev->dev, "can't get the platform data\n"); | 764 | dev_err(&pdev->dev, "can't get the platform data\n"); |
749 | return -EINVAL; | 765 | return -EINVAL; |
750 | } | 766 | } |
751 | 767 | ||
752 | num_cs = mxc_platform_info->num_chipselect; | 768 | ret = of_property_read_u32(np, "fsl,spi-num-chipselects", &num_cs); |
769 | if (ret < 0) | ||
770 | num_cs = mxc_platform_info->num_chipselect; | ||
771 | |||
753 | master = spi_alloc_master(&pdev->dev, | 772 | master = spi_alloc_master(&pdev->dev, |
754 | sizeof(struct spi_imx_data) + sizeof(int) * num_cs); | 773 | sizeof(struct spi_imx_data) + sizeof(int) * num_cs); |
755 | if (!master) | 774 | if (!master) |
@@ -764,9 +783,12 @@ static int __devinit spi_imx_probe(struct platform_device *pdev) | |||
764 | spi_imx->bitbang.master = spi_master_get(master); | 783 | spi_imx->bitbang.master = spi_master_get(master); |
765 | 784 | ||
766 | for (i = 0; i < master->num_chipselect; i++) { | 785 | for (i = 0; i < master->num_chipselect; i++) { |
767 | spi_imx->chipselect[i] = mxc_platform_info->chipselect[i]; | 786 | int cs_gpio = of_get_named_gpio(np, "cs-gpios", i); |
768 | if (spi_imx->chipselect[i] < 0) | 787 | if (cs_gpio < 0) |
788 | cs_gpio = mxc_platform_info->chipselect[i]; | ||
789 | if (cs_gpio < 0) | ||
769 | continue; | 790 | continue; |
791 | spi_imx->chipselect[i] = cs_gpio; | ||
770 | ret = gpio_request(spi_imx->chipselect[i], DRIVER_NAME); | 792 | ret = gpio_request(spi_imx->chipselect[i], DRIVER_NAME); |
771 | if (ret) { | 793 | if (ret) { |
772 | while (i > 0) { | 794 | while (i > 0) { |
@@ -788,7 +810,7 @@ static int __devinit spi_imx_probe(struct platform_device *pdev) | |||
788 | 810 | ||
789 | init_completion(&spi_imx->xfer_done); | 811 | init_completion(&spi_imx->xfer_done); |
790 | 812 | ||
791 | spi_imx->devtype_data = | 813 | spi_imx->devtype_data = of_id ? of_id->data : |
792 | (struct spi_imx_devtype_data *) pdev->id_entry->driver_data; | 814 | (struct spi_imx_devtype_data *) pdev->id_entry->driver_data; |
793 | 815 | ||
794 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 816 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -836,6 +858,7 @@ static int __devinit spi_imx_probe(struct platform_device *pdev) | |||
836 | 858 | ||
837 | spi_imx->devtype_data->intctrl(spi_imx, 0); | 859 | spi_imx->devtype_data->intctrl(spi_imx, 0); |
838 | 860 | ||
861 | master->dev.of_node = pdev->dev.of_node; | ||
839 | ret = spi_bitbang_start(&spi_imx->bitbang); | 862 | ret = spi_bitbang_start(&spi_imx->bitbang); |
840 | if (ret) { | 863 | if (ret) { |
841 | dev_err(&pdev->dev, "bitbang start failed with %d\n", ret); | 864 | dev_err(&pdev->dev, "bitbang start failed with %d\n", ret); |
@@ -898,6 +921,7 @@ static struct platform_driver spi_imx_driver = { | |||
898 | .driver = { | 921 | .driver = { |
899 | .name = DRIVER_NAME, | 922 | .name = DRIVER_NAME, |
900 | .owner = THIS_MODULE, | 923 | .owner = THIS_MODULE, |
924 | .of_match_table = spi_imx_dt_ids, | ||
901 | }, | 925 | }, |
902 | .id_table = spi_imx_devtype, | 926 | .id_table = spi_imx_devtype, |
903 | .probe = spi_imx_probe, | 927 | .probe = spi_imx_probe, |