ff8471411f5786f95ff8f19641d1b6ff139b8916
[openwrt/staging/ldir.git] /
1 From 380c336af070edf85826abbb0057bf92a03ec466 Mon Sep 17 00:00:00 2001
2 From: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
3 Date: Wed, 1 Mar 2023 17:57:11 +0000
4 Subject: [PATCH] drivers: spi: Fix spi-gpio to correctly implement
5 sck-idle-input
6
7 Formerly, if configured using DT, CS GPIOs were driven from spi.c
8 and it was possible for CS to be asserted (low) *before* starting
9 to drive SCK. CS GPIOs have been brought under control of this
10 driver in both ACPI and DT cases, with a fixup for GPIO polarity.
11
12 Signed-off-by: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
13 ---
14 drivers/spi/spi-gpio.c | 74 +++++++++++++++++++++++++++++-------------
15 1 file changed, 51 insertions(+), 23 deletions(-)
16
17 --- a/drivers/spi/spi-gpio.c
18 +++ b/drivers/spi/spi-gpio.c
19 @@ -37,6 +37,7 @@ struct spi_gpio {
20 struct gpio_desc *mosi;
21 bool sck_idle_input;
22 struct gpio_desc **cs_gpios;
23 + bool cs_dont_invert;
24 };
25
26 /*----------------------------------------------------------------------*/
27 @@ -233,12 +234,18 @@ static void spi_gpio_chipselect(struct s
28 gpiod_set_value_cansleep(spi_gpio->sck, spi->mode & SPI_CPOL);
29 }
30
31 - /* Drive chip select line, if we have one */
32 + /*
33 + * Drive chip select line, if we have one.
34 + * SPI chip selects are normally active-low, but when
35 + * cs_dont_invert is set, we assume their polarity is
36 + * controlled by the GPIO, and write '1' to assert.
37 + */
38 if (spi_gpio->cs_gpios) {
39 struct gpio_desc *cs = spi_gpio->cs_gpios[spi->chip_select];
40 + int val = ((spi->mode & SPI_CS_HIGH) || spi_gpio->cs_dont_invert) ?
41 + is_active : !is_active;
42
43 - /* SPI chip selects are normally active-low */
44 - gpiod_set_value_cansleep(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
45 + gpiod_set_value_cansleep(cs, val);
46 }
47
48 if (spi_gpio->sck_idle_input && !is_active)
49 @@ -254,12 +261,14 @@ static int spi_gpio_setup(struct spi_dev
50 /*
51 * The CS GPIOs have already been
52 * initialized from the descriptor lookup.
53 + * Here we set them to the non-asserted state.
54 */
55 if (spi_gpio->cs_gpios) {
56 cs = spi_gpio->cs_gpios[spi->chip_select];
57 if (!spi->controller_state && cs)
58 status = gpiod_direction_output(cs,
59 - !(spi->mode & SPI_CS_HIGH));
60 + !((spi->mode & SPI_CS_HIGH) ||
61 + spi_gpio->cs_dont_invert));
62 }
63
64 if (!status)
65 @@ -336,6 +345,38 @@ static int spi_gpio_request(struct devic
66 return PTR_ERR_OR_ZERO(spi_gpio->sck);
67 }
68
69 +/*
70 + * In order to implement "sck-idle-input" (which requires SCK
71 + * direction and CS level to be switched in a particular order),
72 + * we need to control GPIO chip selects from within this driver.
73 + */
74 +
75 +static int spi_gpio_probe_get_cs_gpios(struct device *dev,
76 + struct spi_master *master,
77 + bool gpio_defines_polarity)
78 +{
79 + int i;
80 + struct spi_gpio *spi_gpio = spi_master_get_devdata(master);
81 +
82 + spi_gpio->cs_dont_invert = gpio_defines_polarity;
83 + spi_gpio->cs_gpios = devm_kcalloc(dev, master->num_chipselect,
84 + sizeof(*spi_gpio->cs_gpios),
85 + GFP_KERNEL);
86 + if (!spi_gpio->cs_gpios)
87 + return -ENOMEM;
88 +
89 + for (i = 0; i < master->num_chipselect; i++) {
90 + spi_gpio->cs_gpios[i] =
91 + devm_gpiod_get_index(dev, "cs", i,
92 + gpio_defines_polarity ?
93 + GPIOD_OUT_LOW : GPIOD_OUT_HIGH);
94 + if (IS_ERR(spi_gpio->cs_gpios[i]))
95 + return PTR_ERR(spi_gpio->cs_gpios[i]);
96 + }
97 +
98 + return 0;
99 +}
100 +
101 #ifdef CONFIG_OF
102 static const struct of_device_id spi_gpio_dt_ids[] = {
103 { .compatible = "spi-gpio" },
104 @@ -346,10 +387,12 @@ MODULE_DEVICE_TABLE(of, spi_gpio_dt_ids)
105 static int spi_gpio_probe_dt(struct platform_device *pdev,
106 struct spi_master *master)
107 {
108 - master->dev.of_node = pdev->dev.of_node;
109 - master->use_gpio_descriptors = true;
110 + struct device *dev = &pdev->dev;
111
112 - return 0;
113 + master->dev.of_node = dev->of_node;
114 + master->num_chipselect = gpiod_count(dev, "cs");
115 +
116 + return spi_gpio_probe_get_cs_gpios(dev, master, true);
117 }
118 #else
119 static inline int spi_gpio_probe_dt(struct platform_device *pdev,
120 @@ -364,8 +407,6 @@ static int spi_gpio_probe_pdata(struct p
121 {
122 struct device *dev = &pdev->dev;
123 struct spi_gpio_platform_data *pdata = dev_get_platdata(dev);
124 - struct spi_gpio *spi_gpio = spi_master_get_devdata(master);
125 - int i;
126
127 #ifdef GENERIC_BITBANG
128 if (!pdata || !pdata->num_chipselect)
129 @@ -377,20 +418,7 @@ static int spi_gpio_probe_pdata(struct p
130 */
131 master->num_chipselect = pdata->num_chipselect ?: 1;
132
133 - spi_gpio->cs_gpios = devm_kcalloc(dev, master->num_chipselect,
134 - sizeof(*spi_gpio->cs_gpios),
135 - GFP_KERNEL);
136 - if (!spi_gpio->cs_gpios)
137 - return -ENOMEM;
138 -
139 - for (i = 0; i < master->num_chipselect; i++) {
140 - spi_gpio->cs_gpios[i] = devm_gpiod_get_index(dev, "cs", i,
141 - GPIOD_OUT_HIGH);
142 - if (IS_ERR(spi_gpio->cs_gpios[i]))
143 - return PTR_ERR(spi_gpio->cs_gpios[i]);
144 - }
145 -
146 - return 0;
147 + return spi_gpio_probe_get_cs_gpios(dev, master, false);
148 }
149
150 static int spi_gpio_probe(struct platform_device *pdev)