aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhou Wang <wangzhou1@hisilicon.com>2014-04-14 18:58:53 +0800
committerZhou Wang <wangzhou1@hisilicon.com>2014-04-15 20:37:09 +0800
commitdbad38ebccadc0d41540ac18991e1a08eb89593b (patch)
tree1be2fa42b225c8d165a2f858504636a03b53d967
parentd99cd69f183a6844d9a83c2cf5fd976342922853 (diff)
change as maintainer's commentswz_gpio
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-hip04.txt2
-rw-r--r--arch/arm/boot/dts/hip04.dtsi17
-rw-r--r--drivers/gpio/gpio-hip04.c209
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",