From 4edd7901eee13f878e7b5fd5efba610e70b09313 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 12 Nov 2013 11:52:32 +0200 Subject: gpio/lynxpoint: add new ACPI ID Newer Intel PCHs have the same GPIO controller than Haswell but the ACPI ID is different. Add this ID to the driver supported IDs list. Signed-off-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/gpio/gpio-lynxpoint.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c index a0804740a0b7..f1ca9d5880b6 100644 --- a/drivers/gpio/gpio-lynxpoint.c +++ b/drivers/gpio/gpio-lynxpoint.c @@ -438,6 +438,7 @@ static const struct dev_pm_ops lp_gpio_pm_ops = { static const struct acpi_device_id lynxpoint_gpio_acpi_match[] = { { "INT33C7", 0 }, + { "INT3437", 0 }, { } }; MODULE_DEVICE_TABLE(acpi, lynxpoint_gpio_acpi_match); -- cgit v1.2.1 From 661553b9c67c1c7496de5f603ee3d338ecad6850 Mon Sep 17 00:00:00 2001 From: Victor Kamensky Date: Sat, 16 Nov 2013 02:01:04 +0200 Subject: gpio/omap: raw read and write endian fix All OMAP IP blocks expect LE data, but CPU may operate in BE mode. Need to use endian neutral functions to read/write h/w registers. I.e instead of __raw_read[lw] and __raw_write[lw] functions code need to use read[lw]_relaxed and write[lw]_relaxed functions. If the first simply reads/writes register, the second will byteswap it if host operates in BE mode. Changes are trivial sed like replacement of __raw_xxx functions with xxx_relaxed variant. Signed-off-by: Victor Kamensky Signed-off-by: Taras Kondratiuk Acked-by: Tony Lindgren Acked-by: Kevin Hilman Acked-by: Santosh Shilimkar Tested-by: Javier Martinez Canillas Signed-off-by: Linus Walleij --- drivers/gpio/gpio-omap.c | 188 +++++++++++++++++++++++------------------------ 1 file changed, 94 insertions(+), 94 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index f319c9ffd4a8..424319061e09 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -108,12 +108,12 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input) u32 l; reg += bank->regs->direction; - l = __raw_readl(reg); + l = readl_relaxed(reg); if (is_input) l |= 1 << gpio; else l &= ~(1 << gpio); - __raw_writel(l, reg); + writel_relaxed(l, reg); bank->context.oe = l; } @@ -132,7 +132,7 @@ static void _set_gpio_dataout_reg(struct gpio_bank *bank, int gpio, int enable) bank->context.dataout &= ~l; } - __raw_writel(l, reg); + writel_relaxed(l, reg); } /* set data out value using mask register */ @@ -142,12 +142,12 @@ static void _set_gpio_dataout_mask(struct gpio_bank *bank, int gpio, int enable) u32 gpio_bit = GPIO_BIT(bank, gpio); u32 l; - l = __raw_readl(reg); + l = readl_relaxed(reg); if (enable) l |= gpio_bit; else l &= ~gpio_bit; - __raw_writel(l, reg); + writel_relaxed(l, reg); bank->context.dataout = l; } @@ -155,26 +155,26 @@ static int _get_gpio_datain(struct gpio_bank *bank, int offset) { void __iomem *reg = bank->base + bank->regs->datain; - return (__raw_readl(reg) & (1 << offset)) != 0; + return (readl_relaxed(reg) & (1 << offset)) != 0; } static int _get_gpio_dataout(struct gpio_bank *bank, int offset) { void __iomem *reg = bank->base + bank->regs->dataout; - return (__raw_readl(reg) & (1 << offset)) != 0; + return (readl_relaxed(reg) & (1 << offset)) != 0; } static inline void _gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set) { - int l = __raw_readl(base + reg); + int l = readl_relaxed(base + reg); if (set) l |= mask; else l &= ~mask; - __raw_writel(l, base + reg); + writel_relaxed(l, base + reg); } static inline void _gpio_dbck_enable(struct gpio_bank *bank) @@ -183,7 +183,7 @@ static inline void _gpio_dbck_enable(struct gpio_bank *bank) clk_enable(bank->dbck); bank->dbck_enabled = true; - __raw_writel(bank->dbck_enable_mask, + writel_relaxed(bank->dbck_enable_mask, bank->base + bank->regs->debounce_en); } } @@ -196,7 +196,7 @@ static inline void _gpio_dbck_disable(struct gpio_bank *bank) * enabled but the clock is not, GPIO module seems to be unable * to detect events and generate interrupts at least on OMAP3. */ - __raw_writel(0, bank->base + bank->regs->debounce_en); + writel_relaxed(0, bank->base + bank->regs->debounce_en); clk_disable(bank->dbck); bank->dbck_enabled = false; @@ -233,10 +233,10 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio, clk_enable(bank->dbck); reg = bank->base + bank->regs->debounce; - __raw_writel(debounce, reg); + writel_relaxed(debounce, reg); reg = bank->base + bank->regs->debounce_en; - val = __raw_readl(reg); + val = readl_relaxed(reg); if (debounce) val |= l; @@ -244,7 +244,7 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio, val &= ~l; bank->dbck_enable_mask = val; - __raw_writel(val, reg); + writel_relaxed(val, reg); clk_disable(bank->dbck); /* * Enable debounce clock per module. @@ -283,12 +283,12 @@ static void _clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio) bank->dbck_enable_mask &= ~gpio_bit; bank->context.debounce_en &= ~gpio_bit; - __raw_writel(bank->context.debounce_en, + writel_relaxed(bank->context.debounce_en, bank->base + bank->regs->debounce_en); if (!bank->dbck_enable_mask) { bank->context.debounce = 0; - __raw_writel(bank->context.debounce, bank->base + + writel_relaxed(bank->context.debounce, bank->base + bank->regs->debounce); clk_disable(bank->dbck); bank->dbck_enabled = false; @@ -311,18 +311,18 @@ static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio, trigger & IRQ_TYPE_EDGE_FALLING); bank->context.leveldetect0 = - __raw_readl(bank->base + bank->regs->leveldetect0); + readl_relaxed(bank->base + bank->regs->leveldetect0); bank->context.leveldetect1 = - __raw_readl(bank->base + bank->regs->leveldetect1); + readl_relaxed(bank->base + bank->regs->leveldetect1); bank->context.risingdetect = - __raw_readl(bank->base + bank->regs->risingdetect); + readl_relaxed(bank->base + bank->regs->risingdetect); bank->context.fallingdetect = - __raw_readl(bank->base + bank->regs->fallingdetect); + readl_relaxed(bank->base + bank->regs->fallingdetect); if (likely(!(bank->non_wakeup_gpios & gpio_bit))) { _gpio_rmw(base, bank->regs->wkup_en, gpio_bit, trigger != 0); bank->context.wake_en = - __raw_readl(bank->base + bank->regs->wkup_en); + readl_relaxed(bank->base + bank->regs->wkup_en); } /* This part needs to be executed always for OMAP{34xx, 44xx} */ @@ -347,8 +347,8 @@ static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio, exit: bank->level_mask = - __raw_readl(bank->base + bank->regs->leveldetect0) | - __raw_readl(bank->base + bank->regs->leveldetect1); + readl_relaxed(bank->base + bank->regs->leveldetect0) | + readl_relaxed(bank->base + bank->regs->leveldetect1); } #ifdef CONFIG_ARCH_OMAP1 @@ -366,13 +366,13 @@ static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) reg += bank->regs->irqctrl; - l = __raw_readl(reg); + l = readl_relaxed(reg); if ((l >> gpio) & 1) l &= ~(1 << gpio); else l |= 1 << gpio; - __raw_writel(l, reg); + writel_relaxed(l, reg); } #else static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) {} @@ -390,7 +390,7 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, } else if (bank->regs->irqctrl) { reg += bank->regs->irqctrl; - l = __raw_readl(reg); + l = readl_relaxed(reg); if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) bank->toggle_mask |= 1 << gpio; if (trigger & IRQ_TYPE_EDGE_RISING) @@ -400,7 +400,7 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, else return -EINVAL; - __raw_writel(l, reg); + writel_relaxed(l, reg); } else if (bank->regs->edgectrl1) { if (gpio & 0x08) reg += bank->regs->edgectrl2; @@ -408,7 +408,7 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, reg += bank->regs->edgectrl1; gpio &= 0x07; - l = __raw_readl(reg); + l = readl_relaxed(reg); l &= ~(3 << (gpio << 1)); if (trigger & IRQ_TYPE_EDGE_RISING) l |= 2 << (gpio << 1); @@ -418,8 +418,8 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, /* Enable wake-up during idle for dynamic tick */ _gpio_rmw(base, bank->regs->wkup_en, 1 << gpio, trigger); bank->context.wake_en = - __raw_readl(bank->base + bank->regs->wkup_en); - __raw_writel(l, reg); + readl_relaxed(bank->base + bank->regs->wkup_en); + writel_relaxed(l, reg); } return 0; } @@ -430,17 +430,17 @@ static void _enable_gpio_module(struct gpio_bank *bank, unsigned offset) void __iomem *reg = bank->base + bank->regs->pinctrl; /* Claim the pin for MPU */ - __raw_writel(__raw_readl(reg) | (1 << offset), reg); + writel_relaxed(readl_relaxed(reg) | (1 << offset), reg); } if (bank->regs->ctrl && !BANK_USED(bank)) { void __iomem *reg = bank->base + bank->regs->ctrl; u32 ctrl; - ctrl = __raw_readl(reg); + ctrl = readl_relaxed(reg); /* Module is enabled, clocks are not gated */ ctrl &= ~GPIO_MOD_CTRL_BIT; - __raw_writel(ctrl, reg); + writel_relaxed(ctrl, reg); bank->context.ctrl = ctrl; } } @@ -455,17 +455,17 @@ static void _disable_gpio_module(struct gpio_bank *bank, unsigned offset) /* Disable wake-up during idle for dynamic tick */ _gpio_rmw(base, bank->regs->wkup_en, 1 << offset, 0); bank->context.wake_en = - __raw_readl(bank->base + bank->regs->wkup_en); + readl_relaxed(bank->base + bank->regs->wkup_en); } if (bank->regs->ctrl && !BANK_USED(bank)) { void __iomem *reg = bank->base + bank->regs->ctrl; u32 ctrl; - ctrl = __raw_readl(reg); + ctrl = readl_relaxed(reg); /* Module is disabled, clocks are gated */ ctrl |= GPIO_MOD_CTRL_BIT; - __raw_writel(ctrl, reg); + writel_relaxed(ctrl, reg); bank->context.ctrl = ctrl; } } @@ -474,7 +474,7 @@ static int gpio_is_input(struct gpio_bank *bank, int mask) { void __iomem *reg = bank->base + bank->regs->direction; - return __raw_readl(reg) & mask; + return readl_relaxed(reg) & mask; } static int gpio_irq_type(struct irq_data *d, unsigned type) @@ -538,16 +538,16 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) void __iomem *reg = bank->base; reg += bank->regs->irqstatus; - __raw_writel(gpio_mask, reg); + writel_relaxed(gpio_mask, reg); /* Workaround for clearing DSP GPIO interrupts to allow retention */ if (bank->regs->irqstatus2) { reg = bank->base + bank->regs->irqstatus2; - __raw_writel(gpio_mask, reg); + writel_relaxed(gpio_mask, reg); } /* Flush posted write for the irq status to avoid spurious interrupts */ - __raw_readl(reg); + readl_relaxed(reg); } static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio) @@ -562,7 +562,7 @@ static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank) u32 mask = (1 << bank->width) - 1; reg += bank->regs->irqenable; - l = __raw_readl(reg); + l = readl_relaxed(reg); if (bank->regs->irqenable_inv) l = ~l; l &= mask; @@ -580,7 +580,7 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) bank->context.irqenable1 |= gpio_mask; } else { reg += bank->regs->irqenable; - l = __raw_readl(reg); + l = readl_relaxed(reg); if (bank->regs->irqenable_inv) l &= ~gpio_mask; else @@ -588,7 +588,7 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) bank->context.irqenable1 = l; } - __raw_writel(l, reg); + writel_relaxed(l, reg); } static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) @@ -602,7 +602,7 @@ static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) bank->context.irqenable1 &= ~gpio_mask; } else { reg += bank->regs->irqenable; - l = __raw_readl(reg); + l = readl_relaxed(reg); if (bank->regs->irqenable_inv) l |= gpio_mask; else @@ -610,7 +610,7 @@ static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) bank->context.irqenable1 = l; } - __raw_writel(l, reg); + writel_relaxed(l, reg); } static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable) @@ -646,7 +646,7 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable) else bank->context.wake_en &= ~gpio_bit; - __raw_writel(bank->context.wake_en, bank->base + bank->regs->wkup_en); + writel_relaxed(bank->context.wake_en, bank->base + bank->regs->wkup_en); spin_unlock_irqrestore(&bank->lock, flags); return 0; @@ -748,7 +748,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) u32 enabled; enabled = _get_gpio_irqbank_mask(bank); - isr_saved = isr = __raw_readl(isr_reg) & enabled; + isr_saved = isr = readl_relaxed(isr_reg) & enabled; if (bank->level_mask) level_mask = bank->level_mask & enabled; @@ -883,7 +883,7 @@ static int omap_mpuio_suspend_noirq(struct device *dev) unsigned long flags; spin_lock_irqsave(&bank->lock, flags); - __raw_writel(0xffff & ~bank->context.wake_en, mask_reg); + writel_relaxed(0xffff & ~bank->context.wake_en, mask_reg); spin_unlock_irqrestore(&bank->lock, flags); return 0; @@ -898,7 +898,7 @@ static int omap_mpuio_resume_noirq(struct device *dev) unsigned long flags; spin_lock_irqsave(&bank->lock, flags); - __raw_writel(bank->context.wake_en, mask_reg); + writel_relaxed(bank->context.wake_en, mask_reg); spin_unlock_irqrestore(&bank->lock, flags); return 0; @@ -1011,7 +1011,7 @@ static void __init omap_gpio_show_rev(struct gpio_bank *bank) if (called || bank->regs->revision == USHRT_MAX) return; - rev = __raw_readw(bank->base + bank->regs->revision); + rev = readw_relaxed(bank->base + bank->regs->revision); pr_info("OMAP GPIO hardware version %d.%d\n", (rev >> 4) & 0x0f, rev & 0x0f); @@ -1032,20 +1032,20 @@ static void omap_gpio_mod_init(struct gpio_bank *bank) l = 0xffff; if (bank->is_mpuio) { - __raw_writel(l, bank->base + bank->regs->irqenable); + writel_relaxed(l, bank->base + bank->regs->irqenable); return; } _gpio_rmw(base, bank->regs->irqenable, l, bank->regs->irqenable_inv); _gpio_rmw(base, bank->regs->irqstatus, l, !bank->regs->irqenable_inv); if (bank->regs->debounce_en) - __raw_writel(0, base + bank->regs->debounce_en); + writel_relaxed(0, base + bank->regs->debounce_en); /* Save OE default value (0xffffffff) in the context */ - bank->context.oe = __raw_readl(bank->base + bank->regs->direction); + bank->context.oe = readl_relaxed(bank->base + bank->regs->direction); /* Initialize interface clk ungated, module enabled */ if (bank->regs->ctrl) - __raw_writel(0, base + bank->regs->ctrl); + writel_relaxed(0, base + bank->regs->ctrl); bank->dbck = clk_get(bank->dev, "dbclk"); if (IS_ERR(bank->dbck)) @@ -1282,11 +1282,11 @@ static int omap_gpio_runtime_suspend(struct device *dev) */ wake_low = bank->context.leveldetect0 & bank->context.wake_en; if (wake_low) - __raw_writel(wake_low | bank->context.fallingdetect, + writel_relaxed(wake_low | bank->context.fallingdetect, bank->base + bank->regs->fallingdetect); wake_hi = bank->context.leveldetect1 & bank->context.wake_en; if (wake_hi) - __raw_writel(wake_hi | bank->context.risingdetect, + writel_relaxed(wake_hi | bank->context.risingdetect, bank->base + bank->regs->risingdetect); if (!bank->enabled_non_wakeup_gpios) @@ -1301,7 +1301,7 @@ static int omap_gpio_runtime_suspend(struct device *dev) * non-wakeup GPIOs. Otherwise spurious IRQs will be * generated. See OMAP2420 Errata item 1.101. */ - bank->saved_datain = __raw_readl(bank->base + + bank->saved_datain = readl_relaxed(bank->base + bank->regs->datain); l1 = bank->context.fallingdetect; l2 = bank->context.risingdetect; @@ -1309,8 +1309,8 @@ static int omap_gpio_runtime_suspend(struct device *dev) l1 &= ~bank->enabled_non_wakeup_gpios; l2 &= ~bank->enabled_non_wakeup_gpios; - __raw_writel(l1, bank->base + bank->regs->fallingdetect); - __raw_writel(l2, bank->base + bank->regs->risingdetect); + writel_relaxed(l1, bank->base + bank->regs->fallingdetect); + writel_relaxed(l2, bank->base + bank->regs->risingdetect); bank->workaround_enabled = true; @@ -1358,9 +1358,9 @@ static int omap_gpio_runtime_resume(struct device *dev) * generate a PRCM wakeup. Here we restore the * pre-runtime_suspend() values for edge triggering. */ - __raw_writel(bank->context.fallingdetect, + writel_relaxed(bank->context.fallingdetect, bank->base + bank->regs->fallingdetect); - __raw_writel(bank->context.risingdetect, + writel_relaxed(bank->context.risingdetect, bank->base + bank->regs->risingdetect); if (bank->loses_context) { @@ -1382,7 +1382,7 @@ static int omap_gpio_runtime_resume(struct device *dev) return 0; } - l = __raw_readl(bank->base + bank->regs->datain); + l = readl_relaxed(bank->base + bank->regs->datain); /* * Check if any of the non-wakeup interrupt GPIOs have changed @@ -1412,24 +1412,24 @@ static int omap_gpio_runtime_resume(struct device *dev) if (gen) { u32 old0, old1; - old0 = __raw_readl(bank->base + bank->regs->leveldetect0); - old1 = __raw_readl(bank->base + bank->regs->leveldetect1); + old0 = readl_relaxed(bank->base + bank->regs->leveldetect0); + old1 = readl_relaxed(bank->base + bank->regs->leveldetect1); if (!bank->regs->irqstatus_raw0) { - __raw_writel(old0 | gen, bank->base + + writel_relaxed(old0 | gen, bank->base + bank->regs->leveldetect0); - __raw_writel(old1 | gen, bank->base + + writel_relaxed(old1 | gen, bank->base + bank->regs->leveldetect1); } if (bank->regs->irqstatus_raw0) { - __raw_writel(old0 | l, bank->base + + writel_relaxed(old0 | l, bank->base + bank->regs->leveldetect0); - __raw_writel(old1 | l, bank->base + + writel_relaxed(old1 | l, bank->base + bank->regs->leveldetect1); } - __raw_writel(old0, bank->base + bank->regs->leveldetect0); - __raw_writel(old1, bank->base + bank->regs->leveldetect1); + writel_relaxed(old0, bank->base + bank->regs->leveldetect0); + writel_relaxed(old1, bank->base + bank->regs->leveldetect1); } bank->workaround_enabled = false; @@ -1471,55 +1471,55 @@ static void omap_gpio_init_context(struct gpio_bank *p) struct omap_gpio_reg_offs *regs = p->regs; void __iomem *base = p->base; - p->context.ctrl = __raw_readl(base + regs->ctrl); - p->context.oe = __raw_readl(base + regs->direction); - p->context.wake_en = __raw_readl(base + regs->wkup_en); - p->context.leveldetect0 = __raw_readl(base + regs->leveldetect0); - p->context.leveldetect1 = __raw_readl(base + regs->leveldetect1); - p->context.risingdetect = __raw_readl(base + regs->risingdetect); - p->context.fallingdetect = __raw_readl(base + regs->fallingdetect); - p->context.irqenable1 = __raw_readl(base + regs->irqenable); - p->context.irqenable2 = __raw_readl(base + regs->irqenable2); + p->context.ctrl = readl_relaxed(base + regs->ctrl); + p->context.oe = readl_relaxed(base + regs->direction); + p->context.wake_en = readl_relaxed(base + regs->wkup_en); + p->context.leveldetect0 = readl_relaxed(base + regs->leveldetect0); + p->context.leveldetect1 = readl_relaxed(base + regs->leveldetect1); + p->context.risingdetect = readl_relaxed(base + regs->risingdetect); + p->context.fallingdetect = readl_relaxed(base + regs->fallingdetect); + p->context.irqenable1 = readl_relaxed(base + regs->irqenable); + p->context.irqenable2 = readl_relaxed(base + regs->irqenable2); if (regs->set_dataout && p->regs->clr_dataout) - p->context.dataout = __raw_readl(base + regs->set_dataout); + p->context.dataout = readl_relaxed(base + regs->set_dataout); else - p->context.dataout = __raw_readl(base + regs->dataout); + p->context.dataout = readl_relaxed(base + regs->dataout); p->context_valid = true; } static void omap_gpio_restore_context(struct gpio_bank *bank) { - __raw_writel(bank->context.wake_en, + writel_relaxed(bank->context.wake_en, bank->base + bank->regs->wkup_en); - __raw_writel(bank->context.ctrl, bank->base + bank->regs->ctrl); - __raw_writel(bank->context.leveldetect0, + writel_relaxed(bank->context.ctrl, bank->base + bank->regs->ctrl); + writel_relaxed(bank->context.leveldetect0, bank->base + bank->regs->leveldetect0); - __raw_writel(bank->context.leveldetect1, + writel_relaxed(bank->context.leveldetect1, bank->base + bank->regs->leveldetect1); - __raw_writel(bank->context.risingdetect, + writel_relaxed(bank->context.risingdetect, bank->base + bank->regs->risingdetect); - __raw_writel(bank->context.fallingdetect, + writel_relaxed(bank->context.fallingdetect, bank->base + bank->regs->fallingdetect); if (bank->regs->set_dataout && bank->regs->clr_dataout) - __raw_writel(bank->context.dataout, + writel_relaxed(bank->context.dataout, bank->base + bank->regs->set_dataout); else - __raw_writel(bank->context.dataout, + writel_relaxed(bank->context.dataout, bank->base + bank->regs->dataout); - __raw_writel(bank->context.oe, bank->base + bank->regs->direction); + writel_relaxed(bank->context.oe, bank->base + bank->regs->direction); if (bank->dbck_enable_mask) { - __raw_writel(bank->context.debounce, bank->base + + writel_relaxed(bank->context.debounce, bank->base + bank->regs->debounce); - __raw_writel(bank->context.debounce_en, + writel_relaxed(bank->context.debounce_en, bank->base + bank->regs->debounce_en); } - __raw_writel(bank->context.irqenable1, + writel_relaxed(bank->context.irqenable1, bank->base + bank->regs->irqenable); - __raw_writel(bank->context.irqenable2, + writel_relaxed(bank->context.irqenable2, bank->base + bank->regs->irqenable2); } #endif /* CONFIG_PM_RUNTIME */ -- cgit v1.2.1 From fba968a1e6b84be01e548f4b28b78e0542f3adaa Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 20 Nov 2013 09:23:08 +0900 Subject: gpio: rcar: Use lazy disable Set the ->irq_enable() and ->irq_disable() methods to NULL to enable lazy disable of interrupts. This by itself provides some level of optimization, but is mainly enabled as ground work for future Suspend-to-RAM wake up support. Signed-off-by: Magnus Damm Acked-by: Laurent Pinchart Signed-off-by: Linus Walleij --- drivers/gpio/gpio-rcar.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index d3f15ae93bd3..a194bdb413fd 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -369,8 +369,6 @@ static int gpio_rcar_probe(struct platform_device *pdev) irq_chip->name = name; irq_chip->irq_mask = gpio_rcar_irq_disable; irq_chip->irq_unmask = gpio_rcar_irq_enable; - irq_chip->irq_enable = gpio_rcar_irq_enable; - irq_chip->irq_disable = gpio_rcar_irq_disable; irq_chip->irq_set_type = gpio_rcar_irq_set_type; irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_SET_TYPE_MASKED; -- cgit v1.2.1 From 403961120667bed7161777d33483596edd0b05f2 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 20 Nov 2013 09:23:17 +0900 Subject: gpio: rcar: Enable mask on suspend Now when lazy interrupt disable has been enabled in the driver then extend the code to set IRQCHIP_MASK_ON_SUSPEND which tells the core that only IRQs marked as wakeups need to stay enabled during Suspend-to-RAM. Tested on the Lager board with GPIO-keys and Suspend-to-RAM. Signed-off-by: Magnus Damm Acked-by: Laurent Pinchart Signed-off-by: Linus Walleij --- drivers/gpio/gpio-rcar.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index a194bdb413fd..d2c34da7b3bf 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -370,7 +370,8 @@ static int gpio_rcar_probe(struct platform_device *pdev) irq_chip->irq_mask = gpio_rcar_irq_disable; irq_chip->irq_unmask = gpio_rcar_irq_enable; irq_chip->irq_set_type = gpio_rcar_irq_set_type; - irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_SET_TYPE_MASKED; + irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_SET_TYPE_MASKED + | IRQCHIP_MASK_ON_SUSPEND; p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, p->config.number_of_pins, -- cgit v1.2.1 From 969bf7aec86ccd6ce1934ed634e29517ae2b8e10 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 20 Nov 2013 09:23:26 +0900 Subject: gpio: em: Setup gpiochip->dev Make sure gpio_chip->dev is setup so of_gpiochip_add() will work as expected. Signed-off-by: Magnus Damm Acked-by: Laurent Pinchart Signed-off-by: Linus Walleij --- drivers/gpio/gpio-em.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c index ec190361bf2e..b1decec9b359 100644 --- a/drivers/gpio/gpio-em.c +++ b/drivers/gpio/gpio-em.c @@ -328,6 +328,7 @@ static int em_gio_probe(struct platform_device *pdev) gpio_chip->request = em_gio_request; gpio_chip->free = em_gio_free; gpio_chip->label = name; + gpio_chip->dev = &pdev->dev; gpio_chip->owner = THIS_MODULE; gpio_chip->base = pdata->gpio_base; gpio_chip->ngpio = pdata->number_of_pins; -- cgit v1.2.1 From 664734c012e6f3a88b2da4c586002cd62a277003 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 20 Nov 2013 09:23:35 +0900 Subject: gpio: em: Use lazy disable Set the ->irq_enable() and ->irq_disable() methods to NULL to enable lazy disable of interrupts. This by itself provides some level of optimization, but is mainly enabled as ground work for future Suspend-to-RAM wake up support. Signed-off-by: Magnus Damm Acked-by: Laurent Pinchart Signed-off-by: Linus Walleij --- drivers/gpio/gpio-em.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c index b1decec9b359..225eda662c6c 100644 --- a/drivers/gpio/gpio-em.c +++ b/drivers/gpio/gpio-em.c @@ -337,8 +337,6 @@ static int em_gio_probe(struct platform_device *pdev) irq_chip->name = name; irq_chip->irq_mask = em_gio_irq_disable; irq_chip->irq_unmask = em_gio_irq_enable; - irq_chip->irq_enable = em_gio_irq_enable; - irq_chip->irq_disable = em_gio_irq_disable; irq_chip->irq_set_type = em_gio_irq_set_type; irq_chip->flags = IRQCHIP_SKIP_SET_WAKE; -- cgit v1.2.1 From 03621b60529edfbeb32d199fa754da19574cfefc Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 20 Nov 2013 09:23:44 +0900 Subject: gpio: em: Enable mask on suspend Now when lazy interrupt disable has been enabled in the driver then extend the code to set IRQCHIP_MASK_ON_SUSPEND which tells the core that only IRQs marked as wakeups need to stay enabled during Suspend-to-RAM. Tested on the KZM9D board with GPIO-keys. Signed-off-by: Magnus Damm Acked-by: Laurent Pinchart Signed-off-by: Linus Walleij --- drivers/gpio/gpio-em.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c index 225eda662c6c..be7e3b92f986 100644 --- a/drivers/gpio/gpio-em.c +++ b/drivers/gpio/gpio-em.c @@ -338,7 +338,7 @@ static int em_gio_probe(struct platform_device *pdev) irq_chip->irq_mask = em_gio_irq_disable; irq_chip->irq_unmask = em_gio_irq_enable; irq_chip->irq_set_type = em_gio_irq_set_type; - irq_chip->flags = IRQCHIP_SKIP_SET_WAKE; + irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND; p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, pdata->number_of_pins, -- cgit v1.2.1 From e5428a682ca726249a89201c79ddd0599669c484 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 26 Nov 2013 14:28:32 +0100 Subject: gpio: drop users of irq_set_chip_and_handler_name() Switch all users of irq_set_chip_and_handler_name() to simply use irq_set_chip_and_handler(), all just provide a boilerplate name like "demux" or "mux" - a fact which is anyway obvious from the hwirq number from the irqdomain now present in e.g. /proc/interrupts. Cc: Mathias Nyman Cc: Dan Carpenter Acked-by: David Cohen Acked-by: Mika Westerberg Tested-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/gpio/gpio-intel-mid.c | 3 +-- drivers/gpio/gpio-lynxpoint.c | 3 +-- drivers/gpio/gpio-msic.c | 7 +++---- drivers/gpio/gpio-timberdale.c | 4 ++-- 4 files changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c index be803af658ac..17f135046c7f 100644 --- a/drivers/gpio/gpio-intel-mid.c +++ b/drivers/gpio/gpio-intel-mid.c @@ -358,8 +358,7 @@ static int intel_gpio_irq_map(struct irq_domain *d, unsigned int irq, { struct intel_mid_gpio *priv = d->host_data; - irq_set_chip_and_handler_name(irq, &intel_mid_irqchip, - handle_simple_irq, "demux"); + irq_set_chip_and_handler(irq, &intel_mid_irqchip, handle_simple_irq); irq_set_chip_data(irq, priv); irq_set_irq_type(irq, IRQ_TYPE_NONE); diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c index f1ca9d5880b6..89867ed7bd50 100644 --- a/drivers/gpio/gpio-lynxpoint.c +++ b/drivers/gpio/gpio-lynxpoint.c @@ -331,8 +331,7 @@ static int lp_gpio_irq_map(struct irq_domain *d, unsigned int irq, { struct lp_gpio *lg = d->host_data; - irq_set_chip_and_handler_name(irq, &lp_irqchip, handle_simple_irq, - "demux"); + irq_set_chip_and_handler(irq, &lp_irqchip, handle_simple_irq); irq_set_chip_data(irq, lg); irq_set_irq_type(irq, IRQ_TYPE_NONE); diff --git a/drivers/gpio/gpio-msic.c b/drivers/gpio/gpio-msic.c index d75eaa3a1dcc..69d60ab1d698 100644 --- a/drivers/gpio/gpio-msic.c +++ b/drivers/gpio/gpio-msic.c @@ -305,10 +305,9 @@ static int platform_msic_gpio_probe(struct platform_device *pdev) for (i = 0; i < mg->chip.ngpio; i++) { irq_set_chip_data(i + mg->irq_base, mg); - irq_set_chip_and_handler_name(i + mg->irq_base, - &msic_irqchip, - handle_simple_irq, - "demux"); + irq_set_chip_and_handler(i + mg->irq_base, + &msic_irqchip, + handle_simple_irq); } irq_set_chained_handler(mg->irq, msic_gpio_irq_handler); irq_set_handler_data(mg->irq, mg); diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c index 7a0e956ef1ed..521971e6a9f5 100644 --- a/drivers/gpio/gpio-timberdale.c +++ b/drivers/gpio/gpio-timberdale.c @@ -290,8 +290,8 @@ static int timbgpio_probe(struct platform_device *pdev) return 0; for (i = 0; i < pdata->nr_pins; i++) { - irq_set_chip_and_handler_name(tgpio->irq_base + i, - &timbgpio_irqchip, handle_simple_irq, "mux"); + irq_set_chip_and_handler(tgpio->irq_base + i, + &timbgpio_irqchip, handle_simple_irq); irq_set_chip_data(tgpio->irq_base + i, tgpio); #ifdef CONFIG_ARM set_irq_flags(tgpio->irq_base + i, IRQF_VALID | IRQF_PROBE); -- cgit v1.2.1 From eef80f333fe659b2a5782abcaae93848d3963b57 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 21 Nov 2013 13:55:14 +0100 Subject: ARM: lpc32xx: move custom GPIO header Move to . Acked-by: Roland Stigge Signed-off-by: Linus Walleij --- drivers/gpio/gpio-lpc32xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c index 2d5555decf0c..a7093e010149 100644 --- a/drivers/gpio/gpio-lpc32xx.c +++ b/drivers/gpio/gpio-lpc32xx.c @@ -25,10 +25,10 @@ #include #include #include +#include #include #include -#include #include #define LPC32XX_GPIO_P3_INP_STATE _GPREG(0x000) -- cgit v1.2.1 From d463c6ff88108d187c73396280f5dae8b4a78e65 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 27 Nov 2013 15:46:06 +0100 Subject: gpio-lynxpoint: Allow building as a module Change CONFIG_GPIO_LYNXPOINT from bool to tristate so that the gpio-lynxpoint driver can be built as a module. Add the required glue: an exit function to unregister the driver, and module information. Signed-off-by: Jean Delvare Cc: Mathias Nyman Cc: Linus Walleij Acked-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 2 +- drivers/gpio/gpio-lynxpoint.c | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 0f0444475bf0..58d98dd9e4b9 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -353,7 +353,7 @@ config GPIO_GE_FPGA board computers. config GPIO_LYNXPOINT - bool "Intel Lynxpoint GPIO support" + tristate "Intel Lynxpoint GPIO support" depends on ACPI && X86 select IRQ_DOMAIN help diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c index 89867ed7bd50..1a7443ee6016 100644 --- a/drivers/gpio/gpio-lynxpoint.c +++ b/drivers/gpio/gpio-lynxpoint.c @@ -469,4 +469,15 @@ static int __init lp_gpio_init(void) return platform_driver_register(&lp_gpio_driver); } +static void __exit lp_gpio_exit(void) +{ + platform_driver_unregister(&lp_gpio_driver); +} + subsys_initcall(lp_gpio_init); +module_exit(lp_gpio_exit); + +MODULE_AUTHOR("Mathias Nyman (Intel)"); +MODULE_DESCRIPTION("GPIO interface for Intel Lynxpoint"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:lp_gpio"); -- cgit v1.2.1 From 850dfe17e3c467f50a0b9a527a65831873740c23 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 29 Nov 2013 14:48:00 +0100 Subject: gpio: rcar: Support both edge trigger with DT Some versions of the R-Car GPIO controller support triggering on both edges of the input signal. Whether this capability is supported is currently specified in platform data. R-Car GPIO devices instantiated from the device tree have the capability turned off even when the hardware supports it. To fix this, add DT match data support to the driver, initialize both edge trigger support from match data and enable both edge trigger in r8a7790 and r8a7791 match data. Signed-off-by: Laurent Pinchart Acked-by: Magnus Damm Signed-off-by: Linus Walleij --- drivers/gpio/gpio-rcar.c | 56 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 13 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index d2c34da7b3bf..28fa94a316ff 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -284,7 +284,34 @@ static struct irq_domain_ops gpio_rcar_irq_domain_ops = { .map = gpio_rcar_irq_domain_map, }; -static void gpio_rcar_parse_pdata(struct gpio_rcar_priv *p) +struct gpio_rcar_info { + bool has_both_edge_trigger; +}; + +static const struct of_device_id gpio_rcar_of_table[] = { + { + .compatible = "renesas,gpio-r8a7790", + .data = (void *)&(const struct gpio_rcar_info) { + .has_both_edge_trigger = true, + }, + }, { + .compatible = "renesas,gpio-r8a7791", + .data = (void *)&(const struct gpio_rcar_info) { + .has_both_edge_trigger = true, + }, + }, { + .compatible = "renesas,gpio-rcar", + .data = (void *)&(const struct gpio_rcar_info) { + .has_both_edge_trigger = false, + }, + }, { + /* Terminator */ + }, +}; + +MODULE_DEVICE_TABLE(of, gpio_rcar_of_table); + +static int gpio_rcar_parse_pdata(struct gpio_rcar_priv *p) { struct gpio_rcar_config *pdata = dev_get_platdata(&p->pdev->dev); struct device_node *np = p->pdev->dev.of_node; @@ -294,11 +321,21 @@ static void gpio_rcar_parse_pdata(struct gpio_rcar_priv *p) if (pdata) { p->config = *pdata; } else if (IS_ENABLED(CONFIG_OF) && np) { + const struct of_device_id *match; + const struct gpio_rcar_info *info; + + match = of_match_node(gpio_rcar_of_table, np); + if (!match) + return -EINVAL; + + info = match->data; + ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &args); p->config.number_of_pins = ret == 0 ? args.args[2] : RCAR_MAX_GPIO_PER_BANK; p->config.gpio_base = -1; + p->config.has_both_edge_trigger = info->has_both_edge_trigger; } if (p->config.number_of_pins == 0 || @@ -308,6 +345,8 @@ static void gpio_rcar_parse_pdata(struct gpio_rcar_priv *p) p->config.number_of_pins, RCAR_MAX_GPIO_PER_BANK); p->config.number_of_pins = RCAR_MAX_GPIO_PER_BANK; } + + return 0; } static int gpio_rcar_probe(struct platform_device *pdev) @@ -330,7 +369,9 @@ static int gpio_rcar_probe(struct platform_device *pdev) spin_lock_init(&p->lock); /* Get device configuration from DT node or platform data. */ - gpio_rcar_parse_pdata(p); + ret = gpio_rcar_parse_pdata(p); + if (ret < 0) + return ret; platform_set_drvdata(pdev, p); @@ -434,17 +475,6 @@ static int gpio_rcar_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_OF -static const struct of_device_id gpio_rcar_of_table[] = { - { - .compatible = "renesas,gpio-rcar", - }, - { }, -}; - -MODULE_DEVICE_TABLE(of, gpio_rcar_of_table); -#endif - static struct platform_driver gpio_rcar_device_driver = { .probe = gpio_rcar_probe, .remove = gpio_rcar_remove, -- cgit v1.2.1 From 0299b77b44531ae0963fe86d8b9cb9b5ddb584b7 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Fri, 29 Nov 2013 12:11:34 +0100 Subject: gpio: Add MOXA ART GPIO driver Add GPIO driver for MOXA ART SoCs. Signed-off-by: Jonas Jensen Acked-by: Arnd Bergmann Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 7 ++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-moxart.c | 162 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 170 insertions(+) create mode 100644 drivers/gpio/gpio-moxart.c (limited to 'drivers/gpio') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 58d98dd9e4b9..ae3682d25a3c 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -156,6 +156,13 @@ config GPIO_F7188X To compile this driver as a module, choose M here: the module will be called f7188x-gpio. +config GPIO_MOXART + bool "MOXART GPIO support" + depends on ARCH_MOXART + help + Select this option to enable GPIO driver for + MOXA ART SoC devices. + config GPIO_MPC5200 def_bool y depends on PPC_MPC52xx diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 7971e36b8b12..ee95154cb1d2 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o obj-$(CONFIG_GPIO_MM_LANTIQ) += gpio-mm-lantiq.o +obj-$(CONFIG_GPIO_MOXART) += gpio-moxart.o obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o diff --git a/drivers/gpio/gpio-moxart.c b/drivers/gpio/gpio-moxart.c new file mode 100644 index 000000000000..d662cdededac --- /dev/null +++ b/drivers/gpio/gpio-moxart.c @@ -0,0 +1,162 @@ +/* + * MOXA ART SoCs GPIO driver. + * + * Copyright (C) 2013 Jonas Jensen + * + * Jonas Jensen + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GPIO_DATA_OUT 0x00 +#define GPIO_DATA_IN 0x04 +#define GPIO_PIN_DIRECTION 0x08 + +struct moxart_gpio_chip { + struct gpio_chip gpio; + void __iomem *moxart_gpio_base; +}; + +static inline struct moxart_gpio_chip *to_moxart_gpio(struct gpio_chip *chip) +{ + return container_of(chip, struct moxart_gpio_chip, gpio); +} + +static int moxart_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + return pinctrl_request_gpio(offset); +} + +static void moxart_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + pinctrl_free_gpio(offset); +} + +static int moxart_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + struct moxart_gpio_chip *gc = to_moxart_gpio(chip); + void __iomem *ioaddr = gc->moxart_gpio_base + GPIO_PIN_DIRECTION; + + writel(readl(ioaddr) & ~BIT(offset), ioaddr); + return 0; +} + +static int moxart_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct moxart_gpio_chip *gc = to_moxart_gpio(chip); + void __iomem *ioaddr = gc->moxart_gpio_base + GPIO_PIN_DIRECTION; + + writel(readl(ioaddr) | BIT(offset), ioaddr); + return 0; +} + +static void moxart_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + struct moxart_gpio_chip *gc = to_moxart_gpio(chip); + void __iomem *ioaddr = gc->moxart_gpio_base + GPIO_DATA_OUT; + u32 reg = readl(ioaddr); + + if (value) + reg = reg | BIT(offset); + else + reg = reg & ~BIT(offset); + + + writel(reg, ioaddr); +} + +static int moxart_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct moxart_gpio_chip *gc = to_moxart_gpio(chip); + u32 ret = readl(gc->moxart_gpio_base + GPIO_PIN_DIRECTION); + + if (ret & BIT(offset)) + return !!(readl(gc->moxart_gpio_base + GPIO_DATA_OUT) & + BIT(offset)); + else + return !!(readl(gc->moxart_gpio_base + GPIO_DATA_IN) & + BIT(offset)); +} + +static struct gpio_chip moxart_template_chip = { + .label = "moxart-gpio", + .request = moxart_gpio_request, + .free = moxart_gpio_free, + .direction_input = moxart_gpio_direction_input, + .direction_output = moxart_gpio_direction_output, + .set = moxart_gpio_set, + .get = moxart_gpio_get, + .base = 0, + .ngpio = 32, + .can_sleep = 0, +}; + +static int moxart_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct resource *res; + struct moxart_gpio_chip *mgc; + int ret; + + mgc = devm_kzalloc(dev, sizeof(*mgc), GFP_KERNEL); + if (!mgc) { + dev_err(dev, "can't allocate GPIO chip container\n"); + return -ENOMEM; + } + mgc->gpio = moxart_template_chip; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mgc->moxart_gpio_base = devm_ioremap_resource(dev, res); + if (IS_ERR(mgc->moxart_gpio_base)) { + dev_err(dev, "%s: devm_ioremap_resource res_gpio failed\n", + dev->of_node->full_name); + return PTR_ERR(mgc->moxart_gpio_base); + } + + mgc->gpio.dev = dev; + + ret = gpiochip_add(&mgc->gpio); + if (ret) { + dev_err(dev, "%s: gpiochip_add failed\n", + dev->of_node->full_name); + return ret; + } + + return 0; +} + +static const struct of_device_id moxart_gpio_match[] = { + { .compatible = "moxa,moxart-gpio" }, + { } +}; + +static struct platform_driver moxart_gpio_driver = { + .driver = { + .name = "moxart-gpio", + .owner = THIS_MODULE, + .of_match_table = moxart_gpio_match, + }, + .probe = moxart_gpio_probe, +}; +module_platform_driver(moxart_gpio_driver); + +MODULE_DESCRIPTION("MOXART GPIO chip driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jonas Jensen "); -- cgit v1.2.1 From 14f4a8838acac0fe6bf710ec08fc4cce57c0011b Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 3 Dec 2013 08:08:45 +0900 Subject: gpio: remove DEFINE_PCI_DEVICE_TABLE macro Don't use DEFINE_PCI_DEVICE_TABLE macro, because this macro is not preferred. Signed-off-by: Jingoo Han Signed-off-by: Linus Walleij --- drivers/gpio/gpio-amd8111.c | 2 +- drivers/gpio/gpio-bt8xx.c | 2 +- drivers/gpio/gpio-intel-mid.c | 2 +- drivers/gpio/gpio-ml-ioh.c | 2 +- drivers/gpio/gpio-pch.c | 2 +- drivers/gpio/gpio-sodaville.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-amd8111.c b/drivers/gpio/gpio-amd8111.c index 710fafcdd1b1..94e9992f8904 100644 --- a/drivers/gpio/gpio-amd8111.c +++ b/drivers/gpio/gpio-amd8111.c @@ -60,7 +60,7 @@ * register a pci_driver, because someone else might one day * want to register another driver on the same PCI id. */ -static DEFINE_PCI_DEVICE_TABLE(pci_tbl) = { +static const struct pci_device_id pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS), 0 }, { 0, }, /* terminate list */ }; diff --git a/drivers/gpio/gpio-bt8xx.c b/drivers/gpio/gpio-bt8xx.c index 9dfe36fd8baf..c5c356b7f2ce 100644 --- a/drivers/gpio/gpio-bt8xx.c +++ b/drivers/gpio/gpio-bt8xx.c @@ -308,7 +308,7 @@ static int bt8xxgpio_resume(struct pci_dev *pdev) #define bt8xxgpio_resume NULL #endif /* CONFIG_PM */ -static DEFINE_PCI_DEVICE_TABLE(bt8xxgpio_pci_tbl) = { +static const struct pci_device_id bt8xxgpio_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848) }, { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849) }, { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878) }, diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c index 17f135046c7f..f2035c01577f 100644 --- a/drivers/gpio/gpio-intel-mid.c +++ b/drivers/gpio/gpio-intel-mid.c @@ -275,7 +275,7 @@ static const struct intel_mid_gpio_ddata gpio_tangier = { .chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE, }; -static DEFINE_PCI_DEVICE_TABLE(intel_gpio_ids) = { +static const struct pci_device_id intel_gpio_ids[] = { { /* Lincroft */ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f), diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c index 6da6d7667c6d..5c94af3c84e0 100644 --- a/drivers/gpio/gpio-ml-ioh.c +++ b/drivers/gpio/gpio-ml-ioh.c @@ -596,7 +596,7 @@ static int ioh_gpio_resume(struct pci_dev *pdev) #define ioh_gpio_resume NULL #endif -static DEFINE_PCI_DEVICE_TABLE(ioh_gpio_pcidev_id) = { +static const struct pci_device_id ioh_gpio_pcidev_id[] = { { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x802E) }, { 0, } }; diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index 0fec097e838d..ef7a756c9ded 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c @@ -518,7 +518,7 @@ static int pch_gpio_resume(struct pci_dev *pdev) #endif #define PCI_VENDOR_ID_ROHM 0x10DB -static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = { +static const struct pci_device_id pch_gpio_pcidev_id[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) }, { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) }, { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8043) }, diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c index 88f374ac7753..5d171e0182db 100644 --- a/drivers/gpio/gpio-sodaville.c +++ b/drivers/gpio/gpio-sodaville.c @@ -270,7 +270,7 @@ static void sdv_gpio_remove(struct pci_dev *pdev) kfree(sd); } -static DEFINE_PCI_DEVICE_TABLE(sdv_gpio_pci_ids) = { +static const struct pci_device_id sdv_gpio_pci_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_SDV_GPIO) }, { 0, }, }; -- cgit v1.2.1 From a87854da2c55b15adc7326a9ee5f8fde281ffe43 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Mon, 2 Dec 2013 11:27:59 +0100 Subject: gpio: MOXA ART: rename moxart_gpio_base to base Renaming "moxart_gpio_base" to "base" allows better fit, remove line breaks in moxart_gpio_get(). While doing trivial cleanup, also remove fields initialized with zero in moxart_template_chip. Signed-off-by: Jonas Jensen Signed-off-by: Linus Walleij --- drivers/gpio/gpio-moxart.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-moxart.c b/drivers/gpio/gpio-moxart.c index d662cdededac..4ecd195e4a5b 100644 --- a/drivers/gpio/gpio-moxart.c +++ b/drivers/gpio/gpio-moxart.c @@ -30,7 +30,7 @@ struct moxart_gpio_chip { struct gpio_chip gpio; - void __iomem *moxart_gpio_base; + void __iomem *base; }; static inline struct moxart_gpio_chip *to_moxart_gpio(struct gpio_chip *chip) @@ -51,7 +51,7 @@ static void moxart_gpio_free(struct gpio_chip *chip, unsigned offset) static int moxart_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { struct moxart_gpio_chip *gc = to_moxart_gpio(chip); - void __iomem *ioaddr = gc->moxart_gpio_base + GPIO_PIN_DIRECTION; + void __iomem *ioaddr = gc->base + GPIO_PIN_DIRECTION; writel(readl(ioaddr) & ~BIT(offset), ioaddr); return 0; @@ -61,7 +61,7 @@ static int moxart_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { struct moxart_gpio_chip *gc = to_moxart_gpio(chip); - void __iomem *ioaddr = gc->moxart_gpio_base + GPIO_PIN_DIRECTION; + void __iomem *ioaddr = gc->base + GPIO_PIN_DIRECTION; writel(readl(ioaddr) | BIT(offset), ioaddr); return 0; @@ -70,7 +70,7 @@ static int moxart_gpio_direction_output(struct gpio_chip *chip, static void moxart_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { struct moxart_gpio_chip *gc = to_moxart_gpio(chip); - void __iomem *ioaddr = gc->moxart_gpio_base + GPIO_DATA_OUT; + void __iomem *ioaddr = gc->base + GPIO_DATA_OUT; u32 reg = readl(ioaddr); if (value) @@ -85,14 +85,12 @@ static void moxart_gpio_set(struct gpio_chip *chip, unsigned offset, int value) static int moxart_gpio_get(struct gpio_chip *chip, unsigned offset) { struct moxart_gpio_chip *gc = to_moxart_gpio(chip); - u32 ret = readl(gc->moxart_gpio_base + GPIO_PIN_DIRECTION); + u32 ret = readl(gc->base + GPIO_PIN_DIRECTION); if (ret & BIT(offset)) - return !!(readl(gc->moxart_gpio_base + GPIO_DATA_OUT) & - BIT(offset)); + return !!(readl(gc->base + GPIO_DATA_OUT) & BIT(offset)); else - return !!(readl(gc->moxart_gpio_base + GPIO_DATA_IN) & - BIT(offset)); + return !!(readl(gc->base + GPIO_DATA_IN) & BIT(offset)); } static struct gpio_chip moxart_template_chip = { @@ -103,9 +101,7 @@ static struct gpio_chip moxart_template_chip = { .direction_output = moxart_gpio_direction_output, .set = moxart_gpio_set, .get = moxart_gpio_get, - .base = 0, .ngpio = 32, - .can_sleep = 0, }; static int moxart_gpio_probe(struct platform_device *pdev) @@ -123,11 +119,11 @@ static int moxart_gpio_probe(struct platform_device *pdev) mgc->gpio = moxart_template_chip; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mgc->moxart_gpio_base = devm_ioremap_resource(dev, res); - if (IS_ERR(mgc->moxart_gpio_base)) { + mgc->base = devm_ioremap_resource(dev, res); + if (IS_ERR(mgc->base)) { dev_err(dev, "%s: devm_ioremap_resource res_gpio failed\n", dev->of_node->full_name); - return PTR_ERR(mgc->moxart_gpio_base); + return PTR_ERR(mgc->base); } mgc->gpio.dev = dev; -- cgit v1.2.1 From b7d0a28a9f65c4f8a547ceece820b8167a854968 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Tue, 3 Dec 2013 12:31:11 +0900 Subject: gpio: rewrite gpiochip_offset_to_desc() gpiochip_offset_to_desc() was using gpio_to_desc(), which directly addresses the global GPIO array we are hoping to get rid of someday. Reimplement it using the descriptor array of the chip itself, after checking the requested offset is within the valid bounds of the chip. Signed-off-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 4e10b10d3ddd..c6326e44e2c0 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -150,9 +150,10 @@ EXPORT_SYMBOL_GPL(gpio_to_desc); static struct gpio_desc *gpiochip_offset_to_desc(struct gpio_chip *chip, unsigned int offset) { - unsigned int gpio = chip->base + offset; + if (offset >= chip->ngpio) + return ERR_PTR(-EINVAL); - return gpio_to_desc(gpio); + return &chip->desc[offset]; } /** -- cgit v1.2.1 From 9fb1f39eb2d6707d265087ee186376e24995f55a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 4 Dec 2013 14:42:46 +0100 Subject: gpio/pinctrl: make gpio_chip members typed boolean This switches the two members of struct gpio_chip that were defined as unsigned foo:1 to bool, because that is indeed what they are. Switch all users in the gpio and pinctrl subsystems to assign these values with true/false instead of 0/1. The users outside these subsystems will survive since true/false is 1/0, atleast we set some kind of more strict typing example. Signed-off-by: Linus Walleij --- drivers/gpio/gpio-74x164.c | 2 +- drivers/gpio/gpio-adnp.c | 2 +- drivers/gpio/gpio-adp5520.c | 2 +- drivers/gpio/gpio-adp5588.c | 2 +- drivers/gpio/gpio-arizona.c | 2 +- drivers/gpio/gpio-bt8xx.c | 2 +- drivers/gpio/gpio-da9052.c | 2 +- drivers/gpio/gpio-da9055.c | 2 +- drivers/gpio/gpio-ich.c | 2 +- drivers/gpio/gpio-intel-mid.c | 2 +- drivers/gpio/gpio-kempld.c | 2 +- drivers/gpio/gpio-ks8695.c | 2 +- drivers/gpio/gpio-lpc32xx.c | 12 ++++++------ drivers/gpio/gpio-lynxpoint.c | 2 +- drivers/gpio/gpio-max730x.c | 2 +- drivers/gpio/gpio-max732x.c | 2 +- drivers/gpio/gpio-mc33880.c | 2 +- drivers/gpio/gpio-mc9s08dz60.c | 2 +- drivers/gpio/gpio-mcp23s08.c | 2 +- drivers/gpio/gpio-ml-ioh.c | 2 +- drivers/gpio/gpio-msic.c | 2 +- drivers/gpio/gpio-mvebu.c | 2 +- drivers/gpio/gpio-octeon.c | 2 +- drivers/gpio/gpio-palmas.c | 2 +- drivers/gpio/gpio-pca953x.c | 2 +- drivers/gpio/gpio-pcf857x.c | 2 +- drivers/gpio/gpio-pch.c | 2 +- drivers/gpio/gpio-rc5t583.c | 2 +- drivers/gpio/gpio-sta2x11.c | 2 +- drivers/gpio/gpio-stmpe.c | 2 +- drivers/gpio/gpio-sx150x.c | 2 +- drivers/gpio/gpio-tb10x.c | 2 +- drivers/gpio/gpio-tc3589x.c | 2 +- drivers/gpio/gpio-timberdale.c | 2 +- drivers/gpio/gpio-tnetv107x.c | 2 +- drivers/gpio/gpio-tps6586x.c | 2 +- drivers/gpio/gpio-tps65910.c | 2 +- drivers/gpio/gpio-tps65912.c | 2 +- drivers/gpio/gpio-twl4030.c | 2 +- drivers/gpio/gpio-twl6040.c | 2 +- drivers/gpio/gpio-ucb1400.c | 2 +- drivers/gpio/gpio-viperboard.c | 4 ++-- drivers/gpio/gpio-vx855.c | 2 +- drivers/gpio/gpio-wm831x.c | 2 +- drivers/gpio/gpio-wm8350.c | 2 +- drivers/gpio/gpio-wm8994.c | 2 +- drivers/gpio/gpiolib.c | 2 +- 47 files changed, 53 insertions(+), 53 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c index 1e04bf91328d..ddb831232407 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c @@ -159,7 +159,7 @@ static int gen_74x164_probe(struct spi_device *spi) goto exit_destroy; } - chip->gpio_chip.can_sleep = 1; + chip->gpio_chip.can_sleep = true; chip->gpio_chip.dev = &spi->dev; chip->gpio_chip.owner = THIS_MODULE; diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c index b204033acaeb..030a3897d9f7 100644 --- a/drivers/gpio/gpio-adnp.c +++ b/drivers/gpio/gpio-adnp.c @@ -260,7 +260,7 @@ static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios) chip->direction_output = adnp_gpio_direction_output; chip->get = adnp_gpio_get; chip->set = adnp_gpio_set; - chip->can_sleep = 1; + chip->can_sleep = true; if (IS_ENABLED(CONFIG_DEBUG_FS)) chip->dbg_show = adnp_gpio_dbg_show; diff --git a/drivers/gpio/gpio-adp5520.c b/drivers/gpio/gpio-adp5520.c index 084337d5514d..613265944e2e 100644 --- a/drivers/gpio/gpio-adp5520.c +++ b/drivers/gpio/gpio-adp5520.c @@ -127,7 +127,7 @@ static int adp5520_gpio_probe(struct platform_device *pdev) gc->direction_output = adp5520_gpio_direction_output; gc->get = adp5520_gpio_get_value; gc->set = adp5520_gpio_set_value; - gc->can_sleep = 1; + gc->can_sleep = true; gc->base = pdata->gpio_start; gc->ngpio = gpios; diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/gpio-adp5588.c index 90fc4c99c024..3f190e68f973 100644 --- a/drivers/gpio/gpio-adp5588.c +++ b/drivers/gpio/gpio-adp5588.c @@ -380,7 +380,7 @@ static int adp5588_gpio_probe(struct i2c_client *client, gc->direction_output = adp5588_gpio_direction_output; gc->get = adp5588_gpio_get_value; gc->set = adp5588_gpio_set_value; - gc->can_sleep = 1; + gc->can_sleep = true; gc->base = pdata->gpio_start; gc->ngpio = ADP5588_MAXGPIO; diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c index dceb5dcf9d16..29bdff558981 100644 --- a/drivers/gpio/gpio-arizona.c +++ b/drivers/gpio/gpio-arizona.c @@ -91,7 +91,7 @@ static struct gpio_chip template_chip = { .get = arizona_gpio_get, .direction_output = arizona_gpio_direction_out, .set = arizona_gpio_set, - .can_sleep = 1, + .can_sleep = true, }; static int arizona_gpio_probe(struct platform_device *pdev) diff --git a/drivers/gpio/gpio-bt8xx.c b/drivers/gpio/gpio-bt8xx.c index c5c356b7f2ce..ecb3ca2d1d10 100644 --- a/drivers/gpio/gpio-bt8xx.c +++ b/drivers/gpio/gpio-bt8xx.c @@ -169,7 +169,7 @@ static void bt8xxgpio_gpio_setup(struct bt8xxgpio *bg) c->dbg_show = NULL; c->base = modparam_gpiobase; c->ngpio = BT8XXGPIO_NR_GPIOS; - c->can_sleep = 0; + c->can_sleep = false; } static int bt8xxgpio_probe(struct pci_dev *dev, diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c index 9b77dc05d4ad..416cdf786b05 100644 --- a/drivers/gpio/gpio-da9052.c +++ b/drivers/gpio/gpio-da9052.c @@ -200,7 +200,7 @@ static struct gpio_chip reference_gp = { .direction_input = da9052_gpio_direction_input, .direction_output = da9052_gpio_direction_output, .to_irq = da9052_gpio_to_irq, - .can_sleep = 1, + .can_sleep = true, .ngpio = 16, .base = -1, }; diff --git a/drivers/gpio/gpio-da9055.c b/drivers/gpio/gpio-da9055.c index 7ef0820032bd..f992997bc301 100644 --- a/drivers/gpio/gpio-da9055.c +++ b/drivers/gpio/gpio-da9055.c @@ -134,7 +134,7 @@ static struct gpio_chip reference_gp = { .direction_input = da9055_gpio_direction_input, .direction_output = da9055_gpio_direction_output, .to_irq = da9055_gpio_to_irq, - .can_sleep = 1, + .can_sleep = true, .ngpio = 3, .base = -1, }; diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c index 814addb62d2c..f5bf3c38bca6 100644 --- a/drivers/gpio/gpio-ich.c +++ b/drivers/gpio/gpio-ich.c @@ -252,7 +252,7 @@ static void ichx_gpiolib_setup(struct gpio_chip *chip) chip->direction_output = ichx_gpio_direction_output; chip->base = modparam_gpiobase; chip->ngpio = ichx_priv.desc->ngpio; - chip->can_sleep = 0; + chip->can_sleep = false; chip->dbg_show = NULL; } diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c index f2035c01577f..1535ebae8fc8 100644 --- a/drivers/gpio/gpio-intel-mid.c +++ b/drivers/gpio/gpio-intel-mid.c @@ -425,7 +425,7 @@ static int intel_gpio_probe(struct pci_dev *pdev, priv->chip.to_irq = intel_gpio_to_irq; priv->chip.base = gpio_base; priv->chip.ngpio = ddata->ngpio; - priv->chip.can_sleep = 0; + priv->chip.can_sleep = false; priv->pdev = pdev; spin_lock_init(&priv->lock); diff --git a/drivers/gpio/gpio-kempld.c b/drivers/gpio/gpio-kempld.c index efdc3924d7df..c6d88173f5a2 100644 --- a/drivers/gpio/gpio-kempld.c +++ b/drivers/gpio/gpio-kempld.c @@ -167,7 +167,7 @@ static int kempld_gpio_probe(struct platform_device *pdev) chip->label = "gpio-kempld"; chip->owner = THIS_MODULE; chip->dev = dev; - chip->can_sleep = 1; + chip->can_sleep = true; if (pdata && pdata->gpio_base) chip->base = pdata->gpio_base; else diff --git a/drivers/gpio/gpio-ks8695.c b/drivers/gpio/gpio-ks8695.c index a3ac66ea364b..464a83de0d6a 100644 --- a/drivers/gpio/gpio-ks8695.c +++ b/drivers/gpio/gpio-ks8695.c @@ -228,7 +228,7 @@ static struct gpio_chip ks8695_gpio_chip = { .to_irq = ks8695_gpio_to_irq, .base = 0, .ngpio = 16, - .can_sleep = 0, + .can_sleep = false, }; /* Register the GPIOs */ diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c index a7093e010149..225344d66404 100644 --- a/drivers/gpio/gpio-lpc32xx.c +++ b/drivers/gpio/gpio-lpc32xx.c @@ -448,7 +448,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = { .base = LPC32XX_GPIO_P0_GRP, .ngpio = LPC32XX_GPIO_P0_MAX, .names = gpio_p0_names, - .can_sleep = 0, + .can_sleep = false, }, .gpio_grp = &gpio_grp_regs_p0, }, @@ -464,7 +464,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = { .base = LPC32XX_GPIO_P1_GRP, .ngpio = LPC32XX_GPIO_P1_MAX, .names = gpio_p1_names, - .can_sleep = 0, + .can_sleep = false, }, .gpio_grp = &gpio_grp_regs_p1, }, @@ -479,7 +479,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = { .base = LPC32XX_GPIO_P2_GRP, .ngpio = LPC32XX_GPIO_P2_MAX, .names = gpio_p2_names, - .can_sleep = 0, + .can_sleep = false, }, .gpio_grp = &gpio_grp_regs_p2, }, @@ -495,7 +495,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = { .base = LPC32XX_GPIO_P3_GRP, .ngpio = LPC32XX_GPIO_P3_MAX, .names = gpio_p3_names, - .can_sleep = 0, + .can_sleep = false, }, .gpio_grp = &gpio_grp_regs_p3, }, @@ -509,7 +509,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = { .base = LPC32XX_GPI_P3_GRP, .ngpio = LPC32XX_GPI_P3_MAX, .names = gpi_p3_names, - .can_sleep = 0, + .can_sleep = false, }, .gpio_grp = &gpio_grp_regs_p3, }, @@ -523,7 +523,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = { .base = LPC32XX_GPO_P3_GRP, .ngpio = LPC32XX_GPO_P3_MAX, .names = gpo_p3_names, - .can_sleep = 0, + .can_sleep = false, }, .gpio_grp = &gpio_grp_regs_p3, }, diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c index 1a7443ee6016..c283cd3b247a 100644 --- a/drivers/gpio/gpio-lynxpoint.c +++ b/drivers/gpio/gpio-lynxpoint.c @@ -391,7 +391,7 @@ static int lp_gpio_probe(struct platform_device *pdev) gc->set = lp_gpio_set; gc->base = -1; gc->ngpio = LP_NUM_GPIO; - gc->can_sleep = 0; + gc->can_sleep = false; gc->dev = dev; /* set up interrupts */ diff --git a/drivers/gpio/gpio-max730x.c b/drivers/gpio/gpio-max730x.c index f4f4ed19bdc1..89226a36b08c 100644 --- a/drivers/gpio/gpio-max730x.c +++ b/drivers/gpio/gpio-max730x.c @@ -188,7 +188,7 @@ int __max730x_probe(struct max7301 *ts) ts->chip.set = max7301_set; ts->chip.ngpio = PIN_NUMBER; - ts->chip.can_sleep = 1; + ts->chip.can_sleep = true; ts->chip.dev = dev; ts->chip.owner = THIS_MODULE; diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c index 91ad74dea8ce..36cb290764b6 100644 --- a/drivers/gpio/gpio-max732x.c +++ b/drivers/gpio/gpio-max732x.c @@ -564,7 +564,7 @@ static int max732x_setup_gpio(struct max732x_chip *chip, gc->set = max732x_gpio_set_value; } gc->get = max732x_gpio_get_value; - gc->can_sleep = 1; + gc->can_sleep = true; gc->base = gpio_start; gc->ngpio = port; diff --git a/drivers/gpio/gpio-mc33880.c b/drivers/gpio/gpio-mc33880.c index c0b7835f5136..553a80a5eaf3 100644 --- a/drivers/gpio/gpio-mc33880.c +++ b/drivers/gpio/gpio-mc33880.c @@ -115,7 +115,7 @@ static int mc33880_probe(struct spi_device *spi) mc->chip.set = mc33880_set; mc->chip.base = pdata->base; mc->chip.ngpio = PIN_NUMBER; - mc->chip.can_sleep = 1; + mc->chip.can_sleep = true; mc->chip.dev = &spi->dev; mc->chip.owner = THIS_MODULE; diff --git a/drivers/gpio/gpio-mc9s08dz60.c b/drivers/gpio/gpio-mc9s08dz60.c index 0ab700046a23..dce35ff00db7 100644 --- a/drivers/gpio/gpio-mc9s08dz60.c +++ b/drivers/gpio/gpio-mc9s08dz60.c @@ -102,7 +102,7 @@ static int mc9s08dz60_probe(struct i2c_client *client, mc9s->chip.dev = &client->dev; mc9s->chip.owner = THIS_MODULE; mc9s->chip.ngpio = GPIO_NUM; - mc9s->chip.can_sleep = 1; + mc9s->chip.can_sleep = true; mc9s->chip.get = mc9s08dz60_get_value; mc9s->chip.set = mc9s08dz60_set_value; mc9s->chip.direction_output = mc9s08dz60_direction_output; diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index 2deb0c5e54a4..b16401ee4766 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c @@ -425,7 +425,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, } mcp->chip.base = base; - mcp->chip.can_sleep = 1; + mcp->chip.can_sleep = true; mcp->chip.dev = dev; mcp->chip.owner = THIS_MODULE; diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c index 5c94af3c84e0..d51329d23d38 100644 --- a/drivers/gpio/gpio-ml-ioh.c +++ b/drivers/gpio/gpio-ml-ioh.c @@ -242,7 +242,7 @@ static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port) gpio->dbg_show = NULL; gpio->base = -1; gpio->ngpio = num_port; - gpio->can_sleep = 0; + gpio->can_sleep = false; gpio->to_irq = ioh_gpio_to_irq; } diff --git a/drivers/gpio/gpio-msic.c b/drivers/gpio/gpio-msic.c index 69d60ab1d698..8f70ded82a2b 100644 --- a/drivers/gpio/gpio-msic.c +++ b/drivers/gpio/gpio-msic.c @@ -292,7 +292,7 @@ static int platform_msic_gpio_probe(struct platform_device *pdev) mg->chip.to_irq = msic_gpio_to_irq; mg->chip.base = pdata->gpio_base; mg->chip.ngpio = MSIC_NUM_GPIO; - mg->chip.can_sleep = 1; + mg->chip.can_sleep = true; mg->chip.dev = dev; mutex_init(&mg->buslock); diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 3c3321f94053..a8908009803f 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -600,7 +600,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev) mvchip->chip.to_irq = mvebu_gpio_to_irq; mvchip->chip.base = id * MVEBU_MAX_GPIO_PER_BANK; mvchip->chip.ngpio = ngpios; - mvchip->chip.can_sleep = 0; + mvchip->chip.can_sleep = false; mvchip->chip.of_node = np; mvchip->chip.dbg_show = mvebu_gpio_dbg_show; diff --git a/drivers/gpio/gpio-octeon.c b/drivers/gpio/gpio-octeon.c index 71a4a318315d..dbb08546b9ec 100644 --- a/drivers/gpio/gpio-octeon.c +++ b/drivers/gpio/gpio-octeon.c @@ -111,7 +111,7 @@ static int octeon_gpio_probe(struct platform_device *pdev) chip->dev = &pdev->dev; chip->owner = THIS_MODULE; chip->base = 0; - chip->can_sleep = 0; + chip->can_sleep = false; chip->ngpio = 20; chip->direction_input = octeon_gpio_dir_in; chip->get = octeon_gpio_get; diff --git a/drivers/gpio/gpio-palmas.c b/drivers/gpio/gpio-palmas.c index 11801e986dd9..da9d33252e56 100644 --- a/drivers/gpio/gpio-palmas.c +++ b/drivers/gpio/gpio-palmas.c @@ -182,7 +182,7 @@ static int palmas_gpio_probe(struct platform_device *pdev) palmas_gpio->gpio_chip.owner = THIS_MODULE; palmas_gpio->gpio_chip.label = dev_name(&pdev->dev); palmas_gpio->gpio_chip.ngpio = dev_data->ngpio; - palmas_gpio->gpio_chip.can_sleep = 1; + palmas_gpio->gpio_chip.can_sleep = true; palmas_gpio->gpio_chip.direction_input = palmas_gpio_input; palmas_gpio->gpio_chip.direction_output = palmas_gpio_output; palmas_gpio->gpio_chip.to_irq = palmas_gpio_to_irq; diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 6e48c07e3d8c..019b23b955a2 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -354,7 +354,7 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) gc->direction_output = pca953x_gpio_direction_output; gc->get = pca953x_gpio_get_value; gc->set = pca953x_gpio_set_value; - gc->can_sleep = 1; + gc->can_sleep = true; gc->base = chip->gpio_start; gc->ngpio = gpios; diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c index 1535686e74ea..82735822bc9d 100644 --- a/drivers/gpio/gpio-pcf857x.c +++ b/drivers/gpio/gpio-pcf857x.c @@ -305,7 +305,7 @@ static int pcf857x_probe(struct i2c_client *client, spin_lock_init(&gpio->slock); gpio->chip.base = pdata ? pdata->gpio_base : -1; - gpio->chip.can_sleep = 1; + gpio->chip.can_sleep = true; gpio->chip.dev = &client->dev; gpio->chip.owner = THIS_MODULE; gpio->chip.get = pcf857x_get; diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index ef7a756c9ded..9656c196772e 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c @@ -224,7 +224,7 @@ static void pch_gpio_setup(struct pch_gpio *chip) gpio->dbg_show = NULL; gpio->base = -1; gpio->ngpio = gpio_pins[chip->ioh]; - gpio->can_sleep = 0; + gpio->can_sleep = false; gpio->to_irq = pch_gpio_to_irq; } diff --git a/drivers/gpio/gpio-rc5t583.c b/drivers/gpio/gpio-rc5t583.c index e63d6a397e17..122b776fdc0b 100644 --- a/drivers/gpio/gpio-rc5t583.c +++ b/drivers/gpio/gpio-rc5t583.c @@ -133,7 +133,7 @@ static int rc5t583_gpio_probe(struct platform_device *pdev) rc5t583_gpio->gpio_chip.get = rc5t583_gpio_get, rc5t583_gpio->gpio_chip.to_irq = rc5t583_gpio_to_irq, rc5t583_gpio->gpio_chip.ngpio = RC5T583_MAX_GPIO, - rc5t583_gpio->gpio_chip.can_sleep = 1, + rc5t583_gpio->gpio_chip.can_sleep = true, rc5t583_gpio->gpio_chip.dev = &pdev->dev; rc5t583_gpio->gpio_chip.base = -1; rc5t583_gpio->rc5t583 = rc5t583; diff --git a/drivers/gpio/gpio-sta2x11.c b/drivers/gpio/gpio-sta2x11.c index f2fb12c18da9..68e3fcb1acea 100644 --- a/drivers/gpio/gpio-sta2x11.c +++ b/drivers/gpio/gpio-sta2x11.c @@ -146,7 +146,7 @@ static void gsta_gpio_setup(struct gsta_gpio *chip) /* called from probe */ gpio->dbg_show = NULL; gpio->base = gpio_base; gpio->ngpio = GSTA_NR_GPIO; - gpio->can_sleep = 0; + gpio->can_sleep = false; gpio->to_irq = gsta_gpio_to_irq; /* diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c index 2647e243d471..2776a09bee58 100644 --- a/drivers/gpio/gpio-stmpe.c +++ b/drivers/gpio/gpio-stmpe.c @@ -129,7 +129,7 @@ static struct gpio_chip template_chip = { .set = stmpe_gpio_set, .to_irq = stmpe_gpio_to_irq, .request = stmpe_gpio_request, - .can_sleep = 1, + .can_sleep = true, }; static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type) diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c index d2983e9ad6af..13d73fb2b5e1 100644 --- a/drivers/gpio/gpio-sx150x.c +++ b/drivers/gpio/gpio-sx150x.c @@ -436,7 +436,7 @@ static void sx150x_init_chip(struct sx150x_chip *chip, chip->gpio_chip.set = sx150x_gpio_set; chip->gpio_chip.to_irq = sx150x_gpio_to_irq; chip->gpio_chip.base = pdata->gpio_base; - chip->gpio_chip.can_sleep = 1; + chip->gpio_chip.can_sleep = true; chip->gpio_chip.ngpio = chip->dev_cfg->ngpios; if (pdata->oscio_is_gpo) ++chip->gpio_chip.ngpio; diff --git a/drivers/gpio/gpio-tb10x.c b/drivers/gpio/gpio-tb10x.c index 0502b9a041a5..66a54ea4f779 100644 --- a/drivers/gpio/gpio-tb10x.c +++ b/drivers/gpio/gpio-tb10x.c @@ -221,7 +221,7 @@ static int tb10x_gpio_probe(struct platform_device *pdev) tb10x_gpio->gc.free = tb10x_gpio_free; tb10x_gpio->gc.base = -1; tb10x_gpio->gc.ngpio = ngpio; - tb10x_gpio->gc.can_sleep = 0; + tb10x_gpio->gc.can_sleep = false; ret = gpiochip_add(&tb10x_gpio->gc); diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c index ddb5fefaa715..1019320984d7 100644 --- a/drivers/gpio/gpio-tc3589x.c +++ b/drivers/gpio/gpio-tc3589x.c @@ -127,7 +127,7 @@ static struct gpio_chip template_chip = { .direction_output = tc3589x_gpio_direction_output, .set = tc3589x_gpio_set, .to_irq = tc3589x_gpio_to_irq, - .can_sleep = 1, + .can_sleep = true, }; static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type) diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c index 521971e6a9f5..f9a8fbde108e 100644 --- a/drivers/gpio/gpio-timberdale.c +++ b/drivers/gpio/gpio-timberdale.c @@ -275,7 +275,7 @@ static int timbgpio_probe(struct platform_device *pdev) gc->dbg_show = NULL; gc->base = pdata->gpio_base; gc->ngpio = pdata->nr_pins; - gc->can_sleep = 0; + gc->can_sleep = false; err = gpiochip_add(gc); if (err) diff --git a/drivers/gpio/gpio-tnetv107x.c b/drivers/gpio/gpio-tnetv107x.c index 58445bb69106..4aa481579a05 100644 --- a/drivers/gpio/gpio-tnetv107x.c +++ b/drivers/gpio/gpio-tnetv107x.c @@ -176,7 +176,7 @@ static int __init tnetv107x_gpio_setup(void) ctlr = &chips[i]; ctlr->chip.label = "tnetv107x"; - ctlr->chip.can_sleep = 0; + ctlr->chip.can_sleep = false; ctlr->chip.base = base; ctlr->chip.ngpio = ngpio - base; if (ctlr->chip.ngpio > 32) diff --git a/drivers/gpio/gpio-tps6586x.c b/drivers/gpio/gpio-tps6586x.c index 29e8e750bd49..8994dfa13491 100644 --- a/drivers/gpio/gpio-tps6586x.c +++ b/drivers/gpio/gpio-tps6586x.c @@ -108,7 +108,7 @@ static int tps6586x_gpio_probe(struct platform_device *pdev) tps6586x_gpio->gpio_chip.label = pdev->name; tps6586x_gpio->gpio_chip.dev = &pdev->dev; tps6586x_gpio->gpio_chip.ngpio = 4; - tps6586x_gpio->gpio_chip.can_sleep = 1; + tps6586x_gpio->gpio_chip.can_sleep = true; /* FIXME: add handling of GPIOs as dedicated inputs */ tps6586x_gpio->gpio_chip.direction_output = tps6586x_gpio_output; diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c index 06146219d9d2..b6e818e68007 100644 --- a/drivers/gpio/gpio-tps65910.c +++ b/drivers/gpio/gpio-tps65910.c @@ -143,7 +143,7 @@ static int tps65910_gpio_probe(struct platform_device *pdev) default: return -EINVAL; } - tps65910_gpio->gpio_chip.can_sleep = 1; + tps65910_gpio->gpio_chip.can_sleep = true; tps65910_gpio->gpio_chip.direction_input = tps65910_gpio_input; tps65910_gpio->gpio_chip.direction_output = tps65910_gpio_output; tps65910_gpio->gpio_chip.set = tps65910_gpio_set; diff --git a/drivers/gpio/gpio-tps65912.c b/drivers/gpio/gpio-tps65912.c index 276a4229b032..59ee486cb8b9 100644 --- a/drivers/gpio/gpio-tps65912.c +++ b/drivers/gpio/gpio-tps65912.c @@ -79,7 +79,7 @@ static struct gpio_chip template_chip = { .direction_output = tps65912_gpio_output, .get = tps65912_gpio_get, .set = tps65912_gpio_set, - .can_sleep = 1, + .can_sleep = true, .ngpio = 5, .base = -1, }; diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c index 0c7e891c8651..cd06678a29f7 100644 --- a/drivers/gpio/gpio-twl4030.c +++ b/drivers/gpio/gpio-twl4030.c @@ -386,7 +386,7 @@ static struct gpio_chip template_chip = { .direction_output = twl_direction_out, .set = twl_set, .to_irq = twl_to_irq, - .can_sleep = 1, + .can_sleep = true, }; /*----------------------------------------------------------------------*/ diff --git a/drivers/gpio/gpio-twl6040.c b/drivers/gpio/gpio-twl6040.c index d420d30b86e7..0caf5cd1b47d 100644 --- a/drivers/gpio/gpio-twl6040.c +++ b/drivers/gpio/gpio-twl6040.c @@ -77,7 +77,7 @@ static struct gpio_chip twl6040gpo_chip = { .get = twl6040gpo_get, .direction_output = twl6040gpo_direction_out, .set = twl6040gpo_set, - .can_sleep = 1, + .can_sleep = true, }; /*----------------------------------------------------------------------*/ diff --git a/drivers/gpio/gpio-ucb1400.c b/drivers/gpio/gpio-ucb1400.c index 1a605f2a0f55..c6a53971387b 100644 --- a/drivers/gpio/gpio-ucb1400.c +++ b/drivers/gpio/gpio-ucb1400.c @@ -64,7 +64,7 @@ static int ucb1400_gpio_probe(struct platform_device *dev) ucb->gc.direction_output = ucb1400_gpio_dir_out; ucb->gc.get = ucb1400_gpio_get; ucb->gc.set = ucb1400_gpio_set; - ucb->gc.can_sleep = 1; + ucb->gc.can_sleep = true; err = gpiochip_add(&ucb->gc); if (err) diff --git a/drivers/gpio/gpio-viperboard.c b/drivers/gpio/gpio-viperboard.c index 5ac2919197fe..79e3b5836712 100644 --- a/drivers/gpio/gpio-viperboard.c +++ b/drivers/gpio/gpio-viperboard.c @@ -413,7 +413,7 @@ static int vprbrd_gpio_probe(struct platform_device *pdev) vb_gpio->gpioa.owner = THIS_MODULE; vb_gpio->gpioa.base = -1; vb_gpio->gpioa.ngpio = 16; - vb_gpio->gpioa.can_sleep = 1; + vb_gpio->gpioa.can_sleep = true; vb_gpio->gpioa.set = vprbrd_gpioa_set; vb_gpio->gpioa.get = vprbrd_gpioa_get; vb_gpio->gpioa.direction_input = vprbrd_gpioa_direction_input; @@ -430,7 +430,7 @@ static int vprbrd_gpio_probe(struct platform_device *pdev) vb_gpio->gpiob.owner = THIS_MODULE; vb_gpio->gpiob.base = -1; vb_gpio->gpiob.ngpio = 16; - vb_gpio->gpiob.can_sleep = 1; + vb_gpio->gpiob.can_sleep = true; vb_gpio->gpiob.set = vprbrd_gpiob_set; vb_gpio->gpiob.get = vprbrd_gpiob_get; vb_gpio->gpiob.direction_input = vprbrd_gpiob_direction_input; diff --git a/drivers/gpio/gpio-vx855.c b/drivers/gpio/gpio-vx855.c index cddfa22edb41..0fd23b6a753d 100644 --- a/drivers/gpio/gpio-vx855.c +++ b/drivers/gpio/gpio-vx855.c @@ -214,7 +214,7 @@ static void vx855gpio_gpio_setup(struct vx855_gpio *vg) c->dbg_show = NULL; c->base = 0; c->ngpio = NR_VX855_GP; - c->can_sleep = 0; + c->can_sleep = false; c->names = vx855gpio_names; } diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/gpio-wm831x.c index 456000c5c457..b18a1a26425e 100644 --- a/drivers/gpio/gpio-wm831x.c +++ b/drivers/gpio/gpio-wm831x.c @@ -240,7 +240,7 @@ static struct gpio_chip template_chip = { .to_irq = wm831x_gpio_to_irq, .set_debounce = wm831x_gpio_set_debounce, .dbg_show = wm831x_gpio_dbg_show, - .can_sleep = 1, + .can_sleep = true, }; static int wm831x_gpio_probe(struct platform_device *pdev) diff --git a/drivers/gpio/gpio-wm8350.c b/drivers/gpio/gpio-wm8350.c index fc49154be7b1..2487f9d575d3 100644 --- a/drivers/gpio/gpio-wm8350.c +++ b/drivers/gpio/gpio-wm8350.c @@ -106,7 +106,7 @@ static struct gpio_chip template_chip = { .direction_output = wm8350_gpio_direction_out, .set = wm8350_gpio_set, .to_irq = wm8350_gpio_to_irq, - .can_sleep = 1, + .can_sleep = true, }; static int wm8350_gpio_probe(struct platform_device *pdev) diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c index a53dbdefc7ee..d93b6b581677 100644 --- a/drivers/gpio/gpio-wm8994.c +++ b/drivers/gpio/gpio-wm8994.c @@ -242,7 +242,7 @@ static struct gpio_chip template_chip = { .set = wm8994_gpio_set, .to_irq = wm8994_gpio_to_irq, .dbg_show = wm8994_gpio_dbg_show, - .can_sleep = 1, + .can_sleep = true, }; static int wm8994_gpio_probe(struct platform_device *pdev) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index c6326e44e2c0..94467ddb3711 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1051,7 +1051,7 @@ static void gpiochip_unexport(struct gpio_chip *chip) if (dev) { put_device(dev); device_unregister(dev); - chip->exported = 0; + chip->exported = false; status = 0; } else status = -ENODEV; -- cgit v1.2.1 From f41cd3c2876bd31e7c71908548ae3c7a5b7ff649 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Nov 2013 13:34:56 +0100 Subject: gpio: lock adnp IRQs when enabling them This uses the new API for tagging GPIO lines as in use by IRQs. This enforces a few semantic checks on how the underlying GPIO line is used. Only compile tested on the lpc32xx. ChangeLog v2->v3: - Switch to using the startup()/shutdown() callbacks again. Still satisfy the mask/unmask semantics. ChangeLog v1->v2: - Use the .enable() callback from the irq_chip - Call .unmask() from the .enable() callback to satisfy semantics. Cc: Lars Poeschel Cc: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpio-adnp.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c index b204033acaeb..a7b471977dc5 100644 --- a/drivers/gpio/gpio-adnp.c +++ b/drivers/gpio/gpio-adnp.c @@ -408,6 +408,27 @@ static void adnp_irq_bus_unlock(struct irq_data *data) mutex_unlock(&adnp->irq_lock); } +static unsigned int adnp_irq_startup(struct irq_data *data) +{ + struct adnp *adnp = irq_data_get_irq_chip_data(data); + + if (gpio_lock_as_irq(&adnp->gpio, data->hwirq)) + dev_err(adnp->gpio.dev, + "unable to lock HW IRQ %lu for IRQ\n", + data->hwirq); + /* Satisfy the .enable semantics by unmasking the line */ + adnp_irq_unmask(data); + return 0; +} + +static void adnp_irq_shutdown(struct irq_data *data) +{ + struct adnp *adnp = irq_data_get_irq_chip_data(data); + + adnp_irq_mask(data); + gpio_unlock_as_irq(&adnp->gpio, data->hwirq); +} + static struct irq_chip adnp_irq_chip = { .name = "gpio-adnp", .irq_mask = adnp_irq_mask, @@ -415,6 +436,8 @@ static struct irq_chip adnp_irq_chip = { .irq_set_type = adnp_irq_set_type, .irq_bus_lock = adnp_irq_bus_lock, .irq_bus_sync_unlock = adnp_irq_bus_unlock, + .irq_startup = adnp_irq_startup, + .irq_shutdown = adnp_irq_shutdown, }; static int adnp_irq_map(struct irq_domain *domain, unsigned int irq, -- cgit v1.2.1 From db6b3ad1772e0e0e82c52d6337378e79da2effad Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Nov 2013 14:14:50 +0100 Subject: gpio: bcm-kona: lock IRQs when starting them This uses the new API for tagging GPIO lines as in use by IRQs. This enforces a few semantic checks on how the underlying GPIO line is used. Cc: Christian Daudt Cc: Grygorii Strashko Reviewed-by: Markus Mayer Tested-by: Markus Mayer Reviewed-by: Javier Martinez Canillas Signed-off-by: Linus Walleij --- drivers/gpio/gpio-bcm-kona.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c index 72c927dc3be1..3437414eaef2 100644 --- a/drivers/gpio/gpio-bcm-kona.c +++ b/drivers/gpio/gpio-bcm-kona.c @@ -449,12 +449,34 @@ static void bcm_kona_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) chained_irq_exit(chip, desc); } +static unsigned int bcm_kona_gpio_irq_startup(struct irq_data *d) +{ + struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d); + + if (gpio_lock_as_irq(&kona_gpio->gpio_chip, d->hwirq)) + dev_err(kona_gpio->gpio_chip.dev, + "unable to lock HW IRQ %lu for IRQ\n", + d->hwirq); + bcm_kona_gpio_irq_unmask(d); + return 0; +} + +static void bcm_kona_gpio_irq_shutdown(struct irq_data *d) +{ + struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d); + + bcm_kona_gpio_irq_mask(d); + gpio_unlock_as_irq(&kona_gpio->gpio_chip, d->hwirq); +} + static struct irq_chip bcm_gpio_irq_chip = { .name = "bcm-kona-gpio", .irq_ack = bcm_kona_gpio_irq_ack, .irq_mask = bcm_kona_gpio_irq_mask, .irq_unmask = bcm_kona_gpio_irq_unmask, .irq_set_type = bcm_kona_gpio_irq_set_type, + .irq_startup = bcm_kona_gpio_irq_startup, + .irq_shutdown = bcm_kona_gpio_irq_shutdown, }; static struct __initconst of_device_id bcm_kona_gpio_of_match[] = { -- cgit v1.2.1 From 0dc616236961e39e0fefecb4301f9e4632e4a511 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 20 Nov 2013 10:16:54 +0100 Subject: gpio: em: lock IRQs when starting them This uses the new API for tagging GPIO lines as in use by IRQs. This enforces a few semantic checks on how the underlying GPIO line is used. Also assign the gpio_chip.dev pointer to be used for error messages. ChangeLog v1->v2: - Satisfy implicit semantics by calling .enable and .disable callbacks in the startup/shutdown callbacks. Cc: Ian Molton Cc: Simon Horman Acked-by: Magnus Damm Signed-off-by: Linus Walleij --- drivers/gpio/gpio-em.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c index ec190361bf2e..1cc53516e8b4 100644 --- a/drivers/gpio/gpio-em.c +++ b/drivers/gpio/gpio-em.c @@ -99,6 +99,27 @@ static void em_gio_irq_enable(struct irq_data *d) em_gio_write(p, GIO_IEN, BIT(irqd_to_hwirq(d))); } +static unsigned int em_gio_irq_startup(struct irq_data *d) +{ + struct em_gio_priv *p = irq_data_get_irq_chip_data(d); + + if (gpio_lock_as_irq(&p->gpio_chip, irqd_to_hwirq(d))) + dev_err(p->gpio_chip.dev, + "unable to lock HW IRQ %lu for IRQ\n", + irqd_to_hwirq(d)); + em_gio_irq_enable(d); + return 0; +} + +static void em_gio_irq_shutdown(struct irq_data *d) +{ + struct em_gio_priv *p = irq_data_get_irq_chip_data(d); + + em_gio_irq_disable(d); + gpio_unlock_as_irq(&p->gpio_chip, irqd_to_hwirq(d)); +} + + #define GIO_ASYNC(x) (x + 8) static unsigned char em_gio_sense_table[IRQ_TYPE_SENSE_MASK + 1] = { @@ -328,6 +349,7 @@ static int em_gio_probe(struct platform_device *pdev) gpio_chip->request = em_gio_request; gpio_chip->free = em_gio_free; gpio_chip->label = name; + gpio_chip->dev = &pdev->dev; gpio_chip->owner = THIS_MODULE; gpio_chip->base = pdata->gpio_base; gpio_chip->ngpio = pdata->number_of_pins; @@ -339,6 +361,8 @@ static int em_gio_probe(struct platform_device *pdev) irq_chip->irq_enable = em_gio_irq_enable; irq_chip->irq_disable = em_gio_irq_disable; irq_chip->irq_set_type = em_gio_irq_set_type; + irq_chip->irq_startup = em_gio_irq_startup; + irq_chip->irq_shutdown = em_gio_irq_shutdown; irq_chip->flags = IRQCHIP_SKIP_SET_WAKE; p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, -- cgit v1.2.1 From aa6baa7e374dccbec619dcdd1291bc529a008051 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 20 Nov 2013 15:24:32 +0100 Subject: gpio: intel-mid: lock IRQs when starting them This uses the new API for tagging GPIO lines as in use by IRQs. This enforces a few semantic checks on how the underlying GPIO line is used. ChangeLog v1->v2: - Explicitly call the - empty - mask/unmask functions from the startup/shutdown hooks. These are currently empty, but maybe they will not be that forever, so better be safe than sorry. Acked-by: David Cohen Signed-off-by: Linus Walleij --- drivers/gpio/gpio-intel-mid.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c index be803af658ac..039de0e6cf16 100644 --- a/drivers/gpio/gpio-intel-mid.c +++ b/drivers/gpio/gpio-intel-mid.c @@ -235,11 +235,33 @@ static void intel_mid_irq_mask(struct irq_data *d) { } +static unsigned int intel_mid_irq_startup(struct irq_data *d) +{ + struct intel_mid_gpio *priv = irq_data_get_irq_chip_data(d); + + if (gpio_lock_as_irq(&priv->chip, irqd_to_hwirq(d))) + dev_err(priv->chip.dev, + "unable to lock HW IRQ %lu for IRQ\n", + irqd_to_hwirq(d)); + intel_mid_irq_unmask(d); + return 0; +} + +static void intel_mid_irq_shutdown(struct irq_data *d) +{ + struct intel_mid_gpio *priv = irq_data_get_irq_chip_data(d); + + intel_mid_irq_mask(d); + gpio_unlock_as_irq(&priv->chip, irqd_to_hwirq(d)); +} + static struct irq_chip intel_mid_irqchip = { .name = "INTEL_MID-GPIO", .irq_mask = intel_mid_irq_mask, .irq_unmask = intel_mid_irq_unmask, .irq_set_type = intel_mid_irq_type, + .irq_startup = intel_mid_irq_startup, + .irq_shutdown = intel_mid_irq_shutdown, }; static const struct intel_mid_gpio_ddata gpio_lincroft = { @@ -418,6 +440,7 @@ static int intel_gpio_probe(struct pci_dev *pdev, priv->reg_base = pcim_iomap_table(pdev)[0]; priv->chip.label = dev_name(&pdev->dev); + priv->chip.dev = &pdev->dev; priv->chip.request = intel_gpio_request; priv->chip.direction_input = intel_gpio_direction_input; priv->chip.direction_output = intel_gpio_direction_output; -- cgit v1.2.1 From eb7cce1ea96b6399672abce787598f6e7a4352c3 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 20 Nov 2013 15:36:53 +0100 Subject: gpio: lynxpoint: lock IRQs when starting them This uses the new API for tagging GPIO lines as in use by IRQs. This enforces a few semantic checks on how the underlying GPIO line is used. Cc: Mathias Nyman Tested-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/gpio/gpio-lynxpoint.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c index a0804740a0b7..70831e4b2c8b 100644 --- a/drivers/gpio/gpio-lynxpoint.c +++ b/drivers/gpio/gpio-lynxpoint.c @@ -301,6 +301,26 @@ static void lp_irq_disable(struct irq_data *d) spin_unlock_irqrestore(&lg->lock, flags); } +static unsigned int lp_irq_startup(struct irq_data *d) +{ + struct lp_gpio *lg = irq_data_get_irq_chip_data(d); + + if (gpio_lock_as_irq(&lg->chip, irqd_to_hwirq(d))) + dev_err(lg->chip.dev, + "unable to lock HW IRQ %lu for IRQ\n", + irqd_to_hwirq(d)); + lp_irq_enable(d); + return 0; +} + +static void lp_irq_shutdown(struct irq_data *d) +{ + struct lp_gpio *lg = irq_data_get_irq_chip_data(d); + + lp_irq_disable(d); + gpio_unlock_as_irq(&lg->chip, irqd_to_hwirq(d)); +} + static struct irq_chip lp_irqchip = { .name = "LP-GPIO", .irq_mask = lp_irq_mask, @@ -308,6 +328,8 @@ static struct irq_chip lp_irqchip = { .irq_enable = lp_irq_enable, .irq_disable = lp_irq_disable, .irq_set_type = lp_irq_type, + .irq_startup = lp_irq_startup, + .irq_shutdown = lp_irq_shutdown, .flags = IRQCHIP_SKIP_SET_WAKE, }; -- cgit v1.2.1 From ad824783fb23bbc8295cffb6214b3b82d25f7d4a Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Tue, 3 Dec 2013 12:20:11 +0900 Subject: gpio: better lookup method for platform GPIOs Change the format of the platform GPIO lookup tables to make them less confusing and improve lookup efficiency. The previous format was a single linked-list that required to compare the device name and function ID of every single GPIO defined for each lookup. Switch that to a list of per-device tables, so that the lookup can be done in two steps, omitting the GPIOs that are not relevant for a particular device. The matching rules are now defined as follows: - The device name must match *exactly*, and can be NULL for GPIOs not assigned to a particular device, - If the function ID in the lookup table is NULL, the con_id argument of gpiod_get() will not be used for lookup. However, if it is defined, it must match exactly. - The index must always match. Signed-off-by: Alexandre Courbot Acked-by: Mika Westerberg Reviewed-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 108 ++++++++++++++++++++++++++----------------------- 1 file changed, 58 insertions(+), 50 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 44a232701179..4eb262a31777 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2260,18 +2260,14 @@ void gpiod_set_value_cansleep(struct gpio_desc *desc, int value) EXPORT_SYMBOL_GPL(gpiod_set_value_cansleep); /** - * gpiod_add_table() - register GPIO device consumers - * @table: array of consumers to register - * @num: number of consumers in table + * gpiod_add_lookup_table() - register GPIO device consumers + * @table: table of consumers to register */ -void gpiod_add_table(struct gpiod_lookup *table, size_t size) +void gpiod_add_lookup_table(struct gpiod_lookup_table *table) { mutex_lock(&gpio_lookup_lock); - while (size--) { - list_add_tail(&table->list, &gpio_lookup_list); - table++; - } + list_add_tail(&table->list, &gpio_lookup_list); mutex_unlock(&gpio_lookup_lock); } @@ -2327,72 +2323,84 @@ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id, return desc; } -static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, - unsigned int idx, - enum gpio_lookup_flags *flags) +static struct gpiod_lookup_table *gpiod_find_lookup_table(struct device *dev) { const char *dev_id = dev ? dev_name(dev) : NULL; - struct gpio_desc *desc = ERR_PTR(-ENODEV); - unsigned int match, best = 0; - struct gpiod_lookup *p; + struct gpiod_lookup_table *table; mutex_lock(&gpio_lookup_lock); - list_for_each_entry(p, &gpio_lookup_list, list) { - match = 0; + list_for_each_entry(table, &gpio_lookup_list, list) { + if (table->dev_id && dev_id) { + /* + * Valid strings on both ends, must be identical to have + * a match + */ + if (!strcmp(table->dev_id, dev_id)) + goto found; + } else { + /* + * One of the pointers is NULL, so both must be to have + * a match + */ + if (dev_id == table->dev_id) + goto found; + } + } + table = NULL; - if (p->dev_id) { - if (!dev_id || strcmp(p->dev_id, dev_id)) - continue; +found: + mutex_unlock(&gpio_lookup_lock); + return table; +} - match += 2; - } +static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, + unsigned int idx, + enum gpio_lookup_flags *flags) +{ + struct gpio_desc *desc = ERR_PTR(-ENODEV); + struct gpiod_lookup_table *table; + struct gpiod_lookup *p; - if (p->con_id) { - if (!con_id || strcmp(p->con_id, con_id)) - continue; + table = gpiod_find_lookup_table(dev); + if (!table) + return desc; - match += 1; - } + for (p = &table->table[0]; p->chip_label; p++) { + struct gpio_chip *chip; + /* idx must always match exactly */ if (p->idx != idx) continue; - if (match > best) { - struct gpio_chip *chip; - - chip = find_chip_by_name(p->chip_label); - - if (!chip) { - dev_warn(dev, "cannot find GPIO chip %s\n", - p->chip_label); - continue; - } + /* If the lookup entry has a con_id, require exact match */ + if (p->con_id && (!con_id || strcmp(p->con_id, con_id))) + continue; - if (chip->ngpio <= p->chip_hwnum) { - dev_warn(dev, "GPIO chip %s has %d GPIOs\n", - chip->label, chip->ngpio); - continue; - } + chip = find_chip_by_name(p->chip_label); - desc = gpio_to_desc(chip->base + p->chip_hwnum); - *flags = p->flags; + if (!chip) { + dev_warn(dev, "cannot find GPIO chip %s\n", + p->chip_label); + continue; + } - if (match != 3) - best = match; - else - break; + if (chip->ngpio <= p->chip_hwnum) { + dev_warn(dev, "GPIO chip %s has %d GPIOs\n", + chip->label, chip->ngpio); + continue; } - } - mutex_unlock(&gpio_lookup_lock); + desc = gpiochip_offset_to_desc(chip, p->chip_hwnum); + *flags = p->flags; + } return desc; } /** * gpio_get - obtain a GPIO for a given GPIO function - * @dev: GPIO consumer + * @dev: GPIO consumer, can be NULL for system-global GPIOs * @con_id: function within the GPIO consumer * * Return the GPIO descriptor corresponding to the function con_id of device -- cgit v1.2.1 From 7589e59fc0be799fed069591b83d0e57f11058cc Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 5 Dec 2013 11:26:23 +0200 Subject: gpiolib: unify pr_* messages format This patch includes the following amendments: 1) use "?" as a label when the last one is not defined in gpiod_*; 2) whenever it's possible gpiod_* are used; 3) print a function name, if it's already used in other messages. Additionally it fixes an indentation in few places. Signed-off-by: Andy Shevchenko Acked-by: Alexandre Courbot Reviewed-by: Alexandre Courbot Reviewed-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 74 +++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 4eb262a31777..2dc3657e99ba 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -85,36 +85,36 @@ static int gpiod_request(struct gpio_desc *desc, const char *label); static void gpiod_free(struct gpio_desc *desc); #ifdef CONFIG_DEBUG_FS -#define gpiod_emerg(desc, fmt, ...) \ - pr_emerg("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \ +#define gpiod_emerg(desc, fmt, ...) \ + pr_emerg("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",\ ##__VA_ARGS__) -#define gpiod_crit(desc, fmt, ...) \ - pr_crit("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \ +#define gpiod_crit(desc, fmt, ...) \ + pr_crit("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \ ##__VA_ARGS__) -#define gpiod_err(desc, fmt, ...) \ - pr_err("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \ +#define gpiod_err(desc, fmt, ...) \ + pr_err("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \ ##__VA_ARGS__) -#define gpiod_warn(desc, fmt, ...) \ - pr_warn("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \ +#define gpiod_warn(desc, fmt, ...) \ + pr_warn("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \ ##__VA_ARGS__) -#define gpiod_info(desc, fmt, ...) \ - pr_info("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \ +#define gpiod_info(desc, fmt, ...) \ + pr_info("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \ ##__VA_ARGS__) -#define gpiod_dbg(desc, fmt, ...) \ - pr_debug("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \ +#define gpiod_dbg(desc, fmt, ...) \ + pr_debug("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",\ ##__VA_ARGS__) #else -#define gpiod_emerg(desc, fmt, ...) \ +#define gpiod_emerg(desc, fmt, ...) \ pr_emerg("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) -#define gpiod_crit(desc, fmt, ...) \ +#define gpiod_crit(desc, fmt, ...) \ pr_crit("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) -#define gpiod_err(desc, fmt, ...) \ +#define gpiod_err(desc, fmt, ...) \ pr_err("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) -#define gpiod_warn(desc, fmt, ...) \ +#define gpiod_warn(desc, fmt, ...) \ pr_warn("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) -#define gpiod_info(desc, fmt, ...) \ +#define gpiod_info(desc, fmt, ...) \ pr_info("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) -#define gpiod_dbg(desc, fmt, ...) \ +#define gpiod_dbg(desc, fmt, ...) \ pr_debug("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) #endif @@ -188,7 +188,8 @@ static int gpio_ensure_requested(struct gpio_desc *desc) if (WARN(test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0, "autorequest GPIO-%d\n", gpio)) { if (!try_module_get(chip->owner)) { - pr_err("GPIO-%d: module can't be gotten \n", gpio); + gpiod_err(desc, "%s: module can't be gotten\n", + __func__); clear_bit(FLAG_REQUESTED, &desc->flags); /* lose */ return -EIO; @@ -809,8 +810,8 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change) if (!test_bit(FLAG_REQUESTED, &desc->flags) || test_bit(FLAG_EXPORT, &desc->flags)) { spin_unlock_irqrestore(&gpio_lock, flags); - pr_debug("%s: gpio %d unavailable (requested=%d, exported=%d)\n", - __func__, desc_to_gpio(desc), + gpiod_dbg(desc, "%s: unavailable (requested=%d, exported=%d)\n", + __func__, test_bit(FLAG_REQUESTED, &desc->flags), test_bit(FLAG_EXPORT, &desc->flags)); status = -EPERM; @@ -858,8 +859,7 @@ fail_unregister_device: device_unregister(dev); fail_unlock: mutex_unlock(&sysfs_lock); - pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), - status); + gpiod_dbg(desc, "%s: status %d\n", __func__, status); return status; } EXPORT_SYMBOL_GPL(gpiod_export); @@ -907,8 +907,7 @@ int gpiod_export_link(struct device *dev, const char *name, mutex_unlock(&sysfs_lock); if (status) - pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), - status); + gpiod_dbg(desc, "%s: status %d\n", __func__, status); return status; } @@ -952,8 +951,7 @@ unlock: mutex_unlock(&sysfs_lock); if (status) - pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), - status); + gpiod_dbg(desc, "%s: status %d\n", __func__, status); return status; } @@ -995,8 +993,7 @@ void gpiod_unexport(struct gpio_desc *desc) } if (status) - pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), - status); + gpiod_dbg(desc, "%s: status %d\n", __func__, status); } EXPORT_SYMBOL_GPL(gpiod_unexport); @@ -1222,7 +1219,7 @@ int gpiochip_add(struct gpio_chip *chip) if (status) goto fail; - pr_debug("gpiochip_add: registered GPIOs %d to %d on device: %s\n", + pr_debug("%s: registered GPIOs %d to %d on device: %s\n", __func__, chip->base, chip->base + chip->ngpio - 1, chip->label ? : "generic"); @@ -1232,7 +1229,7 @@ unlock: spin_unlock_irqrestore(&gpio_lock, flags); fail: /* failures here can mean systems won't boot... */ - pr_err("gpiochip_add: gpios %d..%d (%s) failed to register\n", + pr_err("%s: GPIOs %d..%d (%s) failed to register\n", __func__, chip->base, chip->base + chip->ngpio - 1, chip->label ? : "generic"); return status; @@ -1500,8 +1497,7 @@ static int gpiod_request(struct gpio_desc *desc, const char *label) } done: if (status) - pr_debug("_gpio_request: gpio-%d (%s) status %d\n", - desc_to_gpio(desc), label ? : "?", status); + gpiod_dbg(desc, "%s: status %d\n", __func__, status); spin_unlock_irqrestore(&gpio_lock, flags); return status; } @@ -1702,7 +1698,7 @@ int gpiod_direction_input(struct gpio_desc *desc) if (!chip->get || !chip->direction_input) { gpiod_warn(desc, "%s: missing get() or direction_input() operations\n", - __func__); + __func__); return -EIO; } @@ -1722,7 +1718,8 @@ int gpiod_direction_input(struct gpio_desc *desc) if (status) { status = chip->request(chip, offset); if (status < 0) { - gpiod_dbg(desc, "chip request fail, %d\n", status); + gpiod_dbg(desc, "%s: chip request fail, %d\n", + __func__, status); /* and it's not available to anyone else ... * gpio_request() is the fully clean solution. */ @@ -1740,7 +1737,7 @@ lose: fail: spin_unlock_irqrestore(&gpio_lock, flags); if (status) - gpiod_dbg(desc, "%s status %d\n", __func__, status); + gpiod_dbg(desc, "%s: status %d\n", __func__, status); return status; } EXPORT_SYMBOL_GPL(gpiod_direction_input); @@ -1807,7 +1804,8 @@ int gpiod_direction_output(struct gpio_desc *desc, int value) if (status) { status = chip->request(chip, offset); if (status < 0) { - gpiod_dbg(desc, "chip request fail, %d\n", status); + gpiod_dbg(desc, "%s: chip request fail, %d\n", + __func__, status); /* and it's not available to anyone else ... * gpio_request() is the fully clean solution. */ @@ -2448,8 +2446,10 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, */ if (!desc || IS_ERR(desc)) { struct gpio_desc *pdesc; + dev_dbg(dev, "using lookup tables for GPIO lookup"); pdesc = gpiod_find(dev, con_id, idx, &flags); + /* If used as fallback, do not replace the previous error */ if (!IS_ERR(pdesc) || !desc) desc = pdesc; -- cgit v1.2.1 From 1a2a99c69eaea30da25dede555a3d70d7a412ae2 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 5 Dec 2013 11:26:24 +0200 Subject: gpiolib: introduce chip_* to print with chip->label prefix In several places we are printing messages with prefix based on chip->label. Introduced macros help us to do this easier and in uniform way. Signed-off-by: Andy Shevchenko Reviewed-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 2dc3657e99ba..30ae38681fef 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -84,6 +84,8 @@ static DEFINE_IDR(dirent_idr); static int gpiod_request(struct gpio_desc *desc, const char *label); static void gpiod_free(struct gpio_desc *desc); +/* With descriptor prefix */ + #ifdef CONFIG_DEBUG_FS #define gpiod_emerg(desc, fmt, ...) \ pr_emerg("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",\ @@ -118,6 +120,21 @@ static void gpiod_free(struct gpio_desc *desc); pr_debug("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) #endif +/* With chip prefix */ + +#define chip_emerg(chip, fmt, ...) \ + pr_emerg("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__) +#define chip_crit(chip, fmt, ...) \ + pr_crit("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__) +#define chip_err(chip, fmt, ...) \ + pr_err("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__) +#define chip_warn(chip, fmt, ...) \ + pr_warn("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__) +#define chip_info(chip, fmt, ...) \ + pr_info("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__) +#define chip_dbg(chip, fmt, ...) \ + pr_debug("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__) + static inline void desc_set_label(struct gpio_desc *d, const char *label) { #ifdef CONFIG_DEBUG_FS @@ -1032,8 +1049,7 @@ static int gpiochip_export(struct gpio_chip *chip) chip->desc[gpio++].chip = NULL; spin_unlock_irqrestore(&gpio_lock, flags); - pr_debug("%s: chip %s status %d\n", __func__, - chip->label, status); + chip_dbg(chip, "%s: status %d\n", __func__, status); } return status; @@ -1056,8 +1072,7 @@ static void gpiochip_unexport(struct gpio_chip *chip) mutex_unlock(&sysfs_lock); if (status) - pr_debug("%s: chip %s status %d\n", __func__, - chip->label, status); + chip_dbg(chip, "%s: status %d\n", __func__, status); } static int __init gpiolib_sysfs_init(void) @@ -1337,8 +1352,7 @@ int gpiochip_add_pingroup_range(struct gpio_chip *chip, pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL); if (!pin_range) { - pr_err("%s: GPIO chip: failed to allocate pin ranges\n", - chip->label); + chip_err(chip, "failed to allocate pin ranges\n"); return -ENOMEM; } @@ -1359,9 +1373,8 @@ int gpiochip_add_pingroup_range(struct gpio_chip *chip, pinctrl_add_gpio_range(pctldev, &pin_range->range); - pr_debug("GPIO chip %s: created GPIO range %d->%d ==> %s PINGRP %s\n", - chip->label, gpio_offset, - gpio_offset + pin_range->range.npins - 1, + chip_dbg(chip, "created GPIO range %d->%d ==> %s PINGRP %s\n", + gpio_offset, gpio_offset + pin_range->range.npins - 1, pinctrl_dev_get_devname(pctldev), pin_group); list_add_tail(&pin_range->node, &chip->pin_ranges); @@ -1388,8 +1401,7 @@ int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL); if (!pin_range) { - pr_err("%s: GPIO chip: failed to allocate pin ranges\n", - chip->label); + chip_err(chip, "failed to allocate pin ranges\n"); return -ENOMEM; } @@ -1404,13 +1416,12 @@ int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, &pin_range->range); if (IS_ERR(pin_range->pctldev)) { ret = PTR_ERR(pin_range->pctldev); - pr_err("%s: GPIO chip: could not create pin range\n", - chip->label); + chip_err(chip, "could not create pin range\n"); kfree(pin_range); return ret; } - pr_debug("GPIO chip %s: created GPIO range %d->%d ==> %s PIN %d->%d\n", - chip->label, gpio_offset, gpio_offset + npins - 1, + chip_dbg(chip, "created GPIO range %d->%d ==> %s PIN %d->%d\n", + gpio_offset, gpio_offset + npins - 1, pinctl_name, pin_offset, pin_offset + npins - 1); -- cgit v1.2.1 From fdd6a5fe89880f1d97bbf62fea27fd7ca76f2d21 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 5 Dec 2013 11:26:26 +0200 Subject: gpiolib: update inline documentation of gpiod_get_index() The patch just accents that @dev could be NULL. There is no functional change. Signed-off-by: Andy Shevchenko Reviewed-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 30ae38681fef..12e47dfabd8d 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2423,7 +2423,7 @@ EXPORT_SYMBOL_GPL(gpiod_get); /** * gpiod_get_index - obtain a GPIO from a multi-index GPIO function - * @dev: GPIO consumer + * @dev: GPIO consumer, can be NULL for system-global GPIOs * @con_id: function within the GPIO consumer * @idx: index of the GPIO to obtain in the consumer * -- cgit v1.2.1 From f57f98a6c0f4f3cb4d2ec9f9566b8e3f21843f03 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 6 Dec 2013 13:36:11 -0700 Subject: gpio: tegra: add missing error handling to probe The call to gpiochip_add() is not currently error-checked. Add the missing checking. Signed-off-by: Stephen Warren Reviewed-by: Thierry Reding Reviewed-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/gpio/gpio-tegra.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index cfd3b9037bc7..2b49f878b56c 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -425,6 +425,7 @@ static int tegra_gpio_probe(struct platform_device *pdev) struct tegra_gpio_soc_config *config; struct resource *res; struct tegra_gpio_bank *bank; + int ret; int gpio; int i; int j; @@ -494,7 +495,11 @@ static int tegra_gpio_probe(struct platform_device *pdev) tegra_gpio_chip.of_node = pdev->dev.of_node; - gpiochip_add(&tegra_gpio_chip); + ret = gpiochip_add(&tegra_gpio_chip); + if (ret < 0) { + irq_domain_remove(irq_domain); + return ret; + } for (gpio = 0; gpio < tegra_gpio_chip.ngpio; gpio++) { int irq = irq_create_mapping(irq_domain, gpio); -- cgit v1.2.1 From 61e7380403efbaf5f796e8cf979827c602bf6c50 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Sat, 7 Dec 2013 14:08:22 +0400 Subject: gpio: 74x164: Remove non-DT support Commit 20bc4d5d565159eb2b942bf4b7fae86fba94e32c (gpio: 74x164: Add support for the daisy-chaining) introduce check for DT for the driver, so driver cannot be used without DT. There are no in-tree users of this driver, so remove non-DT support completely. Signed-off-by: Alexander Shiyan Acked-by: Mark Brown Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 6 +++--- drivers/gpio/gpio-74x164.c | 14 +------------- 2 files changed, 4 insertions(+), 16 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index ae3682d25a3c..4127f68412eb 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -714,10 +714,10 @@ config GPIO_MC33880 config GPIO_74X164 tristate "74x164 serial-in/parallel-out 8-bits shift register" - depends on SPI_MASTER + depends on SPI_MASTER && OF help - Platform driver for 74x164 compatible serial-in/parallel-out - 8-outputs shift registers. This driver can be used to provide access + Driver for 74x164 compatible serial-in/parallel-out 8-outputs + shift registers. This driver can be used to provide access to more gpio outputs. comment "AC97 GPIO expanders:" diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c index ddb831232407..4d4e15ca67e0 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -108,14 +107,8 @@ static int gen_74x164_direction_output(struct gpio_chip *gc, static int gen_74x164_probe(struct spi_device *spi) { struct gen_74x164_chip *chip; - struct gen_74x164_chip_platform_data *pdata; int ret; - if (!spi->dev.of_node) { - dev_err(&spi->dev, "No device tree data available.\n"); - return -EINVAL; - } - /* * bits_per_word cannot be configured in platform data */ @@ -129,12 +122,6 @@ static int gen_74x164_probe(struct spi_device *spi) if (!chip) return -ENOMEM; - pdata = dev_get_platdata(&spi->dev); - if (pdata && pdata->base) - chip->gpio_chip.base = pdata->base; - else - chip->gpio_chip.base = -1; - mutex_init(&chip->lock); spi_set_drvdata(spi, chip); @@ -145,6 +132,7 @@ static int gen_74x164_probe(struct spi_device *spi) chip->gpio_chip.direction_output = gen_74x164_direction_output; chip->gpio_chip.get = gen_74x164_get_value; chip->gpio_chip.set = gen_74x164_set_value; + chip->gpio_chip.base = -1; if (of_property_read_u32(spi->dev.of_node, "registers-number", &chip->registers)) { dev_err(&spi->dev, "Missing registers-number property in the DT.\n"); -- cgit v1.2.1 From bcc0562c776e4b09c7b9f24cddb8724fbe7a3fa5 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Sat, 7 Dec 2013 14:08:23 +0400 Subject: gpio: 74x164: Driver cleanup - Removed excess "spi" field from private data. - Removed excess check for spi_get_drvdata() in remove(). - Removed unneeded message in remove(). - Simplify error path in probe(). - Fixed warnings by scripts/checkfile.pl. Signed-off-by: Alexander Shiyan Signed-off-by: Linus Walleij --- drivers/gpio/gpio-74x164.c | 43 ++++++++++++++++--------------------------- 1 file changed, 16 insertions(+), 27 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c index 4d4e15ca67e0..e4ae29824c32 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c @@ -20,7 +20,6 @@ #define GEN_74X164_NUMBER_GPIOS 8 struct gen_74x164_chip { - struct spi_device *spi; u8 *buffer; struct gpio_chip gpio_chip; struct mutex lock; @@ -34,6 +33,7 @@ static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc) static int __gen_74x164_write_config(struct gen_74x164_chip *chip) { + struct spi_device *spi = to_spi_device(chip->gpio_chip.dev); struct spi_message message; struct spi_transfer *msg_buf; int i, ret = 0; @@ -54,12 +54,12 @@ static int __gen_74x164_write_config(struct gen_74x164_chip *chip) * byte of the buffer will end up in the last register. */ for (i = chip->registers - 1; i >= 0; i--) { - msg_buf[i].tx_buf = chip->buffer +i; + msg_buf[i].tx_buf = chip->buffer + i; msg_buf[i].len = sizeof(u8); spi_message_add_tail(msg_buf + i, &message); } - ret = spi_sync(chip->spi, &message); + ret = spi_sync(spi, &message); kfree(msg_buf); @@ -122,35 +122,32 @@ static int gen_74x164_probe(struct spi_device *spi) if (!chip) return -ENOMEM; - mutex_init(&chip->lock); - spi_set_drvdata(spi, chip); - chip->spi = spi; - chip->gpio_chip.label = spi->modalias; chip->gpio_chip.direction_output = gen_74x164_direction_output; chip->gpio_chip.get = gen_74x164_get_value; chip->gpio_chip.set = gen_74x164_set_value; chip->gpio_chip.base = -1; - if (of_property_read_u32(spi->dev.of_node, "registers-number", &chip->registers)) { - dev_err(&spi->dev, "Missing registers-number property in the DT.\n"); - ret = -EINVAL; - goto exit_destroy; + if (of_property_read_u32(spi->dev.of_node, "registers-number", + &chip->registers)) { + dev_err(&spi->dev, + "Missing registers-number property in the DT.\n"); + return -EINVAL; } chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers; chip->buffer = devm_kzalloc(&spi->dev, chip->registers, GFP_KERNEL); - if (!chip->buffer) { - ret = -ENOMEM; - goto exit_destroy; - } + if (!chip->buffer) + return -ENOMEM; chip->gpio_chip.can_sleep = true; chip->gpio_chip.dev = &spi->dev; chip->gpio_chip.owner = THIS_MODULE; + mutex_init(&chip->lock); + ret = __gen_74x164_write_config(chip); if (ret) { dev_err(&spi->dev, "Failed writing: %d\n", ret); @@ -158,31 +155,23 @@ static int gen_74x164_probe(struct spi_device *spi) } ret = gpiochip_add(&chip->gpio_chip); - if (ret) - goto exit_destroy; - - return ret; + if (!ret) + return 0; exit_destroy: mutex_destroy(&chip->lock); + return ret; } static int gen_74x164_remove(struct spi_device *spi) { - struct gen_74x164_chip *chip; + struct gen_74x164_chip *chip = spi_get_drvdata(spi); int ret; - chip = spi_get_drvdata(spi); - if (chip == NULL) - return -ENODEV; - ret = gpiochip_remove(&chip->gpio_chip); if (!ret) mutex_destroy(&chip->lock); - else - dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n", - ret); return ret; } -- cgit v1.2.1 From 3b31d0eca5fd8d7d485c7cb7319a5cd6a3207726 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Thu, 12 Dec 2013 11:18:41 +0200 Subject: gpio: driver for Xtensa GPIO32 GPIO32 is a standard optional extension to the Xtensa architecture core that provides preconfigured output and input ports for intra SoC signaling. The GPIO32 option is implemented as 32bit Tensilica Instruction Extension (TIE) output state called EXPSTATE, and 32bit input wire called IMPWIRE. This driver treats input and output states as two distinct devices. v3: * Use BUG() in xtensa_impwire_set_value() to indicate that it should never be called (Linus Walleij) v2: * Address the comments of Linus Walleij: - Add a few comments - Expand commit log message - Use the BIT() macro for bit offsets - Rewrite CPENABLE handling as static inlines - Use device_initcall() * Depend on !SMP for reason explained in the comments (Marc Gauthier) * Use XCHAL_CP_ID_XTIOP to enable/disable GPIO32 only Signed-off-by: Baruch Siach Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 8 +++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-xtensa.c | 163 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 172 insertions(+) create mode 100644 drivers/gpio/gpio-xtensa.c (limited to 'drivers/gpio') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 4127f68412eb..02e8d5350f8b 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -288,6 +288,14 @@ config GPIO_XILINX help Say yes here to support the Xilinx FPGA GPIO device +config GPIO_XTENSA + bool "Xtensa GPIO32 support" + depends on XTENSA + depends on !SMP + help + Say yes here to support the Xtensa internal GPIO32 IMPWIRE (input) + and EXPSTATE (output) ports + config GPIO_VR41XX tristate "NEC VR4100 series General-purpose I/O Uint support" depends on CPU_VR41XX diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index ee95154cb1d2..699e7cd96584 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -96,3 +96,4 @@ obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o +obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o diff --git a/drivers/gpio/gpio-xtensa.c b/drivers/gpio/gpio-xtensa.c new file mode 100644 index 000000000000..1d136eceda62 --- /dev/null +++ b/drivers/gpio/gpio-xtensa.c @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2013 TangoTec Ltd. + * Author: Baruch Siach + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Driver for the Xtensa LX4 GPIO32 Option + * + * Documentation: Xtensa LX4 Microprocessor Data Book, Section 2.22 + * + * GPIO32 is a standard optional extension to the Xtensa architecture core that + * provides preconfigured output and input ports for intra SoC signaling. The + * GPIO32 option is implemented as 32bit Tensilica Instruction Extension (TIE) + * output state called EXPSTATE, and 32bit input wire called IMPWIRE. This + * driver treats input and output states as two distinct devices. + * + * Access to GPIO32 specific instructions is controlled by the CPENABLE + * (Coprocessor Enable Bits) register. By default Xtensa Linux startup code + * disables access to all coprocessors. This driver sets the CPENABLE bit + * corresponding to GPIO32 before any GPIO32 specific instruction, and restores + * CPENABLE state after that. + * + * This driver is currently incompatible with SMP. The GPIO32 extension is not + * guaranteed to be available in all cores. Moreover, each core controls a + * different set of IO wires. A theoretical SMP aware version of this driver + * would need to have a per core workqueue to do the actual GPIO manipulation. + */ + +#include +#include +#include +#include +#include + +#include /* CPENABLE read/write macros */ + +#ifndef XCHAL_CP_ID_XTIOP +#error GPIO32 option is not enabled for your xtensa core variant +#endif + +static inline unsigned long enable_cp(unsigned long *cpenable) +{ + unsigned long flags; + + local_irq_save(flags); + RSR_CPENABLE(*cpenable); + WSR_CPENABLE(*cpenable | BIT(XCHAL_CP_ID_XTIOP)); + + return flags; +} + +static inline void disable_cp(unsigned long flags, unsigned long cpenable) +{ + WSR_CPENABLE(cpenable); + local_irq_restore(flags); +} + +static int xtensa_impwire_get_direction(struct gpio_chip *gc, unsigned offset) +{ + return 1; /* input only */ +} + +static int xtensa_impwire_get_value(struct gpio_chip *gc, unsigned offset) +{ + unsigned long flags, saved_cpenable; + u32 impwire; + + flags = enable_cp(&saved_cpenable); + __asm__ __volatile__("read_impwire %0" : "=a" (impwire)); + disable_cp(flags, saved_cpenable); + + return !!(impwire & BIT(offset)); +} + +static void xtensa_impwire_set_value(struct gpio_chip *gc, unsigned offset, + int value) +{ + BUG(); /* output only; should never be called */ +} + +static int xtensa_expstate_get_direction(struct gpio_chip *gc, unsigned offset) +{ + return 0; /* output only */ +} + +static int xtensa_expstate_get_value(struct gpio_chip *gc, unsigned offset) +{ + unsigned long flags, saved_cpenable; + u32 expstate; + + flags = enable_cp(&saved_cpenable); + __asm__ __volatile__("rur.expstate %0" : "=a" (expstate)); + disable_cp(flags, saved_cpenable); + + return !!(expstate & BIT(offset)); +} + +static void xtensa_expstate_set_value(struct gpio_chip *gc, unsigned offset, + int value) +{ + unsigned long flags, saved_cpenable; + u32 mask = BIT(offset); + u32 val = value ? BIT(offset) : 0; + + flags = enable_cp(&saved_cpenable); + __asm__ __volatile__("wrmsk_expstate %0, %1" + :: "a" (val), "a" (mask)); + disable_cp(flags, saved_cpenable); +} + +static struct gpio_chip impwire_chip = { + .label = "impwire", + .base = -1, + .ngpio = 32, + .get_direction = xtensa_impwire_get_direction, + .get = xtensa_impwire_get_value, + .set = xtensa_impwire_set_value, +}; + +static struct gpio_chip expstate_chip = { + .label = "expstate", + .base = -1, + .ngpio = 32, + .get_direction = xtensa_expstate_get_direction, + .get = xtensa_expstate_get_value, + .set = xtensa_expstate_set_value, +}; + +static int xtensa_gpio_probe(struct platform_device *pdev) +{ + int ret; + + ret = gpiochip_add(&impwire_chip); + if (ret) + return ret; + return gpiochip_add(&expstate_chip); +} + +static struct platform_driver xtensa_gpio_driver = { + .driver = { + .name = "xtensa-gpio", + .owner = THIS_MODULE, + }, + .probe = xtensa_gpio_probe, +}; + +static int __init xtensa_gpio_init(void) +{ + struct platform_device *pdev; + + pdev = platform_device_register_simple("xtensa-gpio", 0, NULL, 0); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); + + return platform_driver_register(&xtensa_gpio_driver); +} +device_initcall(xtensa_gpio_init); + +MODULE_AUTHOR("Baruch Siach "); +MODULE_DESCRIPTION("Xtensa LX4 GPIO32 driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.1 From 2a3cf6a3599e901528d3e0025a1bd0722a8d3575 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Wed, 11 Dec 2013 11:32:28 +0900 Subject: gpiolib: return -ENOENT if no GPIO mapping exists Some devices drivers make use of optional GPIO parameters. For such drivers, it is important to discriminate between the case where no GPIO mapping has been defined for the function they are requesting, and the case where a mapping exists but an error occured while resolving it or when acquiring the GPIO. This patch changes the family of gpiod_get() functions such that they will return -ENOENT if and only if no GPIO mapping is defined for the requested function. Other error codes are used when an actual error occured during the GPIO resolution. Signed-off-by: Alexandre Courbot Reviewed-by: Andy Shevchenko Reviewed-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 12e47dfabd8d..c0b06a9adad9 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2367,7 +2367,7 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, unsigned int idx, enum gpio_lookup_flags *flags) { - struct gpio_desc *desc = ERR_PTR(-ENODEV); + struct gpio_desc *desc = ERR_PTR(-ENOENT); struct gpiod_lookup_table *table; struct gpiod_lookup *p; @@ -2389,19 +2389,22 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, chip = find_chip_by_name(p->chip_label); if (!chip) { - dev_warn(dev, "cannot find GPIO chip %s\n", - p->chip_label); - continue; + dev_err(dev, "cannot find GPIO chip %s\n", + p->chip_label); + return ERR_PTR(-ENODEV); } if (chip->ngpio <= p->chip_hwnum) { - dev_warn(dev, "GPIO chip %s has %d GPIOs\n", - chip->label, chip->ngpio); - continue; + dev_err(dev, + "requested GPIO %d is out of range [0..%d] for chip %s\n", + idx, chip->ngpio, chip->label); + return ERR_PTR(-EINVAL); } desc = gpiochip_offset_to_desc(chip, p->chip_hwnum); *flags = p->flags; + + return desc; } return desc; @@ -2413,7 +2416,8 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, * @con_id: function within the GPIO consumer * * Return the GPIO descriptor corresponding to the function con_id of device - * dev, or an IS_ERR() condition if an error occured. + * dev, -ENOENT if no GPIO has been assigned to the requested function, or + * another IS_ERR() code if an error occured while trying to acquire the GPIO. */ struct gpio_desc *__must_check gpiod_get(struct device *dev, const char *con_id) { @@ -2430,7 +2434,9 @@ EXPORT_SYMBOL_GPL(gpiod_get); * This variant of gpiod_get() allows to access GPIOs other than the first * defined one for functions that define several GPIOs. * - * Return a valid GPIO descriptor, or an IS_ERR() condition in case of error. + * Return a valid GPIO descriptor, -ENOENT if no GPIO has been assigned to the + * requested function and/or index, or another IS_ERR() code if an error + * occured while trying to acquire the GPIO. */ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, const char *con_id, @@ -2455,15 +2461,9 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, * Either we are not using DT or ACPI, or their lookup did not return * a result. In that case, use platform lookup as a fallback. */ - if (!desc || IS_ERR(desc)) { - struct gpio_desc *pdesc; - + if (!desc || desc == ERR_PTR(-ENOENT)) { dev_dbg(dev, "using lookup tables for GPIO lookup"); - pdesc = gpiod_find(dev, con_id, idx, &flags); - - /* If used as fallback, do not replace the previous error */ - if (!IS_ERR(pdesc) || !desc) - desc = pdesc; + desc = gpiod_find(dev, con_id, idx, &flags); } if (IS_ERR(desc)) { -- cgit v1.2.1 From fcffa97f8e182306cf76f101ccb3b397399da772 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 10 Dec 2013 15:19:04 -0800 Subject: gpio: msm: Add module device table and mark table const This allows the module to be loaded automatically. Signed-off-by: Stephen Boyd Signed-off-by: Linus Walleij --- drivers/gpio/gpio-msm-v2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-msm-v2.c b/drivers/gpio/gpio-msm-v2.c index 7b37300973db..81c1d55abf72 100644 --- a/drivers/gpio/gpio-msm-v2.c +++ b/drivers/gpio/gpio-msm-v2.c @@ -430,10 +430,11 @@ static int msm_gpio_probe(struct platform_device *pdev) return 0; } -static struct of_device_id msm_gpio_of_match[] = { +static const struct of_device_id msm_gpio_of_match[] = { { .compatible = "qcom,msm-gpio", }, { }, }; +MODULE_DEVICE_TABLE(of, msm_gpio_of_match); static int msm_gpio_remove(struct platform_device *dev) { -- cgit v1.2.1 From a00580c2809f44fd1d284bf2638395a261d28cc9 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 10 Dec 2013 12:00:27 +0200 Subject: gpio / ACPI: return -ENOENT when no mapping exists Doing this allows drivers to distinguish between a real error case (if there was an error when we tried to resolve the GPIO) and when the optional GPIO line was not available. Signed-off-by: Mika Westerberg Acked-by: Alexandre Courbot Acked-by: Rafael J. Wysocki Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index ae0ffdce8bd5..137d20c70afe 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -307,6 +307,6 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index, if (lookup.desc && info) *info = lookup.info; - return lookup.desc ? lookup.desc : ERR_PTR(-ENODEV); + return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT); } EXPORT_SYMBOL_GPL(acpi_get_gpiod_by_index); -- cgit v1.2.1 From 12262bef8f4614df7af8b2963de5beddee18ae5e Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Wed, 4 Dec 2013 23:56:43 +0000 Subject: gpio: add GPIO support for SMSC SCH311x This patch adds support for the GPIOs found on the SMSC "Super I/ SCH311x. The chip detection and I/O functions are copied from sch311x_wdt. Signed-off-by: Bruno Randolf Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 9 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-sch311x.c | 431 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 441 insertions(+) create mode 100644 drivers/gpio/gpio-sch311x.c (limited to 'drivers/gpio') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 02e8d5350f8b..f456b93bb953 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -244,6 +244,15 @@ config GPIO_SAMSUNG Legacy GPIO support. Use only for platforms without support for pinctrl. +config GPIO_SCH311X + tristate "SMSC SCH311x SuperI/O GPIO" + help + Driver to enable the GPIOs found on SMSC SMSC SCH3112, SCH3114 and + SCH3116 "Super I/O" chipsets. + + To compile this driver as a module, choose M here: the module will + be called gpio-sch311x. + config GPIO_SPEAR_SPICS bool "ST SPEAr13xx SPI Chip Select as GPIO support" depends on PLAT_SPEAR diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 699e7cd96584..c44fffac9519 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o obj-$(CONFIG_GPIO_SAMSUNG) += gpio-samsung.o obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o obj-$(CONFIG_GPIO_SCH) += gpio-sch.o +obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o obj-$(CONFIG_GPIO_SPEAR_SPICS) += gpio-spear-spics.o obj-$(CONFIG_GPIO_STA2X11) += gpio-sta2x11.o diff --git a/drivers/gpio/gpio-sch311x.c b/drivers/gpio/gpio-sch311x.c new file mode 100644 index 000000000000..483a6f8bd958 --- /dev/null +++ b/drivers/gpio/gpio-sch311x.c @@ -0,0 +1,431 @@ +/* + * GPIO driver for the SMSC SCH311x Super-I/O chips + * + * Copyright (C) 2013 Bruno Randolf + * + * SuperIO functions and chip detection: + * (c) Copyright 2008 Wim Van Sebroeck . + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "gpio-sch311x" + +#define SCH311X_GPIO_CONF_OUT 0x00 +#define SCH311X_GPIO_CONF_IN 0x01 +#define SCH311X_GPIO_CONF_INVERT 0x02 +#define SCH311X_GPIO_CONF_OPEN_DRAIN 0x80 + +#define SIO_CONFIG_KEY_ENTER 0x55 +#define SIO_CONFIG_KEY_EXIT 0xaa + +#define GP1 0x4b + +static int sch311x_ioports[] = { 0x2e, 0x4e, 0x162e, 0x164e }; + +static struct platform_device *sch311x_gpio_pdev; + +struct sch311x_pdev_data { /* platform device data */ + unsigned short runtime_reg; /* runtime register base address */ +}; + +struct sch311x_gpio_block { /* one GPIO block runtime data */ + struct gpio_chip chip; + unsigned short data_reg; /* from definition below */ + unsigned short *config_regs; /* pointer to definition below */ + unsigned short runtime_reg; /* runtime register */ + spinlock_t lock; /* lock for this GPIO block */ +}; + +struct sch311x_gpio_priv { /* driver private data */ + struct sch311x_gpio_block blocks[6]; +}; + +struct sch311x_gpio_block_def { /* register address definitions */ + unsigned short data_reg; + unsigned short config_regs[8]; + unsigned short base; +}; + +/* Note: some GPIOs are not available, these are marked with 0x00 */ + +static struct sch311x_gpio_block_def sch311x_gpio_blocks[] = { + { + .data_reg = 0x4b, /* GP1 */ + .config_regs = {0x23, 0x24, 0x25, 0x26, 0x27, 0x29, 0x2a, 0x2b}, + .base = 10, + }, + { + .data_reg = 0x4c, /* GP2 */ + .config_regs = {0x00, 0x2c, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x32}, + .base = 20, + }, + { + .data_reg = 0x4d, /* GP3 */ + .config_regs = {0x33, 0x34, 0x35, 0x36, 0x37, 0x00, 0x39, 0x3a}, + .base = 30, + }, + { + .data_reg = 0x4e, /* GP4 */ + .config_regs = {0x3b, 0x00, 0x3d, 0x00, 0x6e, 0x6f, 0x72, 0x73}, + .base = 40, + }, + { + .data_reg = 0x4f, /* GP5 */ + .config_regs = {0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46}, + .base = 50, + }, + { + .data_reg = 0x50, /* GP6 */ + .config_regs = {0x47, 0x48, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59}, + .base = 60, + }, +}; + +static inline struct sch311x_gpio_block * +to_sch311x_gpio_block(struct gpio_chip *chip) +{ + return container_of(chip, struct sch311x_gpio_block, chip); +} + + +/* + * Super-IO functions + */ + +static inline int sch311x_sio_enter(int sio_config_port) +{ + /* Don't step on other drivers' I/O space by accident. */ + if (!request_muxed_region(sio_config_port, 2, DRV_NAME)) { + pr_err(DRV_NAME "I/O address 0x%04x already in use\n", + sio_config_port); + return -EBUSY; + } + + outb(SIO_CONFIG_KEY_ENTER, sio_config_port); + return 0; +} + +static inline void sch311x_sio_exit(int sio_config_port) +{ + outb(SIO_CONFIG_KEY_EXIT, sio_config_port); + release_region(sio_config_port, 2); +} + +static inline int sch311x_sio_inb(int sio_config_port, int reg) +{ + outb(reg, sio_config_port); + return inb(sio_config_port + 1); +} + +static inline void sch311x_sio_outb(int sio_config_port, int reg, int val) +{ + outb(reg, sio_config_port); + outb(val, sio_config_port + 1); +} + + +/* + * GPIO functions + */ + +static int sch311x_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + struct sch311x_gpio_block *block = to_sch311x_gpio_block(chip); + + if (block->config_regs[offset] == 0) /* GPIO is not available */ + return -ENODEV; + + if (!request_region(block->runtime_reg + block->config_regs[offset], + 1, DRV_NAME)) { + dev_err(chip->dev, "Failed to request region 0x%04x.\n", + block->runtime_reg + block->config_regs[offset]); + return -EBUSY; + } + return 0; +} + +static void sch311x_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + struct sch311x_gpio_block *block = to_sch311x_gpio_block(chip); + + if (block->config_regs[offset] == 0) /* GPIO is not available */ + return; + + release_region(block->runtime_reg + block->config_regs[offset], 1); +} + +static int sch311x_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct sch311x_gpio_block *block = to_sch311x_gpio_block(chip); + unsigned char data; + + spin_lock(&block->lock); + data = inb(block->runtime_reg + block->data_reg); + spin_unlock(&block->lock); + + return !!(data & BIT(offset)); +} + +static void __sch311x_gpio_set(struct sch311x_gpio_block *block, + unsigned offset, int value) +{ + unsigned char data = inb(block->runtime_reg + block->data_reg); + if (value) + data |= BIT(offset); + else + data &= ~BIT(offset); + outb(data, block->runtime_reg + block->data_reg); +} + +static void sch311x_gpio_set(struct gpio_chip *chip, unsigned offset, + int value) +{ + struct sch311x_gpio_block *block = to_sch311x_gpio_block(chip); + + spin_lock(&block->lock); + __sch311x_gpio_set(block, offset, value); + spin_unlock(&block->lock); +} + +static int sch311x_gpio_direction_in(struct gpio_chip *chip, unsigned offset) +{ + struct sch311x_gpio_block *block = to_sch311x_gpio_block(chip); + + spin_lock(&block->lock); + outb(SCH311X_GPIO_CONF_IN, block->runtime_reg + + block->config_regs[offset]); + spin_unlock(&block->lock); + + return 0; +} + +static int sch311x_gpio_direction_out(struct gpio_chip *chip, unsigned offset, + int value) +{ + struct sch311x_gpio_block *block = to_sch311x_gpio_block(chip); + + spin_lock(&block->lock); + + outb(SCH311X_GPIO_CONF_OUT, block->runtime_reg + + block->config_regs[offset]); + + __sch311x_gpio_set(block, offset, value); + + spin_unlock(&block->lock); + return 0; +} + +static int sch311x_gpio_probe(struct platform_device *pdev) +{ + struct sch311x_pdev_data *pdata = pdev->dev.platform_data; + struct sch311x_gpio_priv *priv; + struct sch311x_gpio_block *block; + int err, i; + + /* we can register all GPIO data registers at once */ + if (!request_region(pdata->runtime_reg + GP1, 6, DRV_NAME)) { + dev_err(&pdev->dev, "Failed to request region 0x%04x-0x%04x.\n", + pdata->runtime_reg + GP1, pdata->runtime_reg + GP1 + 5); + return -EBUSY; + } + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + platform_set_drvdata(pdev, priv); + + for (i = 0; i < ARRAY_SIZE(priv->blocks); i++) { + block = &priv->blocks[i]; + + spin_lock_init(&block->lock); + + block->chip.label = DRV_NAME; + block->chip.owner = THIS_MODULE; + block->chip.request = sch311x_gpio_request; + block->chip.free = sch311x_gpio_free; + block->chip.direction_input = sch311x_gpio_direction_in; + block->chip.direction_output = sch311x_gpio_direction_out; + block->chip.get = sch311x_gpio_get; + block->chip.set = sch311x_gpio_set; + block->chip.ngpio = 8; + block->chip.dev = &pdev->dev; + block->chip.base = sch311x_gpio_blocks[i].base; + block->config_regs = sch311x_gpio_blocks[i].config_regs; + block->data_reg = sch311x_gpio_blocks[i].data_reg; + block->runtime_reg = pdata->runtime_reg; + + err = gpiochip_add(&block->chip); + if (err < 0) { + dev_err(&pdev->dev, + "Could not register gpiochip, %d\n", err); + goto exit_err; + } + dev_info(&pdev->dev, + "SMSC SCH311x GPIO block %d registered.\n", i); + } + + return 0; + +exit_err: + release_region(pdata->runtime_reg + GP1, 6); + /* release already registered chips */ + for (--i; i >= 0; i--) + gpiochip_remove(&priv->blocks[i].chip); + return err; +} + +static int sch311x_gpio_remove(struct platform_device *pdev) +{ + struct sch311x_pdev_data *pdata = pdev->dev.platform_data; + struct sch311x_gpio_priv *priv = platform_get_drvdata(pdev); + int err, i; + + release_region(pdata->runtime_reg + GP1, 6); + + for (i = 0; i < ARRAY_SIZE(priv->blocks); i++) { + err = gpiochip_remove(&priv->blocks[i].chip); + if (err) + return err; + dev_info(&pdev->dev, + "SMSC SCH311x GPIO block %d unregistered.\n", i); + } + return 0; +} + +static struct platform_driver sch311x_gpio_driver = { + .driver.name = DRV_NAME, + .driver.owner = THIS_MODULE, + .probe = sch311x_gpio_probe, + .remove = sch311x_gpio_remove, +}; + + +/* + * Init & exit routines + */ + +static int __init sch311x_detect(int sio_config_port, unsigned short *addr) +{ + int err = 0, reg; + unsigned short base_addr; + unsigned char dev_id; + + err = sch311x_sio_enter(sio_config_port); + if (err) + return err; + + /* Check device ID. We currently know about: + * SCH3112 (0x7c), SCH3114 (0x7d), and SCH3116 (0x7f). */ + reg = sch311x_sio_inb(sio_config_port, 0x20); + if (!(reg == 0x7c || reg == 0x7d || reg == 0x7f)) { + err = -ENODEV; + goto exit; + } + dev_id = reg == 0x7c ? 2 : reg == 0x7d ? 4 : 6; + + /* Select logical device A (runtime registers) */ + sch311x_sio_outb(sio_config_port, 0x07, 0x0a); + + /* Check if Logical Device Register is currently active */ + if ((sch311x_sio_inb(sio_config_port, 0x30) & 0x01) == 0) + pr_info("Seems that LDN 0x0a is not active...\n"); + + /* Get the base address of the runtime registers */ + base_addr = (sch311x_sio_inb(sio_config_port, 0x60) << 8) | + sch311x_sio_inb(sio_config_port, 0x61); + if (!base_addr) { + pr_err("Base address not set\n"); + err = -ENODEV; + goto exit; + } + *addr = base_addr; + + pr_info("Found an SMSC SCH311%d chip at 0x%04x\n", dev_id, base_addr); + +exit: + sch311x_sio_exit(sio_config_port); + return err; +} + +static int __init sch311x_gpio_pdev_add(const unsigned short addr) +{ + struct sch311x_pdev_data pdata; + int err; + + pdata.runtime_reg = addr; + + sch311x_gpio_pdev = platform_device_alloc(DRV_NAME, -1); + if (!sch311x_gpio_pdev) + return -ENOMEM; + + err = platform_device_add_data(sch311x_gpio_pdev, + &pdata, sizeof(pdata)); + if (err) { + pr_err(DRV_NAME "Platform data allocation failed\n"); + goto err; + } + + err = platform_device_add(sch311x_gpio_pdev); + if (err) { + pr_err(DRV_NAME "Device addition failed\n"); + goto err; + } + return 0; + +err: + platform_device_put(sch311x_gpio_pdev); + return err; +} + +static int __init sch311x_gpio_init(void) +{ + int err, i; + unsigned short addr = 0; + + for (i = 0; i < ARRAY_SIZE(sch311x_ioports); i++) + if (sch311x_detect(sch311x_ioports[i], &addr) == 0) + break; + + if (!addr) + return -ENODEV; + + err = platform_driver_register(&sch311x_gpio_driver); + if (err) + return err; + + err = sch311x_gpio_pdev_add(addr); + if (err) + goto unreg_platform_driver; + + return 0; + +unreg_platform_driver: + platform_driver_unregister(&sch311x_gpio_driver); + return err; +} + +static void __exit sch311x_gpio_exit(void) +{ + platform_device_unregister(sch311x_gpio_pdev); + platform_driver_unregister(&sch311x_gpio_driver); +} + +module_init(sch311x_gpio_init); +module_exit(sch311x_gpio_exit); + +MODULE_AUTHOR("Bruno Randolf "); +MODULE_DESCRIPTION("SMSC SCH311x GPIO Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:gpio-sch311x"); -- cgit v1.2.1 From 50d7c9c841176887e138422045f53c7ce607a3da Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 16 Dec 2013 10:11:34 +0800 Subject: gpio: moxart: add missing .owner to struct gpio_chip Add missing .owner of struct gpio_chip. This prevents the module from being removed from underneath its users. Signed-off-by: Wei Yongjun Signed-off-by: Linus Walleij --- drivers/gpio/gpio-moxart.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-moxart.c b/drivers/gpio/gpio-moxart.c index 4ecd195e4a5b..79b93415c620 100644 --- a/drivers/gpio/gpio-moxart.c +++ b/drivers/gpio/gpio-moxart.c @@ -102,6 +102,7 @@ static struct gpio_chip moxart_template_chip = { .set = moxart_gpio_set, .get = moxart_gpio_get, .ngpio = 32, + .owner = THIS_MODULE, }; static int moxart_gpio_probe(struct platform_device *pdev) -- cgit v1.2.1 From ca0ae81d13d9ddb8b94fadc11d5c76b5499ac1b9 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 16 Dec 2013 10:12:38 +0800 Subject: gpio: moxart: remove redundant dev_err call in moxart_gpio_probe() There is a error message within devm_ioremap_resource already, so remove the dev_err call to avoid redundant error message. Signed-off-by: Wei Yongjun Signed-off-by: Linus Walleij --- drivers/gpio/gpio-moxart.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-moxart.c b/drivers/gpio/gpio-moxart.c index 79b93415c620..2af990022cc9 100644 --- a/drivers/gpio/gpio-moxart.c +++ b/drivers/gpio/gpio-moxart.c @@ -121,11 +121,8 @@ static int moxart_gpio_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); mgc->base = devm_ioremap_resource(dev, res); - if (IS_ERR(mgc->base)) { - dev_err(dev, "%s: devm_ioremap_resource res_gpio failed\n", - dev->of_node->full_name); + if (IS_ERR(mgc->base)) return PTR_ERR(mgc->base); - } mgc->gpio.dev = dev; -- cgit v1.2.1 From e6ae9195909a51fb8c3a7e95c2568aefe9bc912f Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 16 Dec 2013 13:52:04 +0800 Subject: gpio: sodaville: fix some error return code on error path Fix to return a negative error code from the error handling case instead of 0. Signed-off-by: Wei Yongjun Signed-off-by: Linus Walleij --- drivers/gpio/gpio-sodaville.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c index 5d171e0182db..7c6c518929bc 100644 --- a/drivers/gpio/gpio-sodaville.c +++ b/drivers/gpio/gpio-sodaville.c @@ -176,8 +176,10 @@ static int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd, sd->id = irq_domain_add_legacy(pdev->dev.of_node, SDV_NUM_PUB_GPIOS, sd->irq_base, 0, &irq_domain_sdv_ops, sd); - if (!sd->id) + if (!sd->id) { + ret = -ENODEV; goto out_free_irq; + } return 0; out_free_irq: free_irq(pdev->irq, sd); @@ -212,8 +214,10 @@ static int sdv_gpio_probe(struct pci_dev *pdev, } addr = pci_resource_start(pdev, GPIO_BAR); - if (!addr) + if (!addr) { + ret = -ENODEV; goto release_reg; + } sd->gpio_pub_base = ioremap(addr, pci_resource_len(pdev, GPIO_BAR)); prop = of_get_property(pdev->dev.of_node, "intel,muxctl", &len); -- cgit v1.2.1 From c67d0f29262bf6f863ce74d0756618bbd9ba80fd Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 6 Dec 2013 10:05:49 +0100 Subject: ARM: s3c24xx: get rid of custom This isolates the custom S3C24xx GPIO definition table to as this is used in a few different places in the kernel, removing the need to depend on the implicit inclusion of from and thus getting rid of a few nasty cross-dependencies. We also delete the nifty CONFIG_S3C24XX_GPIO_EXTRA stuff. The biggest this can ever be for the S3C24XX is CONFIG_S3C24XX_GPIO_EXTRA = 128, and then for CPU_S3C2443 or CPU_S3C2416 32*12 GPIOs are added, so 32*12+128 = 512 is the absolute roof value on this platform. So we set the size of ARCH_NR_GPIO to this and the GPIOs array will fit any S3C24XX platform, as per pattern from other archs. ChangeLog v2->v3: - Move the movement of the S3C64XX gpio.h file out of this patch and into the follow-up patch where it belongs. ChangeLog v1->v2: - Added an #ifdef ARCH_S3C24XX around the header inclusion in drivers/gpio/gpio-samsung.c as we would otherwise have colliding definitions when compiling S3C64XX. - Rename inclusion guard in the header file. Cc: Tomasz Figa Cc: Sylwester Nawrocki Cc: Ben Dooks Cc: linux-samsung-soc@vger.kernel.org Acked-by: Kukjin Kim Acked-by: Heiko Stuebner Tested-by: Heiko Stuebner Signed-off-by: Linus Walleij --- drivers/gpio/gpio-samsung.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index 76e02b9460e6..268214c57799 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c @@ -27,6 +27,9 @@ #include #include #include +#ifdef CONFIG_ARCH_S3C24XX +#include +#endif #include -- cgit v1.2.1 From 41c3548e6da67786bcaf8ee7b406f6f85ddd816b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 6 Dec 2013 12:46:27 +0100 Subject: ARM: s3c64xx: get rid of custom This isolates the custom S3C64xx GPIO definition table to as this is used in a few different places in the kernel, removing the need to depend on the implicit inclusion of from and thus getting rid of a few nasty cross-dependencies. Also delete the CONFIG_SAMSUNG_GPIO_EXTRA stuff. Instead roof the number of GPIOs for this platform: First sum up all the GPIO banks from A to Q: 187 GPIOs. Add the 16 "board GPIOs" and the roof for SAMSUNG_GPIO_EXTRA, 128, so in total maximum 187+16+128 = 331 GPIOs, so let's take the same roof as for S3C24XX: 512. This way we can do away with the GPIO calculation macros for GPIO_BOARD_START, BOARD_NR_GPIOS and the definition of ARCH_NR_GPIOS. Cc: Mark Brown [on Mini6410 board] Tested-by: Tomasz Figa [for changes in mach-s3c64xx] Acked-by: Tomasz Figa Tested-by: Mark Brown Acked-by: Kukjin Kim Signed-off-by: Linus Walleij --- drivers/gpio/gpio-samsung.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index 268214c57799..be7b0bd4eed4 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c @@ -30,6 +30,9 @@ #ifdef CONFIG_ARCH_S3C24XX #include #endif +#ifdef CONFIG_ARCH_S3C64XX +#include +#endif #include -- cgit v1.2.1 From 523639e6feb83892c15208027d7f0374cfcc1961 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 23 Dec 2013 18:12:48 +0100 Subject: gpio: sch311x: fix compilation error Compilation failed on some platforms due to implicit inclusion of , make this dependency explicit. Signed-off-by: Linus Walleij --- drivers/gpio/gpio-sch311x.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-sch311x.c b/drivers/gpio/gpio-sch311x.c index 483a6f8bd958..0357387b3645 100644 --- a/drivers/gpio/gpio-sch311x.c +++ b/drivers/gpio/gpio-sch311x.c @@ -18,6 +18,7 @@ #include #include #include +#include #define DRV_NAME "gpio-sch311x" -- cgit v1.2.1 From 035b2f7c8e64f2c7f87e1e11373b17c5dd1fbff4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Miguel=20Gon=C3=A7alves?= Date: Wed, 11 Sep 2013 09:46:13 +0100 Subject: ARM: S3C24XX: Fix configuration of gpio port sizes on S3C24XX. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some GPIO line limits are incorrectly set which, for instance, does not allow nRTS1 (GPH11) configuration on a S3C2416 chip. Signed-off-by: José Miguel Gonçalves Reviewed-by: Heiko Stuebner Acked-by: Kukjin Kim Signed-off-by: Linus Walleij --- drivers/gpio/gpio-samsung.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index be7b0bd4eed4..7138bb270c26 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c @@ -1059,7 +1059,7 @@ struct samsung_gpio_chip s3c24xx_gpios[] = { .base = S3C2410_GPA(0), .owner = THIS_MODULE, .label = "GPIOA", - .ngpio = 24, + .ngpio = 27, .direction_input = s3c24xx_gpiolib_banka_input, .direction_output = s3c24xx_gpiolib_banka_output, }, @@ -1068,7 +1068,7 @@ struct samsung_gpio_chip s3c24xx_gpios[] = { .base = S3C2410_GPB(0), .owner = THIS_MODULE, .label = "GPIOB", - .ngpio = 16, + .ngpio = 11, }, }, { .chip = { @@ -1113,7 +1113,7 @@ struct samsung_gpio_chip s3c24xx_gpios[] = { .base = S3C2410_GPH(0), .owner = THIS_MODULE, .label = "GPIOH", - .ngpio = 11, + .ngpio = 15, }, }, /* GPIOS for the S3C2443 and later devices. */ -- cgit v1.2.1 From db04030ab2500c5a0eb234ad8dc4e106829c5c71 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sat, 21 Dec 2013 12:55:38 +0530 Subject: gpio: max730x: Remove redundant dev_set_drvdata Driver core sets it to NULL upon probe failure or release. Signed-off-by: Sachin Kamat Signed-off-by: Linus Walleij --- drivers/gpio/gpio-max730x.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-max730x.c b/drivers/gpio/gpio-max730x.c index 89226a36b08c..8672755f95c9 100644 --- a/drivers/gpio/gpio-max730x.c +++ b/drivers/gpio/gpio-max730x.c @@ -220,7 +220,6 @@ int __max730x_probe(struct max7301 *ts) return ret; exit_destroy: - dev_set_drvdata(dev, NULL); mutex_destroy(&ts->lock); return ret; } @@ -234,8 +233,6 @@ int __max730x_remove(struct device *dev) if (ts == NULL) return -ENODEV; - dev_set_drvdata(dev, NULL); - /* Power down the chip and disable IRQ output */ ts->write(dev, 0x04, 0x00); -- cgit v1.2.1 From 5ea80e4910cd47270ae4c13b1fce0899aaa28410 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sat, 21 Dec 2013 13:05:57 +0530 Subject: gpio: mxc: Do not hard code return value Silences the following warning: why not propagate 'port->irq' from platform_get_irq() instead of (-22)? Signed-off-by: Sachin Kamat Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mxc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 3307f6db3a92..db83b3c0a449 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -422,7 +422,7 @@ static int mxc_gpio_probe(struct platform_device *pdev) port->irq_high = platform_get_irq(pdev, 1); port->irq = platform_get_irq(pdev, 0); if (port->irq < 0) - return -EINVAL; + return port->irq; /* disable the interrupt and clear the status */ writel(0, port->base + GPIO_IMR); -- cgit v1.2.1 From 3509c6fa05f013047b6039e2a134cd1e2db76114 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sat, 21 Dec 2013 13:05:58 +0530 Subject: gpio: mvebu: Do not hard code error code Return the appropriate error code instead of hardcoding it. Signed-off-by: Sachin Kamat Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mvebu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index bc78a9da5502..3b1fd1ce460f 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -676,7 +676,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev) mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1); if (mvchip->irqbase < 0) { dev_err(&pdev->dev, "no irqs\n"); - return -ENOMEM; + return mvchip->irqbase; } gc = irq_alloc_generic_chip("mvebu_gpio_irq", 2, mvchip->irqbase, -- cgit v1.2.1 From b10b45c0a17bdad9204abb41f6aa56daba050614 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sat, 21 Dec 2013 15:57:41 +0530 Subject: gpio: tb10x: Remove redundant of_match_ptr helper 'tb10x_gpio_dt_ids' is always compiled in. Hence the helper macro is not needed. Signed-off-by: Sachin Kamat Signed-off-by: Linus Walleij --- drivers/gpio/gpio-tb10x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-tb10x.c b/drivers/gpio/gpio-tb10x.c index 3162555ca1cb..07bce97647a6 100644 --- a/drivers/gpio/gpio-tb10x.c +++ b/drivers/gpio/gpio-tb10x.c @@ -318,7 +318,7 @@ static struct platform_driver tb10x_gpio_driver = { .remove = tb10x_gpio_remove, .driver = { .name = "tb10x-gpio", - .of_match_table = of_match_ptr(tb10x_gpio_dt_ids), + .of_match_table = tb10x_gpio_dt_ids, .owner = THIS_MODULE, } }; -- cgit v1.2.1 From e8b49e0712cb319d6cc732ed1e1433ef4df7b88e Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Tue, 24 Dec 2013 18:08:53 +0400 Subject: gpio: clps711x: Use of_match_ptr() There is no reason to keep the OF data if the driver was compiled without DT support. Signed-off-by: Alexander Shiyan Signed-off-by: Linus Walleij --- drivers/gpio/gpio-clps711x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c index 0924f20fa47f..d3550274b8f7 100644 --- a/drivers/gpio/gpio-clps711x.c +++ b/drivers/gpio/gpio-clps711x.c @@ -77,7 +77,7 @@ static int clps711x_gpio_remove(struct platform_device *pdev) return bgpio_remove(bgc); } -static const struct of_device_id clps711x_gpio_ids[] = { +static const struct of_device_id __maybe_unused clps711x_gpio_ids[] = { { .compatible = "cirrus,clps711x-gpio" }, { } }; @@ -87,7 +87,7 @@ static struct platform_driver clps711x_gpio_driver = { .driver = { .name = "clps711x-gpio", .owner = THIS_MODULE, - .of_match_table = clps711x_gpio_ids, + .of_match_table = of_match_ptr(clps711x_gpio_ids), }, .probe = clps711x_gpio_probe, .remove = clps711x_gpio_remove, -- cgit v1.2.1 From ffd4bf1a9e8a88c4b2a47007b1a9e69be28599fe Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Tue, 24 Dec 2013 18:08:54 +0400 Subject: gpio: clps711x: Enable driver compilation with COMPILE_TEST This helps increasing build testing coverage. Signed-off-by: Alexander Shiyan Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index f456b93bb953..1a07c4044839 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -110,7 +110,7 @@ comment "Memory mapped GPIO drivers:" config GPIO_CLPS711X tristate "CLPS711X GPIO support" - depends on ARCH_CLPS711X + depends on ARCH_CLPS711X || COMPILE_TEST select GPIO_GENERIC help Say yes here to support GPIO on CLPS711X SoCs. -- cgit v1.2.1 From a1a2bdec4772228274dfb3f9a41ac5234b93a5e9 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Wed, 18 Dec 2013 09:10:29 +0200 Subject: gpio: xtensa: depend on HAVE_XTENSA_GPIO32 Prevent build failure when the selected variant does not support GPIO32. Acked-by: Max Filippov Signed-off-by: Baruch Siach Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 1a07c4044839..858d489f6bae 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -300,6 +300,7 @@ config GPIO_XILINX config GPIO_XTENSA bool "Xtensa GPIO32 support" depends on XTENSA + depends on HAVE_XTENSA_GPIO32 depends on !SMP help Say yes here to support the Xtensa internal GPIO32 IMPWIRE (input) -- cgit v1.2.1 From 527d164a736acb5591f0a1412844b3600b0ee7c0 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 3 Jan 2014 15:06:24 +0530 Subject: gpio: samsung: Remove hardware.h inclusion The contents of this header file are not referenced in the driver. Remove its inclusion. Signed-off-by: Sachin Kamat Cc: Heiko Stuebner Signed-off-by: Linus Walleij --- drivers/gpio/gpio-samsung.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index 7138bb270c26..990754b97f2e 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c @@ -36,7 +36,6 @@ #include -#include #include #include -- cgit v1.2.1 From aeccc1b4a9b9e3b9a0703e93ed1db673432a29c0 Mon Sep 17 00:00:00 2001 From: Simon Guinot Date: Fri, 3 Jan 2014 16:04:08 +0100 Subject: gpio: f7188x: set can_sleep attribute Since request_muxed_region() is used to synchronize access on the Super-I/O controller, then the can_sleep attribute must be set for the f7188x GPIO chips. Signed-off-by: Simon Guinot Signed-off-by: Linus Walleij --- drivers/gpio/gpio-f7188x.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c index 9cb8320e1181..8f73ee093739 100644 --- a/drivers/gpio/gpio-f7188x.c +++ b/drivers/gpio/gpio-f7188x.c @@ -135,6 +135,7 @@ static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value); .set = f7188x_gpio_set, \ .base = _base, \ .ngpio = _ngpio, \ + .can_sleep = true, \ }, \ .regbase = _regbase, \ } -- cgit v1.2.1 From 664e3e5ac64c8a1999e2d94bc307e5bcd17d3646 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Wed, 8 Jan 2014 12:40:54 +0200 Subject: gpio / ACPI: register to ACPI events automatically Instead of asking each driver to register to ACPI events we can just call acpi_gpiochip_register_interrupts() for each chip that has an ACPI handle. The function checks chip->to_irq and if it is set to NULL (a GPIO driver that doesn't do interrupts) the function does nothing. We also add the a new header drivers/gpio/gpiolib.h that is used for functions internal to gpiolib and add ACPI GPIO chip registering functions to that header. Once that is done we can remove call to acpi_gpiochip_register_interrupts() from its only user, pinctrl-baytrail.c Signed-off-by: Mika Westerberg Acked-by: Rafael J. Wysocki Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-acpi.c | 16 ++++++++++++---- drivers/gpio/gpiolib.c | 4 ++++ drivers/gpio/gpiolib.h | 23 +++++++++++++++++++++++ 3 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 drivers/gpio/gpiolib.h (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 137d20c70afe..739b72b6731a 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -94,7 +94,7 @@ static void acpi_gpio_evt_dh(acpi_handle handle, void *data) * gpio pins have acpi event methods and assigns interrupt handlers that calls * the acpi event methods for those pins. */ -void acpi_gpiochip_request_interrupts(struct gpio_chip *chip) +static void acpi_gpiochip_request_interrupts(struct gpio_chip *chip) { struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL}; struct acpi_resource *res; @@ -192,7 +192,6 @@ void acpi_gpiochip_request_interrupts(struct gpio_chip *chip) irq); } } -EXPORT_SYMBOL(acpi_gpiochip_request_interrupts); /** * acpi_gpiochip_free_interrupts() - Free GPIO _EVT ACPI event interrupts. @@ -203,7 +202,7 @@ EXPORT_SYMBOL(acpi_gpiochip_request_interrupts); * The remaining ACPI event interrupts associated with the chip are freed * automatically. */ -void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) +static void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { acpi_handle handle; acpi_status status; @@ -230,7 +229,6 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) acpi_detach_data(handle, acpi_gpio_evt_dh); kfree(evt_pins); } -EXPORT_SYMBOL(acpi_gpiochip_free_interrupts); struct acpi_gpio_lookup { struct acpi_gpio_info info; @@ -310,3 +308,13 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index, return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT); } EXPORT_SYMBOL_GPL(acpi_get_gpiod_by_index); + +void acpi_gpiochip_add(struct gpio_chip *chip) +{ + acpi_gpiochip_request_interrupts(chip); +} + +void acpi_gpiochip_remove(struct gpio_chip *chip) +{ + acpi_gpiochip_free_interrupts(chip); +} diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index c0b06a9adad9..0de4069e33ab 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -16,6 +16,8 @@ #include #include +#include "gpiolib.h" + #define CREATE_TRACE_POINTS #include @@ -1226,6 +1228,7 @@ int gpiochip_add(struct gpio_chip *chip) #endif of_gpiochip_add(chip); + acpi_gpiochip_add(chip); if (status) goto fail; @@ -1267,6 +1270,7 @@ int gpiochip_remove(struct gpio_chip *chip) gpiochip_remove_pin_ranges(chip); of_gpiochip_remove(chip); + acpi_gpiochip_remove(chip); for (id = 0; id < chip->ngpio; id++) { if (test_bit(FLAG_REQUESTED, &chip->desc[id].flags)) { diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h new file mode 100644 index 000000000000..2ed23ab8298c --- /dev/null +++ b/drivers/gpio/gpiolib.h @@ -0,0 +1,23 @@ +/* + * Internal GPIO functions. + * + * Copyright (C) 2013, Intel Corporation + * Author: Mika Westerberg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef GPIOLIB_H +#define GPIOLIB_H + +#ifdef CONFIG_ACPI +void acpi_gpiochip_add(struct gpio_chip *chip); +void acpi_gpiochip_remove(struct gpio_chip *chip); +#else +static inline void acpi_gpiochip_add(struct gpio_chip *chip) { } +static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { } +#endif + +#endif /* GPIOLIB_H */ -- cgit v1.2.1 From 5ccff85276addfdaad0046390bc5624f7e44e614 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Wed, 8 Jan 2014 12:40:56 +0200 Subject: gpio / ACPI: get rid of acpi_gpio.h Now that all users of acpi_gpio.h have been moved to use either the GPIO descriptor interface or to the internal gpiolib.h we can get rid of acpi_gpio.h entirely. Once this is done the only interface to get GPIOs to drivers enumerated from ACPI namespace is the descriptor based interface. Signed-off-by: Mika Westerberg Acked-by: Rafael J. Wysocki Acked-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-acpi.c | 5 +++-- drivers/gpio/gpiolib.c | 1 - drivers/gpio/gpiolib.h | 23 +++++++++++++++++++++++ 3 files changed, 26 insertions(+), 3 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 739b72b6731a..716ee9843110 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -12,11 +12,13 @@ #include #include +#include #include -#include #include #include +#include "gpiolib.h" + struct acpi_gpio_evt_pin { struct list_head node; acpi_handle *evt_handle; @@ -307,7 +309,6 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index, return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT); } -EXPORT_SYMBOL_GPL(acpi_get_gpiod_by_index); void acpi_gpiochip_add(struct gpio_chip *chip) { diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 0de4069e33ab..ea0eba572333 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 2ed23ab8298c..82be586c1f90 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -12,12 +12,35 @@ #ifndef GPIOLIB_H #define GPIOLIB_H +#include +#include + +/** + * struct acpi_gpio_info - ACPI GPIO specific information + * @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo + * @active_low: in case of @gpioint, the pin is active low + */ +struct acpi_gpio_info { + bool gpioint; + bool active_low; +}; + #ifdef CONFIG_ACPI void acpi_gpiochip_add(struct gpio_chip *chip); void acpi_gpiochip_remove(struct gpio_chip *chip); + +struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index, + struct acpi_gpio_info *info); #else static inline void acpi_gpiochip_add(struct gpio_chip *chip) { } static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { } + +static inline struct gpio_desc * +acpi_get_gpiod_by_index(struct device *dev, int index, + struct acpi_gpio_info *info) +{ + return ERR_PTR(-ENOSYS); +} #endif #endif /* GPIOLIB_H */ -- cgit v1.2.1 From b0161caa72b6ff60f82f5531b9b728f3b6d19e1b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 14 Jan 2014 14:24:24 +0100 Subject: ARM: S3C[24|64]xx: move includes back under scope When refactoring and breaking out the includes for the machine-specific GPIO configuration, two files were created in , but as that namespace shall be used for defining data exchanged between machines and drivers, using it for these broad macros and config settings is wrong. Move the headers back into the machine-local file and think about the next step. Reported-by: Arnd Bergmann Cc: Tomasz Figa Cc: Sylwester Nawrocki Cc: Ben Dooks Cc: Kukjin Kim Cc: linux-samsung-soc@vger.kernel.org Acked-by: Mark Brown Acked-by: Arnd Bergmann Acked-by: Heiko Stuebner Signed-off-by: Linus Walleij --- drivers/gpio/gpio-samsung.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index 990754b97f2e..9741cce11df5 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c @@ -27,17 +27,12 @@ #include #include #include -#ifdef CONFIG_ARCH_S3C24XX -#include -#endif -#ifdef CONFIG_ARCH_S3C64XX -#include -#endif #include #include #include +#include #include #include -- cgit v1.2.1 From 3018fd81310688c3dfe8938a98680a9341982d02 Mon Sep 17 00:00:00 2001 From: Neil Zhang Date: Thu, 9 Jan 2014 17:25:57 +0800 Subject: gpio: pxa: clamp gpio get value to [0,1] It would be convenient to normalize the return value for gpio_get. I have checked mach-mmp / mach-pxa / plat-pxa / plat-orion / mach-orion5x. It's OK for all of them to change this function to return 0 and 1. Signed-off-by: Neil Zhang Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pxa.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index cc13d1b74fad..42e6e64f2120 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -263,7 +263,8 @@ static int pxa_gpio_direction_output(struct gpio_chip *chip, static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset) { - return readl_relaxed(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset); + u32 gplr = readl_relaxed(gpio_chip_base(chip) + GPLR_OFFSET); + return !!(gplr & (1 << offset)); } static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -- cgit v1.2.1 From 785acec3eecf4c21bab9e24afb5d354b57a72e03 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 15 Jan 2014 14:31:29 +0530 Subject: ARM: S5P[v210|c100|64x0]: Fix build error gpio-samsung.h header file introduced by commit 93177be0910c ("ARM: S3C[24|64]xx: move includes back under scope") is required only by S3C[24|64]xx machines. Include them conditionally to avoid the following build errors for other machine configurations. drivers/gpio/gpio-samsung.c:35:31: fatal error: mach/gpio-samsung.h: No such file or directory arch/arm/plat-samsung/pm-gpio.c:22:31: fatal error: mach/gpio-samsung.h: No such file or directory Signed-off-by: Sachin Kamat Signed-off-by: Linus Walleij --- drivers/gpio/gpio-samsung.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index 9741cce11df5..a85e00bf9834 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c @@ -32,7 +32,10 @@ #include #include + +#if defined(CONFIG_ARCH_S3C24XX) || defined(CONFIG_ARCH_S3C64XX) #include +#endif #include #include -- cgit v1.2.1 From 4e47f91bf741e011a90ceb6241b8d78141709733 Mon Sep 17 00:00:00 2001 From: Lars Poeschel Date: Thu, 16 Jan 2014 11:44:15 +0100 Subject: gpio: mcp23s08: Add irq functionality for i2c chips This adds interrupt functionality for i2c chips to the driver. They can act as a interrupt-controller and generate interrupts, if the inputs change. This is tested with a mcp23017 chip on an arm based platform. v3: - be a bit more clear that the irq functionality is also available on spi versions of the chips, but the linux driver does not support this yet v2: - some more word about irq-mirror property in binding doc - use of_read_bool instead of of_find_property for "interrupt-contrller" and "irq-mirror" - cache the "interrupt-controller" for remove function - do set the irq-mirror bit only if device is marked as interrupt-controller - do create the irq mapping and setup of irq_desc of all possible interrupts in probe path instead of in gpio_to_irq - mark gpios as in use as interrupts in irq in irq_startup and unlock it in irq_shutdown - rename virq to child_irq - remove dev argument from mcp23s08_irq_setup function - move gpiochip_add before mcp23s08_irq_setup in probe path Signed-off-by: Lars Poeschel Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 1 + drivers/gpio/gpio-mcp23s08.c | 248 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 244 insertions(+), 5 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 858d489f6bae..2d49784109b5 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -722,6 +722,7 @@ config GPIO_MCP23S08 SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017 I/O expanders. This provides a GPIO interface supporting inputs and outputs. + The I2C versions of the chips can be used as interrupt-controller. config GPIO_MC33880 tristate "Freescale MC33880 high-side/low-side switch" diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index b16401ee4766..ef3fd48aca3b 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c @@ -1,5 +1,13 @@ /* - * MCP23S08 SPI/GPIO gpio expander driver + * MCP23S08 SPI/I2C GPIO gpio expander driver + * + * The inputs and outputs of the mcp23s08, mcp23s17, mcp23008 and mcp23017 are + * supported. + * For the I2C versions of the chips (mcp23008 and mcp23017) generation of + * interrupts is also supported. + * The hardware of the SPI versions of the chips (mcp23s08 and mcp23s17) is + * also capable of generating interrupts, but the linux driver does not + * support that yet. */ #include @@ -12,7 +20,8 @@ #include #include #include -#include +#include +#include #include /** @@ -34,6 +43,7 @@ #define MCP_DEFVAL 0x03 #define MCP_INTCON 0x04 #define MCP_IOCON 0x05 +# define IOCON_MIRROR (1 << 6) # define IOCON_SEQOP (1 << 5) # define IOCON_HAEN (1 << 3) # define IOCON_ODR (1 << 2) @@ -57,8 +67,14 @@ struct mcp23s08 { u8 addr; u16 cache[11]; + u16 irq_rise; + u16 irq_fall; + int irq; + bool irq_controller; /* lock protects the cached values */ struct mutex lock; + struct mutex irq_lock; + struct irq_domain *irq_domain; struct gpio_chip chip; @@ -77,6 +93,11 @@ struct mcp23s08_driver_data { struct mcp23s08 chip[]; }; +/* This lock class tells lockdep that GPIO irqs are in a different + * category than their parents, so it won't report false recursion. + */ +static struct lock_class_key gpio_lock_class; + /*----------------------------------------------------------------------*/ #if IS_ENABLED(CONFIG_I2C) @@ -315,6 +336,195 @@ mcp23s08_direction_output(struct gpio_chip *chip, unsigned offset, int value) return status; } +/*----------------------------------------------------------------------*/ +static irqreturn_t mcp23s08_irq(int irq, void *data) +{ + struct mcp23s08 *mcp = data; + int intcap, intf, i; + unsigned int child_irq; + + mutex_lock(&mcp->lock); + intf = mcp->ops->read(mcp, MCP_INTF); + if (intf < 0) { + mutex_unlock(&mcp->lock); + return IRQ_HANDLED; + } + + mcp->cache[MCP_INTF] = intf; + + intcap = mcp->ops->read(mcp, MCP_INTCAP); + if (intcap < 0) { + mutex_unlock(&mcp->lock); + return IRQ_HANDLED; + } + + mcp->cache[MCP_INTCAP] = intcap; + mutex_unlock(&mcp->lock); + + + for (i = 0; i < mcp->chip.ngpio; i++) { + if ((BIT(i) & mcp->cache[MCP_INTF]) && + ((BIT(i) & intcap & mcp->irq_rise) || + (mcp->irq_fall & ~intcap & BIT(i)))) { + child_irq = irq_find_mapping(mcp->irq_domain, i); + handle_nested_irq(child_irq); + } + } + + return IRQ_HANDLED; +} + +static int mcp23s08_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip); + + return irq_find_mapping(mcp->irq_domain, offset); +} + +static void mcp23s08_irq_mask(struct irq_data *data) +{ + struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + unsigned int pos = data->hwirq; + + mcp->cache[MCP_GPINTEN] &= ~BIT(pos); +} + +static void mcp23s08_irq_unmask(struct irq_data *data) +{ + struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + unsigned int pos = data->hwirq; + + mcp->cache[MCP_GPINTEN] |= BIT(pos); +} + +static int mcp23s08_irq_set_type(struct irq_data *data, unsigned int type) +{ + struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + unsigned int pos = data->hwirq; + int status = 0; + + if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) { + mcp->cache[MCP_INTCON] &= ~BIT(pos); + mcp->irq_rise |= BIT(pos); + mcp->irq_fall |= BIT(pos); + } else if (type & IRQ_TYPE_EDGE_RISING) { + mcp->cache[MCP_INTCON] &= ~BIT(pos); + mcp->irq_rise |= BIT(pos); + mcp->irq_fall &= ~BIT(pos); + } else if (type & IRQ_TYPE_EDGE_FALLING) { + mcp->cache[MCP_INTCON] &= ~BIT(pos); + mcp->irq_rise &= ~BIT(pos); + mcp->irq_fall |= BIT(pos); + } else + return -EINVAL; + + return status; +} + +static void mcp23s08_irq_bus_lock(struct irq_data *data) +{ + struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + + mutex_lock(&mcp->irq_lock); +} + +static void mcp23s08_irq_bus_unlock(struct irq_data *data) +{ + struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + + mutex_lock(&mcp->lock); + mcp->ops->write(mcp, MCP_GPINTEN, mcp->cache[MCP_GPINTEN]); + mcp->ops->write(mcp, MCP_DEFVAL, mcp->cache[MCP_DEFVAL]); + mcp->ops->write(mcp, MCP_INTCON, mcp->cache[MCP_INTCON]); + mutex_unlock(&mcp->lock); + mutex_unlock(&mcp->irq_lock); +} + +static unsigned int mcp23s08_irq_startup(struct irq_data *data) +{ + struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + + if (gpio_lock_as_irq(&mcp->chip, data->hwirq)) + dev_err(mcp->chip.dev, + "unable to lock HW IRQ %lu for IRQ usage\n", + data->hwirq); + + mcp23s08_irq_unmask(data); + return 0; +} + +static void mcp23s08_irq_shutdown(struct irq_data *data) +{ + struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + + mcp23s08_irq_mask(data); + gpio_unlock_as_irq(&mcp->chip, data->hwirq); +} + +static struct irq_chip mcp23s08_irq_chip = { + .name = "gpio-mcp23xxx", + .irq_mask = mcp23s08_irq_mask, + .irq_unmask = mcp23s08_irq_unmask, + .irq_set_type = mcp23s08_irq_set_type, + .irq_bus_lock = mcp23s08_irq_bus_lock, + .irq_bus_sync_unlock = mcp23s08_irq_bus_unlock, + .irq_startup = mcp23s08_irq_startup, + .irq_shutdown = mcp23s08_irq_shutdown, +}; + +static int mcp23s08_irq_setup(struct mcp23s08 *mcp) +{ + struct gpio_chip *chip = &mcp->chip; + int err, irq, j; + + mutex_init(&mcp->irq_lock); + + mcp->irq_domain = irq_domain_add_linear(chip->of_node, chip->ngpio, + &irq_domain_simple_ops, mcp); + if (!mcp->irq_domain) + return -ENODEV; + + err = devm_request_threaded_irq(chip->dev, mcp->irq, NULL, mcp23s08_irq, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + dev_name(chip->dev), mcp); + if (err != 0) { + dev_err(chip->dev, "unable to request IRQ#%d: %d\n", + mcp->irq, err); + return err; + } + + chip->to_irq = mcp23s08_gpio_to_irq; + + for (j = 0; j < mcp->chip.ngpio; j++) { + irq = irq_create_mapping(mcp->irq_domain, j); + irq_set_lockdep_class(irq, &gpio_lock_class); + irq_set_chip_data(irq, mcp); + irq_set_chip(irq, &mcp23s08_irq_chip); + irq_set_nested_thread(irq, true); +#ifdef CONFIG_ARM + set_irq_flags(irq, IRQF_VALID); +#else + irq_set_noprobe(irq); +#endif + } + return 0; +} + +static void mcp23s08_irq_teardown(struct mcp23s08 *mcp) +{ + unsigned int irq, i; + + free_irq(mcp->irq, mcp); + + for (i = 0; i < mcp->chip.ngpio; i++) { + irq = irq_find_mapping(mcp->irq_domain, i); + if (irq > 0) + irq_dispose_mapping(irq); + } + + irq_domain_remove(mcp->irq_domain); +} + /*----------------------------------------------------------------------*/ #ifdef CONFIG_DEBUG_FS @@ -370,10 +580,11 @@ done: /*----------------------------------------------------------------------*/ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, - void *data, unsigned addr, - unsigned type, unsigned base, unsigned pullups) + void *data, unsigned addr, unsigned type, + unsigned base, unsigned pullups) { int status; + bool mirror = false; mutex_init(&mcp->lock); @@ -432,13 +643,25 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, /* verify MCP_IOCON.SEQOP = 0, so sequential reads work, * and MCP_IOCON.HAEN = 1, so we work with all chips. */ + status = mcp->ops->read(mcp, MCP_IOCON); if (status < 0) goto fail; - if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN)) { + + mcp->irq_controller = of_property_read_bool(mcp->chip.of_node, + "interrupt-controller"); + if (mcp->irq && mcp->irq_controller && (type == MCP_TYPE_017)) + mirror = of_property_read_bool(mcp->chip.of_node, + "microchip,irq-mirror"); + + if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN) || mirror) { /* mcp23s17 has IOCON twice, make sure they are in sync */ status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8)); status |= IOCON_HAEN | (IOCON_HAEN << 8); + status &= ~(IOCON_INTPOL | (IOCON_INTPOL << 8)); + if (mirror) + status |= IOCON_MIRROR | (IOCON_MIRROR << 8); + status = mcp->ops->write(mcp, MCP_IOCON, status); if (status < 0) goto fail; @@ -470,6 +693,16 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, } status = gpiochip_add(&mcp->chip); + if (status < 0) + goto fail; + + if (mcp->irq && mcp->irq_controller) { + status = mcp23s08_irq_setup(mcp); + if (status) { + mcp23s08_irq_teardown(mcp); + goto fail; + } + } fail: if (status < 0) dev_dbg(dev, "can't setup chip %d, --> %d\n", @@ -546,6 +779,7 @@ static int mcp230xx_probe(struct i2c_client *client, if (match || !pdata) { base = -1; pullups = 0; + client->irq = irq_of_parse_and_map(client->dev.of_node, 0); } else { if (!gpio_is_valid(pdata->base)) { dev_dbg(&client->dev, "invalid platform data\n"); @@ -559,6 +793,7 @@ static int mcp230xx_probe(struct i2c_client *client, if (!mcp) return -ENOMEM; + mcp->irq = client->irq; status = mcp23s08_probe_one(mcp, &client->dev, client, client->addr, id->driver_data, base, pullups); if (status) @@ -579,6 +814,9 @@ static int mcp230xx_remove(struct i2c_client *client) struct mcp23s08 *mcp = i2c_get_clientdata(client); int status; + if (client->irq && mcp->irq_controller) + mcp23s08_irq_teardown(mcp); + status = gpiochip_remove(&mcp->chip); if (status == 0) kfree(mcp); -- cgit v1.2.1 From 01d7004181c8ff6d63bf5e8e2b771022c4f78289 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 20 Jan 2014 09:07:34 +0100 Subject: gpio: mcp23s08: depend on OF_GPIO The MCP drivers fails to compile on trial builds due to missing Kconfig dependency on OF_GPIO. Fix it. Cc: Lars Poeschel Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 2d49784109b5..d5bd9eece408 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -717,7 +717,7 @@ config GPIO_MAX7301 config GPIO_MCP23S08 tristate "Microchip MCP23xxx I/O expander" - depends on (SPI_MASTER && !I2C) || I2C + depends on (SPI_MASTER && !I2C) || I2C && OF_GPIO help SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017 I/O expanders. -- cgit v1.2.1 From de755c330512364d3396c7da0c20b1c20b3b08b2 Mon Sep 17 00:00:00 2001 From: SeongJae Park Date: Sat, 18 Jan 2014 13:53:04 +0900 Subject: gpio: mcp23s08: fix casting caused build warning Signed-off-by: SeongJae Park Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mcp23s08.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index ef3fd48aca3b..1ac288ea810d 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c @@ -878,7 +878,7 @@ static int mcp23s08_probe(struct spi_device *spi) match = of_match_device(of_match_ptr(mcp23s08_spi_of_match), &spi->dev); if (match) { - type = (int)match->data; + type = (int)(uintptr_t)match->data; status = of_property_read_u32(spi->dev.of_node, "microchip,spi-present-mask", &spi_present_mask); if (status) { -- cgit v1.2.1