diff options
author | Daniel Mack <zonque@gmail.com> | 2012-09-05 05:04:36 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-09-05 19:41:09 -0400 |
commit | 38ab18caa0ad9c844ba60f9618c5de6d6954da3e (patch) | |
tree | c4be63a707abc38de33cac71ea7c6bf674c2b26f | |
parent | 161c2dd3ca143f0dca50d72292bf651eabe2aa23 (diff) |
spi: spi-gpio: Add DT bindings
This patch adds DT bindings to the spi-gpio driver and some
documentation about how to use it.
Signed-off-by: Daniel Mack <zonque@gmail.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r-- | Documentation/devicetree/bindings/spi/spi-gpio.txt | 29 | ||||
-rw-r--r-- | drivers/spi/spi-gpio.c | 99 |
2 files changed, 125 insertions, 3 deletions
diff --git a/Documentation/devicetree/bindings/spi/spi-gpio.txt b/Documentation/devicetree/bindings/spi/spi-gpio.txt new file mode 100644 index 000000000000..8a824be15754 --- /dev/null +++ b/Documentation/devicetree/bindings/spi/spi-gpio.txt | |||
@@ -0,0 +1,29 @@ | |||
1 | SPI-GPIO devicetree bindings | ||
2 | |||
3 | Required properties: | ||
4 | |||
5 | - compatible: should be set to "spi-gpio" | ||
6 | - #address-cells: should be set to <0x1> | ||
7 | - ranges | ||
8 | - gpio-sck: GPIO spec for the SCK line to use | ||
9 | - gpio-miso: GPIO spec for the MISO line to use | ||
10 | - gpio-mosi: GPIO spec for the MOSI line to use | ||
11 | - cs-gpios: GPIOs to use for chipselect lines | ||
12 | - num-chipselects: number of chipselect lines | ||
13 | |||
14 | Example: | ||
15 | |||
16 | spi { | ||
17 | compatible = "spi-gpio"; | ||
18 | #address-cells = <0x1>; | ||
19 | ranges; | ||
20 | |||
21 | gpio-sck = <&gpio 95 0>; | ||
22 | gpio-miso = <&gpio 98 0>; | ||
23 | gpio-mosi = <&gpio 97 0>; | ||
24 | cs-gpios = <&gpio 125 0>; | ||
25 | num-chipselects = <1>; | ||
26 | |||
27 | /* clients */ | ||
28 | }; | ||
29 | |||
diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index ff7263ce12c7..aed161595840 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c | |||
@@ -22,6 +22,8 @@ | |||
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
25 | #include <linux/of_device.h> | ||
26 | #include <linux/of_gpio.h> | ||
25 | 27 | ||
26 | #include <linux/spi/spi.h> | 28 | #include <linux/spi/spi.h> |
27 | #include <linux/spi/spi_bitbang.h> | 29 | #include <linux/spi/spi_bitbang.h> |
@@ -232,13 +234,27 @@ static void spi_gpio_chipselect(struct spi_device *spi, int is_active) | |||
232 | 234 | ||
233 | static int spi_gpio_setup(struct spi_device *spi) | 235 | static int spi_gpio_setup(struct spi_device *spi) |
234 | { | 236 | { |
235 | unsigned int cs = (unsigned int) spi->controller_data; | 237 | unsigned int cs; |
236 | int status = 0; | 238 | int status = 0; |
237 | struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); | 239 | struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); |
240 | struct device_node *np = spi->master->dev.of_node; | ||
238 | 241 | ||
239 | if (spi->bits_per_word > 32) | 242 | if (spi->bits_per_word > 32) |
240 | return -EINVAL; | 243 | return -EINVAL; |
241 | 244 | ||
245 | if (np) { | ||
246 | /* | ||
247 | * In DT environments, the CS GPIOs have already been | ||
248 | * initialized from the "cs-gpios" property of the node. | ||
249 | */ | ||
250 | cs = spi_gpio->cs_gpios[spi->chip_select]; | ||
251 | } else { | ||
252 | /* | ||
253 | * ... otherwise, take it from spi->controller_data | ||
254 | */ | ||
255 | cs = (unsigned int) spi->controller_data; | ||
256 | } | ||
257 | |||
242 | if (!spi->controller_state) { | 258 | if (!spi->controller_state) { |
243 | if (cs != SPI_GPIO_NO_CHIPSELECT) { | 259 | if (cs != SPI_GPIO_NO_CHIPSELECT) { |
244 | status = gpio_request(cs, dev_name(&spi->dev)); | 260 | status = gpio_request(cs, dev_name(&spi->dev)); |
@@ -250,6 +266,7 @@ static int spi_gpio_setup(struct spi_device *spi) | |||
250 | } | 266 | } |
251 | if (!status) { | 267 | if (!status) { |
252 | status = spi_bitbang_setup(spi); | 268 | status = spi_bitbang_setup(spi); |
269 | /* in case it was initialized from static board data */ | ||
253 | spi_gpio->cs_gpios[spi->chip_select] = cs; | 270 | spi_gpio->cs_gpios[spi->chip_select] = cs; |
254 | } | 271 | } |
255 | 272 | ||
@@ -326,6 +343,55 @@ done: | |||
326 | return value; | 343 | return value; |
327 | } | 344 | } |
328 | 345 | ||
346 | #ifdef CONFIG_OF | ||
347 | static struct of_device_id spi_gpio_dt_ids[] = { | ||
348 | { .compatible = "spi-gpio" }, | ||
349 | {} | ||
350 | }; | ||
351 | MODULE_DEVICE_TABLE(of, spi_gpio_dt_ids); | ||
352 | |||
353 | static int spi_gpio_probe_dt(struct platform_device *pdev) | ||
354 | { | ||
355 | int ret; | ||
356 | u32 tmp; | ||
357 | struct spi_gpio_platform_data *pdata; | ||
358 | struct device_node *np = pdev->dev.of_node; | ||
359 | const struct of_device_id *of_id = | ||
360 | of_match_device(spi_gpio_dt_ids, &pdev->dev); | ||
361 | |||
362 | if (!of_id) | ||
363 | return 0; | ||
364 | |||
365 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
366 | if (!pdata) | ||
367 | return -ENOMEM; | ||
368 | |||
369 | pdata->sck = of_get_named_gpio(np, "gpio-sck", 0); | ||
370 | pdata->miso = of_get_named_gpio(np, "gpio-miso", 0); | ||
371 | pdata->mosi = of_get_named_gpio(np, "gpio-mosi", 0); | ||
372 | |||
373 | ret = of_property_read_u32(np, "num-chipselects", &tmp); | ||
374 | if (ret < 0) { | ||
375 | dev_err(&pdev->dev, "num-chipselects property not found\n"); | ||
376 | goto error_free; | ||
377 | } | ||
378 | |||
379 | pdata->num_chipselect = tmp; | ||
380 | pdev->dev.platform_data = pdata; | ||
381 | |||
382 | return 1; | ||
383 | |||
384 | error_free: | ||
385 | devm_kfree(&pdev->dev, pdata); | ||
386 | return ret; | ||
387 | } | ||
388 | #else | ||
389 | static inline int spi_probe_dt(struct platform_device *) | ||
390 | { | ||
391 | return 0; | ||
392 | } | ||
393 | #endif | ||
394 | |||
329 | static int __devinit spi_gpio_probe(struct platform_device *pdev) | 395 | static int __devinit spi_gpio_probe(struct platform_device *pdev) |
330 | { | 396 | { |
331 | int status; | 397 | int status; |
@@ -333,6 +399,13 @@ static int __devinit spi_gpio_probe(struct platform_device *pdev) | |||
333 | struct spi_gpio *spi_gpio; | 399 | struct spi_gpio *spi_gpio; |
334 | struct spi_gpio_platform_data *pdata; | 400 | struct spi_gpio_platform_data *pdata; |
335 | u16 master_flags = 0; | 401 | u16 master_flags = 0; |
402 | bool use_of = 0; | ||
403 | |||
404 | status = spi_gpio_probe_dt(pdev); | ||
405 | if (status < 0) | ||
406 | return status; | ||
407 | if (status > 0) | ||
408 | use_of = 1; | ||
336 | 409 | ||
337 | pdata = pdev->dev.platform_data; | 410 | pdata = pdev->dev.platform_data; |
338 | #ifdef GENERIC_BITBANG | 411 | #ifdef GENERIC_BITBANG |
@@ -362,6 +435,23 @@ static int __devinit spi_gpio_probe(struct platform_device *pdev) | |||
362 | master->num_chipselect = SPI_N_CHIPSEL; | 435 | master->num_chipselect = SPI_N_CHIPSEL; |
363 | master->setup = spi_gpio_setup; | 436 | master->setup = spi_gpio_setup; |
364 | master->cleanup = spi_gpio_cleanup; | 437 | master->cleanup = spi_gpio_cleanup; |
438 | #ifdef CONFIG_OF | ||
439 | master->dev.of_node = pdev->dev.of_node; | ||
440 | |||
441 | if (use_of) { | ||
442 | int i; | ||
443 | struct device_node *np = pdev->dev.of_node; | ||
444 | |||
445 | /* | ||
446 | * In DT environments, take the CS GPIO from the "cs-gpios" | ||
447 | * property of the node. | ||
448 | */ | ||
449 | |||
450 | for (i = 0; i < SPI_N_CHIPSEL; i++) | ||
451 | spi_gpio->cs_gpios[i] = | ||
452 | of_get_named_gpio(np, "cs-gpios", i); | ||
453 | } | ||
454 | #endif | ||
365 | 455 | ||
366 | spi_gpio->bitbang.master = spi_master_get(master); | 456 | spi_gpio->bitbang.master = spi_master_get(master); |
367 | spi_gpio->bitbang.chipselect = spi_gpio_chipselect; | 457 | spi_gpio->bitbang.chipselect = spi_gpio_chipselect; |
@@ -422,8 +512,11 @@ static int __devexit spi_gpio_remove(struct platform_device *pdev) | |||
422 | MODULE_ALIAS("platform:" DRIVER_NAME); | 512 | MODULE_ALIAS("platform:" DRIVER_NAME); |
423 | 513 | ||
424 | static struct platform_driver spi_gpio_driver = { | 514 | static struct platform_driver spi_gpio_driver = { |
425 | .driver.name = DRIVER_NAME, | 515 | .driver = { |
426 | .driver.owner = THIS_MODULE, | 516 | .name = DRIVER_NAME, |
517 | .owner = THIS_MODULE, | ||
518 | .of_match_table = of_match_ptr(spi_gpio_dt_ids), | ||
519 | }, | ||
427 | .probe = spi_gpio_probe, | 520 | .probe = spi_gpio_probe, |
428 | .remove = __devexit_p(spi_gpio_remove), | 521 | .remove = __devexit_p(spi_gpio_remove), |
429 | }; | 522 | }; |