.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | 3 | * Renesas R-Car GPIO Support |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2014 Renesas Electronics Corporation |
---|
5 | 6 | * Copyright (C) 2013 Magnus Damm |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or modify |
---|
8 | | - * it under the terms of the GNU General Public License as published by |
---|
9 | | - * the Free Software Foundation; either version 2 of the License |
---|
10 | | - * |
---|
11 | | - * This program is distributed in the hope that it will be useful, |
---|
12 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
13 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
14 | | - * GNU General Public License for more details. |
---|
15 | 7 | */ |
---|
16 | 8 | |
---|
17 | 9 | #include <linux/err.h> |
---|
.. | .. |
---|
43 | 35 | struct gpio_rcar_priv { |
---|
44 | 36 | void __iomem *base; |
---|
45 | 37 | spinlock_t lock; |
---|
46 | | - struct platform_device *pdev; |
---|
| 38 | + struct device *dev; |
---|
47 | 39 | struct gpio_chip gpio_chip; |
---|
48 | 40 | struct irq_chip irq_chip; |
---|
49 | 41 | unsigned int irq_parent; |
---|
50 | 42 | atomic_t wakeup_path; |
---|
| 43 | + bool has_outdtsel; |
---|
51 | 44 | bool has_both_edge_trigger; |
---|
52 | 45 | struct gpio_rcar_bank_info bank_info; |
---|
53 | 46 | }; |
---|
.. | .. |
---|
63 | 56 | #define POSNEG 0x20 /* Positive/Negative Logic Select Register */ |
---|
64 | 57 | #define EDGLEVEL 0x24 /* Edge/level Select Register */ |
---|
65 | 58 | #define FILONOFF 0x28 /* Chattering Prevention On/Off Register */ |
---|
| 59 | +#define OUTDTSEL 0x40 /* Output Data Select Register */ |
---|
66 | 60 | #define BOTHEDGE 0x4c /* One Edge/Both Edge Select Register */ |
---|
67 | 61 | |
---|
68 | 62 | #define RCAR_MAX_GPIO_PER_BANK 32 |
---|
.. | .. |
---|
122 | 116 | |
---|
123 | 117 | spin_lock_irqsave(&p->lock, flags); |
---|
124 | 118 | |
---|
125 | | - /* Configure postive or negative logic in POSNEG */ |
---|
| 119 | + /* Configure positive or negative logic in POSNEG */ |
---|
126 | 120 | gpio_rcar_modify_bit(p, POSNEG, hwirq, !active_high_rising_edge); |
---|
127 | 121 | |
---|
128 | 122 | /* Configure edge or level trigger in EDGLEVEL */ |
---|
.. | .. |
---|
148 | 142 | struct gpio_rcar_priv *p = gpiochip_get_data(gc); |
---|
149 | 143 | unsigned int hwirq = irqd_to_hwirq(d); |
---|
150 | 144 | |
---|
151 | | - dev_dbg(&p->pdev->dev, "sense irq = %d, type = %d\n", hwirq, type); |
---|
| 145 | + dev_dbg(p->dev, "sense irq = %d, type = %d\n", hwirq, type); |
---|
152 | 146 | |
---|
153 | 147 | switch (type & IRQ_TYPE_SENSE_MASK) { |
---|
154 | 148 | case IRQ_TYPE_LEVEL_HIGH: |
---|
.. | .. |
---|
188 | 182 | if (p->irq_parent) { |
---|
189 | 183 | error = irq_set_irq_wake(p->irq_parent, on); |
---|
190 | 184 | if (error) { |
---|
191 | | - dev_dbg(&p->pdev->dev, |
---|
192 | | - "irq %u doesn't support irq_set_wake\n", |
---|
| 185 | + dev_dbg(p->dev, "irq %u doesn't support irq_set_wake\n", |
---|
193 | 186 | p->irq_parent); |
---|
194 | 187 | p->irq_parent = 0; |
---|
195 | 188 | } |
---|
.. | .. |
---|
235 | 228 | |
---|
236 | 229 | spin_lock_irqsave(&p->lock, flags); |
---|
237 | 230 | |
---|
238 | | - /* Configure postive logic in POSNEG */ |
---|
| 231 | + /* Configure positive logic in POSNEG */ |
---|
239 | 232 | gpio_rcar_modify_bit(p, POSNEG, gpio, false); |
---|
240 | 233 | |
---|
241 | 234 | /* Select "General Input/Output Mode" in IOINTSEL */ |
---|
.. | .. |
---|
243 | 236 | |
---|
244 | 237 | /* Select Input Mode or Output Mode in INOUTSEL */ |
---|
245 | 238 | gpio_rcar_modify_bit(p, INOUTSEL, gpio, output); |
---|
| 239 | + |
---|
| 240 | + /* Select General Output Register to output data in OUTDTSEL */ |
---|
| 241 | + if (p->has_outdtsel && output) |
---|
| 242 | + gpio_rcar_modify_bit(p, OUTDTSEL, gpio, false); |
---|
246 | 243 | |
---|
247 | 244 | spin_unlock_irqrestore(&p->lock, flags); |
---|
248 | 245 | } |
---|
.. | .. |
---|
252 | 249 | struct gpio_rcar_priv *p = gpiochip_get_data(chip); |
---|
253 | 250 | int error; |
---|
254 | 251 | |
---|
255 | | - error = pm_runtime_get_sync(&p->pdev->dev); |
---|
256 | | - if (error < 0) |
---|
| 252 | + error = pm_runtime_get_sync(p->dev); |
---|
| 253 | + if (error < 0) { |
---|
| 254 | + pm_runtime_put(p->dev); |
---|
257 | 255 | return error; |
---|
| 256 | + } |
---|
258 | 257 | |
---|
259 | 258 | error = pinctrl_gpio_request(chip->base + offset); |
---|
260 | 259 | if (error) |
---|
261 | | - pm_runtime_put(&p->pdev->dev); |
---|
| 260 | + pm_runtime_put(p->dev); |
---|
262 | 261 | |
---|
263 | 262 | return error; |
---|
264 | 263 | } |
---|
.. | .. |
---|
275 | 274 | */ |
---|
276 | 275 | gpio_rcar_config_general_input_output_mode(chip, offset, false); |
---|
277 | 276 | |
---|
278 | | - pm_runtime_put(&p->pdev->dev); |
---|
| 277 | + pm_runtime_put(p->dev); |
---|
279 | 278 | } |
---|
280 | 279 | |
---|
281 | 280 | static int gpio_rcar_get_direction(struct gpio_chip *chip, unsigned int offset) |
---|
282 | 281 | { |
---|
283 | 282 | struct gpio_rcar_priv *p = gpiochip_get_data(chip); |
---|
284 | 283 | |
---|
285 | | - return !(gpio_rcar_read(p, INOUTSEL) & BIT(offset)); |
---|
| 284 | + if (gpio_rcar_read(p, INOUTSEL) & BIT(offset)) |
---|
| 285 | + return GPIO_LINE_DIRECTION_OUT; |
---|
| 286 | + |
---|
| 287 | + return GPIO_LINE_DIRECTION_IN; |
---|
286 | 288 | } |
---|
287 | 289 | |
---|
288 | 290 | static int gpio_rcar_direction_input(struct gpio_chip *chip, unsigned offset) |
---|
.. | .. |
---|
321 | 323 | u32 val, bankmask; |
---|
322 | 324 | |
---|
323 | 325 | bankmask = mask[0] & GENMASK(chip->ngpio - 1, 0); |
---|
| 326 | + if (chip->valid_mask) |
---|
| 327 | + bankmask &= chip->valid_mask[0]; |
---|
| 328 | + |
---|
324 | 329 | if (!bankmask) |
---|
325 | 330 | return; |
---|
326 | 331 | |
---|
.. | .. |
---|
342 | 347 | } |
---|
343 | 348 | |
---|
344 | 349 | struct gpio_rcar_info { |
---|
| 350 | + bool has_outdtsel; |
---|
345 | 351 | bool has_both_edge_trigger; |
---|
346 | 352 | }; |
---|
347 | 353 | |
---|
348 | 354 | static const struct gpio_rcar_info gpio_rcar_info_gen1 = { |
---|
| 355 | + .has_outdtsel = false, |
---|
349 | 356 | .has_both_edge_trigger = false, |
---|
350 | 357 | }; |
---|
351 | 358 | |
---|
352 | 359 | static const struct gpio_rcar_info gpio_rcar_info_gen2 = { |
---|
| 360 | + .has_outdtsel = true, |
---|
353 | 361 | .has_both_edge_trigger = true, |
---|
354 | 362 | }; |
---|
355 | 363 | |
---|
.. | .. |
---|
403 | 411 | |
---|
404 | 412 | static int gpio_rcar_parse_dt(struct gpio_rcar_priv *p, unsigned int *npins) |
---|
405 | 413 | { |
---|
406 | | - struct device_node *np = p->pdev->dev.of_node; |
---|
| 414 | + struct device_node *np = p->dev->of_node; |
---|
407 | 415 | const struct gpio_rcar_info *info; |
---|
408 | 416 | struct of_phandle_args args; |
---|
409 | 417 | int ret; |
---|
410 | 418 | |
---|
411 | | - info = of_device_get_match_data(&p->pdev->dev); |
---|
| 419 | + info = of_device_get_match_data(p->dev); |
---|
| 420 | + p->has_outdtsel = info->has_outdtsel; |
---|
| 421 | + p->has_both_edge_trigger = info->has_both_edge_trigger; |
---|
412 | 422 | |
---|
413 | 423 | ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &args); |
---|
414 | 424 | *npins = ret == 0 ? args.args[2] : RCAR_MAX_GPIO_PER_BANK; |
---|
415 | | - p->has_both_edge_trigger = info->has_both_edge_trigger; |
---|
416 | 425 | |
---|
417 | 426 | if (*npins == 0 || *npins > RCAR_MAX_GPIO_PER_BANK) { |
---|
418 | | - dev_warn(&p->pdev->dev, |
---|
419 | | - "Invalid number of gpio lines %u, using %u\n", *npins, |
---|
420 | | - RCAR_MAX_GPIO_PER_BANK); |
---|
| 427 | + dev_warn(p->dev, "Invalid number of gpio lines %u, using %u\n", |
---|
| 428 | + *npins, RCAR_MAX_GPIO_PER_BANK); |
---|
421 | 429 | *npins = RCAR_MAX_GPIO_PER_BANK; |
---|
422 | 430 | } |
---|
423 | 431 | |
---|
.. | .. |
---|
427 | 435 | static int gpio_rcar_probe(struct platform_device *pdev) |
---|
428 | 436 | { |
---|
429 | 437 | struct gpio_rcar_priv *p; |
---|
430 | | - struct resource *io, *irq; |
---|
| 438 | + struct resource *irq; |
---|
431 | 439 | struct gpio_chip *gpio_chip; |
---|
432 | 440 | struct irq_chip *irq_chip; |
---|
| 441 | + struct gpio_irq_chip *girq; |
---|
433 | 442 | struct device *dev = &pdev->dev; |
---|
434 | 443 | const char *name = dev_name(dev); |
---|
435 | 444 | unsigned int npins; |
---|
.. | .. |
---|
439 | 448 | if (!p) |
---|
440 | 449 | return -ENOMEM; |
---|
441 | 450 | |
---|
442 | | - p->pdev = pdev; |
---|
| 451 | + p->dev = dev; |
---|
443 | 452 | spin_lock_init(&p->lock); |
---|
444 | 453 | |
---|
445 | 454 | /* Get device configuration from DT node */ |
---|
.. | .. |
---|
458 | 467 | goto err0; |
---|
459 | 468 | } |
---|
460 | 469 | |
---|
461 | | - io = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
462 | | - p->base = devm_ioremap_resource(dev, io); |
---|
| 470 | + p->base = devm_platform_ioremap_resource(pdev, 0); |
---|
463 | 471 | if (IS_ERR(p->base)) { |
---|
464 | 472 | ret = PTR_ERR(p->base); |
---|
465 | 473 | goto err0; |
---|
.. | .. |
---|
481 | 489 | gpio_chip->ngpio = npins; |
---|
482 | 490 | |
---|
483 | 491 | irq_chip = &p->irq_chip; |
---|
484 | | - irq_chip->name = name; |
---|
| 492 | + irq_chip->name = "gpio-rcar"; |
---|
485 | 493 | irq_chip->parent_device = dev; |
---|
486 | 494 | irq_chip->irq_mask = gpio_rcar_irq_disable; |
---|
487 | 495 | irq_chip->irq_unmask = gpio_rcar_irq_enable; |
---|
488 | 496 | irq_chip->irq_set_type = gpio_rcar_irq_set_type; |
---|
489 | 497 | irq_chip->irq_set_wake = gpio_rcar_irq_set_wake; |
---|
490 | | - irq_chip->flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND; |
---|
| 498 | + irq_chip->flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND; |
---|
| 499 | + |
---|
| 500 | + girq = &gpio_chip->irq; |
---|
| 501 | + girq->chip = irq_chip; |
---|
| 502 | + /* This will let us handle the parent IRQ in the driver */ |
---|
| 503 | + girq->parent_handler = NULL; |
---|
| 504 | + girq->num_parents = 0; |
---|
| 505 | + girq->parents = NULL; |
---|
| 506 | + girq->default_type = IRQ_TYPE_NONE; |
---|
| 507 | + girq->handler = handle_level_irq; |
---|
491 | 508 | |
---|
492 | 509 | ret = gpiochip_add_data(gpio_chip, p); |
---|
493 | 510 | if (ret) { |
---|
494 | 511 | dev_err(dev, "failed to add GPIO controller\n"); |
---|
495 | 512 | goto err0; |
---|
496 | | - } |
---|
497 | | - |
---|
498 | | - ret = gpiochip_irqchip_add(gpio_chip, irq_chip, 0, handle_level_irq, |
---|
499 | | - IRQ_TYPE_NONE); |
---|
500 | | - if (ret) { |
---|
501 | | - dev_err(dev, "cannot add irqchip\n"); |
---|
502 | | - goto err1; |
---|
503 | 513 | } |
---|
504 | 514 | |
---|
505 | 515 | p->irq_parent = irq->start; |
---|
.. | .. |
---|
558 | 568 | u32 mask; |
---|
559 | 569 | |
---|
560 | 570 | for (offset = 0; offset < p->gpio_chip.ngpio; offset++) { |
---|
| 571 | + if (!gpiochip_line_is_valid(&p->gpio_chip, offset)) |
---|
| 572 | + continue; |
---|
| 573 | + |
---|
561 | 574 | mask = BIT(offset); |
---|
562 | 575 | /* I/O pin */ |
---|
563 | 576 | if (!(p->bank_info.iointsel & mask)) { |
---|