diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-11-04 08:15:19 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-11-04 08:15:19 +0300 |
commit | 90b0c2b2edd1adff742c621e246562fbefa11b70 (patch) | |
tree | f9e877c51959e1c4a96379b15acd50fe28587aad /drivers/pinctrl/intel/pinctrl-intel.c | |
parent | be47c8e326c2375200473e442f3481c386a955c4 (diff) | |
parent | 63bffc2d3a99eaabc786c513eea71be3f597f175 (diff) | |
download | linux-90b0c2b2edd1adff742c621e246562fbefa11b70.tar.xz |
Merge tag 'pinctrl-v6.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl
Pull pin control updates from Linus Walleij:
"No pin control core changes this time.
New drivers:
- Realtek RTD family pin control driver and RTD1619B, RTD1319D and
RTD1315E subdrivers
- Nuvoton NPCM8xx combined pin control and GPIO driver
- Amlogic T7 pin control driver
- Renesas RZ/G3S pin control driver
Improvements:
- A number of additional UART groups added to the Mediatek MT7981
driver
- MPM pin maps added for Qualcomm MSM8996, SM6115, SM6125 and SDM660
- Extra GPIO banks for the Sunxi H616
- MLSP I2C6 function support in Qualcomm MSM8226
- Some __counted_by() annotations for dynamic arrays
- Ongoing work to make remove() return void
- LSBC groups and functions in the Renesas R8A7778"
* tag 'pinctrl-v6.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (110 commits)
pinctrl: Use device_get_match_data()
dt-bindings: pinctrl: qcom,sa8775p-tlmm: add missing wakeup-parent
dt-bindings: pinctrl: nuvoton,npcm845: Add missing additionalProperties on gpio child nodes
dt-bindings: pinctrl: brcm: Ensure all child node properties are documented
pinctrl: renesas: rzn1: Convert to platform remove callback returning void
pinctrl: renesas: rzg2l: Add RZ/G3S support
dt-bindings: pinctrl: renesas: Document RZ/G3S SoC
pinctrl: renesas: rzg2l: Add support for different DS values on different groups
pinctrl: renesas: rzg2l: Move DS and OI to SoC-specific configuration
pinctrl: renesas: rzg2l: Adapt function number for RZ/G3S
pinctrl: renesas: rzg2l: Adapt for different SD/PWPR register offsets
pinctrl: renesas: rzg2l: Index all registers based on port offset
pinctrl: renesas: rzg2l: Add validation of GPIO pin in rzg2l_gpio_request()
pinctrl: renesas: r8a7778: Add LBSC pins, groups, and functions
pinctrl: intel: fetch community only when we need it
pinctrl: cherryview: reduce scope of PIN_CONFIG_BIAS_HIGH_IMPEDANCE case
pinctrl: cherryview: Convert to platform remove callback returning void
pinctrl: sprd-sc9860: Convert to platform remove callback returning void
pinctrl: qcom/msm: Convert to platform remove callback returning void
pinctrl: qcom/lpi: Convert to platform remove callback returning void
...
Diffstat (limited to 'drivers/pinctrl/intel/pinctrl-intel.c')
-rw-r--r-- | drivers/pinctrl/intel/pinctrl-intel.c | 194 |
1 files changed, 81 insertions, 113 deletions
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index 999f453344d2..b19527a8728e 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -8,6 +8,7 @@ */ #include <linux/acpi.h> +#include <linux/cleanup.h> #include <linux/gpio/driver.h> #include <linux/interrupt.h> #include <linux/log2.h> @@ -393,20 +394,17 @@ static int intel_pinmux_set_mux(struct pinctrl_dev *pctldev, { struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); const struct intel_pingroup *grp = &pctrl->soc->groups[group]; - unsigned long flags; int i; - raw_spin_lock_irqsave(&pctrl->lock, flags); + guard(raw_spinlock_irqsave)(&pctrl->lock); /* * All pins in the groups needs to be accessible and writable * before we can enable the mux for this group. */ for (i = 0; i < grp->grp.npins; i++) { - if (!intel_pad_usable(pctrl, grp->grp.pins[i])) { - raw_spin_unlock_irqrestore(&pctrl->lock, flags); + if (!intel_pad_usable(pctrl, grp->grp.pins[i])) return -EBUSY; - } } /* Now enable the mux setting for each pin in the group */ @@ -428,8 +426,6 @@ static int intel_pinmux_set_mux(struct pinctrl_dev *pctldev, writel(value, padcfg0); } - raw_spin_unlock_irqrestore(&pctrl->lock, flags); - return 0; } @@ -485,21 +481,16 @@ static int intel_gpio_request_enable(struct pinctrl_dev *pctldev, { struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); void __iomem *padcfg0; - unsigned long flags; padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0); - raw_spin_lock_irqsave(&pctrl->lock, flags); + guard(raw_spinlock_irqsave)(&pctrl->lock); - if (!intel_pad_owned_by_host(pctrl, pin)) { - raw_spin_unlock_irqrestore(&pctrl->lock, flags); + if (!intel_pad_owned_by_host(pctrl, pin)) return -EBUSY; - } - if (!intel_pad_is_unlocked(pctrl, pin)) { - raw_spin_unlock_irqrestore(&pctrl->lock, flags); + if (!intel_pad_is_unlocked(pctrl, pin)) return 0; - } /* * If pin is already configured in GPIO mode, we assume that @@ -507,15 +498,11 @@ static int intel_gpio_request_enable(struct pinctrl_dev *pctldev, * potential glitches on the pin. Otherwise, for the pin in * alternative mode, consumer has to supply respective flags. */ - if (intel_gpio_get_gpio_mode(padcfg0) == PADCFG0_PMODE_GPIO) { - raw_spin_unlock_irqrestore(&pctrl->lock, flags); + if (intel_gpio_get_gpio_mode(padcfg0) == PADCFG0_PMODE_GPIO) return 0; - } intel_gpio_set_gpio_mode(padcfg0); - raw_spin_unlock_irqrestore(&pctrl->lock, flags); - return 0; } @@ -525,13 +512,12 @@ static int intel_gpio_set_direction(struct pinctrl_dev *pctldev, { struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); void __iomem *padcfg0; - unsigned long flags; padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0); - raw_spin_lock_irqsave(&pctrl->lock, flags); + guard(raw_spinlock_irqsave)(&pctrl->lock); + __intel_gpio_set_direction(padcfg0, input); - raw_spin_unlock_irqrestore(&pctrl->lock, flags); return 0; } @@ -548,17 +534,13 @@ static const struct pinmux_ops intel_pinmux_ops = { static int intel_config_get_pull(struct intel_pinctrl *pctrl, unsigned int pin, enum pin_config_param param, u32 *arg) { - const struct intel_community *community; void __iomem *padcfg1; - unsigned long flags; u32 value, term; - community = intel_get_community(pctrl, pin); padcfg1 = intel_get_padcfg(pctrl, pin, PADCFG1); - raw_spin_lock_irqsave(&pctrl->lock, flags); - value = readl(padcfg1); - raw_spin_unlock_irqrestore(&pctrl->lock, flags); + scoped_guard(raw_spinlock_irqsave, &pctrl->lock) + value = readl(padcfg1); term = (value & PADCFG1_TERM_MASK) >> PADCFG1_TERM_SHIFT; @@ -592,7 +574,9 @@ static int intel_config_get_pull(struct intel_pinctrl *pctrl, unsigned int pin, break; - case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_BIAS_PULL_DOWN: { + const struct intel_community *community = intel_get_community(pctrl, pin); + if (!term || value & PADCFG1_TERM_UP) return -EINVAL; @@ -619,6 +603,7 @@ static int intel_config_get_pull(struct intel_pinctrl *pctrl, unsigned int pin, } break; + } default: return -EINVAL; @@ -631,7 +616,6 @@ static int intel_config_get_debounce(struct intel_pinctrl *pctrl, unsigned int p enum pin_config_param param, u32 *arg) { void __iomem *padcfg2; - unsigned long flags; unsigned long v; u32 value2; @@ -639,9 +623,9 @@ static int intel_config_get_debounce(struct intel_pinctrl *pctrl, unsigned int p if (!padcfg2) return -ENOTSUPP; - raw_spin_lock_irqsave(&pctrl->lock, flags); - value2 = readl(padcfg2); - raw_spin_unlock_irqrestore(&pctrl->lock, flags); + scoped_guard(raw_spinlock_irqsave, &pctrl->lock) + value2 = readl(padcfg2); + if (!(value2 & PADCFG2_DEBEN)) return -EINVAL; @@ -690,19 +674,8 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned int pin, { unsigned int param = pinconf_to_config_param(config); unsigned int arg = pinconf_to_config_argument(config); - const struct intel_community *community; + u32 term = 0, up = 0, value; void __iomem *padcfg1; - unsigned long flags; - int ret = 0; - u32 value; - - community = intel_get_community(pctrl, pin); - padcfg1 = intel_get_padcfg(pctrl, pin, PADCFG1); - - raw_spin_lock_irqsave(&pctrl->lock, flags); - - value = readl(padcfg1); - value &= ~(PADCFG1_TERM_MASK | PADCFG1_TERM_UP); /* Set default strength value in case none is given */ if (arg == 1) @@ -715,78 +688,77 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned int pin, case PIN_CONFIG_BIAS_PULL_UP: switch (arg) { case 20000: - value |= PADCFG1_TERM_20K << PADCFG1_TERM_SHIFT; + term = PADCFG1_TERM_20K; break; case 5000: - value |= PADCFG1_TERM_5K << PADCFG1_TERM_SHIFT; + term = PADCFG1_TERM_5K; break; case 4000: - value |= PADCFG1_TERM_4K << PADCFG1_TERM_SHIFT; + term = PADCFG1_TERM_4K; break; case 1000: - value |= PADCFG1_TERM_1K << PADCFG1_TERM_SHIFT; + term = PADCFG1_TERM_1K; break; case 833: - value |= PADCFG1_TERM_833 << PADCFG1_TERM_SHIFT; + term = PADCFG1_TERM_833; break; default: - ret = -EINVAL; - break; + return -EINVAL; } - value |= PADCFG1_TERM_UP; + up = PADCFG1_TERM_UP; break; - case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_BIAS_PULL_DOWN: { + const struct intel_community *community = intel_get_community(pctrl, pin); + switch (arg) { case 20000: - value |= PADCFG1_TERM_20K << PADCFG1_TERM_SHIFT; + term = PADCFG1_TERM_20K; break; case 5000: - value |= PADCFG1_TERM_5K << PADCFG1_TERM_SHIFT; + term = PADCFG1_TERM_5K; break; case 4000: - value |= PADCFG1_TERM_4K << PADCFG1_TERM_SHIFT; + term = PADCFG1_TERM_4K; break; case 1000: - if (!(community->features & PINCTRL_FEATURE_1K_PD)) { - ret = -EINVAL; - break; - } - value |= PADCFG1_TERM_1K << PADCFG1_TERM_SHIFT; + if (!(community->features & PINCTRL_FEATURE_1K_PD)) + return -EINVAL; + term = PADCFG1_TERM_1K; break; case 833: - if (!(community->features & PINCTRL_FEATURE_1K_PD)) { - ret = -EINVAL; - break; - } - value |= PADCFG1_TERM_833 << PADCFG1_TERM_SHIFT; + if (!(community->features & PINCTRL_FEATURE_1K_PD)) + return -EINVAL; + term = PADCFG1_TERM_833; break; default: - ret = -EINVAL; - break; + return -EINVAL; } break; + } default: - ret = -EINVAL; - break; + return -EINVAL; } - if (!ret) - writel(value, padcfg1); + padcfg1 = intel_get_padcfg(pctrl, pin, PADCFG1); - raw_spin_unlock_irqrestore(&pctrl->lock, flags); + guard(raw_spinlock_irqsave)(&pctrl->lock); - return ret; + value = readl(padcfg1); + value = (value & ~PADCFG1_TERM_MASK) | (term << PADCFG1_TERM_SHIFT); + value = (value & ~PADCFG1_TERM_UP) | up; + writel(value, padcfg1); + + return 0; } static int intel_config_set_debounce(struct intel_pinctrl *pctrl, unsigned int pin, unsigned int debounce) { void __iomem *padcfg0, *padcfg2; - unsigned long flags; u32 value0, value2; padcfg2 = intel_get_padcfg(pctrl, pin, PADCFG2); @@ -795,7 +767,7 @@ static int intel_config_set_debounce(struct intel_pinctrl *pctrl, padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0); - raw_spin_lock_irqsave(&pctrl->lock, flags); + guard(raw_spinlock_irqsave)(&pctrl->lock); value0 = readl(padcfg0); value2 = readl(padcfg2); @@ -808,10 +780,8 @@ static int intel_config_set_debounce(struct intel_pinctrl *pctrl, unsigned long v; v = order_base_2(debounce * NSEC_PER_USEC / DEBOUNCE_PERIOD_NSEC); - if (v < 3 || v > 15) { - raw_spin_unlock_irqrestore(&pctrl->lock, flags); + if (v < 3 || v > 15) return -EINVAL; - } /* Enable glitch filter and debouncer */ value0 |= PADCFG0_PREGFRXSEL; @@ -822,8 +792,6 @@ static int intel_config_set_debounce(struct intel_pinctrl *pctrl, writel(value0, padcfg0); writel(value2, padcfg2); - raw_spin_unlock_irqrestore(&pctrl->lock, flags); - return 0; } @@ -973,7 +941,6 @@ static void intel_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) { struct intel_pinctrl *pctrl = gpiochip_get_data(chip); - unsigned long flags; void __iomem *reg; u32 padcfg0; int pin; @@ -986,20 +953,19 @@ static void intel_gpio_set(struct gpio_chip *chip, unsigned int offset, if (!reg) return; - raw_spin_lock_irqsave(&pctrl->lock, flags); + guard(raw_spinlock_irqsave)(&pctrl->lock); + padcfg0 = readl(reg); if (value) padcfg0 |= PADCFG0_GPIOTXSTATE; else padcfg0 &= ~PADCFG0_GPIOTXSTATE; writel(padcfg0, reg); - raw_spin_unlock_irqrestore(&pctrl->lock, flags); } static int intel_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) { struct intel_pinctrl *pctrl = gpiochip_get_data(chip); - unsigned long flags; void __iomem *reg; u32 padcfg0; int pin; @@ -1012,9 +978,9 @@ static int intel_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) if (!reg) return -EINVAL; - raw_spin_lock_irqsave(&pctrl->lock, flags); - padcfg0 = readl(reg); - raw_spin_unlock_irqrestore(&pctrl->lock, flags); + scoped_guard(raw_spinlock_irqsave, &pctrl->lock) + padcfg0 = readl(reg); + if (padcfg0 & PADCFG0_PMODE_MASK) return -EINVAL; @@ -1058,15 +1024,17 @@ static void intel_gpio_irq_ack(struct irq_data *d) pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), &community, &padgrp); if (pin >= 0) { - unsigned int gpp, gpp_offset, is_offset; + unsigned int gpp, gpp_offset; + void __iomem *is; gpp = padgrp->reg_num; gpp_offset = padgroup_offset(padgrp, pin); - is_offset = community->is_offset + gpp * 4; - raw_spin_lock(&pctrl->lock); - writel(BIT(gpp_offset), community->regs + is_offset); - raw_spin_unlock(&pctrl->lock); + is = community->regs + community->is_offset + gpp * 4; + + guard(raw_spinlock)(&pctrl->lock); + + writel(BIT(gpp_offset), is); } } @@ -1080,7 +1048,6 @@ static void intel_gpio_irq_mask_unmask(struct gpio_chip *gc, irq_hw_number_t hwi pin = intel_gpio_to_pin(pctrl, hwirq, &community, &padgrp); if (pin >= 0) { unsigned int gpp, gpp_offset; - unsigned long flags; void __iomem *reg, *is; u32 value; @@ -1090,7 +1057,7 @@ static void intel_gpio_irq_mask_unmask(struct gpio_chip *gc, irq_hw_number_t hwi reg = community->regs + community->ie_offset + gpp * 4; is = community->regs + community->is_offset + gpp * 4; - raw_spin_lock_irqsave(&pctrl->lock, flags); + guard(raw_spinlock_irqsave)(&pctrl->lock); /* Clear interrupt status first to avoid unexpected interrupt */ writel(BIT(gpp_offset), is); @@ -1101,7 +1068,6 @@ static void intel_gpio_irq_mask_unmask(struct gpio_chip *gc, irq_hw_number_t hwi else value |= BIT(gpp_offset); writel(value, reg); - raw_spin_unlock_irqrestore(&pctrl->lock, flags); } } @@ -1129,7 +1095,6 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned int type) struct intel_pinctrl *pctrl = gpiochip_get_data(gc); unsigned int pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL); u32 rxevcfg, rxinv, value; - unsigned long flags; void __iomem *reg; reg = intel_get_padcfg(pctrl, pin, PADCFG0); @@ -1163,7 +1128,7 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned int type) else rxinv = 0; - raw_spin_lock_irqsave(&pctrl->lock, flags); + guard(raw_spinlock_irqsave)(&pctrl->lock); intel_gpio_set_gpio_mode(reg); @@ -1179,8 +1144,6 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned int type) else if (type & IRQ_TYPE_LEVEL_MASK) irq_set_handler_locked(d, handle_level_irq); - raw_spin_unlock_irqrestore(&pctrl->lock, flags); - return 0; } @@ -1219,16 +1182,19 @@ static int intel_gpio_community_irq_handler(struct intel_pinctrl *pctrl, for (gpp = 0; gpp < community->ngpps; gpp++) { const struct intel_padgroup *padgrp = &community->gpps[gpp]; - unsigned long pending, enabled, gpp_offset; + unsigned long pending, enabled; + unsigned int gpp, gpp_offset; + void __iomem *reg, *is; - raw_spin_lock(&pctrl->lock); + gpp = padgrp->reg_num; - pending = readl(community->regs + community->is_offset + - padgrp->reg_num * 4); - enabled = readl(community->regs + community->ie_offset + - padgrp->reg_num * 4); + reg = community->regs + community->ie_offset + gpp * 4; + is = community->regs + community->is_offset + gpp * 4; - raw_spin_unlock(&pctrl->lock); + scoped_guard(raw_spinlock, &pctrl->lock) { + pending = readl(is); + enabled = readl(reg); + } /* Only interrupts that are enabled */ pending &= enabled; @@ -1264,16 +1230,18 @@ static void intel_gpio_irq_init(struct intel_pinctrl *pctrl) for (i = 0; i < pctrl->ncommunities; i++) { const struct intel_community *community; - void __iomem *base; + void __iomem *reg, *is; unsigned int gpp; community = &pctrl->communities[i]; - base = community->regs; for (gpp = 0; gpp < community->ngpps; gpp++) { + reg = community->regs + community->ie_offset + gpp * 4; + is = community->regs + community->is_offset + gpp * 4; + /* Mask and clear all interrupts */ - writel(0, base + community->ie_offset + gpp * 4); - writel(0xffff, base + community->is_offset + gpp * 4); + writel(0, reg); + writel(0xffff, is); } } } |