Commit 1b5caa3e authored by Linus Torvalds's avatar Linus Torvalds

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

Pull pin control fixes from Linus Walleij:
 "Here is a set of pin control fixes for the v4.6 series.

  A bit bigger than what I hoped for, but all fixes are confined to
  drivers, a few of them also targeted to stable.

  Summary:

   - On Super-H PFC (Renesas) controllers: only use dummies on legacy
     systems.  This fixes a serious ethernet regression on a Renesas
     board.
   - Pistachio: Fix errors in the pin table.
   - Allwinner SunXi: fix the external interrupts to work.
   - Intel: fix so the high level interrupts start working, and fix a
     spurious interrupt issue.
   - Qualcomm ipq4019: fix the number of GPIOs provided (bump to 100),
     correct register offsets and handle GPIO mode properly.
   - Revert the revert on the revert so that Xway has a .to_irq()
     callback again.
   - Minor fixes to errorpaths and debug info.
   - A MAINTAINERS update"

* tag 'pinctrl-v4.6-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl:
  Revert "Revert "pinctrl: lantiq: Implement gpio_chip.to_irq""
  pinctrl: qcom: ipq4019: fix register offsets
  pinctrl: qcom: ipq4019: fix the function enum for gpio mode
  pinctrl: qcom: ipq4019: set ngpios to correct value
  pinctrl: nomadik: fix pull debug print inversion
  MAINTAINERS: pinctrl: samsung: Add two new maintainers
  pinctrl: intel: implement gpio_irq_enable
  pinctrl: intel: make the high level interrupt working
  pinctrl: freescale: imx: fix bogus check of of_iomap() return value
  pinctrl: sunxi: Fix A33 external interrupts not working
  pinctrl: pistachio: fix mfio84-89 function description and pinmux.
  pinctrl: sh-pfc: only use dummy states for non-DT platforms
