Loading Documentation/devicetree/bindings/spi/spi-gpio.txt 0 → 100644 +29 −0 Original line number Diff line number Diff line SPI-GPIO devicetree bindings Required properties: - compatible: should be set to "spi-gpio" - #address-cells: should be set to <0x1> - ranges - gpio-sck: GPIO spec for the SCK line to use - gpio-miso: GPIO spec for the MISO line to use - gpio-mosi: GPIO spec for the MOSI line to use - cs-gpios: GPIOs to use for chipselect lines - num-chipselects: number of chipselect lines Example: spi { compatible = "spi-gpio"; #address-cells = <0x1>; ranges; gpio-sck = <&gpio 95 0>; gpio-miso = <&gpio 98 0>; gpio-mosi = <&gpio 97 0>; cs-gpios = <&gpio 125 0>; num-chipselects = <1>; /* clients */ }; drivers/spi/spi-gpio.c +96 −3 Original line number Diff line number Diff line Loading @@ -22,6 +22,8 @@ #include <linux/init.h> #include <linux/platform_device.h> #include <linux/gpio.h> #include <linux/of_device.h> #include <linux/of_gpio.h> #include <linux/spi/spi.h> #include <linux/spi/spi_bitbang.h> Loading Loading @@ -232,13 +234,27 @@ static void spi_gpio_chipselect(struct spi_device *spi, int is_active) static int spi_gpio_setup(struct spi_device *spi) { unsigned int cs = (unsigned int) spi->controller_data; unsigned int cs; int status = 0; struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); struct device_node *np = spi->master->dev.of_node; if (spi->bits_per_word > 32) return -EINVAL; if (np) { /* * In DT environments, the CS GPIOs have already been * initialized from the "cs-gpios" property of the node. */ cs = spi_gpio->cs_gpios[spi->chip_select]; } else { /* * ... otherwise, take it from spi->controller_data */ cs = (unsigned int) spi->controller_data; } if (!spi->controller_state) { if (cs != SPI_GPIO_NO_CHIPSELECT) { status = gpio_request(cs, dev_name(&spi->dev)); Loading @@ -250,6 +266,7 @@ static int spi_gpio_setup(struct spi_device *spi) } if (!status) { status = spi_bitbang_setup(spi); /* in case it was initialized from static board data */ spi_gpio->cs_gpios[spi->chip_select] = cs; } Loading Loading @@ -326,6 +343,55 @@ spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label, return value; } #ifdef CONFIG_OF static struct of_device_id spi_gpio_dt_ids[] = { { .compatible = "spi-gpio" }, {} }; MODULE_DEVICE_TABLE(of, spi_gpio_dt_ids); static int spi_gpio_probe_dt(struct platform_device *pdev) { int ret; u32 tmp; struct spi_gpio_platform_data *pdata; struct device_node *np = pdev->dev.of_node; const struct of_device_id *of_id = of_match_device(spi_gpio_dt_ids, &pdev->dev); if (!of_id) return 0; pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; pdata->sck = of_get_named_gpio(np, "gpio-sck", 0); pdata->miso = of_get_named_gpio(np, "gpio-miso", 0); pdata->mosi = of_get_named_gpio(np, "gpio-mosi", 0); ret = of_property_read_u32(np, "num-chipselects", &tmp); if (ret < 0) { dev_err(&pdev->dev, "num-chipselects property not found\n"); goto error_free; } pdata->num_chipselect = tmp; pdev->dev.platform_data = pdata; return 1; error_free: devm_kfree(&pdev->dev, pdata); return ret; } #else static inline int spi_probe_dt(struct platform_device *) { return 0; } #endif static int __devinit spi_gpio_probe(struct platform_device *pdev) { int status; Loading @@ -333,6 +399,13 @@ static int __devinit spi_gpio_probe(struct platform_device *pdev) struct spi_gpio *spi_gpio; struct spi_gpio_platform_data *pdata; u16 master_flags = 0; bool use_of = 0; status = spi_gpio_probe_dt(pdev); if (status < 0) return status; if (status > 0) use_of = 1; pdata = pdev->dev.platform_data; #ifdef GENERIC_BITBANG Loading Loading @@ -362,6 +435,23 @@ static int __devinit spi_gpio_probe(struct platform_device *pdev) master->num_chipselect = SPI_N_CHIPSEL; master->setup = spi_gpio_setup; master->cleanup = spi_gpio_cleanup; #ifdef CONFIG_OF master->dev.of_node = pdev->dev.of_node; if (use_of) { int i; struct device_node *np = pdev->dev.of_node; /* * In DT environments, take the CS GPIO from the "cs-gpios" * property of the node. */ for (i = 0; i < SPI_N_CHIPSEL; i++) spi_gpio->cs_gpios[i] = of_get_named_gpio(np, "cs-gpios", i); } #endif spi_gpio->bitbang.master = spi_master_get(master); spi_gpio->bitbang.chipselect = spi_gpio_chipselect; Loading Loading @@ -422,8 +512,11 @@ static int __devexit spi_gpio_remove(struct platform_device *pdev) MODULE_ALIAS("platform:" DRIVER_NAME); static struct platform_driver spi_gpio_driver = { .driver.name = DRIVER_NAME, .driver.owner = THIS_MODULE, .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, .of_match_table = of_match_ptr(spi_gpio_dt_ids), }, .probe = spi_gpio_probe, .remove = __devexit_p(spi_gpio_remove), }; Loading Loading
Documentation/devicetree/bindings/spi/spi-gpio.txt 0 → 100644 +29 −0 Original line number Diff line number Diff line SPI-GPIO devicetree bindings Required properties: - compatible: should be set to "spi-gpio" - #address-cells: should be set to <0x1> - ranges - gpio-sck: GPIO spec for the SCK line to use - gpio-miso: GPIO spec for the MISO line to use - gpio-mosi: GPIO spec for the MOSI line to use - cs-gpios: GPIOs to use for chipselect lines - num-chipselects: number of chipselect lines Example: spi { compatible = "spi-gpio"; #address-cells = <0x1>; ranges; gpio-sck = <&gpio 95 0>; gpio-miso = <&gpio 98 0>; gpio-mosi = <&gpio 97 0>; cs-gpios = <&gpio 125 0>; num-chipselects = <1>; /* clients */ };
drivers/spi/spi-gpio.c +96 −3 Original line number Diff line number Diff line Loading @@ -22,6 +22,8 @@ #include <linux/init.h> #include <linux/platform_device.h> #include <linux/gpio.h> #include <linux/of_device.h> #include <linux/of_gpio.h> #include <linux/spi/spi.h> #include <linux/spi/spi_bitbang.h> Loading Loading @@ -232,13 +234,27 @@ static void spi_gpio_chipselect(struct spi_device *spi, int is_active) static int spi_gpio_setup(struct spi_device *spi) { unsigned int cs = (unsigned int) spi->controller_data; unsigned int cs; int status = 0; struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); struct device_node *np = spi->master->dev.of_node; if (spi->bits_per_word > 32) return -EINVAL; if (np) { /* * In DT environments, the CS GPIOs have already been * initialized from the "cs-gpios" property of the node. */ cs = spi_gpio->cs_gpios[spi->chip_select]; } else { /* * ... otherwise, take it from spi->controller_data */ cs = (unsigned int) spi->controller_data; } if (!spi->controller_state) { if (cs != SPI_GPIO_NO_CHIPSELECT) { status = gpio_request(cs, dev_name(&spi->dev)); Loading @@ -250,6 +266,7 @@ static int spi_gpio_setup(struct spi_device *spi) } if (!status) { status = spi_bitbang_setup(spi); /* in case it was initialized from static board data */ spi_gpio->cs_gpios[spi->chip_select] = cs; } Loading Loading @@ -326,6 +343,55 @@ spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label, return value; } #ifdef CONFIG_OF static struct of_device_id spi_gpio_dt_ids[] = { { .compatible = "spi-gpio" }, {} }; MODULE_DEVICE_TABLE(of, spi_gpio_dt_ids); static int spi_gpio_probe_dt(struct platform_device *pdev) { int ret; u32 tmp; struct spi_gpio_platform_data *pdata; struct device_node *np = pdev->dev.of_node; const struct of_device_id *of_id = of_match_device(spi_gpio_dt_ids, &pdev->dev); if (!of_id) return 0; pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; pdata->sck = of_get_named_gpio(np, "gpio-sck", 0); pdata->miso = of_get_named_gpio(np, "gpio-miso", 0); pdata->mosi = of_get_named_gpio(np, "gpio-mosi", 0); ret = of_property_read_u32(np, "num-chipselects", &tmp); if (ret < 0) { dev_err(&pdev->dev, "num-chipselects property not found\n"); goto error_free; } pdata->num_chipselect = tmp; pdev->dev.platform_data = pdata; return 1; error_free: devm_kfree(&pdev->dev, pdata); return ret; } #else static inline int spi_probe_dt(struct platform_device *) { return 0; } #endif static int __devinit spi_gpio_probe(struct platform_device *pdev) { int status; Loading @@ -333,6 +399,13 @@ static int __devinit spi_gpio_probe(struct platform_device *pdev) struct spi_gpio *spi_gpio; struct spi_gpio_platform_data *pdata; u16 master_flags = 0; bool use_of = 0; status = spi_gpio_probe_dt(pdev); if (status < 0) return status; if (status > 0) use_of = 1; pdata = pdev->dev.platform_data; #ifdef GENERIC_BITBANG Loading Loading @@ -362,6 +435,23 @@ static int __devinit spi_gpio_probe(struct platform_device *pdev) master->num_chipselect = SPI_N_CHIPSEL; master->setup = spi_gpio_setup; master->cleanup = spi_gpio_cleanup; #ifdef CONFIG_OF master->dev.of_node = pdev->dev.of_node; if (use_of) { int i; struct device_node *np = pdev->dev.of_node; /* * In DT environments, take the CS GPIO from the "cs-gpios" * property of the node. */ for (i = 0; i < SPI_N_CHIPSEL; i++) spi_gpio->cs_gpios[i] = of_get_named_gpio(np, "cs-gpios", i); } #endif spi_gpio->bitbang.master = spi_master_get(master); spi_gpio->bitbang.chipselect = spi_gpio_chipselect; Loading Loading @@ -422,8 +512,11 @@ static int __devexit spi_gpio_remove(struct platform_device *pdev) MODULE_ALIAS("platform:" DRIVER_NAME); static struct platform_driver spi_gpio_driver = { .driver.name = DRIVER_NAME, .driver.owner = THIS_MODULE, .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, .of_match_table = of_match_ptr(spi_gpio_dt_ids), }, .probe = spi_gpio_probe, .remove = __devexit_p(spi_gpio_remove), }; Loading