Skip to content

Commit

Permalink
Merge tag 'pinctrl-v5.2-3' of git://git.kernel.org/pub/scm/linux/kern…
Browse files Browse the repository at this point in the history
…el/git/linusw/linux-pinctrl

Pull pin control fixes from Linus Walleij:
 "Sorry to bomb in fixes this late. Maybe I can comfort you by saying it
  is only driver fixes, and mostly IRQ handling which is something GPIO
  and pin control drivers never get right. You think it works and then
  it doesn't.

  Summary:

   - Fix IRQ setup in the MCP23s08.

   - Fix pin setup on pins > 31 in the Ocelot driver.

   - Fix IRQs in the Mediatek driver"

* tag 'pinctrl-v5.2-3' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl:
  pinctrl: mediatek: Update cur_mask in mask/mask ops
  pinctrl: mediatek: Ignore interrupts that are wake only during resume
  pinctrl: ocelot: fix pinmuxing for pins after 31
  pinctrl: ocelot: fix gpio direction for pins after 31
  pinctrl: mcp23s08: Fix add_data and irqchip_add_nested call order
  • Loading branch information
torvalds committed Jun 29, 2019
2 parents 556e2f6 + 9d957a9 commit 0619137
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 27 deletions.
34 changes: 19 additions & 15 deletions drivers/pinctrl/mediatek/mtk-eint.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ static void mtk_eint_mask(struct irq_data *d)
void __iomem *reg = mtk_eint_get_offset(eint, d->hwirq,
eint->regs->mask_set);

eint->cur_mask[d->hwirq >> 5] &= ~mask;

writel(mask, reg);
}

Expand All @@ -123,6 +125,8 @@ static void mtk_eint_unmask(struct irq_data *d)
void __iomem *reg = mtk_eint_get_offset(eint, d->hwirq,
eint->regs->mask_clr);

eint->cur_mask[d->hwirq >> 5] |= mask;

writel(mask, reg);

if (eint->dual_edge[d->hwirq])
Expand Down Expand Up @@ -217,19 +221,6 @@ static void mtk_eint_chip_write_mask(const struct mtk_eint *eint,
}
}

static void mtk_eint_chip_read_mask(const struct mtk_eint *eint,
void __iomem *base, u32 *buf)
{
int port;
void __iomem *reg;

for (port = 0; port < eint->hw->ports; port++) {
reg = base + eint->regs->mask + (port << 2);
buf[port] = ~readl_relaxed(reg);
/* Mask is 0 when irq is enabled, and 1 when disabled. */
}
}

