Lines Matching +full:gpio +full:- +full:range
1 // SPDX-License-Identifier: GPL-2.0
7 #include <linux/gpio/driver.h>
16 #include <dt-bindings/gpio/uniphier-gpio.h>
43 * Unfortunately, the GPIO port registers are not contiguous because in uniphier_gpio_bank_to_reg()
44 * offset 0x90-0x9f is used for IRQ. Add 0x10 when crossing the region. in uniphier_gpio_bank_to_reg()
65 spin_lock_irqsave(&priv->lock, flags); in uniphier_gpio_reg_update()
66 tmp = readl(priv->regs + reg); in uniphier_gpio_reg_update()
69 writel(tmp, priv->regs + reg); in uniphier_gpio_reg_update()
70 spin_unlock_irqrestore(&priv->lock, flags); in uniphier_gpio_reg_update()
107 return !!(readl(priv->regs + reg_offset) & mask); in uniphier_gpio_offset_read()
154 for_each_set_clump8(i, bank_mask, mask, chip->ngpio) { in uniphier_gpio_set_multiple()
170 return -ENXIO; in uniphier_gpio_to_irq()
172 fwspec.fwnode = dev_fwnode(chip->parent); in uniphier_gpio_to_irq()
174 fwspec.param[0] = offset - UNIPHIER_GPIO_IRQ_OFFSET; in uniphier_gpio_to_irq()
177 * temporarily. Anyway, ->irq_set_type() will override it later. in uniphier_gpio_to_irq()
225 struct device_node *np = priv->chip.parent->of_node; in uniphier_gpio_irq_get_parent_hwirq()
226 const __be32 *range; in uniphier_gpio_irq_get_parent_hwirq() local
230 range = of_get_property(np, "socionext,interrupt-ranges", &len); in uniphier_gpio_irq_get_parent_hwirq()
231 if (!range) in uniphier_gpio_irq_get_parent_hwirq()
232 return -EINVAL; in uniphier_gpio_irq_get_parent_hwirq()
234 len /= sizeof(*range); in uniphier_gpio_irq_get_parent_hwirq()
236 for (; len >= 3; len -= 3) { in uniphier_gpio_irq_get_parent_hwirq()
237 base = be32_to_cpu(*range++); in uniphier_gpio_irq_get_parent_hwirq()
238 parent_base = be32_to_cpu(*range++); in uniphier_gpio_irq_get_parent_hwirq()
239 size = be32_to_cpu(*range++); in uniphier_gpio_irq_get_parent_hwirq()
242 return hwirq - base + parent_base; in uniphier_gpio_irq_get_parent_hwirq()
245 return -ENOENT; in uniphier_gpio_irq_get_parent_hwirq()
253 if (WARN_ON(fwspec->param_count < 2)) in uniphier_gpio_irq_domain_translate()
254 return -EINVAL; in uniphier_gpio_irq_domain_translate()
256 *out_hwirq = fwspec->param[0]; in uniphier_gpio_irq_domain_translate()
257 *out_type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK; in uniphier_gpio_irq_domain_translate()
266 struct uniphier_gpio_priv *priv = domain->host_data; in uniphier_gpio_irq_domain_alloc()
273 return -EINVAL; in uniphier_gpio_irq_domain_alloc()
284 parent_fwspec.fwnode = domain->parent->fwnode; in uniphier_gpio_irq_domain_alloc()
291 &priv->irq_chip, priv); in uniphier_gpio_irq_domain_alloc()
301 struct uniphier_gpio_priv *priv = domain->host_data; in uniphier_gpio_irq_domain_activate()
302 struct gpio_chip *chip = &priv->chip; in uniphier_gpio_irq_domain_activate()
311 struct uniphier_gpio_priv *priv = domain->host_data; in uniphier_gpio_irq_domain_deactivate()
312 struct gpio_chip *chip = &priv->chip; in uniphier_gpio_irq_domain_deactivate()
331 * noise from the irq lines. It does not work for GPIO input, so GPIO in uniphier_gpio_hw_init()
335 writel(0xff, priv->regs + UNIPHIER_GPIO_IRQ_FLT_CYC); in uniphier_gpio_hw_init()
345 struct device *dev = &pdev->dev; in uniphier_gpio_probe()
355 parent_np = of_irq_find_parent(dev->of_node); in uniphier_gpio_probe()
357 return -ENXIO; in uniphier_gpio_probe()
362 return -EPROBE_DEFER; in uniphier_gpio_probe()
364 ret = of_property_read_u32(dev->of_node, "ngpios", &ngpios); in uniphier_gpio_probe()
372 return -ENOMEM; in uniphier_gpio_probe()
374 priv->regs = devm_platform_ioremap_resource(pdev, 0); in uniphier_gpio_probe()
375 if (IS_ERR(priv->regs)) in uniphier_gpio_probe()
376 return PTR_ERR(priv->regs); in uniphier_gpio_probe()
378 spin_lock_init(&priv->lock); in uniphier_gpio_probe()
380 chip = &priv->chip; in uniphier_gpio_probe()
381 chip->label = dev_name(dev); in uniphier_gpio_probe()
382 chip->parent = dev; in uniphier_gpio_probe()
383 chip->request = gpiochip_generic_request; in uniphier_gpio_probe()
384 chip->free = gpiochip_generic_free; in uniphier_gpio_probe()
385 chip->get_direction = uniphier_gpio_get_direction; in uniphier_gpio_probe()
386 chip->direction_input = uniphier_gpio_direction_input; in uniphier_gpio_probe()
387 chip->direction_output = uniphier_gpio_direction_output; in uniphier_gpio_probe()
388 chip->get = uniphier_gpio_get; in uniphier_gpio_probe()
389 chip->set = uniphier_gpio_set; in uniphier_gpio_probe()
390 chip->set_multiple = uniphier_gpio_set_multiple; in uniphier_gpio_probe()
391 chip->to_irq = uniphier_gpio_to_irq; in uniphier_gpio_probe()
392 chip->base = -1; in uniphier_gpio_probe()
393 chip->ngpio = ngpios; in uniphier_gpio_probe()
395 irq_chip = &priv->irq_chip; in uniphier_gpio_probe()
396 irq_chip->name = dev_name(dev); in uniphier_gpio_probe()
397 irq_chip->irq_mask = uniphier_gpio_irq_mask; in uniphier_gpio_probe()
398 irq_chip->irq_unmask = uniphier_gpio_irq_unmask; in uniphier_gpio_probe()
399 irq_chip->irq_eoi = irq_chip_eoi_parent; in uniphier_gpio_probe()
400 irq_chip->irq_set_affinity = irq_chip_set_affinity_parent; in uniphier_gpio_probe()
401 irq_chip->irq_set_type = uniphier_gpio_irq_set_type; in uniphier_gpio_probe()
409 priv->domain = irq_domain_create_hierarchy( in uniphier_gpio_probe()
414 if (!priv->domain) in uniphier_gpio_probe()
415 return -ENOMEM; in uniphier_gpio_probe()
426 irq_domain_remove(priv->domain); in uniphier_gpio_remove()
432 unsigned int nbanks = uniphier_gpio_get_nbanks(priv->chip.ngpio); in uniphier_gpio_suspend()
433 u32 *val = priv->saved_vals; in uniphier_gpio_suspend()
440 *val++ = readl(priv->regs + reg + UNIPHIER_GPIO_PORT_DATA); in uniphier_gpio_suspend()
441 *val++ = readl(priv->regs + reg + UNIPHIER_GPIO_PORT_DIR); in uniphier_gpio_suspend()
444 *val++ = readl(priv->regs + UNIPHIER_GPIO_IRQ_EN); in uniphier_gpio_suspend()
445 *val++ = readl(priv->regs + UNIPHIER_GPIO_IRQ_MODE); in uniphier_gpio_suspend()
446 *val++ = readl(priv->regs + UNIPHIER_GPIO_IRQ_FLT_EN); in uniphier_gpio_suspend()
454 unsigned int nbanks = uniphier_gpio_get_nbanks(priv->chip.ngpio); in uniphier_gpio_resume()
455 const u32 *val = priv->saved_vals; in uniphier_gpio_resume()
462 writel(*val++, priv->regs + reg + UNIPHIER_GPIO_PORT_DATA); in uniphier_gpio_resume()
463 writel(*val++, priv->regs + reg + UNIPHIER_GPIO_PORT_DIR); in uniphier_gpio_resume()
466 writel(*val++, priv->regs + UNIPHIER_GPIO_IRQ_EN); in uniphier_gpio_resume()
467 writel(*val++, priv->regs + UNIPHIER_GPIO_IRQ_MODE); in uniphier_gpio_resume()
468 writel(*val++, priv->regs + UNIPHIER_GPIO_IRQ_FLT_EN); in uniphier_gpio_resume()
481 { .compatible = "socionext,uniphier-gpio" },
490 .name = "uniphier-gpio",
498 MODULE_DESCRIPTION("UniPhier GPIO driver");