diff options
author | Geert Uytterhoeven <geert+renesas@linux-m68k.org> | 2014-01-28 04:21:38 -0500 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-01-29 12:56:57 -0500 |
commit | 426ef76dd8a394a0e04d096941cd9acb49539a3e (patch) | |
tree | c6abc0e61b2b5e18fdbf45f982bb6b02067f3596 | |
parent | 29f397b739ceef90c8b848f6579cbacd088e896e (diff) |
spi: rspi: Add DT support
Signed-off-by: Geert Uytterhoeven <geert+renesas@linux-m68k.org>
Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r-- | Documentation/devicetree/bindings/spi/spi-rspi.txt | 59 | ||||
-rw-r--r-- | drivers/spi/spi-rspi.c | 106 |
2 files changed, 136 insertions, 29 deletions
diff --git a/Documentation/devicetree/bindings/spi/spi-rspi.txt b/Documentation/devicetree/bindings/spi/spi-rspi.txt new file mode 100644 index 000000000000..95f9b21d239f --- /dev/null +++ b/Documentation/devicetree/bindings/spi/spi-rspi.txt | |||
@@ -0,0 +1,59 @@ | |||
1 | Device tree configuration for Renesas RSPI/QSPI driver | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : For Renesas Serial Peripheral Interface on legacy SH: | ||
5 | "renesas,rspi-<soctype>", "renesas,rspi" as fallback. | ||
6 | For Renesas Serial Peripheral Interface on RZ/A1H: | ||
7 | "renesas,rspi-<soctype>", "renesas,rspi-rz" as fallback. | ||
8 | For Quad Serial Peripheral Interface on R-Car Gen2: | ||
9 | "renesas,qspi-<soctype>", "renesas,qspi" as fallback. | ||
10 | Examples of valid soctypes are "sh7757" (SH), | ||
11 | "r7s72100" (RZ/A1H), "r8a7790" (R-Car H2), and | ||
12 | "r8a7791" (R-Car M2). | ||
13 | - reg : Address start and address range size of the device | ||
14 | - interrupts : A list of interrupt-specifiers, one for each entry in | ||
15 | interrupt-names. | ||
16 | If interrupt-names is not present, an interrupt specifier | ||
17 | for a single muxed interrupt. | ||
18 | - interrupt-names : A list of interrupt names. Should contain (if present): | ||
19 | - "error" for SPEI, | ||
20 | - "rx" for SPRI, | ||
21 | - "tx" to SPTI, | ||
22 | - "mux" for a single muxed interrupt. | ||
23 | - interrupt-parent : The phandle for the interrupt controller that | ||
24 | services interrupts for this device. | ||
25 | - num-cs : Number of chip selects. Some RSPI cores have more than 1. | ||
26 | - #address-cells : Must be <1> | ||
27 | - #size-cells : Must be <0> | ||
28 | |||
29 | Optional properties: | ||
30 | - clocks: : Must contain a reference to the functional clock. | ||
31 | |||
32 | Pinctrl properties might be needed, too. See | ||
33 | Documentation/devicetree/bindings/pinctrl/renesas,*. | ||
34 | |||
35 | Examples: | ||
36 | |||
37 | spi0: spi@e800c800 { | ||
38 | compatible = "renesas,rspi-r7s72100", "renesas,rspi-rz"; | ||
39 | reg = <0xe800c800 0x24>; | ||
40 | interrupts = <0 238 IRQ_TYPE_LEVEL_HIGH>, | ||
41 | <0 239 IRQ_TYPE_LEVEL_HIGH>, | ||
42 | <0 240 IRQ_TYPE_LEVEL_HIGH>; | ||
43 | interrupt-names = "error", "rx", "tx"; | ||
44 | interrupt-parent = <&gic>; | ||
45 | num-cs = <1>; | ||
46 | #address-cells = <1>; | ||
47 | #size-cells = <0>; | ||
48 | }; | ||
49 | |||
50 | spi: spi@e6b10000 { | ||
51 | compatible = "renesas,qspi-r8a7791", "renesas,qspi"; | ||
52 | reg = <0 0xe6b10000 0 0x2c>; | ||
53 | interrupt-parent = <&gic>; | ||
54 | interrupts = <0 184 IRQ_TYPE_LEVEL_HIGH>; | ||
55 | clocks = <&mstp9_clks R8A7791_CLK_QSPI_MOD>; | ||
56 | num-cs = <1>; | ||
57 | #address-cells = <1>; | ||
58 | #size-cells = <0>; | ||
59 | }; | ||
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index d79a7ed9b92e..e56fcb5f7f99 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/clk.h> | 31 | #include <linux/clk.h> |
32 | #include <linux/dmaengine.h> | 32 | #include <linux/dmaengine.h> |
33 | #include <linux/dma-mapping.h> | 33 | #include <linux/dma-mapping.h> |
34 | #include <linux/of_device.h> | ||
34 | #include <linux/sh_dma.h> | 35 | #include <linux/sh_dma.h> |
35 | #include <linux/spi/spi.h> | 36 | #include <linux/spi/spi.h> |
36 | #include <linux/spi/rspi.h> | 37 | #include <linux/spi/rspi.h> |
@@ -985,6 +986,56 @@ static int rspi_remove(struct platform_device *pdev) | |||
985 | return 0; | 986 | return 0; |
986 | } | 987 | } |
987 | 988 | ||
989 | static const struct spi_ops rspi_ops = { | ||
990 | .set_config_register = rspi_set_config_register, | ||
991 | .transfer_one = rspi_transfer_one, | ||
992 | }; | ||
993 | |||
994 | static const struct spi_ops rspi_rz_ops = { | ||
995 | .set_config_register = rspi_rz_set_config_register, | ||
996 | .transfer_one = rspi_rz_transfer_one, | ||
997 | }; | ||
998 | |||
999 | static const struct spi_ops qspi_ops = { | ||
1000 | .set_config_register = qspi_set_config_register, | ||
1001 | .transfer_one = qspi_transfer_one, | ||
1002 | }; | ||
1003 | |||
1004 | #ifdef CONFIG_OF | ||
1005 | static const struct of_device_id rspi_of_match[] = { | ||
1006 | /* RSPI on legacy SH */ | ||
1007 | { .compatible = "renesas,rspi", .data = &rspi_ops }, | ||
1008 | /* RSPI on RZ/A1H */ | ||
1009 | { .compatible = "renesas,rspi-rz", .data = &rspi_rz_ops }, | ||
1010 | /* QSPI on R-Car Gen2 */ | ||
1011 | { .compatible = "renesas,qspi", .data = &qspi_ops }, | ||
1012 | { /* sentinel */ } | ||
1013 | }; | ||
1014 | |||
1015 | MODULE_DEVICE_TABLE(of, rspi_of_match); | ||
1016 | |||
1017 | static int rspi_parse_dt(struct device *dev, struct spi_master *master) | ||
1018 | { | ||
1019 | u32 num_cs; | ||
1020 | int error; | ||
1021 | |||
1022 | /* Parse DT properties */ | ||
1023 | error = of_property_read_u32(dev->of_node, "num-cs", &num_cs); | ||
1024 | if (error) { | ||
1025 | dev_err(dev, "of_property_read_u32 num-cs failed %d\n", error); | ||
1026 | return error; | ||
1027 | } | ||
1028 | |||
1029 | master->num_chipselect = num_cs; | ||
1030 | return 0; | ||
1031 | } | ||
1032 | #else | ||
1033 | static inline int rspi_parse_dt(struct device *dev, struct spi_master *master) | ||
1034 | { | ||
1035 | return -EINVAL; | ||
1036 | } | ||
1037 | #endif /* CONFIG_OF */ | ||
1038 | |||
988 | static int rspi_request_irq(struct device *dev, unsigned int irq, | 1039 | static int rspi_request_irq(struct device *dev, unsigned int irq, |
989 | irq_handler_t handler, const char *suffix, | 1040 | irq_handler_t handler, const char *suffix, |
990 | void *dev_id) | 1041 | void *dev_id) |
@@ -1004,16 +1055,9 @@ static int rspi_probe(struct platform_device *pdev) | |||
1004 | struct spi_master *master; | 1055 | struct spi_master *master; |
1005 | struct rspi_data *rspi; | 1056 | struct rspi_data *rspi; |
1006 | int ret; | 1057 | int ret; |
1007 | const struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev); | 1058 | const struct of_device_id *of_id; |
1059 | const struct rspi_plat_data *rspi_pd; | ||
1008 | const struct spi_ops *ops; | 1060 | const struct spi_ops *ops; |
1009 | const struct platform_device_id *id_entry = pdev->id_entry; | ||
1010 | |||
1011 | ops = (struct spi_ops *)id_entry->driver_data; | ||
1012 | /* ops parameter check */ | ||
1013 | if (!ops->set_config_register) { | ||
1014 | dev_err(&pdev->dev, "there is no set_config_register\n"); | ||
1015 | return -ENODEV; | ||
1016 | } | ||
1017 | 1061 | ||
1018 | master = spi_alloc_master(&pdev->dev, sizeof(struct rspi_data)); | 1062 | master = spi_alloc_master(&pdev->dev, sizeof(struct rspi_data)); |
1019 | if (master == NULL) { | 1063 | if (master == NULL) { |
@@ -1021,6 +1065,28 @@ static int rspi_probe(struct platform_device *pdev) | |||
1021 | return -ENOMEM; | 1065 | return -ENOMEM; |
1022 | } | 1066 | } |
1023 | 1067 | ||
1068 | of_id = of_match_device(rspi_of_match, &pdev->dev); | ||
1069 | if (of_id) { | ||
1070 | ops = of_id->data; | ||
1071 | ret = rspi_parse_dt(&pdev->dev, master); | ||
1072 | if (ret) | ||
1073 | goto error1; | ||
1074 | } else { | ||
1075 | ops = (struct spi_ops *)pdev->id_entry->driver_data; | ||
1076 | rspi_pd = dev_get_platdata(&pdev->dev); | ||
1077 | if (rspi_pd && rspi_pd->num_chipselect) | ||
1078 | master->num_chipselect = rspi_pd->num_chipselect; | ||
1079 | else | ||
1080 | master->num_chipselect = 2; /* default */ | ||
1081 | }; | ||
1082 | |||
1083 | /* ops parameter check */ | ||
1084 | if (!ops->set_config_register) { | ||
1085 | dev_err(&pdev->dev, "there is no set_config_register\n"); | ||
1086 | ret = -ENODEV; | ||
1087 | goto error1; | ||
1088 | } | ||
1089 | |||
1024 | rspi = spi_master_get_devdata(master); | 1090 | rspi = spi_master_get_devdata(master); |
1025 | platform_set_drvdata(pdev, rspi); | 1091 | platform_set_drvdata(pdev, rspi); |
1026 | rspi->ops = ops; | 1092 | rspi->ops = ops; |
@@ -1048,11 +1114,6 @@ static int rspi_probe(struct platform_device *pdev) | |||
1048 | 1114 | ||
1049 | init_waitqueue_head(&rspi->wait); | 1115 | init_waitqueue_head(&rspi->wait); |
1050 | 1116 | ||
1051 | if (rspi_pd && rspi_pd->num_chipselect) | ||
1052 | master->num_chipselect = rspi_pd->num_chipselect; | ||
1053 | else | ||
1054 | master->num_chipselect = 2; /* default */ | ||
1055 | |||
1056 | master->bus_num = pdev->id; | 1117 | master->bus_num = pdev->id; |
1057 | master->setup = rspi_setup; | 1118 | master->setup = rspi_setup; |
1058 | master->transfer_one = ops->transfer_one; | 1119 | master->transfer_one = ops->transfer_one; |
@@ -1060,6 +1121,7 @@ static int rspi_probe(struct platform_device *pdev) | |||
1060 | master->prepare_message = rspi_prepare_message; | 1121 | master->prepare_message = rspi_prepare_message; |
1061 | master->unprepare_message = rspi_unprepare_message; | 1122 | master->unprepare_message = rspi_unprepare_message; |
1062 | master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP; | 1123 | master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP; |
1124 | master->dev.of_node = pdev->dev.of_node; | ||
1063 | 1125 | ||
1064 | ret = platform_get_irq_byname(pdev, "rx"); | 1126 | ret = platform_get_irq_byname(pdev, "rx"); |
1065 | if (ret < 0) { | 1127 | if (ret < 0) { |
@@ -1122,21 +1184,6 @@ error1: | |||
1122 | return ret; | 1184 | return ret; |
1123 | } | 1185 | } |
1124 | 1186 | ||
1125 | static struct spi_ops rspi_ops = { | ||
1126 | .set_config_register = rspi_set_config_register, | ||
1127 | .transfer_one = rspi_transfer_one, | ||
1128 | }; | ||
1129 | |||
1130 | static struct spi_ops rspi_rz_ops = { | ||
1131 | .set_config_register = rspi_rz_set_config_register, | ||
1132 | .transfer_one = rspi_rz_transfer_one, | ||
1133 | }; | ||
1134 | |||
1135 | static struct spi_ops qspi_ops = { | ||
1136 | .set_config_register = qspi_set_config_register, | ||
1137 | .transfer_one = qspi_transfer_one, | ||
1138 | }; | ||
1139 | |||
1140 | static struct platform_device_id spi_driver_ids[] = { | 1187 | static struct platform_device_id spi_driver_ids[] = { |
1141 | { "rspi", (kernel_ulong_t)&rspi_ops }, | 1188 | { "rspi", (kernel_ulong_t)&rspi_ops }, |
1142 | { "rspi-rz", (kernel_ulong_t)&rspi_rz_ops }, | 1189 | { "rspi-rz", (kernel_ulong_t)&rspi_rz_ops }, |
@@ -1153,6 +1200,7 @@ static struct platform_driver rspi_driver = { | |||
1153 | .driver = { | 1200 | .driver = { |
1154 | .name = "renesas_spi", | 1201 | .name = "renesas_spi", |
1155 | .owner = THIS_MODULE, | 1202 | .owner = THIS_MODULE, |
1203 | .of_match_table = of_match_ptr(rspi_of_match), | ||
1156 | }, | 1204 | }, |
1157 | }; | 1205 | }; |
1158 | module_platform_driver(rspi_driver); | 1206 | module_platform_driver(rspi_driver); |