Commit 3e5832e9 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pinctrl-v5.17-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl

Pull pin control fixes from Linus Walleij:
 "Most interesting and urgent is the Intel stuff affecting Chromebooks
  and laptops.

   - Fix up group name building on the Intel Thunderbay

   - Fix interrupt problems on the Intel Cherryview

   - Fix some pin data on the Sunxi H616

   - Fix up the CONFIG_PINCTRL_ST Kconfig sort order as noted during the
     merge window

   - Fix an unexpected interrupt problem on the Intel Sunrisepoint

   - Fix a glitch when updating IRQ flags on all Intel pin controllers

   - Revert a Zynqmp patch to unify the pin naming, let's find some
     better solution

   - Fix some error paths in the Broadcom BCM2835 driver

   - Fix a Kconfig problem pertaining to the BCM63XX drivers

   - Fix the regmap support in the Microchip SGPIO driver"

* tag 'pinctrl-v5.17-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl:
  pinctrl: microchip-sgpio: Fix support for regmap
  pinctrl: bcm63xx: fix unmet dependency on REGMAP for GPIO_REGMAP
  pinctrl: bcm2835: Fix a few error paths
  pinctrl: zynqmp: Revert "Unify pin naming"
  pinctrl: intel: Fix a glitch when updating IRQ flags on a preconfigured line
  pinctrl: intel: fix unexpected interrupt
  pinctrl: Place correctly CONFIG_PINCTRL_ST in the Makefile
  pinctrl: sunxi: Fix H616 I2S3 pin data
  pinctrl: cherryview: Trigger hwirq0 for interrupt-lines without a mapping
  pinctrl: thunderbay: rework loops looking for groups names
  pinctrl: thunderbay: comment process of building functions a bit
