| .. | .. |
|---|
| 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)) { |
|---|