Lines Matching +full:rcar +full:- +full:gen2 +full:- +full:gpio
1 // SPDX-License-Identifier: GPL-2.0
3 * Renesas R-Car GPIO Support
10 #include <linux/gpio/driver.h>
72 return ioread32(p->base + offs); in gpio_rcar_read()
78 iowrite32(value, p->base + offs); in gpio_rcar_write()
122 /* follow steps in the GPIO documentation for in gpio_rcar_config_interrupt_input_mode()
123 * "Setting Edge-Sensitive Interrupt Input Mode" and in gpio_rcar_config_interrupt_input_mode()
124 * "Setting Level-Sensitive Interrupt Input Mode" in gpio_rcar_config_interrupt_input_mode()
127 spin_lock_irqsave(&p->lock, flags); in gpio_rcar_config_interrupt_input_mode()
136 if (p->info.has_both_edge_trigger) in gpio_rcar_config_interrupt_input_mode()
146 spin_unlock_irqrestore(&p->lock, flags); in gpio_rcar_config_interrupt_input_mode()
155 dev_dbg(p->dev, "sense irq = %d, type = %d\n", hwirq, type); in gpio_rcar_irq_set_type()
175 if (!p->info.has_both_edge_trigger) in gpio_rcar_irq_set_type()
176 return -EINVAL; in gpio_rcar_irq_set_type()
181 return -EINVAL; in gpio_rcar_irq_set_type()
192 if (p->irq_parent) { in gpio_rcar_irq_set_wake()
193 error = irq_set_irq_wake(p->irq_parent, on); in gpio_rcar_irq_set_wake()
195 dev_dbg(p->dev, "irq %u doesn't support irq_set_wake\n", in gpio_rcar_irq_set_wake()
196 p->irq_parent); in gpio_rcar_irq_set_wake()
197 p->irq_parent = 0; in gpio_rcar_irq_set_wake()
202 atomic_inc(&p->wakeup_path); in gpio_rcar_irq_set_wake()
204 atomic_dec(&p->wakeup_path); in gpio_rcar_irq_set_wake()
210 .name = "gpio-rcar",
230 generic_handle_domain_irq(p->gpio_chip.irq.domain, in gpio_rcar_irq_handler()
239 unsigned int gpio, in gpio_rcar_config_general_input_output_mode() argument
245 /* follow steps in the GPIO documentation for in gpio_rcar_config_general_input_output_mode()
250 spin_lock_irqsave(&p->lock, flags); in gpio_rcar_config_general_input_output_mode()
253 gpio_rcar_modify_bit(p, POSNEG, gpio, false); in gpio_rcar_config_general_input_output_mode()
256 gpio_rcar_modify_bit(p, IOINTSEL, gpio, false); in gpio_rcar_config_general_input_output_mode()
259 gpio_rcar_modify_bit(p, INOUTSEL, gpio, output); in gpio_rcar_config_general_input_output_mode()
262 if (p->info.has_outdtsel && output) in gpio_rcar_config_general_input_output_mode()
263 gpio_rcar_modify_bit(p, OUTDTSEL, gpio, false); in gpio_rcar_config_general_input_output_mode()
265 spin_unlock_irqrestore(&p->lock, flags); in gpio_rcar_config_general_input_output_mode()
273 error = pm_runtime_get_sync(p->dev); in gpio_rcar_request()
275 pm_runtime_put(p->dev); in gpio_rcar_request()
279 error = pinctrl_gpio_request(chip->base + offset); in gpio_rcar_request()
281 pm_runtime_put(p->dev); in gpio_rcar_request()
290 pinctrl_gpio_free(chip->base + offset); in gpio_rcar_free()
293 * Set the GPIO as an input to ensure that the next GPIO request won't in gpio_rcar_free()
294 * drive the GPIO pin as an output. in gpio_rcar_free()
298 pm_runtime_put(p->dev); in gpio_rcar_free()
323 * Before R-Car Gen3, INDT does not show correct pin state when in gpio_rcar_get()
326 if (!p->info.has_always_in && (gpio_rcar_read(p, INOUTSEL) & bit)) in gpio_rcar_get()
339 bankmask = mask[0] & GENMASK(chip->ngpio - 1, 0); in gpio_rcar_get_multiple()
340 if (chip->valid_mask) in gpio_rcar_get_multiple()
341 bankmask &= chip->valid_mask[0]; in gpio_rcar_get_multiple()
346 if (p->info.has_always_in) { in gpio_rcar_get_multiple()
351 spin_lock_irqsave(&p->lock, flags); in gpio_rcar_get_multiple()
360 spin_unlock_irqrestore(&p->lock, flags); in gpio_rcar_get_multiple()
371 spin_lock_irqsave(&p->lock, flags); in gpio_rcar_set()
373 spin_unlock_irqrestore(&p->lock, flags); in gpio_rcar_set()
383 bankmask = mask[0] & GENMASK(chip->ngpio - 1, 0); in gpio_rcar_set_multiple()
384 if (chip->valid_mask) in gpio_rcar_set_multiple()
385 bankmask &= chip->valid_mask[0]; in gpio_rcar_set_multiple()
390 spin_lock_irqsave(&p->lock, flags); in gpio_rcar_set_multiple()
395 spin_unlock_irqrestore(&p->lock, flags); in gpio_rcar_set_multiple()
401 /* write GPIO value to output before selecting output mode of pin */ in gpio_rcar_direction_output()
437 .compatible = "renesas,gpio-r8a779a0",
440 .compatible = "renesas,rcar-gen1-gpio",
443 .compatible = "renesas,rcar-gen2-gpio",
446 .compatible = "renesas,rcar-gen3-gpio",
449 .compatible = "renesas,rcar-gen4-gpio",
452 .compatible = "renesas,gpio-rcar",
463 struct device_node *np = p->dev->of_node; in gpio_rcar_parse_dt()
468 info = of_device_get_match_data(p->dev); in gpio_rcar_parse_dt()
469 p->info = *info; in gpio_rcar_parse_dt()
471 ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &args); in gpio_rcar_parse_dt()
475 dev_warn(p->dev, "Invalid number of gpio lines %u, using %u\n", in gpio_rcar_parse_dt()
485 u32 mask = GENMASK(p->gpio_chip.ngpio - 1, 0); in gpio_rcar_enable_inputs()
488 if (p->gpio_chip.valid_mask) in gpio_rcar_enable_inputs()
489 mask &= p->gpio_chip.valid_mask[0]; in gpio_rcar_enable_inputs()
499 struct device *dev = &pdev->dev; in gpio_rcar_probe()
506 return -ENOMEM; in gpio_rcar_probe()
508 p->dev = dev; in gpio_rcar_probe()
509 spin_lock_init(&p->lock); in gpio_rcar_probe()
523 p->irq_parent = ret; in gpio_rcar_probe()
525 p->base = devm_platform_ioremap_resource(pdev, 0); in gpio_rcar_probe()
526 if (IS_ERR(p->base)) { in gpio_rcar_probe()
527 ret = PTR_ERR(p->base); in gpio_rcar_probe()
531 gpio_chip = &p->gpio_chip; in gpio_rcar_probe()
532 gpio_chip->request = gpio_rcar_request; in gpio_rcar_probe()
533 gpio_chip->free = gpio_rcar_free; in gpio_rcar_probe()
534 gpio_chip->get_direction = gpio_rcar_get_direction; in gpio_rcar_probe()
535 gpio_chip->direction_input = gpio_rcar_direction_input; in gpio_rcar_probe()
536 gpio_chip->get = gpio_rcar_get; in gpio_rcar_probe()
537 gpio_chip->get_multiple = gpio_rcar_get_multiple; in gpio_rcar_probe()
538 gpio_chip->direction_output = gpio_rcar_direction_output; in gpio_rcar_probe()
539 gpio_chip->set = gpio_rcar_set; in gpio_rcar_probe()
540 gpio_chip->set_multiple = gpio_rcar_set_multiple; in gpio_rcar_probe()
541 gpio_chip->label = name; in gpio_rcar_probe()
542 gpio_chip->parent = dev; in gpio_rcar_probe()
543 gpio_chip->owner = THIS_MODULE; in gpio_rcar_probe()
544 gpio_chip->base = -1; in gpio_rcar_probe()
545 gpio_chip->ngpio = npins; in gpio_rcar_probe()
547 girq = &gpio_chip->irq; in gpio_rcar_probe()
550 girq->parent_handler = NULL; in gpio_rcar_probe()
551 girq->num_parents = 0; in gpio_rcar_probe()
552 girq->parents = NULL; in gpio_rcar_probe()
553 girq->default_type = IRQ_TYPE_NONE; in gpio_rcar_probe()
554 girq->handler = handle_level_irq; in gpio_rcar_probe()
558 dev_err(dev, "failed to add GPIO controller\n"); in gpio_rcar_probe()
562 irq_domain_set_pm_device(gpio_chip->irq.domain, dev); in gpio_rcar_probe()
563 ret = devm_request_irq(dev, p->irq_parent, gpio_rcar_irq_handler, in gpio_rcar_probe()
570 if (p->info.has_inen) { in gpio_rcar_probe()
591 gpiochip_remove(&p->gpio_chip); in gpio_rcar_remove()
593 pm_runtime_disable(&pdev->dev); in gpio_rcar_remove()
602 p->bank_info.iointsel = gpio_rcar_read(p, IOINTSEL); in gpio_rcar_suspend()
603 p->bank_info.inoutsel = gpio_rcar_read(p, INOUTSEL); in gpio_rcar_suspend()
604 p->bank_info.outdt = gpio_rcar_read(p, OUTDT); in gpio_rcar_suspend()
605 p->bank_info.intmsk = gpio_rcar_read(p, INTMSK); in gpio_rcar_suspend()
606 p->bank_info.posneg = gpio_rcar_read(p, POSNEG); in gpio_rcar_suspend()
607 p->bank_info.edglevel = gpio_rcar_read(p, EDGLEVEL); in gpio_rcar_suspend()
608 if (p->info.has_both_edge_trigger) in gpio_rcar_suspend()
609 p->bank_info.bothedge = gpio_rcar_read(p, BOTHEDGE); in gpio_rcar_suspend()
611 if (atomic_read(&p->wakeup_path)) in gpio_rcar_suspend()
623 for (offset = 0; offset < p->gpio_chip.ngpio; offset++) { in gpio_rcar_resume()
624 if (!gpiochip_line_is_valid(&p->gpio_chip, offset)) in gpio_rcar_resume()
629 if (!(p->bank_info.iointsel & mask)) { in gpio_rcar_resume()
630 if (p->bank_info.inoutsel & mask) in gpio_rcar_resume()
632 &p->gpio_chip, offset, in gpio_rcar_resume()
633 !!(p->bank_info.outdt & mask)); in gpio_rcar_resume()
635 gpio_rcar_direction_input(&p->gpio_chip, in gpio_rcar_resume()
642 !(p->bank_info.posneg & mask), in gpio_rcar_resume()
643 !(p->bank_info.edglevel & mask), in gpio_rcar_resume()
644 !!(p->bank_info.bothedge & mask)); in gpio_rcar_resume()
646 if (p->bank_info.intmsk & mask) in gpio_rcar_resume()
651 if (p->info.has_inen) in gpio_rcar_resume()
673 MODULE_DESCRIPTION("Renesas R-Car GPIO Driver");