1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | // Copyright (C) 2014-2017 Broadcom |
3 | |
4 | /* |
5 | * This file contains the Broadcom Northstar Plus (NSP) GPIO driver that |
6 | * supports the chipCommonA GPIO controller. Basic PINCONF such as bias, |
7 | * pull up/down, slew and drive strength are also supported in this driver. |
8 | * |
9 | * Pins from the chipCommonA GPIO can be individually muxed to GPIO function, |
10 | * through the interaction with the NSP IOMUX controller. |
11 | */ |
12 | |
13 | #include <linux/gpio/driver.h> |
14 | #include <linux/interrupt.h> |
15 | #include <linux/io.h> |
16 | #include <linux/ioport.h> |
17 | #include <linux/kernel.h> |
18 | #include <linux/of.h> |
19 | #include <linux/pinctrl/pinconf.h> |
20 | #include <linux/pinctrl/pinconf-generic.h> |
21 | #include <linux/pinctrl/pinctrl.h> |
22 | #include <linux/platform_device.h> |
23 | #include <linux/slab.h> |
24 | |
25 | #include "../pinctrl-utils.h" |
26 | |
27 | #define NSP_CHIP_A_INT_STATUS 0x00 |
28 | #define NSP_CHIP_A_INT_MASK 0x04 |
29 | #define NSP_GPIO_DATA_IN 0x40 |
30 | #define NSP_GPIO_DATA_OUT 0x44 |
31 | #define NSP_GPIO_OUT_EN 0x48 |
32 | #define NSP_GPIO_INT_POLARITY 0x50 |
33 | #define NSP_GPIO_INT_MASK 0x54 |
34 | #define NSP_GPIO_EVENT 0x58 |
35 | #define NSP_GPIO_EVENT_INT_MASK 0x5c |
36 | #define NSP_GPIO_EVENT_INT_POLARITY 0x64 |
37 | #define NSP_CHIP_A_GPIO_INT_BIT 0x01 |
38 | |
39 | /* I/O parameters offset for chipcommon A GPIO */ |
40 | #define NSP_GPIO_DRV_CTRL 0x00 |
41 | #define NSP_GPIO_HYSTERESIS_EN 0x10 |
42 | #define NSP_GPIO_SLEW_RATE_EN 0x14 |
43 | #define NSP_PULL_UP_EN 0x18 |
44 | #define NSP_PULL_DOWN_EN 0x1c |
45 | #define GPIO_DRV_STRENGTH_BITS 0x03 |
46 | |
47 | /* |
48 | * nsp GPIO core |
49 | * |
50 | * @dev: pointer to device |
51 | * @base: I/O register base for nsp GPIO controller |
52 | * @io_ctrl: I/O register base for PINCONF support outside the GPIO block |
53 | * @gc: GPIO chip |
54 | * @pctl: pointer to pinctrl_dev |
55 | * @pctldesc: pinctrl descriptor |
56 | * @lock: lock to protect access to I/O registers |
57 | */ |
58 | struct nsp_gpio { |
59 | struct device *dev; |
60 | void __iomem *base; |
61 | void __iomem *io_ctrl; |
62 | struct gpio_chip gc; |
63 | struct pinctrl_dev *pctl; |
64 | struct pinctrl_desc pctldesc; |
65 | raw_spinlock_t lock; |
66 | }; |
67 | |
68 | enum base_type { |
69 | REG, |
70 | IO_CTRL |
71 | }; |
72 | |
73 | /* |
74 | * Mapping from PINCONF pins to GPIO pins is 1-to-1 |
75 | */ |
76 | static inline unsigned nsp_pin_to_gpio(unsigned pin) |
77 | { |
78 | return pin; |
79 | } |
80 | |
81 | /* |
82 | * nsp_set_bit - set or clear one bit (corresponding to the GPIO pin) in a |
83 | * nsp GPIO register |
84 | * |
85 | * @nsp_gpio: nsp GPIO device |
86 | * @base_type: reg base to modify |
87 | * @reg: register offset |
88 | * @gpio: GPIO pin |
89 | * @set: set or clear |
90 | */ |
91 | static inline void nsp_set_bit(struct nsp_gpio *chip, enum base_type address, |
92 | unsigned int reg, unsigned gpio, bool set) |
93 | { |
94 | u32 val; |
95 | void __iomem *base_address; |
96 | |
97 | if (address == IO_CTRL) |
98 | base_address = chip->io_ctrl; |
99 | else |
100 | base_address = chip->base; |
101 | |
102 | val = readl(addr: base_address + reg); |
103 | if (set) |
104 | val |= BIT(gpio); |
105 | else |
106 | val &= ~BIT(gpio); |
107 | |
108 | writel(val, addr: base_address + reg); |
109 | } |
110 | |
111 | /* |
112 | * nsp_get_bit - get one bit (corresponding to the GPIO pin) in a |
113 | * nsp GPIO register |
114 | */ |
115 | static inline bool nsp_get_bit(struct nsp_gpio *chip, enum base_type address, |
116 | unsigned int reg, unsigned gpio) |
117 | { |
118 | if (address == IO_CTRL) |
119 | return !!(readl(addr: chip->io_ctrl + reg) & BIT(gpio)); |
120 | else |
121 | return !!(readl(addr: chip->base + reg) & BIT(gpio)); |
122 | } |
123 | |
124 | static irqreturn_t nsp_gpio_irq_handler(int irq, void *data) |
125 | { |
126 | struct gpio_chip *gc = (struct gpio_chip *)data; |
127 | struct nsp_gpio *chip = gpiochip_get_data(gc); |
128 | int bit; |
129 | unsigned long int_bits = 0; |
130 | u32 int_status; |
131 | |
132 | /* go through the entire GPIOs and handle all interrupts */ |
133 | int_status = readl(addr: chip->base + NSP_CHIP_A_INT_STATUS); |
134 | if (int_status & NSP_CHIP_A_GPIO_INT_BIT) { |
135 | unsigned int event, level; |
136 | |
137 | /* Get level and edge interrupts */ |
138 | event = readl(addr: chip->base + NSP_GPIO_EVENT_INT_MASK) & |
139 | readl(addr: chip->base + NSP_GPIO_EVENT); |
140 | level = readl(addr: chip->base + NSP_GPIO_DATA_IN) ^ |
141 | readl(addr: chip->base + NSP_GPIO_INT_POLARITY); |
142 | level &= readl(addr: chip->base + NSP_GPIO_INT_MASK); |
143 | int_bits = level | event; |
144 | |
145 | for_each_set_bit(bit, &int_bits, gc->ngpio) |
146 | generic_handle_domain_irq(domain: gc->irq.domain, hwirq: bit); |
147 | } |
148 | |
149 | return int_bits ? IRQ_HANDLED : IRQ_NONE; |
150 | } |
151 | |
152 | static void nsp_gpio_irq_ack(struct irq_data *d) |
153 | { |
154 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
155 | struct nsp_gpio *chip = gpiochip_get_data(gc); |
156 | unsigned gpio = d->hwirq; |
157 | u32 val = BIT(gpio); |
158 | u32 trigger_type; |
159 | |
160 | trigger_type = irq_get_trigger_type(irq: d->irq); |
161 | if (trigger_type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) |
162 | writel(val, addr: chip->base + NSP_GPIO_EVENT); |
163 | } |
164 | |
165 | /* |
166 | * nsp_gpio_irq_set_mask - mask/unmask a GPIO interrupt |
167 | * |
168 | * @d: IRQ chip data |
169 | * @unmask: mask/unmask GPIO interrupt |
170 | */ |
171 | static void nsp_gpio_irq_set_mask(struct irq_data *d, bool unmask) |
172 | { |
173 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
174 | struct nsp_gpio *chip = gpiochip_get_data(gc); |
175 | unsigned gpio = d->hwirq; |
176 | u32 trigger_type; |
177 | |
178 | trigger_type = irq_get_trigger_type(irq: d->irq); |
179 | if (trigger_type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) |
180 | nsp_set_bit(chip, address: REG, NSP_GPIO_EVENT_INT_MASK, gpio, set: unmask); |
181 | else |
182 | nsp_set_bit(chip, address: REG, NSP_GPIO_INT_MASK, gpio, set: unmask); |
183 | } |
184 | |
185 | static void nsp_gpio_irq_mask(struct irq_data *d) |
186 | { |
187 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
188 | struct nsp_gpio *chip = gpiochip_get_data(gc); |
189 | unsigned long flags; |
190 | |
191 | raw_spin_lock_irqsave(&chip->lock, flags); |
192 | nsp_gpio_irq_set_mask(d, unmask: false); |
193 | raw_spin_unlock_irqrestore(&chip->lock, flags); |
194 | gpiochip_disable_irq(gc, offset: irqd_to_hwirq(d)); |
195 | } |
196 | |
197 | static void nsp_gpio_irq_unmask(struct irq_data *d) |
198 | { |
199 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
200 | struct nsp_gpio *chip = gpiochip_get_data(gc); |
201 | unsigned long flags; |
202 | |
203 | gpiochip_enable_irq(gc, offset: irqd_to_hwirq(d)); |
204 | raw_spin_lock_irqsave(&chip->lock, flags); |
205 | nsp_gpio_irq_set_mask(d, unmask: true); |
206 | raw_spin_unlock_irqrestore(&chip->lock, flags); |
207 | } |
208 | |
209 | static int nsp_gpio_irq_set_type(struct irq_data *d, unsigned int type) |
210 | { |
211 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
212 | struct nsp_gpio *chip = gpiochip_get_data(gc); |
213 | unsigned gpio = d->hwirq; |
214 | bool level_low; |
215 | bool falling; |
216 | unsigned long flags; |
217 | |
218 | raw_spin_lock_irqsave(&chip->lock, flags); |
219 | falling = nsp_get_bit(chip, address: REG, NSP_GPIO_EVENT_INT_POLARITY, gpio); |
220 | level_low = nsp_get_bit(chip, address: REG, NSP_GPIO_INT_POLARITY, gpio); |
221 | |
222 | switch (type & IRQ_TYPE_SENSE_MASK) { |
223 | case IRQ_TYPE_EDGE_RISING: |
224 | falling = false; |
225 | break; |
226 | |
227 | case IRQ_TYPE_EDGE_FALLING: |
228 | falling = true; |
229 | break; |
230 | |
231 | case IRQ_TYPE_LEVEL_HIGH: |
232 | level_low = false; |
233 | break; |
234 | |
235 | case IRQ_TYPE_LEVEL_LOW: |
236 | level_low = true; |
237 | break; |
238 | |
239 | default: |
240 | dev_err(chip->dev, "invalid GPIO IRQ type 0x%x\n" , |
241 | type); |
242 | raw_spin_unlock_irqrestore(&chip->lock, flags); |
243 | return -EINVAL; |
244 | } |
245 | |
246 | nsp_set_bit(chip, address: REG, NSP_GPIO_EVENT_INT_POLARITY, gpio, set: falling); |
247 | nsp_set_bit(chip, address: REG, NSP_GPIO_INT_POLARITY, gpio, set: level_low); |
248 | |
249 | if (type & IRQ_TYPE_EDGE_BOTH) |
250 | irq_set_handler_locked(data: d, handler: handle_edge_irq); |
251 | else |
252 | irq_set_handler_locked(data: d, handler: handle_level_irq); |
253 | |
254 | raw_spin_unlock_irqrestore(&chip->lock, flags); |
255 | |
256 | dev_dbg(chip->dev, "gpio:%u level_low:%s falling:%s\n" , gpio, |
257 | level_low ? "true" : "false" , falling ? "true" : "false" ); |
258 | return 0; |
259 | } |
260 | |
261 | static const struct irq_chip nsp_gpio_irq_chip = { |
262 | .name = "gpio-a" , |
263 | .irq_ack = nsp_gpio_irq_ack, |
264 | .irq_mask = nsp_gpio_irq_mask, |
265 | .irq_unmask = nsp_gpio_irq_unmask, |
266 | .irq_set_type = nsp_gpio_irq_set_type, |
267 | .flags = IRQCHIP_IMMUTABLE, |
268 | GPIOCHIP_IRQ_RESOURCE_HELPERS, |
269 | }; |
270 | |
271 | static int nsp_gpio_direction_input(struct gpio_chip *gc, unsigned gpio) |
272 | { |
273 | struct nsp_gpio *chip = gpiochip_get_data(gc); |
274 | unsigned long flags; |
275 | |
276 | raw_spin_lock_irqsave(&chip->lock, flags); |
277 | nsp_set_bit(chip, address: REG, NSP_GPIO_OUT_EN, gpio, set: false); |
278 | raw_spin_unlock_irqrestore(&chip->lock, flags); |
279 | |
280 | dev_dbg(chip->dev, "gpio:%u set input\n" , gpio); |
281 | return 0; |
282 | } |
283 | |
284 | static int nsp_gpio_direction_output(struct gpio_chip *gc, unsigned gpio, |
285 | int val) |
286 | { |
287 | struct nsp_gpio *chip = gpiochip_get_data(gc); |
288 | unsigned long flags; |
289 | |
290 | raw_spin_lock_irqsave(&chip->lock, flags); |
291 | nsp_set_bit(chip, address: REG, NSP_GPIO_OUT_EN, gpio, set: true); |
292 | nsp_set_bit(chip, address: REG, NSP_GPIO_DATA_OUT, gpio, set: !!(val)); |
293 | raw_spin_unlock_irqrestore(&chip->lock, flags); |
294 | |
295 | dev_dbg(chip->dev, "gpio:%u set output, value:%d\n" , gpio, val); |
296 | return 0; |
297 | } |
298 | |
299 | static int nsp_gpio_get_direction(struct gpio_chip *gc, unsigned gpio) |
300 | { |
301 | struct nsp_gpio *chip = gpiochip_get_data(gc); |
302 | unsigned long flags; |
303 | int val; |
304 | |
305 | raw_spin_lock_irqsave(&chip->lock, flags); |
306 | val = nsp_get_bit(chip, address: REG, NSP_GPIO_OUT_EN, gpio); |
307 | raw_spin_unlock_irqrestore(&chip->lock, flags); |
308 | |
309 | return !val; |
310 | } |
311 | |
312 | static void nsp_gpio_set(struct gpio_chip *gc, unsigned gpio, int val) |
313 | { |
314 | struct nsp_gpio *chip = gpiochip_get_data(gc); |
315 | unsigned long flags; |
316 | |
317 | raw_spin_lock_irqsave(&chip->lock, flags); |
318 | nsp_set_bit(chip, address: REG, NSP_GPIO_DATA_OUT, gpio, set: !!(val)); |
319 | raw_spin_unlock_irqrestore(&chip->lock, flags); |
320 | |
321 | dev_dbg(chip->dev, "gpio:%u set, value:%d\n" , gpio, val); |
322 | } |
323 | |
324 | static int nsp_gpio_get(struct gpio_chip *gc, unsigned gpio) |
325 | { |
326 | struct nsp_gpio *chip = gpiochip_get_data(gc); |
327 | |
328 | return !!(readl(addr: chip->base + NSP_GPIO_DATA_IN) & BIT(gpio)); |
329 | } |
330 | |
331 | static int nsp_get_groups_count(struct pinctrl_dev *pctldev) |
332 | { |
333 | return 1; |
334 | } |
335 | |
336 | /* |
337 | * Only one group: "gpio_grp", since this local pinctrl device only performs |
338 | * GPIO specific PINCONF configurations |
339 | */ |
340 | static const char *nsp_get_group_name(struct pinctrl_dev *pctldev, |
341 | unsigned selector) |
342 | { |
343 | return "gpio_grp" ; |
344 | } |
345 | |
346 | static const struct pinctrl_ops nsp_pctrl_ops = { |
347 | .get_groups_count = nsp_get_groups_count, |
348 | .get_group_name = nsp_get_group_name, |
349 | .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, |
350 | .dt_free_map = pinctrl_utils_free_map, |
351 | }; |
352 | |
353 | static int nsp_gpio_set_slew(struct nsp_gpio *chip, unsigned gpio, u32 slew) |
354 | { |
355 | if (slew) |
356 | nsp_set_bit(chip, address: IO_CTRL, NSP_GPIO_SLEW_RATE_EN, gpio, set: true); |
357 | else |
358 | nsp_set_bit(chip, address: IO_CTRL, NSP_GPIO_SLEW_RATE_EN, gpio, set: false); |
359 | |
360 | return 0; |
361 | } |
362 | |
363 | static int nsp_gpio_set_pull(struct nsp_gpio *chip, unsigned gpio, |
364 | bool pull_up, bool pull_down) |
365 | { |
366 | unsigned long flags; |
367 | |
368 | raw_spin_lock_irqsave(&chip->lock, flags); |
369 | nsp_set_bit(chip, address: IO_CTRL, NSP_PULL_DOWN_EN, gpio, set: pull_down); |
370 | nsp_set_bit(chip, address: IO_CTRL, NSP_PULL_UP_EN, gpio, set: pull_up); |
371 | raw_spin_unlock_irqrestore(&chip->lock, flags); |
372 | |
373 | dev_dbg(chip->dev, "gpio:%u set pullup:%d pulldown: %d\n" , |
374 | gpio, pull_up, pull_down); |
375 | return 0; |
376 | } |
377 | |
378 | static void nsp_gpio_get_pull(struct nsp_gpio *chip, unsigned gpio, |
379 | bool *pull_up, bool *pull_down) |
380 | { |
381 | unsigned long flags; |
382 | |
383 | raw_spin_lock_irqsave(&chip->lock, flags); |
384 | *pull_up = nsp_get_bit(chip, address: IO_CTRL, NSP_PULL_UP_EN, gpio); |
385 | *pull_down = nsp_get_bit(chip, address: IO_CTRL, NSP_PULL_DOWN_EN, gpio); |
386 | raw_spin_unlock_irqrestore(&chip->lock, flags); |
387 | } |
388 | |
389 | static int nsp_gpio_set_strength(struct nsp_gpio *chip, unsigned gpio, |
390 | u32 strength) |
391 | { |
392 | u32 offset, shift, i; |
393 | u32 val; |
394 | unsigned long flags; |
395 | |
396 | /* make sure drive strength is supported */ |
397 | if (strength < 2 || strength > 16 || (strength % 2)) |
398 | return -ENOTSUPP; |
399 | |
400 | shift = gpio; |
401 | offset = NSP_GPIO_DRV_CTRL; |
402 | dev_dbg(chip->dev, "gpio:%u set drive strength:%d mA\n" , gpio, |
403 | strength); |
404 | raw_spin_lock_irqsave(&chip->lock, flags); |
405 | strength = (strength / 2) - 1; |
406 | for (i = GPIO_DRV_STRENGTH_BITS; i > 0; i--) { |
407 | val = readl(addr: chip->io_ctrl + offset); |
408 | val &= ~BIT(shift); |
409 | val |= ((strength >> (i-1)) & 0x1) << shift; |
410 | writel(val, addr: chip->io_ctrl + offset); |
411 | offset += 4; |
412 | } |
413 | raw_spin_unlock_irqrestore(&chip->lock, flags); |
414 | |
415 | return 0; |
416 | } |
417 | |
418 | static int nsp_gpio_get_strength(struct nsp_gpio *chip, unsigned gpio, |
419 | u16 *strength) |
420 | { |
421 | unsigned int offset, shift; |
422 | u32 val; |
423 | unsigned long flags; |
424 | int i; |
425 | |
426 | offset = NSP_GPIO_DRV_CTRL; |
427 | shift = gpio; |
428 | |
429 | raw_spin_lock_irqsave(&chip->lock, flags); |
430 | *strength = 0; |
431 | for (i = (GPIO_DRV_STRENGTH_BITS - 1); i >= 0; i--) { |
432 | val = readl(addr: chip->io_ctrl + offset) & BIT(shift); |
433 | val >>= shift; |
434 | *strength += (val << i); |
435 | offset += 4; |
436 | } |
437 | |
438 | /* convert to mA */ |
439 | *strength = (*strength + 1) * 2; |
440 | raw_spin_unlock_irqrestore(&chip->lock, flags); |
441 | |
442 | return 0; |
443 | } |
444 | |
445 | static int nsp_pin_config_group_get(struct pinctrl_dev *pctldev, |
446 | unsigned selector, |
447 | unsigned long *config) |
448 | { |
449 | return 0; |
450 | } |
451 | |
452 | static int nsp_pin_config_group_set(struct pinctrl_dev *pctldev, |
453 | unsigned selector, |
454 | unsigned long *configs, unsigned num_configs) |
455 | { |
456 | return 0; |
457 | } |
458 | |
459 | static int nsp_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin, |
460 | unsigned long *config) |
461 | { |
462 | struct nsp_gpio *chip = pinctrl_dev_get_drvdata(pctldev); |
463 | enum pin_config_param param = pinconf_to_config_param(config: *config); |
464 | unsigned int gpio; |
465 | u16 arg = 0; |
466 | bool pull_up, pull_down; |
467 | int ret; |
468 | |
469 | gpio = nsp_pin_to_gpio(pin); |
470 | switch (param) { |
471 | case PIN_CONFIG_BIAS_DISABLE: |
472 | nsp_gpio_get_pull(chip, gpio, pull_up: &pull_up, pull_down: &pull_down); |
473 | if ((pull_up == false) && (pull_down == false)) |
474 | return 0; |
475 | else |
476 | return -EINVAL; |
477 | |
478 | case PIN_CONFIG_BIAS_PULL_UP: |
479 | nsp_gpio_get_pull(chip, gpio, pull_up: &pull_up, pull_down: &pull_down); |
480 | if (pull_up) |
481 | return 0; |
482 | else |
483 | return -EINVAL; |
484 | |
485 | case PIN_CONFIG_BIAS_PULL_DOWN: |
486 | nsp_gpio_get_pull(chip, gpio, pull_up: &pull_up, pull_down: &pull_down); |
487 | if (pull_down) |
488 | return 0; |
489 | else |
490 | return -EINVAL; |
491 | |
492 | case PIN_CONFIG_DRIVE_STRENGTH: |
493 | ret = nsp_gpio_get_strength(chip, gpio, strength: &arg); |
494 | if (ret) |
495 | return ret; |
496 | *config = pinconf_to_config_packed(param, argument: arg); |
497 | return 0; |
498 | |
499 | default: |
500 | return -ENOTSUPP; |
501 | } |
502 | } |
503 | |
504 | static int nsp_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin, |
505 | unsigned long *configs, unsigned num_configs) |
506 | { |
507 | struct nsp_gpio *chip = pinctrl_dev_get_drvdata(pctldev); |
508 | enum pin_config_param param; |
509 | u32 arg; |
510 | unsigned int i, gpio; |
511 | int ret = -ENOTSUPP; |
512 | |
513 | gpio = nsp_pin_to_gpio(pin); |
514 | for (i = 0; i < num_configs; i++) { |
515 | param = pinconf_to_config_param(config: configs[i]); |
516 | arg = pinconf_to_config_argument(config: configs[i]); |
517 | |
518 | switch (param) { |
519 | case PIN_CONFIG_BIAS_DISABLE: |
520 | ret = nsp_gpio_set_pull(chip, gpio, pull_up: false, pull_down: false); |
521 | if (ret < 0) |
522 | goto out; |
523 | break; |
524 | |
525 | case PIN_CONFIG_BIAS_PULL_UP: |
526 | ret = nsp_gpio_set_pull(chip, gpio, pull_up: true, pull_down: false); |
527 | if (ret < 0) |
528 | goto out; |
529 | break; |
530 | |
531 | case PIN_CONFIG_BIAS_PULL_DOWN: |
532 | ret = nsp_gpio_set_pull(chip, gpio, pull_up: false, pull_down: true); |
533 | if (ret < 0) |
534 | goto out; |
535 | break; |
536 | |
537 | case PIN_CONFIG_DRIVE_STRENGTH: |
538 | ret = nsp_gpio_set_strength(chip, gpio, strength: arg); |
539 | if (ret < 0) |
540 | goto out; |
541 | break; |
542 | |
543 | case PIN_CONFIG_SLEW_RATE: |
544 | ret = nsp_gpio_set_slew(chip, gpio, slew: arg); |
545 | if (ret < 0) |
546 | goto out; |
547 | break; |
548 | |
549 | default: |
550 | dev_err(chip->dev, "invalid configuration\n" ); |
551 | return -ENOTSUPP; |
552 | } |
553 | } |
554 | |
555 | out: |
556 | return ret; |
557 | } |
558 | |
559 | static const struct pinconf_ops nsp_pconf_ops = { |
560 | .is_generic = true, |
561 | .pin_config_get = nsp_pin_config_get, |
562 | .pin_config_set = nsp_pin_config_set, |
563 | .pin_config_group_get = nsp_pin_config_group_get, |
564 | .pin_config_group_set = nsp_pin_config_group_set, |
565 | }; |
566 | |
567 | /* |
568 | * NSP GPIO controller supports some PINCONF related configurations such as |
569 | * pull up, pull down, slew and drive strength, when the pin is configured |
570 | * to GPIO. |
571 | * |
572 | * Here a local pinctrl device is created with simple 1-to-1 pin mapping to the |
573 | * local GPIO pins |
574 | */ |
575 | static int nsp_gpio_register_pinconf(struct nsp_gpio *chip) |
576 | { |
577 | struct pinctrl_desc *pctldesc = &chip->pctldesc; |
578 | struct pinctrl_pin_desc *pins; |
579 | struct gpio_chip *gc = &chip->gc; |
580 | int i; |
581 | |
582 | pins = devm_kcalloc(dev: chip->dev, n: gc->ngpio, size: sizeof(*pins), GFP_KERNEL); |
583 | if (!pins) |
584 | return -ENOMEM; |
585 | for (i = 0; i < gc->ngpio; i++) { |
586 | pins[i].number = i; |
587 | pins[i].name = devm_kasprintf(dev: chip->dev, GFP_KERNEL, |
588 | fmt: "gpio-%d" , i); |
589 | if (!pins[i].name) |
590 | return -ENOMEM; |
591 | } |
592 | pctldesc->name = dev_name(dev: chip->dev); |
593 | pctldesc->pctlops = &nsp_pctrl_ops; |
594 | pctldesc->pins = pins; |
595 | pctldesc->npins = gc->ngpio; |
596 | pctldesc->confops = &nsp_pconf_ops; |
597 | |
598 | chip->pctl = devm_pinctrl_register(dev: chip->dev, pctldesc, driver_data: chip); |
599 | if (IS_ERR(ptr: chip->pctl)) { |
600 | dev_err(chip->dev, "unable to register pinctrl device\n" ); |
601 | return PTR_ERR(ptr: chip->pctl); |
602 | } |
603 | |
604 | return 0; |
605 | } |
606 | |
607 | static const struct of_device_id nsp_gpio_of_match[] = { |
608 | {.compatible = "brcm,nsp-gpio-a" ,}, |
609 | {} |
610 | }; |
611 | |
612 | static int nsp_gpio_probe(struct platform_device *pdev) |
613 | { |
614 | struct device *dev = &pdev->dev; |
615 | struct nsp_gpio *chip; |
616 | struct gpio_chip *gc; |
617 | u32 val; |
618 | int irq, ret; |
619 | |
620 | if (of_property_read_u32(np: pdev->dev.of_node, propname: "ngpios" , out_value: &val)) { |
621 | dev_err(&pdev->dev, "Missing ngpios OF property\n" ); |
622 | return -ENODEV; |
623 | } |
624 | |
625 | chip = devm_kzalloc(dev, size: sizeof(*chip), GFP_KERNEL); |
626 | if (!chip) |
627 | return -ENOMEM; |
628 | |
629 | chip->dev = dev; |
630 | platform_set_drvdata(pdev, data: chip); |
631 | |
632 | chip->base = devm_platform_ioremap_resource(pdev, index: 0); |
633 | if (IS_ERR(ptr: chip->base)) { |
634 | dev_err(dev, "unable to map I/O memory\n" ); |
635 | return PTR_ERR(ptr: chip->base); |
636 | } |
637 | |
638 | chip->io_ctrl = devm_platform_ioremap_resource(pdev, index: 1); |
639 | if (IS_ERR(ptr: chip->io_ctrl)) { |
640 | dev_err(dev, "unable to map I/O memory\n" ); |
641 | return PTR_ERR(ptr: chip->io_ctrl); |
642 | } |
643 | |
644 | raw_spin_lock_init(&chip->lock); |
645 | gc = &chip->gc; |
646 | gc->base = -1; |
647 | gc->can_sleep = false; |
648 | gc->ngpio = val; |
649 | gc->label = dev_name(dev); |
650 | gc->parent = dev; |
651 | gc->request = gpiochip_generic_request; |
652 | gc->free = gpiochip_generic_free; |
653 | gc->direction_input = nsp_gpio_direction_input; |
654 | gc->direction_output = nsp_gpio_direction_output; |
655 | gc->get_direction = nsp_gpio_get_direction; |
656 | gc->set = nsp_gpio_set; |
657 | gc->get = nsp_gpio_get; |
658 | |
659 | /* optional GPIO interrupt support */ |
660 | irq = platform_get_irq(pdev, 0); |
661 | if (irq > 0) { |
662 | struct gpio_irq_chip *girq; |
663 | |
664 | val = readl(addr: chip->base + NSP_CHIP_A_INT_MASK); |
665 | val = val | NSP_CHIP_A_GPIO_INT_BIT; |
666 | writel(val, addr: (chip->base + NSP_CHIP_A_INT_MASK)); |
667 | |
668 | /* Install ISR for this GPIO controller. */ |
669 | ret = devm_request_irq(dev, irq, handler: nsp_gpio_irq_handler, |
670 | IRQF_SHARED, devname: "gpio-a" , dev_id: &chip->gc); |
671 | if (ret) { |
672 | dev_err(&pdev->dev, "Unable to request IRQ%d: %d\n" , |
673 | irq, ret); |
674 | return ret; |
675 | } |
676 | |
677 | girq = &chip->gc.irq; |
678 | gpio_irq_chip_set_chip(girq, chip: &nsp_gpio_irq_chip); |
679 | /* This will let us handle the parent IRQ in the driver */ |
680 | girq->parent_handler = NULL; |
681 | girq->num_parents = 0; |
682 | girq->parents = NULL; |
683 | girq->default_type = IRQ_TYPE_NONE; |
684 | girq->handler = handle_bad_irq; |
685 | } |
686 | |
687 | ret = devm_gpiochip_add_data(dev, gc, chip); |
688 | if (ret < 0) |
689 | return dev_err_probe(dev, err: ret, fmt: "unable to add GPIO chip\n" ); |
690 | |
691 | ret = nsp_gpio_register_pinconf(chip); |
692 | if (ret) { |
693 | dev_err(dev, "unable to register pinconf\n" ); |
694 | return ret; |
695 | } |
696 | |
697 | return 0; |
698 | } |
699 | |
700 | static struct platform_driver nsp_gpio_driver = { |
701 | .driver = { |
702 | .name = "nsp-gpio-a" , |
703 | .of_match_table = nsp_gpio_of_match, |
704 | }, |
705 | .probe = nsp_gpio_probe, |
706 | }; |
707 | |
708 | static int __init nsp_gpio_init(void) |
709 | { |
710 | return platform_driver_register(&nsp_gpio_driver); |
711 | } |
712 | arch_initcall_sync(nsp_gpio_init); |
713 | |