diff options
-rw-r--r-- | Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt | 7 | ||||
-rw-r--r-- | drivers/spi/spi-fsl-dspi.c | 3 | ||||
-rw-r--r-- | drivers/spi/spi-fsl-spi.c | 3 | ||||
-rw-r--r-- | drivers/spi/spi-imx.c | 20 | ||||
-rw-r--r-- | drivers/spi/spi-lantiq-ssc.c | 1 | ||||
-rw-r--r-- | drivers/spi/spi.c | 34 | ||||
-rw-r--r-- | include/linux/spi/spi.h | 4 |
7 files changed, 62 insertions, 10 deletions
diff --git a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt index 8bc95e2fc47f..31b5b21598ff 100644 --- a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt +++ b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt | |||
@@ -23,6 +23,12 @@ See the clock consumer binding, | |||
23 | Obsolete properties: | 23 | Obsolete properties: |
24 | - fsl,spi-num-chipselects : Contains the number of the chipselect | 24 | - fsl,spi-num-chipselects : Contains the number of the chipselect |
25 | 25 | ||
26 | Optional properties: | ||
27 | - fsl,spi-rdy-drctl: Integer, representing the value of DRCTL, the register | ||
28 | controlling the SPI_READY handling. Note that to enable the DRCTL consideration, | ||
29 | the SPI_READY mode-flag needs to be set too. | ||
30 | Valid values are: 0 (disabled), 1 (edge-triggered burst) and 2 (level-triggered burst). | ||
31 | |||
26 | Example: | 32 | Example: |
27 | 33 | ||
28 | ecspi@70010000 { | 34 | ecspi@70010000 { |
@@ -35,4 +41,5 @@ ecspi@70010000 { | |||
35 | <&gpio3 25 0>; /* GPIO3_25 */ | 41 | <&gpio3 25 0>; /* GPIO3_25 */ |
36 | dmas = <&sdma 3 7 1>, <&sdma 4 7 2>; | 42 | dmas = <&sdma 3 7 1>, <&sdma 4 7 2>; |
37 | dma-names = "rx", "tx"; | 43 | dma-names = "rx", "tx"; |
44 | fsl,spi-rdy-drctl = <1>; | ||
38 | }; | 45 | }; |
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 14c8e7ce1913..15201645bdc4 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c | |||
@@ -1002,7 +1002,8 @@ static int dspi_probe(struct platform_device *pdev) | |||
1002 | if (IS_ERR(dspi->regmap)) { | 1002 | if (IS_ERR(dspi->regmap)) { |
1003 | dev_err(&pdev->dev, "failed to init regmap: %ld\n", | 1003 | dev_err(&pdev->dev, "failed to init regmap: %ld\n", |
1004 | PTR_ERR(dspi->regmap)); | 1004 | PTR_ERR(dspi->regmap)); |
1005 | return PTR_ERR(dspi->regmap); | 1005 | ret = PTR_ERR(dspi->regmap); |
1006 | goto out_master_put; | ||
1006 | } | 1007 | } |
1007 | 1008 | ||
1008 | dspi_init(dspi); | 1009 | dspi_init(dspi); |
diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c index 0fc3452652ae..8f2e97857e8b 100644 --- a/drivers/spi/spi-fsl-spi.c +++ b/drivers/spi/spi-fsl-spi.c | |||
@@ -814,7 +814,7 @@ static int of_fsl_spi_probe(struct platform_device *ofdev) | |||
814 | struct device_node *np = ofdev->dev.of_node; | 814 | struct device_node *np = ofdev->dev.of_node; |
815 | struct spi_master *master; | 815 | struct spi_master *master; |
816 | struct resource mem; | 816 | struct resource mem; |
817 | int irq, type; | 817 | int irq = 0, type; |
818 | int ret = -ENOMEM; | 818 | int ret = -ENOMEM; |
819 | 819 | ||
820 | ret = of_mpc8xxx_spi_probe(ofdev); | 820 | ret = of_mpc8xxx_spi_probe(ofdev); |
@@ -847,6 +847,7 @@ static int of_fsl_spi_probe(struct platform_device *ofdev) | |||
847 | return 0; | 847 | return 0; |
848 | 848 | ||
849 | err: | 849 | err: |
850 | irq_dispose_mapping(irq); | ||
850 | if (type == TYPE_FSL) | 851 | if (type == TYPE_FSL) |
851 | of_fsl_spi_free_chipselects(dev); | 852 | of_fsl_spi_free_chipselects(dev); |
852 | return ret; | 853 | return ret; |
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 9a7c62f471dc..b402530a7a9a 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c | |||
@@ -95,6 +95,7 @@ struct spi_imx_data { | |||
95 | unsigned int spi_bus_clk; | 95 | unsigned int spi_bus_clk; |
96 | 96 | ||
97 | unsigned int bytes_per_word; | 97 | unsigned int bytes_per_word; |
98 | unsigned int spi_drctl; | ||
98 | 99 | ||
99 | unsigned int count; | 100 | unsigned int count; |
100 | void (*tx)(struct spi_imx_data *); | 101 | void (*tx)(struct spi_imx_data *); |
@@ -246,6 +247,7 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, | |||
246 | #define MX51_ECSPI_CTRL_XCH (1 << 2) | 247 | #define MX51_ECSPI_CTRL_XCH (1 << 2) |
247 | #define MX51_ECSPI_CTRL_SMC (1 << 3) | 248 | #define MX51_ECSPI_CTRL_SMC (1 << 3) |
248 | #define MX51_ECSPI_CTRL_MODE_MASK (0xf << 4) | 249 | #define MX51_ECSPI_CTRL_MODE_MASK (0xf << 4) |
250 | #define MX51_ECSPI_CTRL_DRCTL(drctl) ((drctl) << 16) | ||
249 | #define MX51_ECSPI_CTRL_POSTDIV_OFFSET 8 | 251 | #define MX51_ECSPI_CTRL_POSTDIV_OFFSET 8 |
250 | #define MX51_ECSPI_CTRL_PREDIV_OFFSET 12 | 252 | #define MX51_ECSPI_CTRL_PREDIV_OFFSET 12 |
251 | #define MX51_ECSPI_CTRL_CS(cs) ((cs) << 18) | 253 | #define MX51_ECSPI_CTRL_CS(cs) ((cs) << 18) |
@@ -355,6 +357,12 @@ static int mx51_ecspi_config(struct spi_device *spi, | |||
355 | */ | 357 | */ |
356 | ctrl |= MX51_ECSPI_CTRL_MODE_MASK; | 358 | ctrl |= MX51_ECSPI_CTRL_MODE_MASK; |
357 | 359 | ||
360 | /* | ||
361 | * Enable SPI_RDY handling (falling edge/level triggered). | ||
362 | */ | ||
363 | if (spi->mode & SPI_READY) | ||
364 | ctrl |= MX51_ECSPI_CTRL_DRCTL(spi_imx->spi_drctl); | ||
365 | |||
358 | /* set clock speed */ | 366 | /* set clock speed */ |
359 | ctrl |= mx51_ecspi_clkdiv(spi_imx, config->speed_hz, &clk); | 367 | ctrl |= mx51_ecspi_clkdiv(spi_imx, config->speed_hz, &clk); |
360 | spi_imx->spi_bus_clk = clk; | 368 | spi_imx->spi_bus_clk = clk; |
@@ -1173,7 +1181,7 @@ static int spi_imx_probe(struct platform_device *pdev) | |||
1173 | struct spi_master *master; | 1181 | struct spi_master *master; |
1174 | struct spi_imx_data *spi_imx; | 1182 | struct spi_imx_data *spi_imx; |
1175 | struct resource *res; | 1183 | struct resource *res; |
1176 | int i, ret, irq; | 1184 | int i, ret, irq, spi_drctl; |
1177 | 1185 | ||
1178 | if (!np && !mxc_platform_info) { | 1186 | if (!np && !mxc_platform_info) { |
1179 | dev_err(&pdev->dev, "can't get the platform data\n"); | 1187 | dev_err(&pdev->dev, "can't get the platform data\n"); |
@@ -1181,6 +1189,12 @@ static int spi_imx_probe(struct platform_device *pdev) | |||
1181 | } | 1189 | } |
1182 | 1190 | ||
1183 | master = spi_alloc_master(&pdev->dev, sizeof(struct spi_imx_data)); | 1191 | master = spi_alloc_master(&pdev->dev, sizeof(struct spi_imx_data)); |
1192 | ret = of_property_read_u32(np, "fsl,spi-rdy-drctl", &spi_drctl); | ||
1193 | if ((ret < 0) || (spi_drctl >= 0x3)) { | ||
1194 | /* '11' is reserved */ | ||
1195 | spi_drctl = 0; | ||
1196 | } | ||
1197 | |||
1184 | if (!master) | 1198 | if (!master) |
1185 | return -ENOMEM; | 1199 | return -ENOMEM; |
1186 | 1200 | ||
@@ -1216,7 +1230,9 @@ static int spi_imx_probe(struct platform_device *pdev) | |||
1216 | spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message; | 1230 | spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message; |
1217 | spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; | 1231 | spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; |
1218 | if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx)) | 1232 | if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx)) |
1219 | spi_imx->bitbang.master->mode_bits |= SPI_LOOP; | 1233 | spi_imx->bitbang.master->mode_bits |= SPI_LOOP | SPI_READY; |
1234 | |||
1235 | spi_imx->spi_drctl = spi_drctl; | ||
1220 | 1236 | ||
1221 | init_completion(&spi_imx->xfer_done); | 1237 | init_completion(&spi_imx->xfer_done); |
1222 | 1238 | ||
diff --git a/drivers/spi/spi-lantiq-ssc.c b/drivers/spi/spi-lantiq-ssc.c index 633c30b4d5a6..d5976615d924 100644 --- a/drivers/spi/spi-lantiq-ssc.c +++ b/drivers/spi/spi-lantiq-ssc.c | |||
@@ -977,7 +977,6 @@ static struct platform_driver lantiq_ssc_driver = { | |||
977 | .remove = lantiq_ssc_remove, | 977 | .remove = lantiq_ssc_remove, |
978 | .driver = { | 978 | .driver = { |
979 | .name = "spi-lantiq-ssc", | 979 | .name = "spi-lantiq-ssc", |
980 | .owner = THIS_MODULE, | ||
981 | .of_match_table = lantiq_ssc_match, | 980 | .of_match_table = lantiq_ssc_match, |
982 | }, | 981 | }, |
983 | }; | 982 | }; |
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index b4a8bb7759b2..2c36c0ac708a 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/of_gpio.h> | 31 | #include <linux/of_gpio.h> |
32 | #include <linux/pm_runtime.h> | 32 | #include <linux/pm_runtime.h> |
33 | #include <linux/pm_domain.h> | 33 | #include <linux/pm_domain.h> |
34 | #include <linux/property.h> | ||
34 | #include <linux/export.h> | 35 | #include <linux/export.h> |
35 | #include <linux/sched/rt.h> | 36 | #include <linux/sched/rt.h> |
36 | #include <uapi/linux/sched/types.h> | 37 | #include <uapi/linux/sched/types.h> |
@@ -600,13 +601,28 @@ struct spi_device *spi_new_device(struct spi_master *master, | |||
600 | proxy->controller_data = chip->controller_data; | 601 | proxy->controller_data = chip->controller_data; |
601 | proxy->controller_state = NULL; | 602 | proxy->controller_state = NULL; |
602 | 603 | ||
603 | status = spi_add_device(proxy); | 604 | if (chip->properties) { |
604 | if (status < 0) { | 605 | status = device_add_properties(&proxy->dev, chip->properties); |
605 | spi_dev_put(proxy); | 606 | if (status) { |
606 | return NULL; | 607 | dev_err(&master->dev, |
608 | "failed to add properties to '%s': %d\n", | ||
609 | chip->modalias, status); | ||
610 | goto err_dev_put; | ||
611 | } | ||
607 | } | 612 | } |
608 | 613 | ||
614 | status = spi_add_device(proxy); | ||
615 | if (status < 0) | ||
616 | goto err_remove_props; | ||
617 | |||
609 | return proxy; | 618 | return proxy; |
619 | |||
620 | err_remove_props: | ||
621 | if (chip->properties) | ||
622 | device_remove_properties(&proxy->dev); | ||
623 | err_dev_put: | ||
624 | spi_dev_put(proxy); | ||
625 | return NULL; | ||
610 | } | 626 | } |
611 | EXPORT_SYMBOL_GPL(spi_new_device); | 627 | EXPORT_SYMBOL_GPL(spi_new_device); |
612 | 628 | ||
@@ -664,6 +680,7 @@ static void spi_match_master_to_boardinfo(struct spi_master *master, | |||
664 | * | 680 | * |
665 | * The board info passed can safely be __initdata ... but be careful of | 681 | * The board info passed can safely be __initdata ... but be careful of |
666 | * any embedded pointers (platform_data, etc), they're copied as-is. | 682 | * any embedded pointers (platform_data, etc), they're copied as-is. |
683 | * Device properties are deep-copied though. | ||
667 | * | 684 | * |
668 | * Return: zero on success, else a negative error code. | 685 | * Return: zero on success, else a negative error code. |
669 | */ | 686 | */ |
@@ -673,7 +690,7 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n) | |||
673 | int i; | 690 | int i; |
674 | 691 | ||
675 | if (!n) | 692 | if (!n) |
676 | return -EINVAL; | 693 | return 0; |
677 | 694 | ||
678 | bi = kcalloc(n, sizeof(*bi), GFP_KERNEL); | 695 | bi = kcalloc(n, sizeof(*bi), GFP_KERNEL); |
679 | if (!bi) | 696 | if (!bi) |
@@ -683,6 +700,13 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n) | |||
683 | struct spi_master *master; | 700 | struct spi_master *master; |
684 | 701 | ||
685 | memcpy(&bi->board_info, info, sizeof(*info)); | 702 | memcpy(&bi->board_info, info, sizeof(*info)); |
703 | if (info->properties) { | ||
704 | bi->board_info.properties = | ||
705 | property_entries_dup(info->properties); | ||
706 | if (IS_ERR(bi->board_info.properties)) | ||
707 | return PTR_ERR(bi->board_info.properties); | ||
708 | } | ||
709 | |||
686 | mutex_lock(&board_lock); | 710 | mutex_lock(&board_lock); |
687 | list_add_tail(&bi->list, &board_list); | 711 | list_add_tail(&bi->list, &board_list); |
688 | list_for_each_entry(master, &spi_master_list, list) | 712 | list_for_each_entry(master, &spi_master_list, list) |
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 3b0070695375..805878d61a8f 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/scatterlist.h> | 23 | #include <linux/scatterlist.h> |
24 | 24 | ||
25 | struct dma_chan; | 25 | struct dma_chan; |
26 | struct property_entry; | ||
26 | struct spi_master; | 27 | struct spi_master; |
27 | struct spi_transfer; | 28 | struct spi_transfer; |
28 | struct spi_flash_read_message; | 29 | struct spi_flash_read_message; |
@@ -1209,6 +1210,7 @@ int spi_flash_read(struct spi_device *spi, | |||
1209 | * @modalias: Initializes spi_device.modalias; identifies the driver. | 1210 | * @modalias: Initializes spi_device.modalias; identifies the driver. |
1210 | * @platform_data: Initializes spi_device.platform_data; the particular | 1211 | * @platform_data: Initializes spi_device.platform_data; the particular |
1211 | * data stored there is driver-specific. | 1212 | * data stored there is driver-specific. |
1213 | * @properties: Additional device properties for the device. | ||
1212 | * @controller_data: Initializes spi_device.controller_data; some | 1214 | * @controller_data: Initializes spi_device.controller_data; some |
1213 | * controllers need hints about hardware setup, e.g. for DMA. | 1215 | * controllers need hints about hardware setup, e.g. for DMA. |
1214 | * @irq: Initializes spi_device.irq; depends on how the board is wired. | 1216 | * @irq: Initializes spi_device.irq; depends on how the board is wired. |
@@ -1241,10 +1243,12 @@ struct spi_board_info { | |||
1241 | * | 1243 | * |
1242 | * platform_data goes to spi_device.dev.platform_data, | 1244 | * platform_data goes to spi_device.dev.platform_data, |
1243 | * controller_data goes to spi_device.controller_data, | 1245 | * controller_data goes to spi_device.controller_data, |
1246 | * device properties are copied and attached to spi_device, | ||
1244 | * irq is copied too | 1247 | * irq is copied too |
1245 | */ | 1248 | */ |
1246 | char modalias[SPI_NAME_SIZE]; | 1249 | char modalias[SPI_NAME_SIZE]; |
1247 | const void *platform_data; | 1250 | const void *platform_data; |
1251 | const struct property_entry *properties; | ||
1248 | void *controller_data; | 1252 | void *controller_data; |
1249 | int irq; | 1253 | int irq; |
1250 | 1254 | ||