diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2015-12-04 14:02:58 +0100 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2016-01-05 11:21:00 +0100 |
commit | 0f4630f3720e7e6e921bf525c8357fea7ef3dbab (patch) | |
tree | 61c1904593d1ee424464c2d57668ba0fd2fbcbb4 /drivers/gpio/gpio-brcmstb.c | |
parent | 3208b0f0c010b26e4d461a3bca59989d03ed9087 (diff) |
gpio: generic: factor into gpio_chip struct
The separate struct bgpio_chip has been a pain to handle, both
by being confusingly similar in name to struct gpio_chip and
for being contained inside a struct so that struct gpio_chip
is contained in a struct contained in a struct, making several
steps of dereferencing necessary.
Make things simpler: include the fields directly into
<linux/gpio/driver.h>, #ifdef:ed for CONFIG_GENERIC_GPIO, and
get rid of the <linux/basic_mmio_gpio.h> altogether. Prefix
some of the member variables with bgpio_* and add proper
kerneldoc while we're at it.
Modify all users to handle the change and use a struct
gpio_chip directly. And while we're at it: replace all
container_of() dereferencing by gpiochip_get_data() and
registering the gpio_chip with gpiochip_add_data().
Cc: arm@kernel.org
Cc: Alexander Shiyan <shc_work@mail.ru>
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: Kukjin Kim <kgene@kernel.org>
Cc: Alexandre Courbot <gnurou@gmail.com>
Cc: Brian Norris <computersforpeace@gmail.com>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Sudeep Holla <sudeep.holla@arm.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
Cc: Olof Johansson <olof@lixom.net>
Cc: Vladimir Zapolskiy <vladimir_zapolskiy@mentor.com>
Cc: Rabin Vincent <rabin@rab.in>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-omap@vger.kernel.org
Cc: linux-samsung-soc@vger.kernel.org
Cc: bcm-kernel-feedback-list@broadcom.com
Acked-by: Gregory Fong <gregory.0xf0@gmail.com>
Acked-by: Liviu Dudau <Liviu.Dudau@arm.com>
Acked-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Acked-by: Tony Lindgren <tony@atomide.com>
Acked-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Acked-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio/gpio-brcmstb.c')
-rw-r--r-- | drivers/gpio/gpio-brcmstb.c | 80 |
1 files changed, 34 insertions, 46 deletions
diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c index 4c64627c6bb5..dc3f0395693b 100644 --- a/drivers/gpio/gpio-brcmstb.c +++ b/drivers/gpio/gpio-brcmstb.c @@ -16,7 +16,6 @@ #include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/module.h> -#include <linux/basic_mmio_gpio.h> #include <linux/irqdomain.h> #include <linux/irqchip/chained_irq.h> #include <linux/interrupt.h> @@ -35,7 +34,7 @@ struct brcmstb_gpio_bank { struct list_head node; int id; - struct bgpio_chip bgc; + struct gpio_chip gc; struct brcmstb_gpio_priv *parent_priv; u32 width; struct irq_chip irq_chip; @@ -57,37 +56,30 @@ struct brcmstb_gpio_priv { /* assumes MAX_GPIO_PER_BANK is a multiple of 2 */ #define GPIO_BIT(gpio) ((gpio) & (MAX_GPIO_PER_BANK - 1)) -static inline struct brcmstb_gpio_bank * -brcmstb_gpio_gc_to_bank(struct gpio_chip *gc) -{ - struct bgpio_chip *bgc = to_bgpio_chip(gc); - return container_of(bgc, struct brcmstb_gpio_bank, bgc); -} - static inline struct brcmstb_gpio_priv * brcmstb_gpio_gc_to_priv(struct gpio_chip *gc) { - struct brcmstb_gpio_bank *bank = brcmstb_gpio_gc_to_bank(gc); + struct brcmstb_gpio_bank *bank = gpiochip_get_data(gc); return bank->parent_priv; } static void brcmstb_gpio_set_imask(struct brcmstb_gpio_bank *bank, unsigned int offset, bool enable) { - struct bgpio_chip *bgc = &bank->bgc; + struct gpio_chip *gc = &bank->gc; struct brcmstb_gpio_priv *priv = bank->parent_priv; - u32 mask = bgc->pin2mask(bgc, offset); + u32 mask = gc->pin2mask(gc, offset); u32 imask; unsigned long flags; - spin_lock_irqsave(&bgc->lock, flags); - imask = bgc->read_reg(priv->reg_base + GIO_MASK(bank->id)); + spin_lock_irqsave(&gc->bgpio_lock, flags); + imask = gc->read_reg(priv->reg_base + GIO_MASK(bank->id)); if (enable) imask |= mask; else imask &= ~mask; - bgc->write_reg(priv->reg_base + GIO_MASK(bank->id), imask); - spin_unlock_irqrestore(&bgc->lock, flags); + gc->write_reg(priv->reg_base + GIO_MASK(bank->id), imask); + spin_unlock_irqrestore(&gc->bgpio_lock, flags); } /* -------------------- IRQ chip functions -------------------- */ @@ -95,7 +87,7 @@ static void brcmstb_gpio_set_imask(struct brcmstb_gpio_bank *bank, static void brcmstb_gpio_irq_mask(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct brcmstb_gpio_bank *bank = brcmstb_gpio_gc_to_bank(gc); + struct brcmstb_gpio_bank *bank = gpiochip_get_data(gc); brcmstb_gpio_set_imask(bank, d->hwirq, false); } @@ -103,7 +95,7 @@ static void brcmstb_gpio_irq_mask(struct irq_data *d) static void brcmstb_gpio_irq_unmask(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct brcmstb_gpio_bank *bank = brcmstb_gpio_gc_to_bank(gc); + struct brcmstb_gpio_bank *bank = gpiochip_get_data(gc); brcmstb_gpio_set_imask(bank, d->hwirq, true); } @@ -111,7 +103,7 @@ static void brcmstb_gpio_irq_unmask(struct irq_data *d) static int brcmstb_gpio_irq_set_type(struct irq_data *d, unsigned int type) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct brcmstb_gpio_bank *bank = brcmstb_gpio_gc_to_bank(gc); + struct brcmstb_gpio_bank *bank = gpiochip_get_data(gc); struct brcmstb_gpio_priv *priv = bank->parent_priv; u32 mask = BIT(d->hwirq); u32 edge_insensitive, iedge_insensitive; @@ -149,23 +141,23 @@ static int brcmstb_gpio_irq_set_type(struct irq_data *d, unsigned int type) return -EINVAL; } - spin_lock_irqsave(&bank->bgc.lock, flags); + spin_lock_irqsave(&bank->gc.bgpio_lock, flags); - iedge_config = bank->bgc.read_reg(priv->reg_base + + iedge_config = bank->gc.read_reg(priv->reg_base + GIO_EC(bank->id)) & ~mask; - iedge_insensitive = bank->bgc.read_reg(priv->reg_base + + iedge_insensitive = bank->gc.read_reg(priv->reg_base + GIO_EI(bank->id)) & ~mask; - ilevel = bank->bgc.read_reg(priv->reg_base + + ilevel = bank->gc.read_reg(priv->reg_base + GIO_LEVEL(bank->id)) & ~mask; - bank->bgc.write_reg(priv->reg_base + GIO_EC(bank->id), + bank->gc.write_reg(priv->reg_base + GIO_EC(bank->id), iedge_config | edge_config); - bank->bgc.write_reg(priv->reg_base + GIO_EI(bank->id), + bank->gc.write_reg(priv->reg_base + GIO_EI(bank->id), iedge_insensitive | edge_insensitive); - bank->bgc.write_reg(priv->reg_base + GIO_LEVEL(bank->id), + bank->gc.write_reg(priv->reg_base + GIO_LEVEL(bank->id), ilevel | level); - spin_unlock_irqrestore(&bank->bgc.lock, flags); + spin_unlock_irqrestore(&bank->gc.bgpio_lock, flags); return 0; } @@ -210,29 +202,29 @@ static irqreturn_t brcmstb_gpio_wake_irq_handler(int irq, void *data) static void brcmstb_gpio_irq_bank_handler(struct brcmstb_gpio_bank *bank) { struct brcmstb_gpio_priv *priv = bank->parent_priv; - struct irq_domain *irq_domain = bank->bgc.gc.irqdomain; + struct irq_domain *irq_domain = bank->gc.irqdomain; void __iomem *reg_base = priv->reg_base; unsigned long status; unsigned long flags; - spin_lock_irqsave(&bank->bgc.lock, flags); - while ((status = bank->bgc.read_reg(reg_base + GIO_STAT(bank->id)) & - bank->bgc.read_reg(reg_base + GIO_MASK(bank->id)))) { + spin_lock_irqsave(&bank->gc.bgpio_lock, flags); + while ((status = bank->gc.read_reg(reg_base + GIO_STAT(bank->id)) & + bank->gc.read_reg(reg_base + GIO_MASK(bank->id)))) { int bit; for_each_set_bit(bit, &status, 32) { - u32 stat = bank->bgc.read_reg(reg_base + + u32 stat = bank->gc.read_reg(reg_base + GIO_STAT(bank->id)); if (bit >= bank->width) dev_warn(&priv->pdev->dev, "IRQ for invalid GPIO (bank=%d, offset=%d)\n", bank->id, bit); - bank->bgc.write_reg(reg_base + GIO_STAT(bank->id), + bank->gc.write_reg(reg_base + GIO_STAT(bank->id), stat | BIT(bit)); generic_handle_irq(irq_find_mapping(irq_domain, bit)); } } - spin_unlock_irqrestore(&bank->bgc.lock, flags); + spin_unlock_irqrestore(&bank->gc.bgpio_lock, flags); } /* Each UPG GIO block has one IRQ for all banks */ @@ -303,9 +295,7 @@ static int brcmstb_gpio_remove(struct platform_device *pdev) */ list_for_each(pos, &priv->bank_list) { bank = list_entry(pos, struct brcmstb_gpio_bank, node); - ret = bgpio_remove(&bank->bgc); - if (ret) - dev_err(&pdev->dev, "gpiochip_remove fail in cleanup\n"); + gpiochip_remove(&bank->gc); } if (priv->reboot_notifier.notifier_call) { ret = unregister_reboot_notifier(&priv->reboot_notifier); @@ -320,7 +310,7 @@ static int brcmstb_gpio_of_xlate(struct gpio_chip *gc, const struct of_phandle_args *gpiospec, u32 *flags) { struct brcmstb_gpio_priv *priv = brcmstb_gpio_gc_to_priv(gc); - struct brcmstb_gpio_bank *bank = brcmstb_gpio_gc_to_bank(gc); + struct brcmstb_gpio_bank *bank = gpiochip_get_data(gc); int offset; if (gc->of_gpio_n_cells != 2) { @@ -398,9 +388,9 @@ static int brcmstb_gpio_irq_setup(struct platform_device *pdev, if (priv->can_wake) bank->irq_chip.irq_set_wake = brcmstb_gpio_irq_set_wake; - gpiochip_irqchip_add(&bank->bgc.gc, &bank->irq_chip, 0, + gpiochip_irqchip_add(&bank->gc, &bank->irq_chip, 0, handle_simple_irq, IRQ_TYPE_NONE); - gpiochip_set_chained_irqchip(&bank->bgc.gc, &bank->irq_chip, + gpiochip_set_chained_irqchip(&bank->gc, &bank->irq_chip, priv->parent_irq, brcmstb_gpio_irq_handler); return 0; @@ -451,7 +441,6 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) of_property_for_each_u32(np, "brcm,gpio-bank-widths", prop, p, bank_width) { struct brcmstb_gpio_bank *bank; - struct bgpio_chip *bgc; struct gpio_chip *gc; bank = devm_kzalloc(dev, sizeof(*bank), GFP_KERNEL); @@ -473,8 +462,8 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) * Regs are 4 bytes wide, have data reg, no set/clear regs, * and direction bits have 0 = output and 1 = input */ - bgc = &bank->bgc; - err = bgpio_init(bgc, dev, 4, + gc = &bank->gc; + err = bgpio_init(gc, dev, 4, reg_base + GIO_DATA(bank->id), NULL, NULL, NULL, reg_base + GIO_IODIR(bank->id), 0); @@ -483,7 +472,6 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) goto fail; } - gc = &bgc->gc; gc->of_node = np; gc->owner = THIS_MODULE; gc->label = np->full_name; @@ -497,9 +485,9 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) * Mask all interrupts by default, since wakeup interrupts may * be retained from S5 cold boot */ - bank->bgc.write_reg(reg_base + GIO_MASK(bank->id), 0); + gc->write_reg(reg_base + GIO_MASK(bank->id), 0); - err = gpiochip_add(gc); + err = gpiochip_add_data(gc, bank); if (err) { dev_err(dev, "Could not add gpiochip for bank %d\n", bank->id); |