Lines Matching +full:gpio +full:- +full:ctrl1
1 // SPDX-License-Identifier: GPL-2.0
8 * This driver is based on the original Cherryview GPIO driver by
17 #include <linux/gpio/driver.h>
24 #include <linux/pinctrl/pinconf-generic.h>
29 #include "pinctrl-intel.h"
82 * struct intel_community_context - community context for Cherryview
83 * @intr_lines: Mapping between 16 HW interrupt wires and GPIO offset (in GPIO number space)
98 .size = (end) - (start) + 1, \
271 * Southwest community can generate GPIO interrupts only for the first 8
272 * interrupts. The upper half (8-15) can only be used to trigger GPEs.
365 * North community can generate GPIO interrupts only for the first 8
366 * interrupts. The upper half (8-15) can only be used to trigger GPEs.
565 * concurrent accesses across the 4 GPIO controllers.
574 const struct intel_community *community = &pctrl->communities[0]; in chv_pctrl_readl()
576 return readl(community->regs + offset); in chv_pctrl_readl()
581 const struct intel_community *community = &pctrl->communities[0]; in chv_pctrl_writel()
582 void __iomem *reg = community->regs + offset; in chv_pctrl_writel()
592 const struct intel_community *community = &pctrl->communities[0]; in chv_padreg()
598 return community->pad_regs + offset + reg; in chv_padreg()
616 static bool chv_pad_is_locked(u32 ctrl1) in chv_pad_is_locked() argument
618 return ctrl1 & CHV_PADCTRL1_CFGLOCK; in chv_pad_is_locked()
630 u32 ctrl0, ctrl1; in chv_pin_dbg_show() local
634 ctrl1 = chv_readl(pctrl, offset, CHV_PADCTRL1); in chv_pin_dbg_show()
638 seq_puts(s, "GPIO "); in chv_pin_dbg_show()
648 seq_printf(s, "0x%08x 0x%08x", ctrl0, ctrl1); in chv_pin_dbg_show()
650 if (chv_pad_is_locked(ctrl1)) in chv_pin_dbg_show()
665 struct device *dev = pctrl->dev; in chv_pinmux_set_mux()
669 grp = &pctrl->soc->groups[group]; in chv_pinmux_set_mux()
674 for (i = 0; i < grp->grp.npins; i++) { in chv_pinmux_set_mux()
675 if (chv_pad_locked(pctrl, grp->grp.pins[i])) { in chv_pinmux_set_mux()
676 dev_warn(dev, "unable to set mode for locked pin %u\n", grp->grp.pins[i]); in chv_pinmux_set_mux()
677 return -EBUSY; in chv_pinmux_set_mux()
681 for (i = 0; i < grp->grp.npins; i++) { in chv_pinmux_set_mux()
682 int pin = grp->grp.pins[i]; in chv_pinmux_set_mux()
687 /* Check if there is pin-specific config */ in chv_pinmux_set_mux()
688 if (grp->modes) in chv_pinmux_set_mux()
689 mode = grp->modes[i]; in chv_pinmux_set_mux()
691 mode = grp->mode; in chv_pinmux_set_mux()
698 /* Disable GPIO mode */ in chv_pinmux_set_mux()
725 * One some devices the GPIO should output the inverted value from what in chv_gpio_clear_triggering()
726 * device-drivers / ACPI code expects (inverted external buffer?). The in chv_gpio_clear_triggering()
728 * preserve this flag if the pin is already setup as GPIO. in chv_gpio_clear_triggering()
753 return -EBUSY; in chv_gpio_request_enable()
756 struct intel_community_context *cctx = &pctrl->context.communities[0]; in chv_gpio_request_enable()
760 for (i = 0; i < ARRAY_SIZE(cctx->intr_lines); i++) { in chv_gpio_request_enable()
761 if (cctx->intr_lines[i] == offset) { in chv_gpio_request_enable()
762 cctx->intr_lines[i] = CHV_INVALID_HWIRQ; in chv_gpio_request_enable()
782 /* Switch to a GPIO mode */ in chv_gpio_request_enable()
838 u32 ctrl0, ctrl1; in chv_config_get() local
844 ctrl1 = chv_readl(pctrl, pin, CHV_PADCTRL1); in chv_config_get()
852 return -EINVAL; in chv_config_get()
857 return -EINVAL; in chv_config_get()
875 return -EINVAL; in chv_config_get()
894 return -EINVAL; in chv_config_get()
900 if (ctrl1 & CHV_PADCTRL1_ODEN) in chv_config_get()
901 return -EINVAL; in chv_config_get()
905 if (!(ctrl1 & CHV_PADCTRL1_ODEN)) in chv_config_get()
906 return -EINVAL; in chv_config_get()
910 return -ENOTSUPP; in chv_config_get()
946 return -EINVAL; in chv_config_set_pull()
963 return -EINVAL; in chv_config_set_pull()
970 return -EINVAL; in chv_config_set_pull()
981 u32 ctrl1; in chv_config_set_oden() local
985 ctrl1 = chv_readl(pctrl, pin, CHV_PADCTRL1); in chv_config_set_oden()
988 ctrl1 |= CHV_PADCTRL1_ODEN; in chv_config_set_oden()
990 ctrl1 &= ~CHV_PADCTRL1_ODEN; in chv_config_set_oden()
992 chv_writel(pctrl, pin, CHV_PADCTRL1, ctrl1); in chv_config_set_oden()
1001 struct device *dev = pctrl->dev; in chv_config_set()
1007 return -EBUSY; in chv_config_set()
1035 return -ENOTSUPP; in chv_config_set()
1240 * In that case ->irq_set_type() will never be called so we need to in chv_gpio_irq_startup()
1247 struct device *dev = pctrl->dev; in chv_gpio_irq_startup()
1248 struct intel_community_context *cctx = &pctrl->context.communities[0]; in chv_gpio_irq_startup()
1263 if (cctx->intr_lines[intsel] == CHV_INVALID_HWIRQ) { in chv_gpio_irq_startup()
1267 cctx->intr_lines[intsel] = hwirq; in chv_gpio_irq_startup()
1277 struct device *dev = pctrl->dev; in chv_gpio_set_intr_line()
1278 struct intel_community_context *cctx = &pctrl->context.communities[0]; in chv_gpio_set_intr_line()
1279 const struct intel_community *community = &pctrl->communities[0]; in chv_gpio_set_intr_line()
1286 if (cctx->intr_lines[intsel] == pin) in chv_gpio_set_intr_line()
1289 if (cctx->intr_lines[intsel] == CHV_INVALID_HWIRQ) { in chv_gpio_set_intr_line()
1291 cctx->intr_lines[intsel] = pin; in chv_gpio_set_intr_line()
1303 cctx->intr_lines[intsel], pin); in chv_gpio_set_intr_line()
1306 return -EBUSY; in chv_gpio_set_intr_line()
1312 for (i = community->nirqs - 1; i >= 0; i--) { in chv_gpio_set_intr_line()
1313 if (cctx->intr_lines[i] == CHV_INVALID_HWIRQ) in chv_gpio_set_intr_line()
1317 return -EBUSY; in chv_gpio_set_intr_line()
1323 cctx->intr_lines[i] = pin; in chv_gpio_set_intr_line()
1385 .name = "chv-gpio",
1399 struct device *dev = pctrl->dev; in chv_gpio_irq_handler()
1400 const struct intel_community *community = &pctrl->communities[0]; in chv_gpio_irq_handler()
1401 struct intel_community_context *cctx = &pctrl->context.communities[0]; in chv_gpio_irq_handler()
1411 for_each_set_bit(intr_line, &pending, community->nirqs) { in chv_gpio_irq_handler()
1414 offset = cctx->intr_lines[intr_line]; in chv_gpio_irq_handler()
1421 generic_handle_domain_irq(gc->irq.domain, offset); in chv_gpio_irq_handler()
1473 const struct intel_community *community = &pctrl->communities[0]; in chv_init_irq_valid_mask()
1477 for (i = 0; i < pctrl->soc->npins; i++) { in chv_init_irq_valid_mask()
1481 desc = &pctrl->soc->pins[i]; in chv_init_irq_valid_mask()
1483 intsel = chv_readl(pctrl, desc->number, CHV_PADCTRL0); in chv_init_irq_valid_mask()
1487 if (intsel >= community->nirqs) in chv_init_irq_valid_mask()
1488 clear_bit(desc->number, valid_mask); in chv_init_irq_valid_mask()
1495 const struct intel_community *community = &pctrl->communities[0]; in chv_gpio_irq_init_hw()
1504 if (!pctrl->chip.irq.init_valid_mask) { in chv_gpio_irq_init_hw()
1509 chv_pctrl_writel(pctrl, CHV_INTMASK, GENMASK(31, community->nirqs)); in chv_gpio_irq_init_hw()
1521 struct device *dev = pctrl->dev; in chv_gpio_add_pin_ranges()
1522 const struct intel_community *community = &pctrl->communities[0]; in chv_gpio_add_pin_ranges()
1526 for (i = 0; i < community->ngpps; i++) { in chv_gpio_add_pin_ranges()
1527 gpp = &community->gpps[i]; in chv_gpio_add_pin_ranges()
1528 ret = gpiochip_add_pin_range(chip, dev_name(dev), gpp->base, gpp->base, gpp->size); in chv_gpio_add_pin_ranges()
1530 dev_err(dev, "failed to add GPIO pin range\n"); in chv_gpio_add_pin_ranges()
1540 const struct intel_community *community = &pctrl->communities[0]; in chv_gpio_probe()
1542 struct gpio_chip *chip = &pctrl->chip; in chv_gpio_probe()
1543 struct device *dev = pctrl->dev; in chv_gpio_probe()
1549 chip->ngpio = pctrl->soc->pins[pctrl->soc->npins - 1].number + 1; in chv_gpio_probe()
1550 chip->label = dev_name(dev); in chv_gpio_probe()
1551 chip->add_pin_ranges = chv_gpio_add_pin_ranges; in chv_gpio_probe()
1552 chip->parent = dev; in chv_gpio_probe()
1553 chip->base = -1; in chv_gpio_probe()
1555 pctrl->irq = irq; in chv_gpio_probe()
1557 gpio_irq_chip_set_chip(&chip->irq, &chv_gpio_irq_chip); in chv_gpio_probe()
1558 chip->irq.init_hw = chv_gpio_irq_init_hw; in chv_gpio_probe()
1559 chip->irq.parent_handler = chv_gpio_irq_handler; in chv_gpio_probe()
1560 chip->irq.num_parents = 1; in chv_gpio_probe()
1561 chip->irq.parents = &pctrl->irq; in chv_gpio_probe()
1562 chip->irq.default_type = IRQ_TYPE_NONE; in chv_gpio_probe()
1563 chip->irq.handler = handle_bad_irq; in chv_gpio_probe()
1565 chip->irq.init_valid_mask = chv_init_irq_valid_mask; in chv_gpio_probe()
1567 irq_base = devm_irq_alloc_descs(dev, -1, 0, pctrl->soc->npins, NUMA_NO_NODE); in chv_gpio_probe()
1581 for (i = 0; i < community->ngpps; i++) { in chv_gpio_probe()
1582 gpp = &community->gpps[i]; in chv_gpio_probe()
1584 irq_domain_associate_many(chip->irq.domain, irq_base, in chv_gpio_probe()
1585 gpp->base, gpp->size); in chv_gpio_probe()
1586 irq_base += gpp->size; in chv_gpio_probe()
1616 struct device *dev = &pdev->dev; in chv_pinctrl_probe()
1628 return -ENOMEM; in chv_pinctrl_probe()
1630 pctrl->dev = dev; in chv_pinctrl_probe()
1631 pctrl->soc = soc_data; in chv_pinctrl_probe()
1633 pctrl->ncommunities = pctrl->soc->ncommunities; in chv_pinctrl_probe()
1634 pctrl->communities = devm_kmemdup(dev, pctrl->soc->communities, in chv_pinctrl_probe()
1635 pctrl->ncommunities * sizeof(*pctrl->communities), in chv_pinctrl_probe()
1637 if (!pctrl->communities) in chv_pinctrl_probe()
1638 return -ENOMEM; in chv_pinctrl_probe()
1640 community = &pctrl->communities[0]; in chv_pinctrl_probe()
1641 community->regs = devm_platform_ioremap_resource(pdev, 0); in chv_pinctrl_probe()
1642 if (IS_ERR(community->regs)) in chv_pinctrl_probe()
1643 return PTR_ERR(community->regs); in chv_pinctrl_probe()
1645 community->pad_regs = community->regs + FAMILY_PAD_REGS_OFF; in chv_pinctrl_probe()
1648 pctrl->context.pads = devm_kcalloc(dev, pctrl->soc->npins, in chv_pinctrl_probe()
1649 sizeof(*pctrl->context.pads), in chv_pinctrl_probe()
1651 if (!pctrl->context.pads) in chv_pinctrl_probe()
1652 return -ENOMEM; in chv_pinctrl_probe()
1655 pctrl->context.communities = devm_kcalloc(dev, pctrl->soc->ncommunities, in chv_pinctrl_probe()
1656 sizeof(*pctrl->context.communities), in chv_pinctrl_probe()
1658 if (!pctrl->context.communities) in chv_pinctrl_probe()
1659 return -ENOMEM; in chv_pinctrl_probe()
1661 cctx = &pctrl->context.communities[0]; in chv_pinctrl_probe()
1662 for (i = 0; i < ARRAY_SIZE(cctx->intr_lines); i++) in chv_pinctrl_probe()
1663 cctx->intr_lines[i] = CHV_INVALID_HWIRQ; in chv_pinctrl_probe()
1669 pctrl->pctldesc = chv_pinctrl_desc; in chv_pinctrl_probe()
1670 pctrl->pctldesc.name = dev_name(dev); in chv_pinctrl_probe()
1671 pctrl->pctldesc.pins = pctrl->soc->pins; in chv_pinctrl_probe()
1672 pctrl->pctldesc.npins = pctrl->soc->npins; in chv_pinctrl_probe()
1674 pctrl->pctldev = devm_pinctrl_register(dev, &pctrl->pctldesc, pctrl); in chv_pinctrl_probe()
1675 if (IS_ERR(pctrl->pctldev)) { in chv_pinctrl_probe()
1677 return PTR_ERR(pctrl->pctldev); in chv_pinctrl_probe()
1685 community->acpi_space_id, in chv_pinctrl_probe()
1699 const struct intel_community *community = &pctrl->communities[0]; in chv_pinctrl_remove()
1701 acpi_remove_address_space_handler(ACPI_HANDLE(&pdev->dev), in chv_pinctrl_remove()
1702 community->acpi_space_id, in chv_pinctrl_remove()
1709 struct intel_community_context *cctx = &pctrl->context.communities[0]; in chv_pinctrl_suspend_noirq()
1714 cctx->saved_intmask = chv_pctrl_readl(pctrl, CHV_INTMASK); in chv_pinctrl_suspend_noirq()
1716 for (i = 0; i < pctrl->soc->npins; i++) { in chv_pinctrl_suspend_noirq()
1718 struct intel_pad_context *ctx = &pctrl->context.pads[i]; in chv_pinctrl_suspend_noirq()
1720 desc = &pctrl->soc->pins[i]; in chv_pinctrl_suspend_noirq()
1721 if (chv_pad_locked(pctrl, desc->number)) in chv_pinctrl_suspend_noirq()
1724 ctx->padctrl0 = chv_readl(pctrl, desc->number, CHV_PADCTRL0); in chv_pinctrl_suspend_noirq()
1725 ctx->padctrl0 &= ~CHV_PADCTRL0_GPIORXSTATE; in chv_pinctrl_suspend_noirq()
1727 ctx->padctrl1 = chv_readl(pctrl, desc->number, CHV_PADCTRL1); in chv_pinctrl_suspend_noirq()
1736 struct intel_community_context *cctx = &pctrl->context.communities[0]; in chv_pinctrl_resume_noirq()
1742 * Mask all interrupts before restoring per-pin configuration in chv_pinctrl_resume_noirq()
1748 for (i = 0; i < pctrl->soc->npins; i++) { in chv_pinctrl_resume_noirq()
1750 struct intel_pad_context *ctx = &pctrl->context.pads[i]; in chv_pinctrl_resume_noirq()
1753 desc = &pctrl->soc->pins[i]; in chv_pinctrl_resume_noirq()
1754 if (chv_pad_locked(pctrl, desc->number)) in chv_pinctrl_resume_noirq()
1758 val = chv_readl(pctrl, desc->number, CHV_PADCTRL0); in chv_pinctrl_resume_noirq()
1760 if (ctx->padctrl0 != val) { in chv_pinctrl_resume_noirq()
1761 chv_writel(pctrl, desc->number, CHV_PADCTRL0, ctx->padctrl0); in chv_pinctrl_resume_noirq()
1762 dev_dbg(dev, "restored pin %2u ctrl0 0x%08x\n", desc->number, in chv_pinctrl_resume_noirq()
1763 chv_readl(pctrl, desc->number, CHV_PADCTRL0)); in chv_pinctrl_resume_noirq()
1766 val = chv_readl(pctrl, desc->number, CHV_PADCTRL1); in chv_pinctrl_resume_noirq()
1767 if (ctx->padctrl1 != val) { in chv_pinctrl_resume_noirq()
1768 chv_writel(pctrl, desc->number, CHV_PADCTRL1, ctx->padctrl1); in chv_pinctrl_resume_noirq()
1769 dev_dbg(dev, "restored pin %2u ctrl1 0x%08x\n", desc->number, in chv_pinctrl_resume_noirq()
1770 chv_readl(pctrl, desc->number, CHV_PADCTRL1)); in chv_pinctrl_resume_noirq()
1779 chv_pctrl_writel(pctrl, CHV_INTMASK, cctx->saved_intmask); in chv_pinctrl_resume_noirq()
1797 .name = "cherryview-pinctrl",