static int mtk_eint_irq_request_resources(struct irq_data *d)
{
struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
Expand Down Expand Up @@ -318,7 +309,7 @@ static void mtk_eint_irq_handler(struct irq_desc *desc)
struct irq_chip *chip = irq_desc_get_chip(desc);
struct mtk_eint *eint = irq_desc_get_handler_data(desc);
unsigned int status, eint_num;
int offset, index, virq;
int offset, mask_offset, index, virq;
void __iomem *reg = mtk_eint_get_offset(eint, 0, eint->regs->stat);
int dual_edge, start_level, curr_level;

Expand All @@ -328,10 +319,24 @@ static void mtk_eint_irq_handler(struct irq_desc *desc)
status = readl(reg);
while (status) {
offset = __ffs(status);
mask_offset = eint_num >> 5;
index = eint_num + offset;
virq = irq_find_mapping(eint->domain, index);
status &= ~BIT(offset);

/*
* If we get an interrupt on pin that was only required
* for wake (but no real interrupt requested), mask the
* interrupt (as would mtk_eint_resume do anyway later
* in the resume sequence).
*/
if (eint->wake_mask[mask_offset] & BIT(offset) &&
!(eint->cur_mask[mask_offset] & BIT(offset))) {
writel_relaxed(BIT(offset), reg -
eint->regs->stat +
eint->regs->mask_set);
}

dual_edge = eint->dual_edge[index];
if (dual_edge) {
/*
Expand Down Expand Up @@ -370,7 +375,6 @@ static void mtk_eint_irq_handler(struct irq_desc *desc)

int mtk_eint_do_suspend(struct mtk_eint *eint)
{
mtk_eint_chip_read_mask(eint, eint->base, eint->cur_mask);
mtk_eint_chip_write_mask(eint, eint->base, eint->wake_mask);

return 0;
Expand Down
8 changes: 4 additions & 4 deletions drivers/pinctrl/pinctrl-mcp23s08.c
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,10 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
if (ret < 0)
goto fail;

ret = devm_gpiochip_add_data(dev, &mcp->chip, mcp);
if (ret < 0)
goto fail;

mcp->irq_controller =
device_property_read_bool(dev, "interrupt-controller");
if (mcp->irq && mcp->irq_controller) {
Expand Down Expand Up @@ -812,10 +816,6 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
goto fail;
}

ret = devm_gpiochip_add_data(dev, &mcp->chip, mcp);
if (ret < 0)
goto fail;

if (one_regmap_config) {
mcp->pinctrl_desc.name = devm_kasprintf(dev, GFP_KERNEL,
"mcp23xxx-pinctrl.%d", raw_chip_address);
Expand Down
18 changes: 10 additions & 8 deletions drivers/pinctrl/pinctrl-ocelot.c
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ static int ocelot_pin_function_idx(struct ocelot_pinctrl *info,
return -1;
}

#define REG(r, info, p) ((r) * (info)->stride + (4 * ((p) / 32)))
#define REG_ALT(msb, info, p) (OCELOT_GPIO_ALT0 * (info)->stride + 4 * ((msb) + ((info)->stride * ((p) / 32))))

static int ocelot_pinmux_set_mux(struct pinctrl_dev *pctldev,
unsigned int selector, unsigned int group)
Expand All @@ -412,27 +412,29 @@ static int ocelot_pinmux_set_mux(struct pinctrl_dev *pctldev,

/*
* f is encoded on two bits.
* bit 0 of f goes in BIT(pin) of ALT0, bit 1 of f goes in BIT(pin) of
* ALT1
* bit 0 of f goes in BIT(pin) of ALT[0], bit 1 of f goes in BIT(pin) of
* ALT[1]
* This is racy because both registers can't be updated at the same time
* but it doesn't matter much for now.
*/
regmap_update_bits(info->map, REG(OCELOT_GPIO_ALT0, info, pin->pin),
regmap_update_bits(info->map, REG_ALT(0, info, pin->pin),
BIT(p), f << p);
regmap_update_bits(info->map, REG(OCELOT_GPIO_ALT1, info, pin->pin),
regmap_update_bits(info->map, REG_ALT(1, info, pin->pin),
BIT(p), f << (p - 1));

return 0;
}

#define REG(r, info, p) ((r) * (info)->stride + (4 * ((p) / 32)))

static int ocelot_gpio_set_direction(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned int pin, bool input)
{
struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
unsigned int p = pin % 32;

regmap_update_bits(info->map, REG(OCELOT_GPIO_OE, info, p), BIT(p),
regmap_update_bits(info->map, REG(OCELOT_GPIO_OE, info, pin), BIT(p),
input ? 0 : BIT(p));

return 0;
Expand All @@ -445,9 +447,9 @@ static int ocelot_gpio_request_enable(struct pinctrl_dev *pctldev,
struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
unsigned int p = offset % 32;

regmap_update_bits(info->map, REG(OCELOT_GPIO_ALT0, info, offset),
regmap_update_bits(info->map, REG_ALT(0, info, offset),
BIT(p), 0);
regmap_update_bits(info->map, REG(OCELOT_GPIO_ALT1, info, offset),
regmap_update_bits(info->map, REG_ALT(1, info, offset),
BIT(p), 0);

return 0;
Expand Down

0 comments on commit 0619137

Please sign in to comment.