Merge tag 'pinctrl-v3.19-3' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl
Pull pin control fixes from Linus Walleij: "Here is a (hopefully final) slew of pin control fixes for the v3.19 series. The deadlock fix is kind of serious and tagged for stable, the rest is business as usual. - Fix two deadlocks around the pin control mutexes, a long-standing issue that manifest itself in plug/unplug of pin controllers. (Tagged for stable.) - Handle an error path with zero functions in the Qualcomm pin controller. - Drop a bogus second GPIO chip added in the Lantiq driver. - Fix sudden IRQ loss on Rockchip pin controllers. - Register the GIT tree in MAINTAINERS" * tag 'pinctrl-v3.19-3' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: pinctrl: MAINTAINERS: add git tree reference pinctrl: qcom: Don't iterate past end of function array pinctrl: lantiq: remove bogus of_gpio_chip_add pinctrl: Fix two deadlocks pinctrl: rockchip: Avoid losing interrupts when supporting both edges
This commit is contained in:
@@ -7410,6 +7410,7 @@ F: drivers/crypto/picoxcell*
|
|||||||
PIN CONTROL SUBSYSTEM
|
PIN CONTROL SUBSYSTEM
|
||||||
M: Linus Walleij <linus.walleij@linaro.org>
|
M: Linus Walleij <linus.walleij@linaro.org>
|
||||||
L: linux-gpio@vger.kernel.org
|
L: linux-gpio@vger.kernel.org
|
||||||
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/pinctrl/
|
F: drivers/pinctrl/
|
||||||
F: include/linux/pinctrl/
|
F: include/linux/pinctrl/
|
||||||
|
@@ -1801,14 +1801,15 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev)
|
|||||||
if (pctldev == NULL)
|
if (pctldev == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mutex_lock(&pinctrldev_list_mutex);
|
|
||||||
mutex_lock(&pctldev->mutex);
|
mutex_lock(&pctldev->mutex);
|
||||||
|
|
||||||
pinctrl_remove_device_debugfs(pctldev);
|
pinctrl_remove_device_debugfs(pctldev);
|
||||||
|
mutex_unlock(&pctldev->mutex);
|
||||||
|
|
||||||
if (!IS_ERR(pctldev->p))
|
if (!IS_ERR(pctldev->p))
|
||||||
pinctrl_put(pctldev->p);
|
pinctrl_put(pctldev->p);
|
||||||
|
|
||||||
|
mutex_lock(&pinctrldev_list_mutex);
|
||||||
|
mutex_lock(&pctldev->mutex);
|
||||||
/* TODO: check that no pinmuxes are still active? */
|
/* TODO: check that no pinmuxes are still active? */
|
||||||
list_del(&pctldev->node);
|
list_del(&pctldev->node);
|
||||||
/* Destroy descriptor tree */
|
/* Destroy descriptor tree */
|
||||||
|
@@ -1398,10 +1398,7 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
|
|||||||
{
|
{
|
||||||
struct irq_chip *chip = irq_get_chip(irq);
|
struct irq_chip *chip = irq_get_chip(irq);
|
||||||
struct rockchip_pin_bank *bank = irq_get_handler_data(irq);
|
struct rockchip_pin_bank *bank = irq_get_handler_data(irq);
|
||||||
u32 polarity = 0, data = 0;
|
|
||||||
u32 pend;
|
u32 pend;
|
||||||
bool edge_changed = false;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
dev_dbg(bank->drvdata->dev, "got irq for bank %s\n", bank->name);
|
dev_dbg(bank->drvdata->dev, "got irq for bank %s\n", bank->name);
|
||||||
|
|
||||||
@@ -1409,12 +1406,6 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
|
|||||||
|
|
||||||
pend = readl_relaxed(bank->reg_base + GPIO_INT_STATUS);
|
pend = readl_relaxed(bank->reg_base + GPIO_INT_STATUS);
|
||||||
|
|
||||||
if (bank->toggle_edge_mode) {
|
|
||||||
polarity = readl_relaxed(bank->reg_base +
|
|
||||||
GPIO_INT_POLARITY);
|
|
||||||
data = readl_relaxed(bank->reg_base + GPIO_EXT_PORT);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (pend) {
|
while (pend) {
|
||||||
unsigned int virq;
|
unsigned int virq;
|
||||||
|
|
||||||
@@ -1434,29 +1425,33 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
|
|||||||
* needs manual intervention.
|
* needs manual intervention.
|
||||||
*/
|
*/
|
||||||
if (bank->toggle_edge_mode & BIT(irq)) {
|
if (bank->toggle_edge_mode & BIT(irq)) {
|
||||||
if (data & BIT(irq))
|
u32 data, data_old, polarity;
|
||||||
polarity &= ~BIT(irq);
|
unsigned long flags;
|
||||||
else
|
|
||||||
polarity |= BIT(irq);
|
|
||||||
|
|
||||||
edge_changed = true;
|
data = readl_relaxed(bank->reg_base + GPIO_EXT_PORT);
|
||||||
|
do {
|
||||||
|
spin_lock_irqsave(&bank->slock, flags);
|
||||||
|
|
||||||
|
polarity = readl_relaxed(bank->reg_base +
|
||||||
|
GPIO_INT_POLARITY);
|
||||||
|
if (data & BIT(irq))
|
||||||
|
polarity &= ~BIT(irq);
|
||||||
|
else
|
||||||
|
polarity |= BIT(irq);
|
||||||
|
writel(polarity,
|
||||||
|
bank->reg_base + GPIO_INT_POLARITY);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&bank->slock, flags);
|
||||||
|
|
||||||
|
data_old = data;
|
||||||
|
data = readl_relaxed(bank->reg_base +
|
||||||
|
GPIO_EXT_PORT);
|
||||||
|
} while ((data & BIT(irq)) != (data_old & BIT(irq)));
|
||||||
}
|
}
|
||||||
|
|
||||||
generic_handle_irq(virq);
|
generic_handle_irq(virq);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bank->toggle_edge_mode && edge_changed) {
|
|
||||||
/* Interrupt params should only be set with ints disabled */
|
|
||||||
spin_lock_irqsave(&bank->slock, flags);
|
|
||||||
|
|
||||||
data = readl_relaxed(bank->reg_base + GPIO_INTEN);
|
|
||||||
writel_relaxed(0, bank->reg_base + GPIO_INTEN);
|
|
||||||
writel(polarity, bank->reg_base + GPIO_INT_POLARITY);
|
|
||||||
writel(data, bank->reg_base + GPIO_INTEN);
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&bank->slock, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
chained_irq_exit(chip, desc);
|
chained_irq_exit(chip, desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -798,10 +798,8 @@ static int pinmux_xway_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
/* load the gpio chip */
|
/* load the gpio chip */
|
||||||
xway_chip.dev = &pdev->dev;
|
xway_chip.dev = &pdev->dev;
|
||||||
of_gpiochip_add(&xway_chip);
|
|
||||||
ret = gpiochip_add(&xway_chip);
|
ret = gpiochip_add(&xway_chip);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
of_gpiochip_remove(&xway_chip);
|
|
||||||
dev_err(&pdev->dev, "Failed to register gpio chip\n");
|
dev_err(&pdev->dev, "Failed to register gpio chip\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@@ -865,10 +865,10 @@ static int msm_ps_hold_restart(struct notifier_block *nb, unsigned long action,
|
|||||||
|
|
||||||
static void msm_pinctrl_setup_pm_reset(struct msm_pinctrl *pctrl)
|
static void msm_pinctrl_setup_pm_reset(struct msm_pinctrl *pctrl)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i;
|
||||||
const struct msm_function *func = pctrl->soc->functions;
|
const struct msm_function *func = pctrl->soc->functions;
|
||||||
|
|
||||||
for (; i <= pctrl->soc->nfunctions; i++)
|
for (i = 0; i < pctrl->soc->nfunctions; i++)
|
||||||
if (!strcmp(func[i].name, "ps_hold")) {
|
if (!strcmp(func[i].name, "ps_hold")) {
|
||||||
pctrl->restart_nb.notifier_call = msm_ps_hold_restart;
|
pctrl->restart_nb.notifier_call = msm_ps_hold_restart;
|
||||||
pctrl->restart_nb.priority = 128;
|
pctrl->restart_nb.priority = 128;
|
||||||
|
Reference in New Issue
Block a user