diff options
Diffstat (limited to 'drivers/spi/spi-gpio.c')
-rw-r--r-- | drivers/spi/spi-gpio.c | 131 |
1 files changed, 119 insertions, 12 deletions
diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index 0b56cfc71fab..a2b50c516b31 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> |
@@ -46,6 +48,7 @@ struct spi_gpio { | |||
46 | struct spi_bitbang bitbang; | 48 | struct spi_bitbang bitbang; |
47 | struct spi_gpio_platform_data pdata; | 49 | struct spi_gpio_platform_data pdata; |
48 | struct platform_device *pdev; | 50 | struct platform_device *pdev; |
51 | int cs_gpios[0]; | ||
49 | }; | 52 | }; |
50 | 53 | ||
51 | /*----------------------------------------------------------------------*/ | 54 | /*----------------------------------------------------------------------*/ |
@@ -89,15 +92,21 @@ struct spi_gpio { | |||
89 | 92 | ||
90 | /*----------------------------------------------------------------------*/ | 93 | /*----------------------------------------------------------------------*/ |
91 | 94 | ||
92 | static inline const struct spi_gpio_platform_data * __pure | 95 | static inline struct spi_gpio * __pure |
93 | spi_to_pdata(const struct spi_device *spi) | 96 | spi_to_spi_gpio(const struct spi_device *spi) |
94 | { | 97 | { |
95 | const struct spi_bitbang *bang; | 98 | const struct spi_bitbang *bang; |
96 | const struct spi_gpio *spi_gpio; | 99 | struct spi_gpio *spi_gpio; |
97 | 100 | ||
98 | bang = spi_master_get_devdata(spi->master); | 101 | bang = spi_master_get_devdata(spi->master); |
99 | spi_gpio = container_of(bang, struct spi_gpio, bitbang); | 102 | spi_gpio = container_of(bang, struct spi_gpio, bitbang); |
100 | return &spi_gpio->pdata; | 103 | return spi_gpio; |
104 | } | ||
105 | |||
106 | static inline struct spi_gpio_platform_data * __pure | ||
107 | spi_to_pdata(const struct spi_device *spi) | ||
108 | { | ||
109 | return &spi_to_spi_gpio(spi)->pdata; | ||
101 | } | 110 | } |
102 | 111 | ||
103 | /* this is #defined to avoid unused-variable warnings when inlining */ | 112 | /* this is #defined to avoid unused-variable warnings when inlining */ |
@@ -210,7 +219,8 @@ static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi, | |||
210 | 219 | ||
211 | static void spi_gpio_chipselect(struct spi_device *spi, int is_active) | 220 | static void spi_gpio_chipselect(struct spi_device *spi, int is_active) |
212 | { | 221 | { |
213 | unsigned long cs = (unsigned long) spi->controller_data; | 222 | struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); |
223 | unsigned int cs = spi_gpio->cs_gpios[spi->chip_select]; | ||
214 | 224 | ||
215 | /* set initial clock polarity */ | 225 | /* set initial clock polarity */ |
216 | if (is_active) | 226 | if (is_active) |
@@ -224,12 +234,27 @@ static void spi_gpio_chipselect(struct spi_device *spi, int is_active) | |||
224 | 234 | ||
225 | static int spi_gpio_setup(struct spi_device *spi) | 235 | static int spi_gpio_setup(struct spi_device *spi) |
226 | { | 236 | { |
227 | unsigned long cs = (unsigned long) spi->controller_data; | 237 | unsigned int cs; |
228 | int status = 0; | 238 | int status = 0; |
239 | struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); | ||
240 | struct device_node *np = spi->master->dev.of_node; | ||
229 | 241 | ||
230 | if (spi->bits_per_word > 32) | 242 | if (spi->bits_per_word > 32) |
231 | return -EINVAL; | 243 | return -EINVAL; |
232 | 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 | |||
233 | if (!spi->controller_state) { | 258 | if (!spi->controller_state) { |
234 | if (cs != SPI_GPIO_NO_CHIPSELECT) { | 259 | if (cs != SPI_GPIO_NO_CHIPSELECT) { |
235 | status = gpio_request(cs, dev_name(&spi->dev)); | 260 | status = gpio_request(cs, dev_name(&spi->dev)); |
@@ -239,8 +264,12 @@ static int spi_gpio_setup(struct spi_device *spi) | |||
239 | !(spi->mode & SPI_CS_HIGH)); | 264 | !(spi->mode & SPI_CS_HIGH)); |
240 | } | 265 | } |
241 | } | 266 | } |
242 | if (!status) | 267 | if (!status) { |
243 | status = spi_bitbang_setup(spi); | 268 | status = spi_bitbang_setup(spi); |
269 | /* in case it was initialized from static board data */ | ||
270 | spi_gpio->cs_gpios[spi->chip_select] = cs; | ||
271 | } | ||
272 | |||
244 | if (status) { | 273 | if (status) { |
245 | if (!spi->controller_state && cs != SPI_GPIO_NO_CHIPSELECT) | 274 | if (!spi->controller_state && cs != SPI_GPIO_NO_CHIPSELECT) |
246 | gpio_free(cs); | 275 | gpio_free(cs); |
@@ -250,7 +279,8 @@ static int spi_gpio_setup(struct spi_device *spi) | |||
250 | 279 | ||
251 | static void spi_gpio_cleanup(struct spi_device *spi) | 280 | static void spi_gpio_cleanup(struct spi_device *spi) |
252 | { | 281 | { |
253 | unsigned long cs = (unsigned long) spi->controller_data; | 282 | struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); |
283 | unsigned int cs = spi_gpio->cs_gpios[spi->chip_select]; | ||
254 | 284 | ||
255 | if (cs != SPI_GPIO_NO_CHIPSELECT) | 285 | if (cs != SPI_GPIO_NO_CHIPSELECT) |
256 | gpio_free(cs); | 286 | gpio_free(cs); |
@@ -313,6 +343,55 @@ done: | |||
313 | return value; | 343 | return value; |
314 | } | 344 | } |
315 | 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_gpio_probe_dt(struct platform_device *pdev) | ||
390 | { | ||
391 | return 0; | ||
392 | } | ||
393 | #endif | ||
394 | |||
316 | static int __devinit spi_gpio_probe(struct platform_device *pdev) | 395 | static int __devinit spi_gpio_probe(struct platform_device *pdev) |
317 | { | 396 | { |
318 | int status; | 397 | int status; |
@@ -320,6 +399,13 @@ static int __devinit spi_gpio_probe(struct platform_device *pdev) | |||
320 | struct spi_gpio *spi_gpio; | 399 | struct spi_gpio *spi_gpio; |
321 | struct spi_gpio_platform_data *pdata; | 400 | struct spi_gpio_platform_data *pdata; |
322 | 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; | ||
323 | 409 | ||
324 | pdata = pdev->dev.platform_data; | 410 | pdata = pdev->dev.platform_data; |
325 | #ifdef GENERIC_BITBANG | 411 | #ifdef GENERIC_BITBANG |
@@ -331,7 +417,8 @@ static int __devinit spi_gpio_probe(struct platform_device *pdev) | |||
331 | if (status < 0) | 417 | if (status < 0) |
332 | return status; | 418 | return status; |
333 | 419 | ||
334 | master = spi_alloc_master(&pdev->dev, sizeof *spi_gpio); | 420 | master = spi_alloc_master(&pdev->dev, sizeof(*spi_gpio) + |
421 | (sizeof(int) * SPI_N_CHIPSEL)); | ||
335 | if (!master) { | 422 | if (!master) { |
336 | status = -ENOMEM; | 423 | status = -ENOMEM; |
337 | goto gpio_free; | 424 | goto gpio_free; |
@@ -348,6 +435,23 @@ static int __devinit spi_gpio_probe(struct platform_device *pdev) | |||
348 | master->num_chipselect = SPI_N_CHIPSEL; | 435 | master->num_chipselect = SPI_N_CHIPSEL; |
349 | master->setup = spi_gpio_setup; | 436 | master->setup = spi_gpio_setup; |
350 | 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 | ||
351 | 455 | ||
352 | spi_gpio->bitbang.master = spi_master_get(master); | 456 | spi_gpio->bitbang.master = spi_master_get(master); |
353 | spi_gpio->bitbang.chipselect = spi_gpio_chipselect; | 457 | spi_gpio->bitbang.chipselect = spi_gpio_chipselect; |
@@ -408,8 +512,11 @@ static int __devexit spi_gpio_remove(struct platform_device *pdev) | |||
408 | MODULE_ALIAS("platform:" DRIVER_NAME); | 512 | MODULE_ALIAS("platform:" DRIVER_NAME); |
409 | 513 | ||
410 | static struct platform_driver spi_gpio_driver = { | 514 | static struct platform_driver spi_gpio_driver = { |
411 | .driver.name = DRIVER_NAME, | 515 | .driver = { |
412 | .driver.owner = THIS_MODULE, | 516 | .name = DRIVER_NAME, |
517 | .owner = THIS_MODULE, | ||
518 | .of_match_table = of_match_ptr(spi_gpio_dt_ids), | ||
519 | }, | ||
413 | .probe = spi_gpio_probe, | 520 | .probe = spi_gpio_probe, |
414 | .remove = __devexit_p(spi_gpio_remove), | 521 | .remove = __devexit_p(spi_gpio_remove), |
415 | }; | 522 | }; |