summaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2018-02-12 07:45:30 -0500
committerMark Brown <broonie@kernel.org>2018-02-14 11:02:41 -0500
commit9b00bc7b901ff672a9252002d3810fdf9489bc64 (patch)
tree533b0c9c3d81ed36732c69350139a0ca56d085cb /drivers/spi
parent7928b2cbe55b2a410a0f5c1f154610059c57b1b2 (diff)
spi: spi-gpio: Rewrite to use GPIO descriptors
This converts the bit-banged GPIO SPI driver to looking up and using GPIO descriptors to get a handle on GPIO lines for SCK, MOSI, MISO and all CS lines. All existing board files are converted in one go to keep it all consistent. With these conversions I rarely find any interrim steps that makes any sense. Device tree probing and GPIO handling should work like before also after this patch. For board files, we stop using controller data to pass the GPIO line for chip select, instead we pass this as a GPIO descriptor lookup like everything else. In some s3c24xx machines the names of the SPI devices were set to "spi-gpio" rather than "spi_gpio" which can never have worked, I fixed it working (I guess) as part of this patch set. Sometimes I wonder how this code got upstream in the first place, it obviously is not tested. mach-s3c64xx/mach-smartq.c has the same problem and additionally defines the *same* GPIO line for MOSI and MISO which is not going to be accepted by gpiolib. As the lines were number 1,2,2 I assumed it was a typo and use lines 1,2,3. A comment gives awat that line 0 is chip select though no actual SPI device is provided for the LCD supposed to be on this bit-banged SPI bus. I left it intact instead of just deleting the bus though. Kill off board file code that try to initialize the SPI lines to the same values that they will later be set by the spi_gpio driver anyways. Given the huge number of weird things in these board files I do not think this code is very tested or put in with much afterthought anyways. In order to assert that we do not get performance regressions on this crucial bing-banged driver, a ran a script like this dumping the Ilitek ILI9322 regmap 10000 times (it has no caching obviously) on an otherwise idle system in two iterations before and after the patches: #!/bin/sh for run in `seq 10000` do cat /debug/regmap/spi0.0/registers > /dev/null done Before the patch: time test.sh real 3m 41.03s user 0m 29.41s sys 3m 7.22s time test.sh real 3m 44.24s user 0m 32.31s sys 3m 7.60s After the patch: time test.sh real 3m 41.32s user 0m 28.92s sys 3m 8.08s time test.sh real 3m 39.92s user 0m 30.20s sys 3m 5.56s So any performance differences seems to be in the error margin. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Olof Johansson <olof@lixom.net> Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-gpio.c270
1 files changed, 92 insertions, 178 deletions
diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c
index 1c34c9314c8a..b85a93cad44a 100644
--- a/drivers/spi/spi-gpio.c
+++ b/drivers/spi/spi-gpio.c
@@ -2,6 +2,7 @@
2 * SPI master driver using generic bitbanged GPIO 2 * SPI master driver using generic bitbanged GPIO
3 * 3 *
4 * Copyright (C) 2006,2008 David Brownell 4 * Copyright (C) 2006,2008 David Brownell
5 * Copyright (C) 2017 Linus Walleij
5 * 6 *
6 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
@@ -16,10 +17,9 @@
16#include <linux/kernel.h> 17#include <linux/kernel.h>
17#include <linux/module.h> 18#include <linux/module.h>
18#include <linux/platform_device.h> 19#include <linux/platform_device.h>
19#include <linux/gpio.h> 20#include <linux/gpio/consumer.h>
20#include <linux/of.h> 21#include <linux/of.h>
21#include <linux/of_device.h> 22#include <linux/of_device.h>
22#include <linux/of_gpio.h>
23 23
24#include <linux/spi/spi.h> 24#include <linux/spi/spi.h>
25#include <linux/spi/spi_bitbang.h> 25#include <linux/spi/spi_bitbang.h>
@@ -44,7 +44,11 @@ struct spi_gpio {
44 struct spi_bitbang bitbang; 44 struct spi_bitbang bitbang;
45 struct spi_gpio_platform_data pdata; 45 struct spi_gpio_platform_data pdata;
46 struct platform_device *pdev; 46 struct platform_device *pdev;
47 unsigned long cs_gpios[0]; 47 struct gpio_desc *sck;
48 struct gpio_desc *miso;
49 struct gpio_desc *mosi;
50 struct gpio_desc **cs_gpios;
51 bool has_cs;
48}; 52};
49 53
50/*----------------------------------------------------------------------*/ 54/*----------------------------------------------------------------------*/
@@ -77,13 +81,6 @@ struct spi_gpio {
77 81
78#define GENERIC_BITBANG /* vs tight inlines */ 82#define GENERIC_BITBANG /* vs tight inlines */
79 83
80/* all functions referencing these symbols must define pdata */
81#define SPI_MISO_GPIO ((pdata)->miso)
82#define SPI_MOSI_GPIO ((pdata)->mosi)
83#define SPI_SCK_GPIO ((pdata)->sck)
84
85#define SPI_N_CHIPSEL ((pdata)->num_chipselect)
86
87#endif 84#endif
88 85
89/*----------------------------------------------------------------------*/ 86/*----------------------------------------------------------------------*/
@@ -105,25 +102,27 @@ spi_to_pdata(const struct spi_device *spi)
105 return &spi_to_spi_gpio(spi)->pdata; 102 return &spi_to_spi_gpio(spi)->pdata;
106} 103}
107 104
108/* this is #defined to avoid unused-variable warnings when inlining */ 105/* These helpers are in turn called by the bitbang inlines */
109#define pdata spi_to_pdata(spi)
110
111static inline void setsck(const struct spi_device *spi, int is_on) 106static inline void setsck(const struct spi_device *spi, int is_on)
112{ 107{
113 gpio_set_value_cansleep(SPI_SCK_GPIO, is_on); 108 struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
109
110 gpiod_set_value_cansleep(spi_gpio->sck, is_on);
114} 111}
115 112
116static inline void setmosi(const struct spi_device *spi, int is_on) 113static inline void setmosi(const struct spi_device *spi, int is_on)
117{ 114{
118 gpio_set_value_cansleep(SPI_MOSI_GPIO, is_on); 115 struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
116
117 gpiod_set_value_cansleep(spi_gpio->mosi, is_on);
119} 118}
120 119
121static inline int getmiso(const struct spi_device *spi) 120static inline int getmiso(const struct spi_device *spi)
122{ 121{
123 return !!gpio_get_value_cansleep(SPI_MISO_GPIO); 122 struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
124}
125 123
126#undef pdata 124 return !!gpiod_get_value_cansleep(spi_gpio->miso);
125}
127 126
128/* 127/*
129 * NOTE: this clocks "as fast as we can". It "should" be a function of the 128 * NOTE: this clocks "as fast as we can". It "should" be a function of the
@@ -216,123 +215,89 @@ static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi,
216static void spi_gpio_chipselect(struct spi_device *spi, int is_active) 215static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
217{ 216{
218 struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); 217 struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
219 unsigned long cs = spi_gpio->cs_gpios[spi->chip_select];
220 218
221 /* set initial clock polarity */ 219 /* set initial clock line level */
222 if (is_active) 220 if (is_active)
223 setsck(spi, spi->mode & SPI_CPOL); 221 gpiod_set_value_cansleep(spi_gpio->sck, spi->mode & SPI_CPOL);
222
223 /* Drive chip select line, if we have one */
224 if (spi_gpio->has_cs) {
225 struct gpio_desc *cs = spi_gpio->cs_gpios[spi->chip_select];
224 226
225 if (cs != SPI_GPIO_NO_CHIPSELECT) { 227 /* SPI chip selects are normally active-low */
226 /* SPI is normally active-low */ 228 gpiod_set_value_cansleep(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
227 gpio_set_value_cansleep(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
228 } 229 }
229} 230}
230 231
231static int spi_gpio_setup(struct spi_device *spi) 232static int spi_gpio_setup(struct spi_device *spi)
232{ 233{
233 unsigned long cs; 234 struct gpio_desc *cs;
234 int status = 0; 235 int status = 0;
235 struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); 236 struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
236 struct device_node *np = spi->master->dev.of_node;
237
238 if (np) {
239 /*
240 * In DT environments, the CS GPIOs have already been
241 * initialized from the "cs-gpios" property of the node.
242 */
243 cs = spi_gpio->cs_gpios[spi->chip_select];
244 } else {
245 /*
246 * ... otherwise, take it from spi->controller_data
247 */
248 cs = (uintptr_t) spi->controller_data;
249 }
250 237
251 if (!spi->controller_state) { 238 /*
252 if (cs != SPI_GPIO_NO_CHIPSELECT) { 239 * The CS GPIOs have already been
253 status = gpio_request(cs, dev_name(&spi->dev)); 240 * initialized from the descriptor lookup.
254 if (status) 241 */
255 return status; 242 cs = spi_gpio->cs_gpios[spi->chip_select];
256 status = gpio_direction_output(cs, 243 if (!spi->controller_state && cs)
257 !(spi->mode & SPI_CS_HIGH)); 244 status = gpiod_direction_output(cs,
258 } 245 !(spi->mode & SPI_CS_HIGH));
259 } 246
260 if (!status) { 247 if (!status)
261 /* in case it was initialized from static board data */
262 spi_gpio->cs_gpios[spi->chip_select] = cs;
263 status = spi_bitbang_setup(spi); 248 status = spi_bitbang_setup(spi);
264 }
265 249
266 if (status) {
267 if (!spi->controller_state && cs != SPI_GPIO_NO_CHIPSELECT)
268 gpio_free(cs);
269 }
270 return status; 250 return status;
271} 251}
272 252
273static void spi_gpio_cleanup(struct spi_device *spi) 253static void spi_gpio_cleanup(struct spi_device *spi)
274{ 254{
275 struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
276 unsigned long cs = spi_gpio->cs_gpios[spi->chip_select];
277
278 if (cs != SPI_GPIO_NO_CHIPSELECT)
279 gpio_free(cs);
280 spi_bitbang_cleanup(spi); 255 spi_bitbang_cleanup(spi);
281} 256}
282 257
283static int spi_gpio_alloc(unsigned pin, const char *label, bool is_in) 258/*
284{ 259 * It can be convenient to use this driver with pins that have alternate
285 int value; 260 * functions associated with a "native" SPI controller if a driver for that
286 261 * controller is not available, or is missing important functionality.
287 value = gpio_request(pin, label); 262 *
288 if (value == 0) { 263 * On platforms which can do so, configure MISO with a weak pullup unless
289 if (is_in) 264 * there's an external pullup on that signal. That saves power by avoiding
290 value = gpio_direction_input(pin); 265 * floating signals. (A weak pulldown would save power too, but many
291 else 266 * drivers expect to see all-ones data as the no slave "response".)
292 value = gpio_direction_output(pin, 0); 267 */
293 } 268static int spi_gpio_request(struct device *dev,
294 return value; 269 struct spi_gpio *spi_gpio,
295} 270 unsigned int num_chipselects,
296 271 u16 *mflags)
297static int spi_gpio_request(struct spi_gpio_platform_data *pdata,
298 const char *label, u16 *res_flags)
299{ 272{
300 int value; 273 int i;
301
302 /* NOTE: SPI_*_GPIO symbols may reference "pdata" */
303 274
304 if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) { 275 spi_gpio->mosi = devm_gpiod_get_optional(dev, "mosi", GPIOD_OUT_LOW);
305 value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false); 276 if (IS_ERR(spi_gpio->mosi))
306 if (value) 277 return PTR_ERR(spi_gpio->mosi);
307 goto done; 278 if (!spi_gpio->mosi)
308 } else {
309 /* HW configuration without MOSI pin */ 279 /* HW configuration without MOSI pin */
310 *res_flags |= SPI_MASTER_NO_TX; 280 *mflags |= SPI_MASTER_NO_TX;
311 }
312 281
313 if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) { 282 spi_gpio->miso = devm_gpiod_get_optional(dev, "miso", GPIOD_IN);
314 value = spi_gpio_alloc(SPI_MISO_GPIO, label, true); 283 if (IS_ERR(spi_gpio->miso))
315 if (value) 284 return PTR_ERR(spi_gpio->miso);
316 goto free_mosi; 285 if (!spi_gpio->miso)
317 } else {
318 /* HW configuration without MISO pin */ 286 /* HW configuration without MISO pin */
319 *res_flags |= SPI_MASTER_NO_RX; 287 *mflags |= SPI_MASTER_NO_RX;
320 }
321 288
322 value = spi_gpio_alloc(SPI_SCK_GPIO, label, false); 289 spi_gpio->sck = devm_gpiod_get(dev, "sck", GPIOD_OUT_LOW);
323 if (value) 290 if (IS_ERR(spi_gpio->mosi))
324 goto free_miso; 291 return PTR_ERR(spi_gpio->mosi);
325 292
326 goto done; 293 for (i = 0; i < num_chipselects; i++) {
294 spi_gpio->cs_gpios[i] = devm_gpiod_get_index(dev, "cs",
295 i, GPIOD_OUT_HIGH);
296 if (IS_ERR(spi_gpio->cs_gpios[i]))
297 return PTR_ERR(spi_gpio->cs_gpios[i]);
298 }
327 299
328free_miso: 300 return 0;
329 if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
330 gpio_free(SPI_MISO_GPIO);
331free_mosi:
332 if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
333 gpio_free(SPI_MOSI_GPIO);
334done:
335 return value;
336} 301}
337 302
338#ifdef CONFIG_OF 303#ifdef CONFIG_OF
@@ -358,26 +323,6 @@ static int spi_gpio_probe_dt(struct platform_device *pdev)
358 if (!pdata) 323 if (!pdata)
359 return -ENOMEM; 324 return -ENOMEM;
360 325
361 ret = of_get_named_gpio(np, "gpio-sck", 0);
362 if (ret < 0) {
363 dev_err(&pdev->dev, "gpio-sck property not found\n");
364 goto error_free;
365 }
366 pdata->sck = ret;
367
368 ret = of_get_named_gpio(np, "gpio-miso", 0);
369 if (ret < 0) {
370 dev_info(&pdev->dev, "gpio-miso property not found, switching to no-rx mode\n");
371 pdata->miso = SPI_GPIO_NO_MISO;
372 } else
373 pdata->miso = ret;
374
375 ret = of_get_named_gpio(np, "gpio-mosi", 0);
376 if (ret < 0) {
377 dev_info(&pdev->dev, "gpio-mosi property not found, switching to no-tx mode\n");
378 pdata->mosi = SPI_GPIO_NO_MOSI;
379 } else
380 pdata->mosi = ret;
381 326
382 ret = of_property_read_u32(np, "num-chipselects", &tmp); 327 ret = of_property_read_u32(np, "num-chipselects", &tmp);
383 if (ret < 0) { 328 if (ret < 0) {
@@ -409,7 +354,6 @@ static int spi_gpio_probe(struct platform_device *pdev)
409 struct spi_gpio_platform_data *pdata; 354 struct spi_gpio_platform_data *pdata;
410 u16 master_flags = 0; 355 u16 master_flags = 0;
411 bool use_of = 0; 356 bool use_of = 0;
412 int num_devices;
413 357
414 status = spi_gpio_probe_dt(pdev); 358 status = spi_gpio_probe_dt(pdev);
415 if (status < 0) 359 if (status < 0)
@@ -423,59 +367,41 @@ static int spi_gpio_probe(struct platform_device *pdev)
423 return -ENODEV; 367 return -ENODEV;
424#endif 368#endif
425 369
426 if (use_of && !SPI_N_CHIPSEL) 370 master = spi_alloc_master(&pdev->dev, sizeof(*spi_gpio));
427 num_devices = 1; 371 if (!master)
428 else 372 return -ENOMEM;
429 num_devices = SPI_N_CHIPSEL;
430
431 status = spi_gpio_request(pdata, dev_name(&pdev->dev), &master_flags);
432 if (status < 0)
433 return status;
434 373
435 master = spi_alloc_master(&pdev->dev, sizeof(*spi_gpio) +
436 (sizeof(unsigned long) * num_devices));
437 if (!master) {
438 status = -ENOMEM;
439 goto gpio_free;
440 }
441 spi_gpio = spi_master_get_devdata(master); 374 spi_gpio = spi_master_get_devdata(master);
375
376 spi_gpio->cs_gpios = devm_kzalloc(&pdev->dev,
377 pdata->num_chipselect * sizeof(*spi_gpio->cs_gpios),
378 GFP_KERNEL);
379 if (!spi_gpio->cs_gpios)
380 return -ENOMEM;
381
442 platform_set_drvdata(pdev, spi_gpio); 382 platform_set_drvdata(pdev, spi_gpio);
443 383
384 /* Determine if we have chip selects connected */
385 spi_gpio->has_cs = !!pdata->num_chipselect;
386
444 spi_gpio->pdev = pdev; 387 spi_gpio->pdev = pdev;
445 if (pdata) 388 if (pdata)
446 spi_gpio->pdata = *pdata; 389 spi_gpio->pdata = *pdata;
447 390
391 status = spi_gpio_request(&pdev->dev, spi_gpio,
392 pdata->num_chipselect, &master_flags);
393 if (status)
394 return status;
395
448 master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); 396 master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
449 master->flags = master_flags; 397 master->flags = master_flags;
450 master->bus_num = pdev->id; 398 master->bus_num = pdev->id;
451 master->num_chipselect = num_devices; 399 /* The master needs to think there is a chipselect even if not connected */
400 master->num_chipselect = spi_gpio->has_cs ? pdata->num_chipselect : 1;
452 master->setup = spi_gpio_setup; 401 master->setup = spi_gpio_setup;
453 master->cleanup = spi_gpio_cleanup; 402 master->cleanup = spi_gpio_cleanup;
454#ifdef CONFIG_OF 403#ifdef CONFIG_OF
455 master->dev.of_node = pdev->dev.of_node; 404 master->dev.of_node = pdev->dev.of_node;
456
457 if (use_of) {
458 int i;
459 struct device_node *np = pdev->dev.of_node;
460
461 /*
462 * In DT environments, take the CS GPIO from the "cs-gpios"
463 * property of the node.
464 */
465
466 if (!SPI_N_CHIPSEL)
467 spi_gpio->cs_gpios[0] = SPI_GPIO_NO_CHIPSELECT;
468 else
469 for (i = 0; i < SPI_N_CHIPSEL; i++) {
470 status = of_get_named_gpio(np, "cs-gpios", i);
471 if (status < 0) {
472 dev_err(&pdev->dev,
473 "invalid cs-gpios property\n");
474 goto gpio_free;
475 }
476 spi_gpio->cs_gpios[i] = status;
477 }
478 }
479#endif 405#endif
480 406
481 spi_gpio->bitbang.master = master; 407 spi_gpio->bitbang.master = master;
@@ -496,15 +422,8 @@ static int spi_gpio_probe(struct platform_device *pdev)
496 spi_gpio->bitbang.flags = SPI_CS_HIGH; 422 spi_gpio->bitbang.flags = SPI_CS_HIGH;
497 423
498 status = spi_bitbang_start(&spi_gpio->bitbang); 424 status = spi_bitbang_start(&spi_gpio->bitbang);
499 if (status < 0) { 425 if (status)
500gpio_free:
501 if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
502 gpio_free(SPI_MISO_GPIO);
503 if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
504 gpio_free(SPI_MOSI_GPIO);
505 gpio_free(SPI_SCK_GPIO);
506 spi_master_put(master); 426 spi_master_put(master);
507 }
508 427
509 return status; 428 return status;
510} 429}
@@ -520,11 +439,6 @@ static int spi_gpio_remove(struct platform_device *pdev)
520 /* stop() unregisters child devices too */ 439 /* stop() unregisters child devices too */
521 spi_bitbang_stop(&spi_gpio->bitbang); 440 spi_bitbang_stop(&spi_gpio->bitbang);
522 441
523 if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
524 gpio_free(SPI_MISO_GPIO);
525 if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
526 gpio_free(SPI_MOSI_GPIO);
527 gpio_free(SPI_SCK_GPIO);
528 spi_master_put(spi_gpio->bitbang.master); 442 spi_master_put(spi_gpio->bitbang.master);
529 443
530 return 0; 444 return 0;