hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/gpio/gpio-altera.c
....@@ -1,19 +1,7 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Copyright (C) 2013 Altera Corporation
34 * Based on gpio-mpc8xxx.c
4
- *
5
- * This program is free software; you can redistribute it and/or modify
6
- * it under the terms of the GNU General Public License as published by
7
- * the Free Software Foundation; either version 2 of the License, or
8
- * (at your option) any later version.
9
- *
10
- * This program is distributed in the hope that it will be useful,
11
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- * GNU General Public License for more details.
14
- *
15
- * You should have received a copy of the GNU General Public License
16
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
175 */
186
197 #include <linux/io.h>
....@@ -32,16 +20,18 @@
3220 * struct altera_gpio_chip
3321 * @mmchip : memory mapped chip structure.
3422 * @gpio_lock : synchronization lock so that new irq/set/get requests
35
- will be blocked until the current one completes.
23
+* will be blocked until the current one completes.
3624 * @interrupt_trigger : specifies the hardware configured IRQ trigger type
37
- (rising, falling, both, high)
25
+* (rising, falling, both, high)
3826 * @mapped_irq : kernel mapped irq number.
27
+* @irq_chip : IRQ chip configuration
3928 */
4029 struct altera_gpio_chip {
4130 struct of_mm_gpio_chip mmchip;
4231 raw_spinlock_t gpio_lock;
4332 int interrupt_trigger;
4433 int mapped_irq;
34
+ struct irq_chip irq_chip;
4535 };
4636
4737 static void altera_gpio_irq_unmask(struct irq_data *d)
....@@ -80,7 +70,7 @@
8070 raw_spin_unlock_irqrestore(&altera_gc->gpio_lock, flags);
8171 }
8272
83
-/**
73
+/*
8474 * This controller's IRQ type is synthesized in hardware, so this function
8575 * just checks if the requested set_type matches the synthesized IRQ type
8676 */
....@@ -112,15 +102,6 @@
112102
113103 return 0;
114104 }
115
-
116
-static struct irq_chip altera_irq_chip = {
117
- .name = "altera-gpio",
118
- .irq_mask = altera_gpio_irq_mask,
119
- .irq_unmask = altera_gpio_irq_unmask,
120
- .irq_set_type = altera_gpio_irq_set_type,
121
- .irq_startup = altera_gpio_irq_startup,
122
- .irq_shutdown = altera_gpio_irq_mask,
123
-};
124105
125106 static int altera_gpio_get(struct gpio_chip *gc, unsigned offset)
126107 {
....@@ -258,6 +239,7 @@
258239 struct device_node *node = pdev->dev.of_node;
259240 int reg, ret;
260241 struct altera_gpio_chip *altera_gc;
242
+ struct gpio_irq_chip *girq;
261243
262244 altera_gc = devm_kzalloc(&pdev->dev, sizeof(*altera_gc), GFP_KERNEL);
263245 if (!altera_gc)
....@@ -285,6 +267,41 @@
285267 altera_gc->mmchip.gc.owner = THIS_MODULE;
286268 altera_gc->mmchip.gc.parent = &pdev->dev;
287269
270
+ altera_gc->mapped_irq = platform_get_irq_optional(pdev, 0);
271
+
272
+ if (altera_gc->mapped_irq < 0)
273
+ goto skip_irq;
274
+
275
+ if (of_property_read_u32(node, "altr,interrupt-type", &reg)) {
276
+ dev_err(&pdev->dev,
277
+ "altr,interrupt-type value not set in device tree\n");
278
+ return -EINVAL;
279
+ }
280
+ altera_gc->interrupt_trigger = reg;
281
+
282
+ altera_gc->irq_chip.name = "altera-gpio";
283
+ altera_gc->irq_chip.irq_mask = altera_gpio_irq_mask;
284
+ altera_gc->irq_chip.irq_unmask = altera_gpio_irq_unmask;
285
+ altera_gc->irq_chip.irq_set_type = altera_gpio_irq_set_type;
286
+ altera_gc->irq_chip.irq_startup = altera_gpio_irq_startup;
287
+ altera_gc->irq_chip.irq_shutdown = altera_gpio_irq_mask;
288
+
289
+ girq = &altera_gc->mmchip.gc.irq;
290
+ girq->chip = &altera_gc->irq_chip;
291
+ if (altera_gc->interrupt_trigger == IRQ_TYPE_LEVEL_HIGH)
292
+ girq->parent_handler = altera_gpio_irq_leveL_high_handler;
293
+ else
294
+ girq->parent_handler = altera_gpio_irq_edge_handler;
295
+ girq->num_parents = 1;
296
+ girq->parents = devm_kcalloc(&pdev->dev, 1, sizeof(*girq->parents),
297
+ GFP_KERNEL);
298
+ if (!girq->parents)
299
+ return -ENOMEM;
300
+ girq->default_type = IRQ_TYPE_NONE;
301
+ girq->handler = handle_bad_irq;
302
+ girq->parents[0] = altera_gc->mapped_irq;
303
+
304
+skip_irq:
288305 ret = of_mm_gpiochip_add_data(node, &altera_gc->mmchip, altera_gc);
289306 if (ret) {
290307 dev_err(&pdev->dev, "Failed adding memory mapped gpiochip\n");
....@@ -293,42 +310,7 @@
293310
294311 platform_set_drvdata(pdev, altera_gc);
295312
296
- altera_gc->mapped_irq = platform_get_irq(pdev, 0);
297
-
298
- if (altera_gc->mapped_irq < 0)
299
- goto skip_irq;
300
-
301
- if (of_property_read_u32(node, "altr,interrupt-type", &reg)) {
302
- ret = -EINVAL;
303
- dev_err(&pdev->dev,
304
- "altr,interrupt-type value not set in device tree\n");
305
- goto teardown;
306
- }
307
- altera_gc->interrupt_trigger = reg;
308
-
309
- ret = gpiochip_irqchip_add(&altera_gc->mmchip.gc, &altera_irq_chip, 0,
310
- handle_bad_irq, IRQ_TYPE_NONE);
311
-
312
- if (ret) {
313
- dev_err(&pdev->dev, "could not add irqchip\n");
314
- goto teardown;
315
- }
316
-
317
- gpiochip_set_chained_irqchip(&altera_gc->mmchip.gc,
318
- &altera_irq_chip,
319
- altera_gc->mapped_irq,
320
- altera_gc->interrupt_trigger == IRQ_TYPE_LEVEL_HIGH ?
321
- altera_gpio_irq_leveL_high_handler :
322
- altera_gpio_irq_edge_handler);
323
-
324
-skip_irq:
325313 return 0;
326
-teardown:
327
- of_mm_gpiochip_remove(&altera_gc->mmchip);
328
- pr_err("%pOF: registration failed with status %d\n",
329
- node, ret);
330
-
331
- return ret;
332314 }
333315
334316 static int altera_gpio_remove(struct platform_device *pdev)