2
2
/*
3
3
* GPIO driver for NXP LPC18xx/43xx.
4
4
*
5
+ * Copyright (C) 2018 Vladimir Zapolskiy <[email protected] >
5
6
* Copyright (C) 2015 Joachim Eastwood <[email protected] >
6
7
*
7
8
*/
8
9
9
10
#include <linux/clk.h>
10
11
#include <linux/gpio/driver.h>
11
12
#include <linux/io.h>
13
+ #include <linux/irqdomain.h>
14
+ #include <linux/irqchip.h>
12
15
#include <linux/module.h>
13
16
#include <linux/of.h>
17
+ #include <linux/of_address.h>
14
18
#include <linux/of_gpio.h>
19
+ #include <linux/of_irq.h>
15
20
#include <linux/pinctrl/consumer.h>
16
21
#include <linux/platform_device.h>
17
22
21
26
#define LPC18XX_MAX_PORTS 8
22
27
#define LPC18XX_PINS_PER_PORT 32
23
28
29
+ /* LPC18xx GPIO pin interrupt controller register offsets */
30
+ #define LPC18XX_GPIO_PIN_IC_ISEL 0x00
31
+ #define LPC18XX_GPIO_PIN_IC_IENR 0x04
32
+ #define LPC18XX_GPIO_PIN_IC_SIENR 0x08
33
+ #define LPC18XX_GPIO_PIN_IC_CIENR 0x0c
34
+ #define LPC18XX_GPIO_PIN_IC_IENF 0x10
35
+ #define LPC18XX_GPIO_PIN_IC_SIENF 0x14
36
+ #define LPC18XX_GPIO_PIN_IC_CIENF 0x18
37
+ #define LPC18XX_GPIO_PIN_IC_RISE 0x1c
38
+ #define LPC18XX_GPIO_PIN_IC_FALL 0x20
39
+ #define LPC18XX_GPIO_PIN_IC_IST 0x24
40
+
41
+ #define NR_LPC18XX_GPIO_PIN_IC_IRQS 8
42
+
43
+ struct lpc18xx_gpio_pin_ic {
44
+ void __iomem * base ;
45
+ struct irq_domain * domain ;
46
+ struct raw_spinlock lock ;
47
+ };
48
+
24
49
struct lpc18xx_gpio_chip {
25
50
struct gpio_chip gpio ;
26
51
void __iomem * base ;
27
52
struct clk * clk ;
53
+ struct lpc18xx_gpio_pin_ic * pin_ic ;
28
54
spinlock_t lock ;
29
55
};
30
56
57
+ static inline void lpc18xx_gpio_pin_ic_isel (struct lpc18xx_gpio_pin_ic * ic ,
58
+ u32 pin , bool set )
59
+ {
60
+ u32 val = readl_relaxed (ic -> base + LPC18XX_GPIO_PIN_IC_ISEL );
61
+
62
+ if (set )
63
+ val &= ~BIT (pin );
64
+ else
65
+ val |= BIT (pin );
66
+
67
+ writel_relaxed (val , ic -> base + LPC18XX_GPIO_PIN_IC_ISEL );
68
+ }
69
+
70
+ static inline void lpc18xx_gpio_pin_ic_set (struct lpc18xx_gpio_pin_ic * ic ,
71
+ u32 pin , u32 reg )
72
+ {
73
+ writel_relaxed (BIT (pin ), ic -> base + reg );
74
+ }
75
+
76
+ static void lpc18xx_gpio_pin_ic_mask (struct irq_data * d )
77
+ {
78
+ struct lpc18xx_gpio_pin_ic * ic = d -> chip_data ;
79
+ u32 type = irqd_get_trigger_type (d );
80
+
81
+ raw_spin_lock (& ic -> lock );
82
+
83
+ if (type & IRQ_TYPE_LEVEL_MASK || type & IRQ_TYPE_EDGE_RISING )
84
+ lpc18xx_gpio_pin_ic_set (ic , d -> hwirq ,
85
+ LPC18XX_GPIO_PIN_IC_CIENR );
86
+
87
+ if (type & IRQ_TYPE_EDGE_FALLING )
88
+ lpc18xx_gpio_pin_ic_set (ic , d -> hwirq ,
89
+ LPC18XX_GPIO_PIN_IC_CIENF );
90
+
91
+ raw_spin_unlock (& ic -> lock );
92
+
93
+ irq_chip_mask_parent (d );
94
+ }
95
+
96
+ static void lpc18xx_gpio_pin_ic_unmask (struct irq_data * d )
97
+ {
98
+ struct lpc18xx_gpio_pin_ic * ic = d -> chip_data ;
99
+ u32 type = irqd_get_trigger_type (d );
100
+
101
+ raw_spin_lock (& ic -> lock );
102
+
103
+ if (type & IRQ_TYPE_LEVEL_MASK || type & IRQ_TYPE_EDGE_RISING )
104
+ lpc18xx_gpio_pin_ic_set (ic , d -> hwirq ,
105
+ LPC18XX_GPIO_PIN_IC_SIENR );
106
+
107
+ if (type & IRQ_TYPE_EDGE_FALLING )
108
+ lpc18xx_gpio_pin_ic_set (ic , d -> hwirq ,
109
+ LPC18XX_GPIO_PIN_IC_SIENF );
110
+
111
+ raw_spin_unlock (& ic -> lock );
112
+
113
+ irq_chip_unmask_parent (d );
114
+ }
115
+
116
+ static void lpc18xx_gpio_pin_ic_eoi (struct irq_data * d )
117
+ {
118
+ struct lpc18xx_gpio_pin_ic * ic = d -> chip_data ;
119
+ u32 type = irqd_get_trigger_type (d );
120
+
121
+ raw_spin_lock (& ic -> lock );
122
+
123
+ if (type & IRQ_TYPE_EDGE_BOTH )
124
+ lpc18xx_gpio_pin_ic_set (ic , d -> hwirq ,
125
+ LPC18XX_GPIO_PIN_IC_IST );
126
+
127
+ raw_spin_unlock (& ic -> lock );
128
+
129
+ irq_chip_eoi_parent (d );
130
+ }
131
+
132
+ static int lpc18xx_gpio_pin_ic_set_type (struct irq_data * d , unsigned int type )
133
+ {
134
+ struct lpc18xx_gpio_pin_ic * ic = d -> chip_data ;
135
+
136
+ raw_spin_lock (& ic -> lock );
137
+
138
+ if (type & IRQ_TYPE_LEVEL_HIGH ) {
139
+ lpc18xx_gpio_pin_ic_isel (ic , d -> hwirq , true);
140
+ lpc18xx_gpio_pin_ic_set (ic , d -> hwirq ,
141
+ LPC18XX_GPIO_PIN_IC_SIENF );
142
+ } else if (type & IRQ_TYPE_LEVEL_LOW ) {
143
+ lpc18xx_gpio_pin_ic_isel (ic , d -> hwirq , true);
144
+ lpc18xx_gpio_pin_ic_set (ic , d -> hwirq ,
145
+ LPC18XX_GPIO_PIN_IC_CIENF );
146
+ } else {
147
+ lpc18xx_gpio_pin_ic_isel (ic , d -> hwirq , false);
148
+ }
149
+
150
+ raw_spin_unlock (& ic -> lock );
151
+
152
+ return 0 ;
153
+ }
154
+
155
+ static struct irq_chip lpc18xx_gpio_pin_ic = {
156
+ .name = "LPC18xx GPIO pin" ,
157
+ .irq_mask = lpc18xx_gpio_pin_ic_mask ,
158
+ .irq_unmask = lpc18xx_gpio_pin_ic_unmask ,
159
+ .irq_eoi = lpc18xx_gpio_pin_ic_eoi ,
160
+ .irq_set_type = lpc18xx_gpio_pin_ic_set_type ,
161
+ .irq_retrigger = irq_chip_retrigger_hierarchy ,
162
+ .flags = IRQCHIP_SET_TYPE_MASKED ,
163
+ };
164
+
165
+ static int lpc18xx_gpio_pin_ic_domain_alloc (struct irq_domain * domain ,
166
+ unsigned int virq ,
167
+ unsigned int nr_irqs , void * data )
168
+ {
169
+ struct irq_fwspec parent_fwspec , * fwspec = data ;
170
+ struct lpc18xx_gpio_pin_ic * ic = domain -> host_data ;
171
+ irq_hw_number_t hwirq ;
172
+ int ret ;
173
+
174
+ if (nr_irqs != 1 )
175
+ return - EINVAL ;
176
+
177
+ hwirq = fwspec -> param [0 ];
178
+ if (hwirq >= NR_LPC18XX_GPIO_PIN_IC_IRQS )
179
+ return - EINVAL ;
180
+
181
+ /*
182
+ * All LPC18xx/LPC43xx GPIO pin hardware interrupts are translated
183
+ * into edge interrupts 32...39 on parent Cortex-M3/M4 NVIC
184
+ */
185
+ parent_fwspec .fwnode = domain -> parent -> fwnode ;
186
+ parent_fwspec .param_count = 1 ;
187
+ parent_fwspec .param [0 ] = hwirq + 32 ;
188
+
189
+ ret = irq_domain_alloc_irqs_parent (domain , virq , 1 , & parent_fwspec );
190
+ if (ret < 0 ) {
191
+ pr_err ("failed to allocate parent irq %u: %d\n" ,
192
+ parent_fwspec .param [0 ], ret );
193
+ return ret ;
194
+ }
195
+
196
+ return irq_domain_set_hwirq_and_chip (domain , virq , hwirq ,
197
+ & lpc18xx_gpio_pin_ic , ic );
198
+ }
199
+
200
+ static const struct irq_domain_ops lpc18xx_gpio_pin_ic_domain_ops = {
201
+ .alloc = lpc18xx_gpio_pin_ic_domain_alloc ,
202
+ .xlate = irq_domain_xlate_twocell ,
203
+ .free = irq_domain_free_irqs_common ,
204
+ };
205
+
206
+ static int lpc18xx_gpio_pin_ic_probe (struct lpc18xx_gpio_chip * gc )
207
+ {
208
+ struct device * dev = gc -> gpio .parent ;
209
+ struct irq_domain * parent_domain ;
210
+ struct device_node * parent_node ;
211
+ struct lpc18xx_gpio_pin_ic * ic ;
212
+ struct resource res ;
213
+ int ret , index ;
214
+
215
+ parent_node = of_irq_find_parent (dev -> of_node );
216
+ if (!parent_node )
217
+ return - ENXIO ;
218
+
219
+ parent_domain = irq_find_host (parent_node );
220
+ of_node_put (parent_node );
221
+ if (!parent_domain )
222
+ return - ENXIO ;
223
+
224
+ ic = devm_kzalloc (dev , sizeof (* ic ), GFP_KERNEL );
225
+ if (!ic )
226
+ return - ENOMEM ;
227
+
228
+ index = of_property_match_string (dev -> of_node , "reg-names" ,
229
+ "gpio-pin-ic" );
230
+ if (index < 0 ) {
231
+ ret = - ENODEV ;
232
+ goto free_ic ;
233
+ }
234
+
235
+ ret = of_address_to_resource (dev -> of_node , index , & res );
236
+ if (ret < 0 )
237
+ goto free_ic ;
238
+
239
+ ic -> base = devm_ioremap_resource (dev , & res );
240
+ if (IS_ERR (ic -> base )) {
241
+ ret = PTR_ERR (ic -> base );
242
+ goto free_ic ;
243
+ }
244
+
245
+ raw_spin_lock_init (& ic -> lock );
246
+
247
+ ic -> domain = irq_domain_add_hierarchy (parent_domain , 0 ,
248
+ NR_LPC18XX_GPIO_PIN_IC_IRQS ,
249
+ dev -> of_node ,
250
+ & lpc18xx_gpio_pin_ic_domain_ops ,
251
+ ic );
252
+ if (!ic -> domain ) {
253
+ pr_err ("unable to add irq domain\n" );
254
+ ret = - ENODEV ;
255
+ goto free_iomap ;
256
+ }
257
+
258
+ gc -> pin_ic = ic ;
259
+
260
+ return 0 ;
261
+
262
+ free_iomap :
263
+ devm_iounmap (dev , ic -> base );
264
+ free_ic :
265
+ devm_kfree (dev , ic );
266
+
267
+ return ret ;
268
+ }
269
+
31
270
static void lpc18xx_gpio_set (struct gpio_chip * chip , unsigned offset , int value )
32
271
{
33
272
struct lpc18xx_gpio_chip * gc = gpiochip_get_data (chip );
@@ -91,8 +330,7 @@ static int lpc18xx_gpio_probe(struct platform_device *pdev)
91
330
{
92
331
struct device * dev = & pdev -> dev ;
93
332
struct lpc18xx_gpio_chip * gc ;
94
- struct resource * res ;
95
- int ret ;
333
+ int index , ret ;
96
334
97
335
gc = devm_kzalloc (dev , sizeof (* gc ), GFP_KERNEL );
98
336
if (!gc )
@@ -101,8 +339,22 @@ static int lpc18xx_gpio_probe(struct platform_device *pdev)
101
339
gc -> gpio = lpc18xx_chip ;
102
340
platform_set_drvdata (pdev , gc );
103
341
104
- res = platform_get_resource (pdev , IORESOURCE_MEM , 0 );
105
- gc -> base = devm_ioremap_resource (dev , res );
342
+ index = of_property_match_string (dev -> of_node , "reg-names" , "gpio" );
343
+ if (index < 0 ) {
344
+ /* To support backward compatibility take the first resource */
345
+ struct resource * res ;
346
+
347
+ res = platform_get_resource (pdev , IORESOURCE_MEM , 0 );
348
+ gc -> base = devm_ioremap_resource (dev , res );
349
+ } else {
350
+ struct resource res ;
351
+
352
+ ret = of_address_to_resource (dev -> of_node , index , & res );
353
+ if (ret < 0 )
354
+ return ret ;
355
+
356
+ gc -> base = devm_ioremap_resource (dev , & res );
357
+ }
106
358
if (IS_ERR (gc -> base ))
107
359
return PTR_ERR (gc -> base );
108
360
@@ -129,13 +381,19 @@ static int lpc18xx_gpio_probe(struct platform_device *pdev)
129
381
return ret ;
130
382
}
131
383
384
+ /* On error GPIO pin interrupt controller just won't be registered */
385
+ lpc18xx_gpio_pin_ic_probe (gc );
386
+
132
387
return 0 ;
133
388
}
134
389
135
390
static int lpc18xx_gpio_remove (struct platform_device * pdev )
136
391
{
137
392
struct lpc18xx_gpio_chip * gc = platform_get_drvdata (pdev );
138
393
394
+ if (gc -> pin_ic )
395
+ irq_domain_remove (gc -> pin_ic -> domain );
396
+
139
397
clk_disable_unprepare (gc -> clk );
140
398
141
399
return 0 ;
@@ -158,5 +416,6 @@ static struct platform_driver lpc18xx_gpio_driver = {
158
416
module_platform_driver (lpc18xx_gpio_driver );
159
417
160
418
MODULE_AUTHOR (
"Joachim Eastwood <[email protected] >" );
419
+ MODULE_AUTHOR (
"Vladimir Zapolskiy <[email protected] >" );
161
420
MODULE_DESCRIPTION ("GPIO driver for LPC18xx/43xx" );
162
421
MODULE_LICENSE ("GPL v2" );
0 commit comments