hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/gpio/gpio-ftgpio010.c
....@@ -15,6 +15,7 @@
1515 #include <linux/interrupt.h>
1616 #include <linux/platform_device.h>
1717 #include <linux/bitops.h>
18
+#include <linux/clk.h>
1819
1920 /* GPIO registers definition */
2021 #define GPIO_DATA_OUT 0x00
....@@ -40,11 +41,16 @@
4041 * struct ftgpio_gpio - Gemini GPIO state container
4142 * @dev: containing device for this instance
4243 * @gc: gpiochip for this instance
44
+ * @irq: irqchip for this instance
45
+ * @base: remapped I/O-memory base
46
+ * @clk: silicon clock
4347 */
4448 struct ftgpio_gpio {
4549 struct device *dev;
4650 struct gpio_chip gc;
51
+ struct irq_chip irq;
4752 void __iomem *base;
53
+ struct clk *clk;
4854 };
4955
5056 static void ftgpio_gpio_ack_irq(struct irq_data *d)
....@@ -130,14 +136,6 @@
130136 return 0;
131137 }
132138
133
-static struct irq_chip ftgpio_gpio_irqchip = {
134
- .name = "FTGPIO010",
135
- .irq_ack = ftgpio_gpio_ack_irq,
136
- .irq_mask = ftgpio_gpio_mask_irq,
137
- .irq_unmask = ftgpio_gpio_unmask_irq,
138
- .irq_set_type = ftgpio_gpio_set_irq_type,
139
-};
140
-
141139 static void ftgpio_gpio_irq_handler(struct irq_desc *desc)
142140 {
143141 struct gpio_chip *gc = irq_desc_get_handler_data(desc);
....@@ -157,11 +155,78 @@
157155 chained_irq_exit(irqchip, desc);
158156 }
159157
158
+static int ftgpio_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
159
+ unsigned long config)
160
+{
161
+ enum pin_config_param param = pinconf_to_config_param(config);
162
+ u32 arg = pinconf_to_config_argument(config);
163
+ struct ftgpio_gpio *g = gpiochip_get_data(gc);
164
+ unsigned long pclk_freq;
165
+ u32 deb_div;
166
+ u32 val;
167
+
168
+ if (param != PIN_CONFIG_INPUT_DEBOUNCE)
169
+ return -ENOTSUPP;
170
+
171
+ /*
172
+ * Debounce only works if interrupts are enabled. The manual
173
+ * states that if PCLK is 66 MHz, and this is set to 0x7D0, then
174
+ * PCLK is divided down to 33 kHz for the debounce timer. 0x7D0 is
175
+ * 2000 decimal, so what they mean is simply that the PCLK is
176
+ * divided by this value.
177
+ *
178
+ * As we get a debounce setting in microseconds, we calculate the
179
+ * desired period time and see if we can get a suitable debounce
180
+ * time.
181
+ */
182
+ pclk_freq = clk_get_rate(g->clk);
183
+ deb_div = DIV_ROUND_CLOSEST(pclk_freq, arg);
184
+
185
+ /* This register is only 24 bits wide */
186
+ if (deb_div > (1 << 24))
187
+ return -ENOTSUPP;
188
+
189
+ dev_dbg(g->dev, "prescale divisor: %08x, resulting frequency %lu Hz\n",
190
+ deb_div, (pclk_freq/deb_div));
191
+
192
+ val = readl(g->base + GPIO_DEBOUNCE_PRESCALE);
193
+ if (val == deb_div) {
194
+ /*
195
+ * The debounce timer happens to already be set to the
196
+ * desirable value, what a coincidence! We can just enable
197
+ * debounce on this GPIO line and return. This happens more
198
+ * often than you think, for example when all GPIO keys
199
+ * on a system are requesting the same debounce interval.
200
+ */
201
+ val = readl(g->base + GPIO_DEBOUNCE_EN);
202
+ val |= BIT(offset);
203
+ writel(val, g->base + GPIO_DEBOUNCE_EN);
204
+ return 0;
205
+ }
206
+
207
+ val = readl(g->base + GPIO_DEBOUNCE_EN);
208
+ if (val) {
209
+ /*
210
+ * Oh no! Someone is already using the debounce with
211
+ * another setting than what we need. Bummer.
212
+ */
213
+ return -ENOTSUPP;
214
+ }
215
+
216
+ /* First come, first serve */
217
+ writel(deb_div, g->base + GPIO_DEBOUNCE_PRESCALE);
218
+ /* Enable debounce */
219
+ val |= BIT(offset);
220
+ writel(val, g->base + GPIO_DEBOUNCE_EN);
221
+
222
+ return 0;
223
+}
224
+
160225 static int ftgpio_gpio_probe(struct platform_device *pdev)
161226 {
162227 struct device *dev = &pdev->dev;
163
- struct resource *res;
164228 struct ftgpio_gpio *g;
229
+ struct gpio_irq_chip *girq;
165230 int irq;
166231 int ret;
167232
....@@ -171,14 +236,26 @@
171236
172237 g->dev = dev;
173238
174
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
175
- g->base = devm_ioremap_resource(dev, res);
239
+ g->base = devm_platform_ioremap_resource(pdev, 0);
176240 if (IS_ERR(g->base))
177241 return PTR_ERR(g->base);
178242
179243 irq = platform_get_irq(pdev, 0);
180244 if (irq <= 0)
181245 return irq ? irq : -EINVAL;
246
+
247
+ g->clk = devm_clk_get(dev, NULL);
248
+ if (!IS_ERR(g->clk)) {
249
+ ret = clk_prepare_enable(g->clk);
250
+ if (ret)
251
+ return ret;
252
+ } else if (PTR_ERR(g->clk) == -EPROBE_DEFER) {
253
+ /*
254
+ * Percolate deferrals, for anything else,
255
+ * just live without the clocking.
256
+ */
257
+ return PTR_ERR(g->clk);
258
+ }
182259
183260 ret = bgpio_init(&g->gc, dev, 4,
184261 g->base + GPIO_DATA_IN,
....@@ -189,7 +266,7 @@
189266 0);
190267 if (ret) {
191268 dev_err(dev, "unable to init generic GPIO\n");
192
- return ret;
269
+ goto dis_clk;
193270 }
194271 g->gc.label = "FTGPIO010";
195272 g->gc.base = -1;
....@@ -197,27 +274,59 @@
197274 g->gc.owner = THIS_MODULE;
198275 /* ngpio is set by bgpio_init() */
199276
200
- ret = devm_gpiochip_add_data(dev, &g->gc, g);
201
- if (ret)
202
- return ret;
277
+ /* We need a silicon clock to do debounce */
278
+ if (!IS_ERR(g->clk))
279
+ g->gc.set_config = ftgpio_gpio_set_config;
280
+
281
+ g->irq.name = "FTGPIO010";
282
+ g->irq.irq_ack = ftgpio_gpio_ack_irq;
283
+ g->irq.irq_mask = ftgpio_gpio_mask_irq;
284
+ g->irq.irq_unmask = ftgpio_gpio_unmask_irq;
285
+ g->irq.irq_set_type = ftgpio_gpio_set_irq_type;
286
+
287
+ girq = &g->gc.irq;
288
+ girq->chip = &g->irq;
289
+ girq->parent_handler = ftgpio_gpio_irq_handler;
290
+ girq->num_parents = 1;
291
+ girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents),
292
+ GFP_KERNEL);
293
+ if (!girq->parents) {
294
+ ret = -ENOMEM;
295
+ goto dis_clk;
296
+ }
297
+ girq->default_type = IRQ_TYPE_NONE;
298
+ girq->handler = handle_bad_irq;
299
+ girq->parents[0] = irq;
203300
204301 /* Disable, unmask and clear all interrupts */
205302 writel(0x0, g->base + GPIO_INT_EN);
206303 writel(0x0, g->base + GPIO_INT_MASK);
207304 writel(~0x0, g->base + GPIO_INT_CLR);
208305
209
- ret = gpiochip_irqchip_add(&g->gc, &ftgpio_gpio_irqchip,
210
- 0, handle_bad_irq,
211
- IRQ_TYPE_NONE);
212
- if (ret) {
213
- dev_info(dev, "could not add irqchip\n");
214
- return ret;
215
- }
216
- gpiochip_set_chained_irqchip(&g->gc, &ftgpio_gpio_irqchip,
217
- irq, ftgpio_gpio_irq_handler);
306
+ /* Clear any use of debounce */
307
+ writel(0x0, g->base + GPIO_DEBOUNCE_EN);
218308
309
+ ret = devm_gpiochip_add_data(dev, &g->gc, g);
310
+ if (ret)
311
+ goto dis_clk;
312
+
313
+ platform_set_drvdata(pdev, g);
219314 dev_info(dev, "FTGPIO010 @%p registered\n", g->base);
220315
316
+ return 0;
317
+
318
+dis_clk:
319
+ if (!IS_ERR(g->clk))
320
+ clk_disable_unprepare(g->clk);
321
+ return ret;
322
+}
323
+
324
+static int ftgpio_gpio_remove(struct platform_device *pdev)
325
+{
326
+ struct ftgpio_gpio *g = platform_get_drvdata(pdev);
327
+
328
+ if (!IS_ERR(g->clk))
329
+ clk_disable_unprepare(g->clk);
221330 return 0;
222331 }
223332
....@@ -239,6 +348,7 @@
239348 .name = "ftgpio010-gpio",
240349 .of_match_table = of_match_ptr(ftgpio_gpio_of_match),
241350 },
242
- .probe = ftgpio_gpio_probe,
351
+ .probe = ftgpio_gpio_probe,
352
+ .remove = ftgpio_gpio_remove,
243353 };
244354 builtin_platform_driver(ftgpio_gpio_driver);