diff options
author | Zhou Wang <wangzhou1@hisilicon.com> | 2014-04-14 18:58:53 +0800 |
---|---|---|
committer | Zhou Wang <wangzhou1@hisilicon.com> | 2014-04-15 20:37:09 +0800 |
commit | dbad38ebccadc0d41540ac18991e1a08eb89593b (patch) | |
tree | 1be2fa42b225c8d165a2f858504636a03b53d967 | |
parent | d99cd69f183a6844d9a83c2cf5fd976342922853 (diff) |
change as maintainer's commentswz_gpio
-rw-r--r-- | Documentation/devicetree/bindings/gpio/gpio-hip04.txt | 2 | ||||
-rw-r--r-- | arch/arm/boot/dts/hip04.dtsi | 17 | ||||
-rw-r--r-- | drivers/gpio/gpio-hip04.c | 209 |
3 files changed, 72 insertions, 156 deletions
diff --git a/Documentation/devicetree/bindings/gpio/gpio-hip04.txt b/Documentation/devicetree/bindings/gpio/gpio-hip04.txt index 2ea490c64fde..9e8e5cb7ef1b 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-hip04.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-hip04.txt @@ -5,7 +5,6 @@ Required properties: - compatible : Should be "hisilicon, hip04-gpio". - reg: Address and length of the register set for the device. - interrupt-parent: Phandle of the parent interrupt controller. -- ngpios: Number of GPIOs this controller has. - gpio-controller: Marks the device node as a gpio controller - #gpio-cells: Should be 2. The first cell is the pin number. The second cell is reserved for flags, unused at the moment. @@ -25,7 +24,6 @@ Example: compatible = "hisilicon,hip04-gpio"; reg = <0x4000000 0x00001000>; interrupt-parent = <&gic>; - ngpios = <32>; gpio-controller; #gpio-cells = <2>; interrupts = <0 389 4>; diff --git a/arch/arm/boot/dts/hip04.dtsi b/arch/arm/boot/dts/hip04.dtsi index dcbb448222bd..6fcd5dc37c39 100644 --- a/arch/arm/boot/dts/hip04.dtsi +++ b/arch/arm/boot/dts/hip04.dtsi @@ -24,7 +24,6 @@ gpio1 = &gpio1; gpio2 = &gpio2; gpio3 = &gpio3; - gpio4 = &gpio4; }; cpus { @@ -191,7 +190,6 @@ compatible = "hisilicon,hip04-gpio"; reg = <0x4000000 0x00001000>; interrupt-parent = <&gic>; - ngpios = <32>; gpio-controller; #gpio-cells = <2>; interrupts = <0 389 4>; @@ -203,7 +201,6 @@ compatible = "hisilicon,hip04-gpio"; reg = <0x4001000 0x00001000>; interrupt-parent = <&gic>; - ngpios = <32>; gpio-controller; #gpio-cells = <2>; interrupts = <0 390 4>; @@ -215,7 +212,6 @@ compatible = "hisilicon,hip04-gpio"; reg = <0x4002000 0x00001000>; interrupt-parent = <&gic>; - ngpios = <32>; gpio-controller; #gpio-cells = <2>; interrupts = <0 391 4>; @@ -227,24 +223,11 @@ compatible = "hisilicon,hip04-gpio"; reg = <0x4003000 0x00001000>; interrupt-parent = <&gic>; - ngpios = <32>; gpio-controller; #gpio-cells = <2>; interrupts = <0 392 4>; interrupt-controller; #interrupt-cells = <2>; }; - - gpio4: gpio@00e4004000 { - compatible = "hisilicon,hip04-gpio"; - reg = <0x4004000 0x00001000>; - interrupt-parent = <&gic>; - ngpios = <32>; - gpio-controller; - #gpio-cells = <2>; - interrupts = <0 393 4>; - interrupt-controller; - #interrupt-cells = <2>; - }; }; }; diff --git a/drivers/gpio/gpio-hip04.c b/drivers/gpio/gpio-hip04.c index 64c464c41a3d..696dc0c815df 100644 --- a/drivers/gpio/gpio-hip04.c +++ b/drivers/gpio/gpio-hip04.c @@ -24,6 +24,7 @@ #include <linux/clk.h> #include <linux/interrupt.h> #include <linux/irqchip/chained_irq.h> +#include <linux/bitops.h> /* * GPIO controller register offsets. @@ -40,12 +41,13 @@ #define GPIO_PORT_EOI 0x004c #define GPIO_EXT_PORT 0x0050 +#define NGPIOS 32 + struct hip04_gpio_chip { struct gpio_chip chip; spinlock_t lock; - void __iomem *membase; + void __iomem *base; int irqbase; - int ngpios; struct irq_domain *domain; }; @@ -60,63 +62,9 @@ static struct of_device_id hip04_gpio_of_match[] = { MODULE_DEVICE_TABLE(of, hip04_gpio_of_match); -/* - * Functions returning addresses of individual registers for a given - * GPIO controller. - */ -static inline void __iomem *hip04_gpioreg_out(struct hip04_gpio_chip *pchip) -{ - return pchip->membase + GPIO_SWPORT_DR; -} - -static inline void __iomem *hip04_gpioreg_io_dir(struct hip04_gpio_chip *pchip) -{ - return pchip->membase + GPIO_SWPORT_DDR; -} - -static inline void __iomem *hip04_gpioreg_data_in(struct hip04_gpio_chip *pchip) -{ - return pchip->membase + GPIO_EXT_PORT; -} - -static void __iomem *hip04_gpioreg_irq_mask(struct hip04_gpio_chip *pchip) -{ - return pchip->membase + GPIO_INMASK; -} - -static void __iomem *hip04_gpioreg_irq_enable(struct hip04_gpio_chip *pchip) -{ - return pchip->membase + GPIO_INTEN; -} - -static void __iomem *hip04_gpioreg_irq_status(struct hip04_gpio_chip *pchip) +static inline struct hip04_gpio_chip *to_hip04(struct gpio_chip *gc) { - return pchip->membase + GPIO_INTSTATUS; -} - -static void __iomem *hip04_gpioreg_irq_raw_status(struct hip04_gpio_chip *pchip) -{ - return pchip->membase + GPIO_RAW_INTSTATUS; -} - -static void __iomem *hip04_gpioreg_debounce(struct hip04_gpio_chip *pchip) -{ - return pchip->membase + GPIO_DEBOUNCE; -} - -static void __iomem *hip04_gpioreg_irq_ack(struct hip04_gpio_chip *pchip) -{ - return pchip->membase + GPIO_PORT_EOI; -} - -static void __iomem *hip04_gpioreg_irq_type(struct hip04_gpio_chip *pchip) -{ - return pchip->membase + GPIO_INTTYPE_LEVEL; -} - -static void __iomem *hip04_gpioreg_irq_polarity(struct hip04_gpio_chip *pchip) -{ - return pchip->membase + GPIO_INT_POLARITY; + return container_of(gc, struct hip04_gpio_chip, chip); } /* @@ -133,46 +81,43 @@ static void hip04_gpio_free(struct gpio_chip *chip, unsigned pin) static void hip04_gpio_set(struct gpio_chip *chip, unsigned pin, int value) { - struct hip04_gpio_chip *pchip = - container_of(chip, struct hip04_gpio_chip, chip); + struct hip04_gpio_chip *pchip = to_hip04(chip); unsigned long flags; u32 u; spin_lock_irqsave(&pchip->lock, flags); - u = readl_relaxed(hip04_gpioreg_out(pchip)); + u = readl_relaxed(pchip->base + GPIO_SWPORT_DR); if (value) - u |= 1 << pin; + u |= BIT(pin); else - u &= ~(1 << pin); - writel_relaxed(u, hip04_gpioreg_out(pchip)); + u &= ~BIT(pin); + writel_relaxed(u, pchip->base + GPIO_SWPORT_DR); spin_unlock_irqrestore(&pchip->lock, flags); } static int hip04_gpio_get(struct gpio_chip *chip, unsigned pin) { - struct hip04_gpio_chip *pchip = - container_of(chip, struct hip04_gpio_chip, chip); + struct hip04_gpio_chip *pchip = to_hip04(chip); u32 u; - if ((~readl_relaxed(hip04_gpioreg_io_dir(pchip))) & (1 << pin)) - u = readl_relaxed(hip04_gpioreg_data_in(pchip)); + if (~readl_relaxed(pchip->base + GPIO_SWPORT_DDR) & BIT(pin)) + u = readl_relaxed(pchip->base + GPIO_EXT_PORT); else - u = readl_relaxed(hip04_gpioreg_out(pchip)); + u = readl_relaxed(pchip->base + GPIO_SWPORT_DR); return (u >> pin) & 1; } static int hip04_gpio_direction_input(struct gpio_chip *chip, unsigned pin) { - struct hip04_gpio_chip *pchip = - container_of(chip, struct hip04_gpio_chip, chip); + struct hip04_gpio_chip *pchip = to_hip04(chip); unsigned long flags; u32 u; spin_lock_irqsave(&pchip->lock, flags); - u = readl_relaxed(hip04_gpioreg_io_dir(pchip)); - u &= ~(1 << pin); - writel_relaxed(u, hip04_gpioreg_io_dir(pchip)); + u = readl_relaxed(pchip->base + GPIO_SWPORT_DDR); + u &= ~BIT(pin); + writel_relaxed(u, pchip->base + GPIO_SWPORT_DDR); spin_unlock_irqrestore(&pchip->lock, flags); return 0; @@ -181,17 +126,16 @@ static int hip04_gpio_direction_input(struct gpio_chip *chip, unsigned pin) static int hip04_gpio_direction_output(struct gpio_chip *chip, unsigned pin, int value) { - struct hip04_gpio_chip *pchip = - container_of(chip, struct hip04_gpio_chip, chip); + struct hip04_gpio_chip *pchip = to_hip04(chip); unsigned long flags; u32 u; hip04_gpio_set(chip, pin, value); spin_lock_irqsave(&pchip->lock, flags); - u = readl_relaxed(hip04_gpioreg_io_dir(pchip)); - u |= 1 << pin; - writel_relaxed(u, hip04_gpioreg_io_dir(pchip)); + u = readl_relaxed(pchip->base + GPIO_SWPORT_DDR); + u |= BIT(pin); + writel_relaxed(u, pchip->base + GPIO_SWPORT_DDR); spin_unlock_irqrestore(&pchip->lock, flags); return 0; @@ -199,9 +143,8 @@ hip04_gpio_direction_output(struct gpio_chip *chip, unsigned pin, int value) static int hip04_gpio_to_irq(struct gpio_chip *chip, unsigned pin) { - struct hip04_gpio_chip *pchip = - container_of(chip, struct hip04_gpio_chip, chip); - return irq_create_mapping(pchip->domain, pin); + struct hip04_gpio_chip *pchip = to_hip04(chip); + return irq_find_mapping(pchip->domain, pin); } /* @@ -212,18 +155,17 @@ static int hip04_gpio_to_irq(struct gpio_chip *chip, unsigned pin) static int hip04_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, unsigned debounce) { - struct hip04_gpio_chip *pchip = - container_of(chip, struct hip04_gpio_chip, chip); + struct hip04_gpio_chip *pchip = to_hip04(chip); unsigned long flags; u32 u; spin_lock_irqsave(&pchip->lock, flags); - u = readl_relaxed(hip04_gpioreg_debounce(pchip)); + u = readl_relaxed(pchip->base + GPIO_DEBOUNCE); if (debounce > 0) - u |= 1 << offset; + u |= BIT(offset); else - u &= ~(1 << offset); - writel_relaxed(u, hip04_gpioreg_debounce(pchip)); + u &= ~BIT(offset); + writel_relaxed(u, pchip->base + GPIO_DEBOUNCE); spin_unlock_irqrestore(&pchip->lock, flags); return 0; @@ -236,11 +178,11 @@ static void hip04_gpio_irq_mask(struct irq_data *d) { struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct hip04_gpio_chip *pchip = gc->private; - u32 pin = 1 << (d->irq - gc->irq_base); + u32 pin = BIT(d->irq - gc->irq_base); irq_gc_lock(gc); gc->mask_cache |= pin; - writel_relaxed(gc->mask_cache, hip04_gpioreg_irq_mask(pchip)); + writel_relaxed(gc->mask_cache, pchip->base + GPIO_INMASK); irq_gc_unlock(gc); } @@ -248,11 +190,11 @@ static void hip04_gpio_irq_unmask(struct irq_data *d) { struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct hip04_gpio_chip *pchip = gc->private; - u32 pin = 1 << (d->irq - gc->irq_base); + u32 pin = BIT(d->irq - gc->irq_base); irq_gc_lock(gc); gc->mask_cache &= ~pin; - writel_relaxed(gc->mask_cache, hip04_gpioreg_irq_mask(pchip)); + writel_relaxed(gc->mask_cache, pchip->base + GPIO_INMASK); irq_gc_unlock(gc); } @@ -264,7 +206,7 @@ static int hip04_gpio_irq_set_type(struct irq_data *d, unsigned int type) pin = d->hwirq; - u = readl_relaxed(hip04_gpioreg_io_dir(pchip)) & (1 << pin); + u = readl_relaxed(pchip->base + GPIO_SWPORT_DDR) & BIT(pin); if (u) return -EINVAL; @@ -272,34 +214,34 @@ static int hip04_gpio_irq_set_type(struct irq_data *d, unsigned int type) if (type == IRQ_TYPE_NONE) return -EINVAL; - irq_type = readl_relaxed(hip04_gpioreg_irq_type(pchip)); - irq_polarity = readl_relaxed(hip04_gpioreg_irq_polarity(pchip)); + irq_type = readl_relaxed(pchip->base + GPIO_INTTYPE_LEVEL); + irq_polarity = readl_relaxed(pchip->base + GPIO_INT_POLARITY); switch (type) { case IRQ_TYPE_EDGE_RISING: - irq_type |= (1 << pin); - irq_polarity |= (1 << pin); + irq_type |= BIT(pin); + irq_polarity |= BIT(pin); __irq_set_handler_locked(d->irq, handle_edge_irq); break; case IRQ_TYPE_LEVEL_HIGH: - irq_type &= ~(1 << pin); - irq_polarity |= (1 << pin); + irq_type &= ~BIT(pin); + irq_polarity |= BIT(pin); __irq_set_handler_locked(d->irq, handle_level_irq); break; case IRQ_TYPE_EDGE_FALLING: - irq_type |= (1 << pin); - irq_polarity &= ~(1 << pin); + irq_type |= BIT(pin); + irq_polarity &= ~BIT(pin); __irq_set_handler_locked(d->irq, handle_edge_irq); break; case IRQ_TYPE_LEVEL_LOW: - irq_type &= ~(1 << pin); - irq_polarity &= ~(1 << pin); + irq_type &= ~BIT(pin); + irq_polarity &= ~BIT(pin); __irq_set_handler_locked(d->irq, handle_level_irq); break; default: return -EINVAL; } - writel_relaxed(irq_type, hip04_gpioreg_irq_type(pchip)); - writel_relaxed(irq_polarity, hip04_gpioreg_irq_polarity(pchip)); + writel_relaxed(irq_type, pchip->base + GPIO_INTTYPE_LEVEL); + writel_relaxed(irq_polarity, pchip->base + GPIO_INT_POLARITY); return 0; } @@ -308,12 +250,12 @@ static void hip04_gpio_irq_enable(struct irq_data *d) { struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct hip04_gpio_chip *pchip = gc->private; - u32 pin = 1 << (d->irq - gc->irq_base); + u32 pin = BIT(d->irq - gc->irq_base); u32 u; irq_gc_lock(gc); - u = readl_relaxed(hip04_gpioreg_irq_enable(pchip)); - writel_relaxed(u | pin, hip04_gpioreg_irq_enable(pchip)); + u = readl_relaxed(pchip->base + GPIO_INTEN); + writel_relaxed(u | pin, pchip->base + GPIO_INTEN); irq_gc_unlock(gc); } @@ -321,12 +263,12 @@ static void hip04_gpio_irq_disable(struct irq_data *d) { struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct hip04_gpio_chip *pchip = gc->private; - u32 pin = 1 << (d->irq - gc->irq_base); + u32 pin = BIT(d->irq - gc->irq_base); u32 u; irq_gc_lock(gc); - u = readl_relaxed(hip04_gpioreg_irq_enable(pchip)); - writel_relaxed(u & ~pin, hip04_gpioreg_irq_enable(pchip)); + u = readl_relaxed(pchip->base + GPIO_INTEN); + writel_relaxed(u & ~pin, pchip->base + GPIO_INTEN); irq_gc_unlock(gc); } @@ -334,10 +276,10 @@ static void hip04_gpio_irq_ack(struct irq_data *d) { struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct hip04_gpio_chip *pchip = gc->private; - u32 pin = 1 << (d->irq - gc->irq_base); + u32 pin = BIT(d->irq - gc->irq_base); irq_gc_lock(gc); - writel_relaxed(pin, hip04_gpioreg_irq_ack(pchip)); + writel_relaxed(pin, pchip->base + GPIO_PORT_EOI); irq_gc_unlock(gc); } @@ -351,18 +293,18 @@ static void hip04_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) return; chained_irq_enter(chip, desc); - cause = readl_relaxed(hip04_gpioreg_irq_status(pchip)) & - ~readl_relaxed(hip04_gpioreg_irq_mask(pchip)); + cause = readl_relaxed(pchip->base + GPIO_INTSTATUS) & + ~readl_relaxed(pchip->base + GPIO_INMASK); for (i = 0; i < pchip->chip.ngpio; i++) { int irq; irq = pchip->irqbase + i; - if (!(cause & (1 << i))) + if (!(cause & BIT(i))) continue; /* if level trigger */ - if (!(readl_relaxed(hip04_gpioreg_irq_type(pchip)) & (1 << i))) - writel_relaxed(1 << i, hip04_gpioreg_irq_mask(pchip)); - writel_relaxed(1 << i, hip04_gpioreg_irq_ack(pchip)); + if (!(readl_relaxed(pchip->base + GPIO_INTTYPE_LEVEL) & BIT(i))) + writel_relaxed(BIT(i), pchip->base + GPIO_INMASK); + writel_relaxed(BIT(i), pchip->base + GPIO_PORT_EOI); generic_handle_irq(irq); } chained_irq_exit(chip, desc); @@ -375,7 +317,6 @@ static int hip04_gpio_probe(struct platform_device *pdev) struct irq_chip_generic *gc; struct irq_chip_type *ct; struct resource *res; - unsigned int ngpios; int id, irq; pchip = devm_kzalloc(&pdev->dev, sizeof(struct hip04_gpio_chip), @@ -383,18 +324,12 @@ static int hip04_gpio_probe(struct platform_device *pdev) if (!pchip) return -ENOMEM; - if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) { - dev_err(&pdev->dev, "Missing ngpios OF property\n"); - return -ENODEV; - } - id = of_alias_get_id(pdev->dev.of_node, "gpio"); if (id < 0) { dev_err(&pdev->dev, "Couldn't get OF id\n"); return id; } - pchip->ngpios = ngpios; pchip->chip.label = dev_name(&pdev->dev); pchip->chip.dev = &pdev->dev; pchip->chip.request = hip04_gpio_request; @@ -405,16 +340,16 @@ static int hip04_gpio_probe(struct platform_device *pdev) pchip->chip.set = hip04_gpio_set; pchip->chip.to_irq = hip04_gpio_to_irq; pchip->chip.set_debounce = hip04_gpio_set_debounce; - pchip->chip.ngpio = ngpios; + pchip->chip.ngpio = NGPIOS; pchip->chip.can_sleep = 0; pchip->chip.of_node = np; - pchip->chip.base = id * ngpios; + pchip->chip.base = id * NGPIOS; spin_lock_init(&pchip->lock); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - pchip->membase = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(pchip->membase)) - return PTR_ERR(pchip->membase); + pchip->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(pchip->base)) + return PTR_ERR(pchip->base); gpiochip_add(&pchip->chip); platform_set_drvdata(pdev, pchip); @@ -423,7 +358,7 @@ static int hip04_gpio_probe(struct platform_device *pdev) irq_set_handler_data(irq, pchip); irq_set_chained_handler(irq, hip04_gpio_irq_handler); - pchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1); + pchip->irqbase = irq_alloc_descs(-1, 0, NGPIOS, -1); if (pchip->irqbase < 0) { dev_err(&pdev->dev, "no irqs\n"); return pchip->irqbase; @@ -431,7 +366,7 @@ static int hip04_gpio_probe(struct platform_device *pdev) /* default is edge trigger */ gc = irq_alloc_generic_chip("hip04_gpio_irq", 1, pchip->irqbase, - pchip->membase, handle_edge_irq); + pchip->base, handle_edge_irq); if (!gc) { dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n"); return -ENOMEM; @@ -448,7 +383,7 @@ static int hip04_gpio_probe(struct platform_device *pdev) ct->chip.irq_disable = hip04_gpio_irq_disable; ct->chip.name = pchip->chip.label; - irq_setup_generic_chip(gc, IRQ_MSK(ngpios), 0, + irq_setup_generic_chip(gc, IRQ_MSK(NGPIOS), 0, IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); pchip->domain = irq_domain_add_simple(np, pchip->chip.ngpio, @@ -457,7 +392,7 @@ static int hip04_gpio_probe(struct platform_device *pdev) if (!pchip->domain) { dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n", pchip->chip.label); - irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST, + irq_remove_generic_chip(gc, IRQ_MSK(NGPIOS), IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); kfree(gc); return -ENODEV; @@ -476,11 +411,11 @@ static int hip04_gpio_remove(struct platform_device *pdev) irq_set_handler(irq, NULL); irq_set_handler_data(irq, NULL); - irq_remove_generic_chip(gc, IRQ_MSK(pchip->ngpios), IRQ_NOREQUEST, + irq_remove_generic_chip(gc, IRQ_MSK(NGPIOS), IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); kfree(gc); irq_domain_remove(pchip->domain); - irq_free_descs(pchip->irqbase, pchip->ngpios); + irq_free_descs(pchip->irqbase, NGPIOS); ret = gpiochip_remove(&pchip->chip); if (ret) { dev_err(&pdev->dev, "%s failed, %d\n", |