diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c index 18fce75fe86c..e8b9a8e57149 100644 --- a/drivers/pinctrl/pinctrl-amd.c +++ b/drivers/pinctrl/pinctrl-amd.c @@ -42,6 +42,8 @@ static struct amd_gpio *pinctrl_dev; static inline void __iomem *amd_gpio_pin_reg(struct amd_gpio *gpio_dev, unsigned int pin) { + if (gpio_dev->base_rgpio && pin >= AMD_GPIO_RGPIO_PIN_BASE) + return gpio_dev->base_rgpio + (pin - AMD_GPIO_RGPIO_PIN_BASE) * 4; return gpio_dev->base + pin * 4; } @@ -244,6 +246,10 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc) i = 192; pin_num = AMD_GPIO_PINS_BANK3 + i; break; + case 4: + i = AMD_GPIO_RGPIO_PIN_BASE; + pin_num = AMD_GPIO_PINS_BANK4 + i; + break; default: /* Illegal bank number, ignore */ continue; @@ -676,6 +682,58 @@ static bool do_amd_gpio_irq_handler(int irq, void *dev_id) raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); } } + + /* + * Unlike WAKE_INT_STATUS_REG0/1, where each status bit covers four + * pins, the RGPIO status register uses one bit per pin. As with the + * main bank status registers, a bit is cleared by acknowledging the + * pending interrupt on its pin below (clearing PIN_IRQ_PENDING); no + * separate write to the RGPIO status register is required. + */ + if (gpio_dev->base_rgpio) { + u32 status_rgpio; + + raw_spin_lock_irqsave(&gpio_dev->lock, flags); + status_rgpio = readl(gpio_dev->base_rgpio + WAKE_INT_STATUS_REG_RGPIO); + raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); + + status_rgpio &= GENMASK(AMD_GPIO_PINS_BANK4 - 1, 0); + + for (i = 0; i < AMD_GPIO_PINS_BANK4; i++) { + unsigned int pin = AMD_GPIO_RGPIO_PIN_BASE + i; + + if (!(status_rgpio & BIT(i))) + continue; + + regval = readl(amd_gpio_pin_reg(gpio_dev, pin)); + + if (regval & PIN_IRQ_PENDING) + pm_pr_dbg("GPIO %d is active: 0x%x", pin, regval); + + /* caused wake on resume context for shared IRQ */ + if (irq < 0 && (regval & BIT(WAKE_STS_OFF))) + return true; + + if (!(regval & PIN_IRQ_PENDING) || + !(regval & BIT(INTERRUPT_MASK_OFF))) + continue; + generic_handle_domain_irq_safe(gc->irq.domain, pin); + + raw_spin_lock_irqsave(&gpio_dev->lock, flags); + regval = readl(amd_gpio_pin_reg(gpio_dev, pin)); + if (!gpiochip_line_is_irq(gc, pin)) { + regval &= ~BIT(INTERRUPT_MASK_OFF); + dev_dbg(&gpio_dev->pdev->dev, + "Disabling spurious GPIO IRQ %d\n", + pin); + } else { + ret = true; + } + writel(regval, amd_gpio_pin_reg(gpio_dev, pin)); + raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); + } + } + /* did not cause wake on resume context for shared IRQ */ if (irq < 0) return false; @@ -747,6 +805,9 @@ static int amd_pinconf_get(struct pinctrl_dev *pctldev, struct amd_gpio *gpio_dev = pinctrl_dev_get_drvdata(pctldev); enum pin_config_param param = pinconf_to_config_param(*config); + if (pin >= AMD_GPIO_RGPIO_PIN_BASE && !gpio_dev->base_rgpio) + return -EOPNOTSUPP; + raw_spin_lock_irqsave(&gpio_dev->lock, flags); pin_reg = readl(amd_gpio_pin_reg(gpio_dev, pin)); raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); @@ -789,6 +850,9 @@ static int amd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, enum pin_config_param param; struct amd_gpio *gpio_dev = pinctrl_dev_get_drvdata(pctldev); + if (pin >= AMD_GPIO_RGPIO_PIN_BASE && !gpio_dev->base_rgpio) + return -EOPNOTSUPP; + raw_spin_lock_irqsave(&gpio_dev->lock, flags); for (i = 0; i < num_configs; i++) { param = pinconf_to_config_param(configs[i]); @@ -898,6 +962,9 @@ static void amd_gpio_irq_init(struct amd_gpio *gpio_dev) if (!pd) continue; + if (pin >= AMD_GPIO_RGPIO_PIN_BASE && !gpio_dev->base_rgpio) + continue; + raw_spin_lock_irqsave(&gpio_dev->lock, flags); pin_reg = readl(amd_gpio_pin_reg(gpio_dev, pin)); @@ -922,6 +989,9 @@ static void amd_gpio_check_pending(void) int pin = desc->pins[i].number; u32 tmp; + if (pin >= AMD_GPIO_RGPIO_PIN_BASE && !gpio_dev->base_rgpio) + continue; + tmp = readl(amd_gpio_pin_reg(gpio_dev, pin)); if (tmp & PIN_IRQ_PENDING) pm_pr_dbg("%s: GPIO %d is active: 0x%x.\n", __func__, pin, tmp); @@ -1068,7 +1138,8 @@ static int amd_get_groups(struct pinctrl_dev *pctrldev, unsigned int selector, { struct amd_gpio *gpio_dev = pinctrl_dev_get_drvdata(pctrldev); - if (!gpio_dev->iomux_base) { + if (!gpio_dev->iomux_base && + pmx_functions[selector].index < AMD_GPIO_RGPIO_PIN_BASE) { dev_err(&gpio_dev->pdev->dev, "iomux function %d group not supported\n", selector); return -EINVAL; } @@ -1084,6 +1155,34 @@ static int amd_set_mux(struct pinctrl_dev *pctrldev, unsigned int function, unsi struct device *dev = &gpio_dev->pdev->dev; struct pin_desc *pd; int ind, index; + unsigned int pin = gpio_dev->groups[group].pins[0]; + + if (pin >= AMD_GPIO_RGPIO_PIN_BASE) { + if (!gpio_dev->base_rgpio) + return -EINVAL; + + for (index = 0; index < NSELECTS; index++) + if (!strcmp(gpio_dev->groups[group].name, + pmx_functions[function].groups[index])) + break; + if (index >= NSELECTS) + return -EINVAL; + + writeb(index, gpio_dev->base_rgpio + AMD_GPIO_RGPIO_MUX_OFFSET + + (pin - AMD_GPIO_RGPIO_PIN_BASE)); + + if (index != (readb(gpio_dev->base_rgpio + AMD_GPIO_RGPIO_MUX_OFFSET + + (pin - AMD_GPIO_RGPIO_PIN_BASE)) & FUNCTION_MASK)) { + dev_err(dev, "RGPIO_GPIO %u mux not present or supported\n", pin); + return -EINVAL; + } + + for (ind = 0; ind < gpio_dev->groups[group].npins; ind++) { + pd = pin_desc_get(gpio_dev->pctrl, gpio_dev->groups[group].pins[ind]); + pd->mux_owner = gpio_dev->groups[group].name; + } + return 0; + } if (!gpio_dev->iomux_base) return -EINVAL; @@ -1184,6 +1283,19 @@ static int amd_gpio_probe(struct platform_device *pdev) return PTR_ERR(gpio_dev->base); } + gpio_dev->base_rgpio = amd_get_named_res(&pdev->dev, pdev, "rgpio", + WAKE_INT_STATUS_REG_RGPIO + sizeof(u32)); + /* + * RGPIO pins are numbered from AMD_GPIO_RGPIO_PIN_BASE, so the main + * bank must span exactly that many register slots for the RGPIO pin + * numbering to line up. Disable RGPIO if the main bank is a different + * size. + */ + if (gpio_dev->base_rgpio && resource_size(res) / 4 != AMD_GPIO_RGPIO_PIN_BASE) { + dev_err(&pdev->dev, "unexpected GPIO bank size, disabling RGPIO\n"); + gpio_dev->base_rgpio = NULL; + } + gpio_dev->irq = platform_get_irq(pdev, 0); if (gpio_dev->irq < 0) return gpio_dev->irq; @@ -1210,14 +1322,17 @@ static int amd_gpio_probe(struct platform_device *pdev) gpio_dev->gc.owner = THIS_MODULE; gpio_dev->gc.parent = &pdev->dev; gpio_dev->gc.ngpio = resource_size(res) / 4; - gpio_dev->hwbank_num = gpio_dev->gc.ngpio / 64; + if (gpio_dev->base_rgpio) { + gpio_dev->gc.ngpio += AMD_GPIO_PINS_BANK4; + gpio_dev->hwbank_num++; + } gpio_dev->groups = kerncz_groups; gpio_dev->ngroups = ARRAY_SIZE(kerncz_groups); amd_pinctrl_desc.name = dev_name(&pdev->dev); gpio_dev->iomux_base = amd_get_named_res(&pdev->dev, pdev, "iomux", 0); - if (!gpio_dev->iomux_base) + if (!gpio_dev->iomux_base && !gpio_dev->base_rgpio) amd_pinctrl_desc.pmxops = NULL; gpio_dev->pctrl = devm_pinctrl_register(&pdev->dev, &amd_pinctrl_desc, gpio_dev); diff --git a/drivers/pinctrl/pinctrl-amd.h b/drivers/pinctrl/pinctrl-amd.h index 3a1e5bffaf6e..c602c4b648bd 100644 --- a/drivers/pinctrl/pinctrl-amd.h +++ b/drivers/pinctrl/pinctrl-amd.h @@ -15,6 +15,18 @@ #define AMD_GPIO_PINS_BANK1 64 #define AMD_GPIO_PINS_BANK2 56 #define AMD_GPIO_PINS_BANK3 32 +#define AMD_GPIO_PINS_BANK4 16 + +/* + * Remote GPIO (RGPIO) is a second GPIO bank on some AMD platforms. Firmware + * advertises its register region as an optional resource named "rgpio" (via + * the pinctrl-resource-names _DSD property). Relative to that region's base, + * RGPIO pin AMD_GPIO_RGPIO_PIN_BASE + n uses a per-pin control register at + * n * 4, a pinmux selector byte at AMD_GPIO_RGPIO_MUX_OFFSET + n, and one + * interrupt status bit (bit n) in WAKE_INT_STATUS_REG_RGPIO. + */ +#define AMD_GPIO_RGPIO_PIN_BASE 256 +#define AMD_GPIO_RGPIO_MUX_OFFSET 0xC0 #define WAKE_INT_MASTER_REG 0xfc #define INTERNAL_GPIO0_DEBOUNCE (1 << 15) @@ -22,6 +34,7 @@ #define WAKE_INT_STATUS_REG0 0x2f8 #define WAKE_INT_STATUS_REG1 0x2fc +#define WAKE_INT_STATUS_REG_RGPIO 0x0F4 #define DB_TMR_OUT_OFF 0 #define DB_TMR_OUT_UNIT_OFF 4 @@ -94,6 +107,7 @@ struct amd_function { struct amd_gpio { raw_spinlock_t lock; void __iomem *base; + void __iomem *base_rgpio; void __iomem *iomux_base; const struct pingroup *groups; @@ -292,6 +306,22 @@ static const struct pinctrl_pin_desc kerncz_pins[] = { PINCTRL_PIN(181, "GPIO_181"), PINCTRL_PIN(182, "GPIO_182"), PINCTRL_PIN(183, "GPIO_183"), + PINCTRL_PIN(256, "GPIO_256"), + PINCTRL_PIN(257, "GPIO_257"), + PINCTRL_PIN(258, "GPIO_258"), + PINCTRL_PIN(259, "GPIO_259"), + PINCTRL_PIN(260, "GPIO_260"), + PINCTRL_PIN(261, "GPIO_261"), + PINCTRL_PIN(262, "GPIO_262"), + PINCTRL_PIN(263, "GPIO_263"), + PINCTRL_PIN(264, "GPIO_264"), + PINCTRL_PIN(265, "GPIO_265"), + PINCTRL_PIN(266, "GPIO_266"), + PINCTRL_PIN(267, "GPIO_267"), + PINCTRL_PIN(268, "GPIO_268"), + PINCTRL_PIN(269, "GPIO_269"), + PINCTRL_PIN(270, "GPIO_270"), + PINCTRL_PIN(271, "GPIO_271"), }; #define AMD_PINS(...) (const unsigned int []){__VA_ARGS__} @@ -873,6 +903,70 @@ enum amd_functions { IMX_F1_GPIO144, IMX_F2_GPIO144, IMX_F3_GPIO144, + IMX_F0_GPIO256, + IMX_F1_GPIO256, + IMX_F2_GPIO256, + IMX_F3_GPIO256, + IMX_F0_GPIO257, + IMX_F1_GPIO257, + IMX_F2_GPIO257, + IMX_F3_GPIO257, + IMX_F0_GPIO258, + IMX_F1_GPIO258, + IMX_F2_GPIO258, + IMX_F3_GPIO258, + IMX_F0_GPIO259, + IMX_F1_GPIO259, + IMX_F2_GPIO259, + IMX_F3_GPIO259, + IMX_F0_GPIO260, + IMX_F1_GPIO260, + IMX_F2_GPIO260, + IMX_F3_GPIO260, + IMX_F0_GPIO261, + IMX_F1_GPIO261, + IMX_F2_GPIO261, + IMX_F3_GPIO261, + IMX_F0_GPIO262, + IMX_F1_GPIO262, + IMX_F2_GPIO262, + IMX_F3_GPIO262, + IMX_F0_GPIO263, + IMX_F1_GPIO263, + IMX_F2_GPIO263, + IMX_F3_GPIO263, + IMX_F0_GPIO264, + IMX_F1_GPIO264, + IMX_F2_GPIO264, + IMX_F3_GPIO264, + IMX_F0_GPIO265, + IMX_F1_GPIO265, + IMX_F2_GPIO265, + IMX_F3_GPIO265, + IMX_F0_GPIO266, + IMX_F1_GPIO266, + IMX_F2_GPIO266, + IMX_F3_GPIO266, + IMX_F0_GPIO267, + IMX_F1_GPIO267, + IMX_F2_GPIO267, + IMX_F3_GPIO267, + IMX_F0_GPIO268, + IMX_F1_GPIO268, + IMX_F2_GPIO268, + IMX_F3_GPIO268, + IMX_F0_GPIO269, + IMX_F1_GPIO269, + IMX_F2_GPIO269, + IMX_F3_GPIO269, + IMX_F0_GPIO270, + IMX_F1_GPIO270, + IMX_F2_GPIO270, + IMX_F3_GPIO270, + IMX_F0_GPIO271, + IMX_F1_GPIO271, + IMX_F2_GPIO271, + IMX_F3_GPIO271, }; #define AMD_PINCTRL_FUNC_GRP(_number, _func) \ @@ -1456,6 +1550,70 @@ static const struct pingroup kerncz_groups[] = { AMD_PINCTRL_FUNC_GRP(144, 1), AMD_PINCTRL_FUNC_GRP(144, 2), AMD_PINCTRL_FUNC_GRP(144, 3), + AMD_PINCTRL_FUNC_GRP(256, 0), + AMD_PINCTRL_FUNC_GRP(256, 1), + AMD_PINCTRL_FUNC_GRP(256, 2), + AMD_PINCTRL_FUNC_GRP(256, 3), + AMD_PINCTRL_FUNC_GRP(257, 0), + AMD_PINCTRL_FUNC_GRP(257, 1), + AMD_PINCTRL_FUNC_GRP(257, 2), + AMD_PINCTRL_FUNC_GRP(257, 3), + AMD_PINCTRL_FUNC_GRP(258, 0), + AMD_PINCTRL_FUNC_GRP(258, 1), + AMD_PINCTRL_FUNC_GRP(258, 2), + AMD_PINCTRL_FUNC_GRP(258, 3), + AMD_PINCTRL_FUNC_GRP(259, 0), + AMD_PINCTRL_FUNC_GRP(259, 1), + AMD_PINCTRL_FUNC_GRP(259, 2), + AMD_PINCTRL_FUNC_GRP(259, 3), + AMD_PINCTRL_FUNC_GRP(260, 0), + AMD_PINCTRL_FUNC_GRP(260, 1), + AMD_PINCTRL_FUNC_GRP(260, 2), + AMD_PINCTRL_FUNC_GRP(260, 3), + AMD_PINCTRL_FUNC_GRP(261, 0), + AMD_PINCTRL_FUNC_GRP(261, 1), + AMD_PINCTRL_FUNC_GRP(261, 2), + AMD_PINCTRL_FUNC_GRP(261, 3), + AMD_PINCTRL_FUNC_GRP(262, 0), + AMD_PINCTRL_FUNC_GRP(262, 1), + AMD_PINCTRL_FUNC_GRP(262, 2), + AMD_PINCTRL_FUNC_GRP(262, 3), + AMD_PINCTRL_FUNC_GRP(263, 0), + AMD_PINCTRL_FUNC_GRP(263, 1), + AMD_PINCTRL_FUNC_GRP(263, 2), + AMD_PINCTRL_FUNC_GRP(263, 3), + AMD_PINCTRL_FUNC_GRP(264, 0), + AMD_PINCTRL_FUNC_GRP(264, 1), + AMD_PINCTRL_FUNC_GRP(264, 2), + AMD_PINCTRL_FUNC_GRP(264, 3), + AMD_PINCTRL_FUNC_GRP(265, 0), + AMD_PINCTRL_FUNC_GRP(265, 1), + AMD_PINCTRL_FUNC_GRP(265, 2), + AMD_PINCTRL_FUNC_GRP(265, 3), + AMD_PINCTRL_FUNC_GRP(266, 0), + AMD_PINCTRL_FUNC_GRP(266, 1), + AMD_PINCTRL_FUNC_GRP(266, 2), + AMD_PINCTRL_FUNC_GRP(266, 3), + AMD_PINCTRL_FUNC_GRP(267, 0), + AMD_PINCTRL_FUNC_GRP(267, 1), + AMD_PINCTRL_FUNC_GRP(267, 2), + AMD_PINCTRL_FUNC_GRP(267, 3), + AMD_PINCTRL_FUNC_GRP(268, 0), + AMD_PINCTRL_FUNC_GRP(268, 1), + AMD_PINCTRL_FUNC_GRP(268, 2), + AMD_PINCTRL_FUNC_GRP(268, 3), + AMD_PINCTRL_FUNC_GRP(269, 0), + AMD_PINCTRL_FUNC_GRP(269, 1), + AMD_PINCTRL_FUNC_GRP(269, 2), + AMD_PINCTRL_FUNC_GRP(269, 3), + AMD_PINCTRL_FUNC_GRP(270, 0), + AMD_PINCTRL_FUNC_GRP(270, 1), + AMD_PINCTRL_FUNC_GRP(270, 2), + AMD_PINCTRL_FUNC_GRP(270, 3), + AMD_PINCTRL_FUNC_GRP(271, 0), + AMD_PINCTRL_FUNC_GRP(271, 1), + AMD_PINCTRL_FUNC_GRP(271, 2), + AMD_PINCTRL_FUNC_GRP(271, 3), PINCTRL_PINGROUP("i2c0", AMD_PINS(145, 146), 2), PINCTRL_PINGROUP("i2c1", AMD_PINS(147, 148), 2), @@ -1620,6 +1778,22 @@ static const struct amd_function pmx_functions[] = { AMD_PMUX_FUNC(142), AMD_PMUX_FUNC(143), AMD_PMUX_FUNC(144), + AMD_PMUX_FUNC(256), + AMD_PMUX_FUNC(257), + AMD_PMUX_FUNC(258), + AMD_PMUX_FUNC(259), + AMD_PMUX_FUNC(260), + AMD_PMUX_FUNC(261), + AMD_PMUX_FUNC(262), + AMD_PMUX_FUNC(263), + AMD_PMUX_FUNC(264), + AMD_PMUX_FUNC(265), + AMD_PMUX_FUNC(266), + AMD_PMUX_FUNC(267), + AMD_PMUX_FUNC(268), + AMD_PMUX_FUNC(269), + AMD_PMUX_FUNC(270), + AMD_PMUX_FUNC(271), }; #endif