parents 62d2def9 e1641c9d
......@@ -134,12 +134,12 @@ mfio80 ddr_debug, mips_trace_data, mips_debug
mfio81 dreq0, mips_trace_data, eth_debug
mfio82 dreq1, mips_trace_data, eth_debug
mfio83 mips_pll_lock, mips_trace_data, usb_debug
mfio84 sys_pll_lock, mips_trace_data, usb_debug
mfio85 wifi_pll_lock, mips_trace_data, sdhost_debug
mfio86 bt_pll_lock, mips_trace_data, sdhost_debug
mfio87 rpu_v_pll_lock, dreq2, socif_debug
mfio88 rpu_l_pll_lock, dreq3, socif_debug
mfio89 audio_pll_lock, dreq4, dreq5
mfio84 audio_pll_lock, mips_trace_data, usb_debug
mfio85 rpu_v_pll_lock, mips_trace_data, sdhost_debug
mfio86 rpu_l_pll_lock, mips_trace_data, sdhost_debug
mfio87 sys_pll_lock, dreq2, socif_debug
mfio88 wifi_pll_lock, dreq3, socif_debug
mfio89 bt_pll_lock, dreq4, dreq5
tck
trstn
tdi
......
......@@ -8712,6 +8712,8 @@ F: drivers/pinctrl/sh-pfc/
PIN CONTROLLER - SAMSUNG
M: Tomasz Figa <tomasz.figa@gmail.com>
M: Krzysztof Kozlowski <k.kozlowski@samsung.com>
M: Sylwester Nawrocki <s.nawrocki@samsung.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
S: Maintained
......
......@@ -762,19 +762,18 @@ int imx_pinctrl_probe(struct platform_device *pdev,
if (of_property_read_bool(dev_np, "fsl,input-sel")) {
np = of_parse_phandle(dev_np, "fsl,input-sel", 0);
if (np) {
ipctl->input_sel_base = of_iomap(np, 0);
if (IS_ERR(ipctl->input_sel_base)) {
of_node_put(np);
dev_err(&pdev->dev,
"iomuxc input select base address not found\n");
return PTR_ERR(ipctl->input_sel_base);
}
} else {
if (!np) {
dev_err(&pdev->dev, "iomuxc fsl,input-sel property not found\n");
return -EINVAL;
}
ipctl->input_sel_base = of_iomap(np, 0);
of_node_put(np);
if (!ipctl->input_sel_base) {
dev_err(&pdev->dev,
"iomuxc input select base address not found\n");
return -ENOMEM;
}
}
imx_pinctrl_desc.name = dev_name(&pdev->dev);
......
......@@ -665,6 +665,35 @@ static void intel_gpio_irq_ack(struct irq_data *d)
spin_unlock(&pctrl->lock);
}
static void intel_gpio_irq_enable(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
const struct intel_community *community;
unsigned pin = irqd_to_hwirq(d);
unsigned long flags;
spin_lock_irqsave(&pctrl->lock, flags);
community = intel_get_community(pctrl, pin);
if (community) {
unsigned padno = pin_to_padno(community, pin);
unsigned gpp_size = community->gpp_size;
unsigned gpp_offset = padno % gpp_size;
unsigned gpp = padno / gpp_size;
u32 value;
/* Clear interrupt status first to avoid unexpected interrupt */
writel(BIT(gpp_offset), community->regs + GPI_IS + gpp * 4);
value = readl(community->regs + community->ie_offset + gpp * 4);
value |= BIT(gpp_offset);
writel(value, community->regs + community->ie_offset + gpp * 4);
}
spin_unlock_irqrestore(&pctrl->lock, flags);
}
static void intel_gpio_irq_mask_unmask(struct irq_data *d, bool mask)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
......@@ -741,8 +770,9 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned type)
value |= PADCFG0_RXINV;
} else if (type & IRQ_TYPE_EDGE_RISING) {
value |= PADCFG0_RXEVCFG_EDGE << PADCFG0_RXEVCFG_SHIFT;
} else if (type & IRQ_TYPE_LEVEL_LOW) {
value |= PADCFG0_RXINV;
} else if (type & IRQ_TYPE_LEVEL_MASK) {
if (type & IRQ_TYPE_LEVEL_LOW)
value |= PADCFG0_RXINV;
} else {
value |= PADCFG0_RXEVCFG_DISABLED << PADCFG0_RXEVCFG_SHIFT;
}
......@@ -852,6 +882,7 @@ static irqreturn_t intel_gpio_irq(int irq, void *data)
static struct irq_chip intel_gpio_irqchip = {
.name = "intel-gpio",
.irq_enable = intel_gpio_irq_enable,
.irq_ack = intel_gpio_irq_ack,
.irq_mask = intel_gpio_irq_mask,
.irq_unmask = intel_gpio_irq_unmask,
......
......@@ -990,7 +990,7 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s,
int val;
if (pull)
pullidx = data_out ? 1 : 2;
pullidx = data_out ? 2 : 1;
seq_printf(s, " gpio-%-3d (%-20.20s) in %s %s",
gpio,
......
......@@ -469,27 +469,27 @@ static const char * const pistachio_mips_pll_lock_groups[] = {
"mfio83",
};
static const char * const pistachio_sys_pll_lock_groups[] = {
static const char * const pistachio_audio_pll_lock_groups[] = {
"mfio84",
};
static const char * const pistachio_wifi_pll_lock_groups[] = {
static const char * const pistachio_rpu_v_pll_lock_groups[] = {
"mfio85",
};
static const char * const pistachio_bt_pll_lock_groups[] = {
static const char * const pistachio_rpu_l_pll_lock_groups[] = {
"mfio86",
};
static const char * const pistachio_rpu_v_pll_lock_groups[] = {
static const char * const pistachio_sys_pll_lock_groups[] = {
"mfio87",
};
static const char * const pistachio_rpu_l_pll_lock_groups[] = {
static const char * const pistachio_wifi_pll_lock_groups[] = {
"mfio88",
};
static const char * const pistachio_audio_pll_lock_groups[] = {
static const char * const pistachio_bt_pll_lock_groups[] = {
"mfio89",
};
......@@ -559,12 +559,12 @@ enum pistachio_mux_option {
PISTACHIO_FUNCTION_DREQ4,
PISTACHIO_FUNCTION_DREQ5,
PISTACHIO_FUNCTION_MIPS_PLL_LOCK,
PISTACHIO_FUNCTION_AUDIO_PLL_LOCK,
PISTACHIO_FUNCTION_RPU_V_PLL_LOCK,
PISTACHIO_FUNCTION_RPU_L_PLL_LOCK,
PISTACHIO_FUNCTION_SYS_PLL_LOCK,
PISTACHIO_FUNCTION_WIFI_PLL_LOCK,
PISTACHIO_FUNCTION_BT_PLL_LOCK,
PISTACHIO_FUNCTION_RPU_V_PLL_LOCK,
PISTACHIO_FUNCTION_RPU_L_PLL_LOCK,
PISTACHIO_FUNCTION_AUDIO_PLL_LOCK,
PISTACHIO_FUNCTION_DEBUG_RAW_CCA_IND,
PISTACHIO_FUNCTION_DEBUG_ED_SEC20_CCA_IND,
PISTACHIO_FUNCTION_DEBUG_ED_SEC40_CCA_IND,
......@@ -620,12 +620,12 @@ static const struct pistachio_function pistachio_functions[] = {
FUNCTION(dreq4),
FUNCTION(dreq5),
FUNCTION(mips_pll_lock),
FUNCTION(audio_pll_lock),
FUNCTION(rpu_v_pll_lock),
FUNCTION(rpu_l_pll_lock),
FUNCTION(sys_pll_lock),
FUNCTION(wifi_pll_lock),
FUNCTION(bt_pll_lock),
FUNCTION(rpu_v_pll_lock),
FUNCTION(rpu_l_pll_lock),
FUNCTION(audio_pll_lock),
FUNCTION(debug_raw_cca_ind),
FUNCTION(debug_ed_sec20_cca_ind),
FUNCTION(debug_ed_sec40_cca_ind),
......
......@@ -1573,6 +1573,22 @@ static int xway_gpio_dir_out(struct gpio_chip *chip, unsigned int pin, int val)
return 0;
}
/*
* gpiolib gpiod_to_irq callback function.
* Returns the mapped IRQ (external interrupt) number for a given GPIO pin.
*/
static int xway_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct ltq_pinmux_info *info = dev_get_drvdata(chip->parent);
int i;
for (i = 0; i < info->num_exin; i++)
if (info->exin[i] == offset)
return ltq_eiu_get_irq(i);
return -1;
}
static struct gpio_chip xway_chip = {
.label = "gpio-xway",
.direction_input = xway_gpio_dir_in,
......@@ -1581,6 +1597,7 @@ static struct gpio_chip xway_chip = {
.set = xway_gpio_set,
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
.to_irq = xway_gpio_to_irq,
.base = -1,
};
......
......@@ -237,7 +237,7 @@ DECLARE_QCA_GPIO_PINS(99);
.pins = gpio##id##_pins, \
.npins = (unsigned)ARRAY_SIZE(gpio##id##_pins), \
.funcs = (int[]){ \
qca_mux_NA, /* gpio mode */ \
qca_mux_gpio, /* gpio mode */ \
qca_mux_##f1, \
qca_mux_##f2, \
qca_mux_##f3, \
......@@ -254,11 +254,11 @@ DECLARE_QCA_GPIO_PINS(99);
qca_mux_##f14 \
}, \
.nfuncs = 15, \
.ctl_reg = 0x1000 + 0x10 * id, \
.io_reg = 0x1004 + 0x10 * id, \
.intr_cfg_reg = 0x1008 + 0x10 * id, \
.intr_status_reg = 0x100c + 0x10 * id, \
.intr_target_reg = 0x400 + 0x4 * id, \
.ctl_reg = 0x0 + 0x1000 * id, \
.io_reg = 0x4 + 0x1000 * id, \
.intr_cfg_reg = 0x8 + 0x1000 * id, \
.intr_status_reg = 0xc + 0x1000 * id, \
.intr_target_reg = 0x8 + 0x1000 * id, \
.mux_bit = 2, \
.pull_bit = 0, \
.drv_bit = 6, \
......@@ -414,7 +414,7 @@ static const struct msm_pinctrl_soc_data ipq4019_pinctrl = {
.nfunctions = ARRAY_SIZE(ipq4019_functions),
.groups = ipq4019_groups,
.ngroups = ARRAY_SIZE(ipq4019_groups),
.ngpios = 70,
.ngpios = 100,
};
static int ipq4019_pinctrl_probe(struct platform_device *pdev)
......
......@@ -546,7 +546,9 @@ static int sh_pfc_probe(struct platform_device *pdev)
return ret;
}
pinctrl_provide_dummies();
/* Enable dummy states for those platforms without pinctrl support */
if (!of_have_populated_dt())
pinctrl_provide_dummies();
ret = sh_pfc_init_ranges(pfc);
if (ret < 0)
......
......@@ -485,6 +485,7 @@ static const struct sunxi_pinctrl_desc sun8i_a33_pinctrl_data = {
.pins = sun8i_a33_pins,
.npins = ARRAY_SIZE(sun8i_a33_pins),
.irq_banks = 2,
.irq_bank_base = 1,
};
static int sun8i_a33_pinctrl_probe(struct platform_device *pdev)
......
......@@ -579,7 +579,7 @@ static void sunxi_pinctrl_irq_release_resources(struct irq_data *d)
static int sunxi_pinctrl_irq_set_type(struct irq_data *d, unsigned int type)
{
struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
u32 reg = sunxi_irq_cfg_reg(d->hwirq);
u32 reg = sunxi_irq_cfg_reg(d->hwirq, pctl->desc->irq_bank_base);
u8 index = sunxi_irq_cfg_offset(d->hwirq);
unsigned long flags;
u32 regval;
......@@ -626,7 +626,8 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d, unsigned int type)
static void sunxi_pinctrl_irq_ack(struct irq_data *d)
{
struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
u32 status_reg = sunxi_irq_status_reg(d->hwirq);
u32 status_reg = sunxi_irq_status_reg(d->hwirq,
pctl->desc->irq_bank_base);
u8 status_idx = sunxi_irq_status_offset(d->hwirq);
/* Clear the IRQ */
......@@ -636,7 +637,7 @@ static void sunxi_pinctrl_irq_ack(struct irq_data *d)
static void sunxi_pinctrl_irq_mask(struct irq_data *d)
{
struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
u32 reg = sunxi_irq_ctrl_reg(d->hwirq);
u32 reg = sunxi_irq_ctrl_reg(d->hwirq, pctl->desc->irq_bank_base);
u8 idx = sunxi_irq_ctrl_offset(d->hwirq);
unsigned long flags;
u32 val;
......@@ -653,7 +654,7 @@ static void sunxi_pinctrl_irq_mask(struct irq_data *d)
static void sunxi_pinctrl_irq_unmask(struct irq_data *d)
{
struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
u32 reg = sunxi_irq_ctrl_reg(d->hwirq);
u32 reg = sunxi_irq_ctrl_reg(d->hwirq, pctl->desc->irq_bank_base);
u8 idx = sunxi_irq_ctrl_offset(d->hwirq);
unsigned long flags;
u32 val;
......@@ -745,7 +746,7 @@ static void sunxi_pinctrl_irq_handler(struct irq_desc *desc)
if (bank == pctl->desc->irq_banks)
return;
reg = sunxi_irq_status_reg_from_bank(bank);
reg = sunxi_irq_status_reg_from_bank(bank, pctl->desc->irq_bank_base);
val = readl(pctl->membase + reg);
if (val) {
......@@ -1024,9 +1025,11 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
for (i = 0; i < pctl->desc->irq_banks; i++) {
/* Mask and clear all IRQs before registering a handler */
writel(0, pctl->membase + sunxi_irq_ctrl_reg_from_bank(i));
writel(0, pctl->membase + sunxi_irq_ctrl_reg_from_bank(i,
pctl->desc->irq_bank_base));
writel(0xffffffff,
pctl->membase + sunxi_irq_status_reg_from_bank(i));
pctl->membase + sunxi_irq_status_reg_from_bank(i,
pctl->desc->irq_bank_base));
irq_set_chained_handler_and_data(pctl->irq[i],
sunxi_pinctrl_irq_handler,
......
......@@ -97,6 +97,7 @@ struct sunxi_pinctrl_desc {
int npins;
unsigned pin_base;
unsigned irq_banks;
unsigned irq_bank_base;
bool irq_read_needs_mux;
};
......@@ -233,12 +234,12 @@ static inline u32 sunxi_pull_offset(u16 pin)
return pin_num * PULL_PINS_BITS;
}
static inline u32 sunxi_irq_cfg_reg(u16 irq)
static inline u32 sunxi_irq_cfg_reg(u16 irq, unsigned bank_base)
{
u8 bank = irq / IRQ_PER_BANK;
u8 reg = (irq % IRQ_PER_BANK) / IRQ_CFG_IRQ_PER_REG * 0x04;
return IRQ_CFG_REG + bank * IRQ_MEM_SIZE + reg;
return IRQ_CFG_REG + (bank_base + bank) * IRQ_MEM_SIZE + reg;
}
static inline u32 sunxi_irq_cfg_offset(u16 irq)
......@@ -247,16 +248,16 @@ static inline u32 sunxi_irq_cfg_offset(u16 irq)
return irq_num * IRQ_CFG_IRQ_BITS;
}
static inline u32 sunxi_irq_ctrl_reg_from_bank(u8 bank)
static inline u32 sunxi_irq_ctrl_reg_from_bank(u8 bank, unsigned bank_base)
{
return IRQ_CTRL_REG + bank * IRQ_MEM_SIZE;
return IRQ_CTRL_REG + (bank_base + bank) * IRQ_MEM_SIZE;
}
static inline u32 sunxi_irq_ctrl_reg(u16 irq)
static inline u32 sunxi_irq_ctrl_reg(u16 irq, unsigned bank_base)
{
u8 bank = irq / IRQ_PER_BANK;
return sunxi_irq_ctrl_reg_from_bank(bank);
return sunxi_irq_ctrl_reg_from_bank(bank, bank_base);
}
static inline u32 sunxi_irq_ctrl_offset(u16 irq)
......@@ -265,16 +266,16 @@ static inline u32 sunxi_irq_ctrl_offset(u16 irq)
return irq_num * IRQ_CTRL_IRQ_BITS;
}
static inline u32 sunxi_irq_status_reg_from_bank(u8 bank)
static inline u32 sunxi_irq_status_reg_from_bank(u8 bank, unsigned bank_base)
{
return IRQ_STATUS_REG + bank * IRQ_MEM_SIZE;
return IRQ_STATUS_REG + (bank_base + bank) * IRQ_MEM_SIZE;
}
static inline u32 sunxi_irq_status_reg(u16 irq)
static inline u32 sunxi_irq_status_reg(u16 irq, unsigned bank_base)
{
u8 bank = irq / IRQ_PER_BANK;
return sunxi_irq_status_reg_from_bank(bank);
return sunxi_irq_status_reg_from_bank(bank, bank_base);
}
static inline u32 sunxi_irq_status_offset(u16 irq)
......
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