parents 9f7fb8de baf927a8
...@@ -42,9 +42,9 @@ obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o ...@@ -42,9 +42,9 @@ obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o
obj-$(CONFIG_PINCTRL_RK805) += pinctrl-rk805.o obj-$(CONFIG_PINCTRL_RK805) += pinctrl-rk805.o
obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o
obj-$(CONFIG_PINCTRL_STARFIVE) += pinctrl-starfive.o obj-$(CONFIG_PINCTRL_STARFIVE) += pinctrl-starfive.o
obj-$(CONFIG_PINCTRL_STMFX) += pinctrl-stmfx.o obj-$(CONFIG_PINCTRL_STMFX) += pinctrl-stmfx.o
obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o
obj-$(CONFIG_PINCTRL_SX150X) += pinctrl-sx150x.o obj-$(CONFIG_PINCTRL_SX150X) += pinctrl-sx150x.o
obj-$(CONFIG_PINCTRL_TB10X) += pinctrl-tb10x.o obj-$(CONFIG_PINCTRL_TB10X) += pinctrl-tb10x.o
obj-$(CONFIG_PINCTRL_THUNDERBAY) += pinctrl-thunderbay.o obj-$(CONFIG_PINCTRL_THUNDERBAY) += pinctrl-thunderbay.o
......
...@@ -35,6 +35,7 @@ config PINCTRL_BCM63XX ...@@ -35,6 +35,7 @@ config PINCTRL_BCM63XX
select PINCONF select PINCONF
select GENERIC_PINCONF select GENERIC_PINCONF
select GPIOLIB select GPIOLIB
select REGMAP
select GPIO_REGMAP select GPIO_REGMAP
config PINCTRL_BCM6318 config PINCTRL_BCM6318
......
...@@ -1269,16 +1269,18 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) ...@@ -1269,16 +1269,18 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
sizeof(*girq->parents), sizeof(*girq->parents),
GFP_KERNEL); GFP_KERNEL);
if (!girq->parents) { if (!girq->parents) {
pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range); err = -ENOMEM;
return -ENOMEM; goto out_remove;
} }
if (is_7211) { if (is_7211) {
pc->wake_irq = devm_kcalloc(dev, BCM2835_NUM_IRQS, pc->wake_irq = devm_kcalloc(dev, BCM2835_NUM_IRQS,
sizeof(*pc->wake_irq), sizeof(*pc->wake_irq),
GFP_KERNEL); GFP_KERNEL);
if (!pc->wake_irq) if (!pc->wake_irq) {
return -ENOMEM; err = -ENOMEM;
goto out_remove;
}
} }
/* /*
...@@ -1306,8 +1308,10 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) ...@@ -1306,8 +1308,10 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
len = strlen(dev_name(pc->dev)) + 16; len = strlen(dev_name(pc->dev)) + 16;
name = devm_kzalloc(pc->dev, len, GFP_KERNEL); name = devm_kzalloc(pc->dev, len, GFP_KERNEL);
if (!name) if (!name) {
return -ENOMEM; err = -ENOMEM;
goto out_remove;
}
snprintf(name, len, "%s:bank%d", dev_name(pc->dev), i); snprintf(name, len, "%s:bank%d", dev_name(pc->dev), i);
...@@ -1326,11 +1330,14 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) ...@@ -1326,11 +1330,14 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
err = gpiochip_add_data(&pc->gpio_chip, pc); err = gpiochip_add_data(&pc->gpio_chip, pc);
if (err) { if (err) {
dev_err(dev, "could not add GPIO chip\n"); dev_err(dev, "could not add GPIO chip\n");
pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range); goto out_remove;
return err;
} }
return 0; return 0;
out_remove:
pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range);
return err;
} }
static struct platform_driver bcm2835_pinctrl_driver = { static struct platform_driver bcm2835_pinctrl_driver = {
......
...@@ -1471,8 +1471,9 @@ static void chv_gpio_irq_handler(struct irq_desc *desc) ...@@ -1471,8 +1471,9 @@ static void chv_gpio_irq_handler(struct irq_desc *desc)
offset = cctx->intr_lines[intr_line]; offset = cctx->intr_lines[intr_line];
if (offset == CHV_INVALID_HWIRQ) { if (offset == CHV_INVALID_HWIRQ) {
dev_err(dev, "interrupt on unused interrupt line %u\n", intr_line); dev_warn_once(dev, "interrupt on unmapped interrupt line %u\n", intr_line);
continue; /* Some boards expect hwirq 0 to trigger in this case */
offset = 0;
} }
generic_handle_domain_irq(gc->irq.domain, offset); generic_handle_domain_irq(gc->irq.domain, offset);
......
...@@ -451,8 +451,8 @@ static void intel_gpio_set_gpio_mode(void __iomem *padcfg0) ...@@ -451,8 +451,8 @@ static void intel_gpio_set_gpio_mode(void __iomem *padcfg0)
value &= ~PADCFG0_PMODE_MASK; value &= ~PADCFG0_PMODE_MASK;
value |= PADCFG0_PMODE_GPIO; value |= PADCFG0_PMODE_GPIO;
/* Disable input and output buffers */ /* Disable TX buffer and enable RX (this will be input) */
value |= PADCFG0_GPIORXDIS; value &= ~PADCFG0_GPIORXDIS;
value |= PADCFG0_GPIOTXDIS; value |= PADCFG0_GPIOTXDIS;
/* Disable SCI/SMI/NMI generation */ /* Disable SCI/SMI/NMI generation */
...@@ -497,9 +497,6 @@ static int intel_gpio_request_enable(struct pinctrl_dev *pctldev, ...@@ -497,9 +497,6 @@ static int intel_gpio_request_enable(struct pinctrl_dev *pctldev,
intel_gpio_set_gpio_mode(padcfg0); intel_gpio_set_gpio_mode(padcfg0);
/* Disable TX buffer and enable RX (this will be input) */
__intel_gpio_set_direction(padcfg0, true);
raw_spin_unlock_irqrestore(&pctrl->lock, flags); raw_spin_unlock_irqrestore(&pctrl->lock, flags);
return 0; return 0;
...@@ -1115,9 +1112,6 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned int type) ...@@ -1115,9 +1112,6 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned int type)
intel_gpio_set_gpio_mode(reg); intel_gpio_set_gpio_mode(reg);
/* Disable TX buffer and enable RX (this will be input) */
__intel_gpio_set_direction(reg, true);
value = readl(reg); value = readl(reg);
value &= ~(PADCFG0_RXEVCFG_MASK | PADCFG0_RXINV); value &= ~(PADCFG0_RXEVCFG_MASK | PADCFG0_RXINV);
...@@ -1216,6 +1210,39 @@ static irqreturn_t intel_gpio_irq(int irq, void *data) ...@@ -1216,6 +1210,39 @@ static irqreturn_t intel_gpio_irq(int irq, void *data)
return IRQ_RETVAL(ret); return IRQ_RETVAL(ret);
} }
static void intel_gpio_irq_init(struct intel_pinctrl *pctrl)
{
int i;
for (i = 0; i < pctrl->ncommunities; i++) {
const struct intel_community *community;
void __iomem *base;
unsigned int gpp;
community = &pctrl->communities[i];
base = community->regs;
for (gpp = 0; gpp < community->ngpps; gpp++) {
/* Mask and clear all interrupts */
writel(0, base + community->ie_offset + gpp * 4);
writel(0xffff, base + community->is_offset + gpp * 4);
}
}
}
static int intel_gpio_irq_init_hw(struct gpio_chip *gc)
{
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
/*
* Make sure the interrupt lines are in a proper state before
* further configuration.
*/
intel_gpio_irq_init(pctrl);
return 0;
}
static int intel_gpio_add_community_ranges(struct intel_pinctrl *pctrl, static int intel_gpio_add_community_ranges(struct intel_pinctrl *pctrl,
const struct intel_community *community) const struct intel_community *community)
{ {
...@@ -1320,6 +1347,7 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq) ...@@ -1320,6 +1347,7 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
girq->num_parents = 0; girq->num_parents = 0;
girq->default_type = IRQ_TYPE_NONE; girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_bad_irq; girq->handler = handle_bad_irq;
girq->init_hw = intel_gpio_irq_init_hw;
ret = devm_gpiochip_add_data(pctrl->dev, &pctrl->chip, pctrl); ret = devm_gpiochip_add_data(pctrl->dev, &pctrl->chip, pctrl);
if (ret) { if (ret) {
...@@ -1695,26 +1723,6 @@ int intel_pinctrl_suspend_noirq(struct device *dev) ...@@ -1695,26 +1723,6 @@ int intel_pinctrl_suspend_noirq(struct device *dev)
} }
EXPORT_SYMBOL_GPL(intel_pinctrl_suspend_noirq); EXPORT_SYMBOL_GPL(intel_pinctrl_suspend_noirq);
static void intel_gpio_irq_init(struct intel_pinctrl *pctrl)
{
size_t i;
for (i = 0; i < pctrl->ncommunities; i++) {
const struct intel_community *community;
void __iomem *base;
unsigned int gpp;
community = &pctrl->communities[i];
base = community->regs;
for (gpp = 0; gpp < community->ngpps; gpp++) {
/* Mask and clear all interrupts */
writel(0, base + community->ie_offset + gpp * 4);
writel(0xffff, base + community->is_offset + gpp * 4);
}
}
}
static bool intel_gpio_update_reg(void __iomem *reg, u32 mask, u32 value) static bool intel_gpio_update_reg(void __iomem *reg, u32 mask, u32 value)
{ {
u32 curr, updated; u32 curr, updated;
......
...@@ -137,7 +137,8 @@ static inline int sgpio_addr_to_pin(struct sgpio_priv *priv, int port, int bit) ...@@ -137,7 +137,8 @@ static inline int sgpio_addr_to_pin(struct sgpio_priv *priv, int port, int bit)
static inline u32 sgpio_get_addr(struct sgpio_priv *priv, u32 rno, u32 off) static inline u32 sgpio_get_addr(struct sgpio_priv *priv, u32 rno, u32 off)
{ {
return priv->properties->regoff[rno] + off; return (priv->properties->regoff[rno] + off) *
regmap_get_reg_stride(priv->regs);
} }
static u32 sgpio_readl(struct sgpio_priv *priv, u32 rno, u32 off) static u32 sgpio_readl(struct sgpio_priv *priv, u32 rno, u32 off)
......
...@@ -773,63 +773,42 @@ static int thunderbay_build_groups(struct thunderbay_pinctrl *tpc) ...@@ -773,63 +773,42 @@ static int thunderbay_build_groups(struct thunderbay_pinctrl *tpc)
static int thunderbay_add_functions(struct thunderbay_pinctrl *tpc, struct function_desc *funcs) static int thunderbay_add_functions(struct thunderbay_pinctrl *tpc, struct function_desc *funcs)
{ {
struct function_desc *function = funcs;
int i; int i;
/* Assign the groups for each function */ /* Assign the groups for each function */
for (i = 0; i < tpc->soc->npins; i++) { for (i = 0; i < tpc->nfuncs; i++) {
const struct pinctrl_pin_desc *pin_info = thunderbay_pins + i; struct function_desc *func = &funcs[i];
struct thunderbay_mux_desc *pin_mux = pin_info->drv_data; const char **group_names;
unsigned int grp_idx = 0;
while (pin_mux->name) { int j;
const char **grp;
int j, grp_num, match = 0; group_names = devm_kcalloc(tpc->dev, func->num_group_names,
size_t grp_size; sizeof(*group_names), GFP_KERNEL);
struct function_desc *func; if (!group_names)
return -ENOMEM;
for (j = 0; j < tpc->nfuncs; j++) {
if (!strcmp(pin_mux->name, function[j].name)) {
match = 1;
break;
}
}
if (!match) for (j = 0; j < tpc->soc->npins; j++) {
return -EINVAL; const struct pinctrl_pin_desc *pin_info = &thunderbay_pins[j];
struct thunderbay_mux_desc *pin_mux;
func = function + j; for (pin_mux = pin_info->drv_data; pin_mux->name; pin_mux++) {
grp_num = func->num_group_names; if (!strcmp(pin_mux->name, func->name))
grp_size = sizeof(*func->group_names); group_names[grp_idx++] = pin_info->name;
if (!func->group_names) {
func->group_names = devm_kcalloc(tpc->dev,
grp_num,
grp_size,
GFP_KERNEL);
if (!func->group_names) {
kfree(func);
return -ENOMEM;
} }
} }
grp = func->group_names; func->group_names = group_names;
while (*grp)
grp++;
*grp = pin_info->name;
pin_mux++;
}
} }
/* Add all functions */ /* Add all functions */
for (i = 0; i < tpc->nfuncs; i++) { for (i = 0; i < tpc->nfuncs; i++) {
pinmux_generic_add_function(tpc->pctrl, pinmux_generic_add_function(tpc->pctrl,
function[i].name, funcs[i].name,
function[i].group_names, funcs[i].group_names,
function[i].num_group_names, funcs[i].num_group_names,
function[i].data); funcs[i].data);
} }
kfree(function); kfree(funcs);
return 0; return 0;
} }
...@@ -839,27 +818,30 @@ static int thunderbay_build_functions(struct thunderbay_pinctrl *tpc) ...@@ -839,27 +818,30 @@ static int thunderbay_build_functions(struct thunderbay_pinctrl *tpc)
void *ptr; void *ptr;
int pin; int pin;
/* Total number of functions is unknown at this point. Allocate first. */ /*
* Allocate maximum possible number of functions. Assume every pin
* being part of 8 (hw maximum) globally unique muxes.
*/
tpc->nfuncs = 0; tpc->nfuncs = 0;
thunderbay_funcs = kcalloc(tpc->soc->npins * 8, thunderbay_funcs = kcalloc(tpc->soc->npins * 8,
sizeof(*thunderbay_funcs), GFP_KERNEL); sizeof(*thunderbay_funcs), GFP_KERNEL);
if (!thunderbay_funcs) if (!thunderbay_funcs)
return -ENOMEM; return -ENOMEM;
/* Find total number of functions and each's properties */ /* Setup 1 function for each unique mux */
for (pin = 0; pin < tpc->soc->npins; pin++) { for (pin = 0; pin < tpc->soc->npins; pin++) {
const struct pinctrl_pin_desc *pin_info = thunderbay_pins + pin; const struct pinctrl_pin_desc *pin_info = thunderbay_pins + pin;
struct thunderbay_mux_desc *pin_mux = pin_info->drv_data; struct thunderbay_mux_desc *pin_mux;
while (pin_mux->name) { for (pin_mux = pin_info->drv_data; pin_mux->name; pin_mux++) {
struct function_desc *func = thunderbay_funcs; struct function_desc *func;
while (func->name) { /* Check if we already have function for this mux */
for (func = thunderbay_funcs; func->name; func++) {
if (!strcmp(pin_mux->name, func->name)) { if (!strcmp(pin_mux->name, func->name)) {
func->num_group_names++; func->num_group_names++;
break; break;
} }
func++;
} }
if (!func->name) { if (!func->name) {
...@@ -868,8 +850,6 @@ static int thunderbay_build_functions(struct thunderbay_pinctrl *tpc) ...@@ -868,8 +850,6 @@ static int thunderbay_build_functions(struct thunderbay_pinctrl *tpc)
func->data = (int *)&pin_mux->mode; func->data = (int *)&pin_mux->mode;
tpc->nfuncs++; tpc->nfuncs++;
} }
pin_mux++;
} }
} }
......
...@@ -809,7 +809,6 @@ static int zynqmp_pinctrl_prepare_pin_desc(struct device *dev, ...@@ -809,7 +809,6 @@ static int zynqmp_pinctrl_prepare_pin_desc(struct device *dev,
unsigned int *npins) unsigned int *npins)
{ {
struct pinctrl_pin_desc *pins, *pin; struct pinctrl_pin_desc *pins, *pin;
char **pin_names;
int ret; int ret;
int i; int i;
...@@ -821,14 +820,13 @@ static int zynqmp_pinctrl_prepare_pin_desc(struct device *dev, ...@@ -821,14 +820,13 @@ static int zynqmp_pinctrl_prepare_pin_desc(struct device *dev,
if (!pins) if (!pins)
return -ENOMEM; return -ENOMEM;
pin_names = devm_kasprintf_strarray(dev, ZYNQMP_PIN_PREFIX, *npins);
if (IS_ERR(pin_names))
return PTR_ERR(pin_names);
for (i = 0; i < *npins; i++) { for (i = 0; i < *npins; i++) {
pin = &pins[i]; pin = &pins[i];
pin->number = i; pin->number = i;
pin->name = pin_names[i]; pin->name = devm_kasprintf(dev, GFP_KERNEL, "%s%d",
ZYNQMP_PIN_PREFIX, i);
if (!pin->name)
return -ENOMEM;
} }
*zynqmp_pins = pins; *zynqmp_pins = pins;
......
...@@ -363,16 +363,16 @@ static const struct sunxi_desc_pin h616_pins[] = { ...@@ -363,16 +363,16 @@ static const struct sunxi_desc_pin h616_pins[] = {
SUNXI_FUNCTION(0x0, "gpio_in"), SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"), SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "uart2"), /* CTS */ SUNXI_FUNCTION(0x2, "uart2"), /* CTS */
SUNXI_FUNCTION(0x3, "i2s3"), /* DO0 */ SUNXI_FUNCTION(0x3, "i2s3_dout0"), /* DO0 */
SUNXI_FUNCTION(0x4, "spi1"), /* MISO */ SUNXI_FUNCTION(0x4, "spi1"), /* MISO */
SUNXI_FUNCTION(0x5, "i2s3"), /* DI1 */ SUNXI_FUNCTION(0x5, "i2s3_din1"), /* DI1 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 8)), /* PH_EINT8 */ SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 8)), /* PH_EINT8 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 9), SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 9),
SUNXI_FUNCTION(0x0, "gpio_in"), SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"), SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x3, "i2s3"), /* DI0 */ SUNXI_FUNCTION(0x3, "i2s3_din0"), /* DI0 */
SUNXI_FUNCTION(0x4, "spi1"), /* CS1 */ SUNXI_FUNCTION(0x4, "spi1"), /* CS1 */
SUNXI_FUNCTION(0x3, "i2s3"), /* DO1 */ SUNXI_FUNCTION(0x5, "i2s3_dout1"), /* DO1 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 9)), /* PH_EINT9 */ SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 9)), /* PH_EINT9 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 10), SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 10),
SUNXI_FUNCTION(0x0, "gpio_in"), SUNXI_FUNCTION(0x0, "gpio_in"),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment