|
@@ -33,21 +33,23 @@
|
|
|
* interrupts.
|
|
|
*/
|
|
|
|
|
|
+#include <linux/bitops.h>
|
|
|
+#include <linux/clk.h>
|
|
|
#include <linux/err.h>
|
|
|
-#include <linux/init.h>
|
|
|
#include <linux/gpio.h>
|
|
|
+#include <linux/init.h>
|
|
|
+#include <linux/io.h>
|
|
|
#include <linux/irq.h>
|
|
|
-#include <linux/slab.h>
|
|
|
+#include <linux/irqchip/chained_irq.h>
|
|
|
#include <linux/irqdomain.h>
|
|
|
-#include <linux/io.h>
|
|
|
-#include <linux/of_irq.h>
|
|
|
+#include <linux/mfd/syscon.h>
|
|
|
#include <linux/of_device.h>
|
|
|
-#include <linux/pwm.h>
|
|
|
-#include <linux/clk.h>
|
|
|
+#include <linux/of_irq.h>
|
|
|
#include <linux/pinctrl/consumer.h>
|
|
|
-#include <linux/irqchip/chained_irq.h>
|
|
|
#include <linux/platform_device.h>
|
|
|
-#include <linux/bitops.h>
|
|
|
+#include <linux/pwm.h>
|
|
|
+#include <linux/regmap.h>
|
|
|
+#include <linux/slab.h>
|
|
|
|
|
|
#include "gpiolib.h"
|
|
|
|
|
@@ -87,6 +89,7 @@
|
|
|
#define MVEBU_GPIO_SOC_VARIANT_ORION 0x1
|
|
|
#define MVEBU_GPIO_SOC_VARIANT_MV78200 0x2
|
|
|
#define MVEBU_GPIO_SOC_VARIANT_ARMADAXP 0x3
|
|
|
+#define MVEBU_GPIO_SOC_VARIANT_A8K 0x4
|
|
|
|
|
|
#define MVEBU_MAX_GPIO_PER_BANK 32
|
|
|
|
|
@@ -106,9 +109,9 @@ struct mvebu_pwm {
|
|
|
|
|
|
struct mvebu_gpio_chip {
|
|
|
struct gpio_chip chip;
|
|
|
- spinlock_t lock;
|
|
|
- void __iomem *membase;
|
|
|
- void __iomem *percpu_membase;
|
|
|
+ struct regmap *regs;
|
|
|
+ u32 offset;
|
|
|
+ struct regmap *percpu_regs;
|
|
|
int irqbase;
|
|
|
struct irq_domain *domain;
|
|
|
int soc_variant;
|
|
@@ -130,92 +133,152 @@ struct mvebu_gpio_chip {
|
|
|
* Functions returning addresses of individual registers for a given
|
|
|
* GPIO controller.
|
|
|
*/
|
|
|
-static void __iomem *mvebu_gpioreg_out(struct mvebu_gpio_chip *mvchip)
|
|
|
-{
|
|
|
- return mvchip->membase + GPIO_OUT_OFF;
|
|
|
-}
|
|
|
|
|
|
-static void __iomem *mvebu_gpioreg_blink(struct mvebu_gpio_chip *mvchip)
|
|
|
+static void mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvchip,
|
|
|
+ struct regmap **map, unsigned int *offset)
|
|
|
{
|
|
|
- return mvchip->membase + GPIO_BLINK_EN_OFF;
|
|
|
-}
|
|
|
+ int cpu;
|
|
|
|
|
|
-static void __iomem *mvebu_gpioreg_blink_counter_select(struct mvebu_gpio_chip
|
|
|
- *mvchip)
|
|
|
-{
|
|
|
- return mvchip->membase + GPIO_BLINK_CNT_SELECT_OFF;
|
|
|
+ switch (mvchip->soc_variant) {
|
|
|
+ case MVEBU_GPIO_SOC_VARIANT_ORION:
|
|
|
+ case MVEBU_GPIO_SOC_VARIANT_MV78200:
|
|
|
+ case MVEBU_GPIO_SOC_VARIANT_A8K:
|
|
|
+ *map = mvchip->regs;
|
|
|
+ *offset = GPIO_EDGE_CAUSE_OFF + mvchip->offset;
|
|
|
+ break;
|
|
|
+ case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
|
|
|
+ cpu = smp_processor_id();
|
|
|
+ *map = mvchip->percpu_regs;
|
|
|
+ *offset = GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ BUG();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-static void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip)
|
|
|
+static u32
|
|
|
+mvebu_gpio_read_edge_cause(struct mvebu_gpio_chip *mvchip)
|
|
|
{
|
|
|
- return mvchip->membase + GPIO_IO_CONF_OFF;
|
|
|
-}
|
|
|
+ struct regmap *map;
|
|
|
+ unsigned int offset;
|
|
|
+ u32 val;
|
|
|
|
|
|
-static void __iomem *mvebu_gpioreg_in_pol(struct mvebu_gpio_chip *mvchip)
|
|
|
-{
|
|
|
- return mvchip->membase + GPIO_IN_POL_OFF;
|
|
|
+ mvebu_gpioreg_edge_cause(mvchip, &map, &offset);
|
|
|
+ regmap_read(map, offset, &val);
|
|
|
+
|
|
|
+ return val;
|
|
|
}
|
|
|
|
|
|
-static void __iomem *mvebu_gpioreg_data_in(struct mvebu_gpio_chip *mvchip)
|
|
|
+static void
|
|
|
+mvebu_gpio_write_edge_cause(struct mvebu_gpio_chip *mvchip, u32 val)
|
|
|
{
|
|
|
- return mvchip->membase + GPIO_DATA_IN_OFF;
|
|
|
+ struct regmap *map;
|
|
|
+ unsigned int offset;
|
|
|
+
|
|
|
+ mvebu_gpioreg_edge_cause(mvchip, &map, &offset);
|
|
|
+ regmap_write(map, offset, val);
|
|
|
}
|
|
|
|
|
|
-static void __iomem *mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvchip)
|
|
|
+static inline void
|
|
|
+mvebu_gpioreg_edge_mask(struct mvebu_gpio_chip *mvchip,
|
|
|
+ struct regmap **map, unsigned int *offset)
|
|
|
{
|
|
|
int cpu;
|
|
|
|
|
|
switch (mvchip->soc_variant) {
|
|
|
case MVEBU_GPIO_SOC_VARIANT_ORION:
|
|
|
+ case MVEBU_GPIO_SOC_VARIANT_A8K:
|
|
|
+ *map = mvchip->regs;
|
|
|
+ *offset = GPIO_EDGE_MASK_OFF + mvchip->offset;
|
|
|
+ break;
|
|
|
case MVEBU_GPIO_SOC_VARIANT_MV78200:
|
|
|
- return mvchip->membase + GPIO_EDGE_CAUSE_OFF;
|
|
|
+ cpu = smp_processor_id();
|
|
|
+ *map = mvchip->regs;
|
|
|
+ *offset = GPIO_EDGE_MASK_MV78200_OFF(cpu);
|
|
|
+ break;
|
|
|
case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
|
|
|
cpu = smp_processor_id();
|
|
|
- return mvchip->percpu_membase +
|
|
|
- GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu);
|
|
|
+ *map = mvchip->percpu_regs;
|
|
|
+ *offset = GPIO_EDGE_MASK_ARMADAXP_OFF(cpu);
|
|
|
+ break;
|
|
|
default:
|
|
|
BUG();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static void __iomem *mvebu_gpioreg_edge_mask(struct mvebu_gpio_chip *mvchip)
|
|
|
+static u32
|
|
|
+mvebu_gpio_read_edge_mask(struct mvebu_gpio_chip *mvchip)
|
|
|
{
|
|
|
- int cpu;
|
|
|
+ struct regmap *map;
|
|
|
+ unsigned int offset;
|
|
|
+ u32 val;
|
|
|
|
|
|
- switch (mvchip->soc_variant) {
|
|
|
- case MVEBU_GPIO_SOC_VARIANT_ORION:
|
|
|
- return mvchip->membase + GPIO_EDGE_MASK_OFF;
|
|
|
- case MVEBU_GPIO_SOC_VARIANT_MV78200:
|
|
|
- cpu = smp_processor_id();
|
|
|
- return mvchip->membase + GPIO_EDGE_MASK_MV78200_OFF(cpu);
|
|
|
- case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
|
|
|
- cpu = smp_processor_id();
|
|
|
- return mvchip->percpu_membase +
|
|
|
- GPIO_EDGE_MASK_ARMADAXP_OFF(cpu);
|
|
|
- default:
|
|
|
- BUG();
|
|
|
- }
|
|
|
+ mvebu_gpioreg_edge_mask(mvchip, &map, &offset);
|
|
|
+ regmap_read(map, offset, &val);
|
|
|
+
|
|
|
+ return val;
|
|
|
}
|
|
|
|
|
|
-static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip)
|
|
|
+static void
|
|
|
+mvebu_gpio_write_edge_mask(struct mvebu_gpio_chip *mvchip, u32 val)
|
|
|
+{
|
|
|
+ struct regmap *map;
|
|
|
+ unsigned int offset;
|
|
|
+
|
|
|
+ mvebu_gpioreg_edge_mask(mvchip, &map, &offset);
|
|
|
+ regmap_write(map, offset, val);
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip,
|
|
|
+ struct regmap **map, unsigned int *offset)
|
|
|
{
|
|
|
int cpu;
|
|
|
|
|
|
switch (mvchip->soc_variant) {
|
|
|
case MVEBU_GPIO_SOC_VARIANT_ORION:
|
|
|
- return mvchip->membase + GPIO_LEVEL_MASK_OFF;
|
|
|
+ case MVEBU_GPIO_SOC_VARIANT_A8K:
|
|
|
+ *map = mvchip->regs;
|
|
|
+ *offset = GPIO_LEVEL_MASK_OFF + mvchip->offset;
|
|
|
+ break;
|
|
|
case MVEBU_GPIO_SOC_VARIANT_MV78200:
|
|
|
cpu = smp_processor_id();
|
|
|
- return mvchip->membase + GPIO_LEVEL_MASK_MV78200_OFF(cpu);
|
|
|
+ *map = mvchip->regs;
|
|
|
+ *offset = GPIO_LEVEL_MASK_MV78200_OFF(cpu);
|
|
|
+ break;
|
|
|
case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
|
|
|
cpu = smp_processor_id();
|
|
|
- return mvchip->percpu_membase +
|
|
|
- GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu);
|
|
|
+ *map = mvchip->percpu_regs;
|
|
|
+ *offset = GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu);
|
|
|
+ break;
|
|
|
default:
|
|
|
BUG();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static u32
|
|
|
+mvebu_gpio_read_level_mask(struct mvebu_gpio_chip *mvchip)
|
|
|
+{
|
|
|
+ struct regmap *map;
|
|
|
+ unsigned int offset;
|
|
|
+ u32 val;
|
|
|
+
|
|
|
+ mvebu_gpioreg_level_mask(mvchip, &map, &offset);
|
|
|
+ regmap_read(map, offset, &val);
|
|
|
+
|
|
|
+ return val;
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+mvebu_gpio_write_level_mask(struct mvebu_gpio_chip *mvchip, u32 val)
|
|
|
+{
|
|
|
+ struct regmap *map;
|
|
|
+ unsigned int offset;
|
|
|
+
|
|
|
+ mvebu_gpioreg_level_mask(mvchip, &map, &offset);
|
|
|
+ regmap_write(map, offset, val);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Functions returning addresses of individual registers for a given
|
|
|
* PWM controller.
|
|
@@ -236,17 +299,9 @@ static void __iomem *mvebu_pwmreg_blink_off_duration(struct mvebu_pwm *mvpwm)
|
|
|
static void mvebu_gpio_set(struct gpio_chip *chip, unsigned int pin, int value)
|
|
|
{
|
|
|
struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip);
|
|
|
- unsigned long flags;
|
|
|
- u32 u;
|
|
|
|
|
|
- spin_lock_irqsave(&mvchip->lock, flags);
|
|
|
- u = readl_relaxed(mvebu_gpioreg_out(mvchip));
|
|
|
- if (value)
|
|
|
- u |= BIT(pin);
|
|
|
- else
|
|
|
- u &= ~BIT(pin);
|
|
|
- writel_relaxed(u, mvebu_gpioreg_out(mvchip));
|
|
|
- spin_unlock_irqrestore(&mvchip->lock, flags);
|
|
|
+ regmap_update_bits(mvchip->regs, GPIO_OUT_OFF + mvchip->offset,
|
|
|
+ BIT(pin), value ? BIT(pin) : 0);
|
|
|
}
|
|
|
|
|
|
static int mvebu_gpio_get(struct gpio_chip *chip, unsigned int pin)
|
|
@@ -254,11 +309,18 @@ static int mvebu_gpio_get(struct gpio_chip *chip, unsigned int pin)
|
|
|
struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip);
|
|
|
u32 u;
|
|
|
|
|
|
- if (readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & BIT(pin)) {
|
|
|
- u = readl_relaxed(mvebu_gpioreg_data_in(mvchip)) ^
|
|
|
- readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
|
|
|
+ regmap_read(mvchip->regs, GPIO_IO_CONF_OFF + mvchip->offset, &u);
|
|
|
+
|
|
|
+ if (u & BIT(pin)) {
|
|
|
+ u32 data_in, in_pol;
|
|
|
+
|
|
|
+ regmap_read(mvchip->regs, GPIO_DATA_IN_OFF + mvchip->offset,
|
|
|
+ &data_in);
|
|
|
+ regmap_read(mvchip->regs, GPIO_IN_POL_OFF + mvchip->offset,
|
|
|
+ &in_pol);
|
|
|
+ u = data_in ^ in_pol;
|
|
|
} else {
|
|
|
- u = readl_relaxed(mvebu_gpioreg_out(mvchip));
|
|
|
+ regmap_read(mvchip->regs, GPIO_OUT_OFF + mvchip->offset, &u);
|
|
|
}
|
|
|
|
|
|
return (u >> pin) & 1;
|
|
@@ -268,25 +330,15 @@ static void mvebu_gpio_blink(struct gpio_chip *chip, unsigned int pin,
|
|
|
int value)
|
|
|
{
|
|
|
struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip);
|
|
|
- unsigned long flags;
|
|
|
- u32 u;
|
|
|
|
|
|
- spin_lock_irqsave(&mvchip->lock, flags);
|
|
|
- u = readl_relaxed(mvebu_gpioreg_blink(mvchip));
|
|
|
- if (value)
|
|
|
- u |= BIT(pin);
|
|
|
- else
|
|
|
- u &= ~BIT(pin);
|
|
|
- writel_relaxed(u, mvebu_gpioreg_blink(mvchip));
|
|
|
- spin_unlock_irqrestore(&mvchip->lock, flags);
|
|
|
+ regmap_update_bits(mvchip->regs, GPIO_BLINK_EN_OFF + mvchip->offset,
|
|
|
+ BIT(pin), value ? BIT(pin) : 0);
|
|
|
}
|
|
|
|
|
|
static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned int pin)
|
|
|
{
|
|
|
struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip);
|
|
|
- unsigned long flags;
|
|
|
int ret;
|
|
|
- u32 u;
|
|
|
|
|
|
/*
|
|
|
* Check with the pinctrl driver whether this pin is usable as
|
|
@@ -296,11 +348,8 @@ static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned int pin)
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
|
- spin_lock_irqsave(&mvchip->lock, flags);
|
|
|
- u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
|
|
|
- u |= BIT(pin);
|
|
|
- writel_relaxed(u, mvebu_gpioreg_io_conf(mvchip));
|
|
|
- spin_unlock_irqrestore(&mvchip->lock, flags);
|
|
|
+ regmap_update_bits(mvchip->regs, GPIO_IO_CONF_OFF + mvchip->offset,
|
|
|
+ BIT(pin), BIT(pin));
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -309,9 +358,7 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned int pin,
|
|
|
int value)
|
|
|
{
|
|
|
struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip);
|
|
|
- unsigned long flags;
|
|
|
int ret;
|
|
|
- u32 u;
|
|
|
|
|
|
/*
|
|
|
* Check with the pinctrl driver whether this pin is usable as
|
|
@@ -324,11 +371,8 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned int pin,
|
|
|
mvebu_gpio_blink(chip, pin, 0);
|
|
|
mvebu_gpio_set(chip, pin, value);
|
|
|
|
|
|
- spin_lock_irqsave(&mvchip->lock, flags);
|
|
|
- u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
|
|
|
- u &= ~BIT(pin);
|
|
|
- writel_relaxed(u, mvebu_gpioreg_io_conf(mvchip));
|
|
|
- spin_unlock_irqrestore(&mvchip->lock, flags);
|
|
|
+ regmap_update_bits(mvchip->regs, GPIO_IO_CONF_OFF + mvchip->offset,
|
|
|
+ BIT(pin), 0);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -350,7 +394,7 @@ static void mvebu_gpio_irq_ack(struct irq_data *d)
|
|
|
u32 mask = d->mask;
|
|
|
|
|
|
irq_gc_lock(gc);
|
|
|
- writel_relaxed(~mask, mvebu_gpioreg_edge_cause(mvchip));
|
|
|
+ mvebu_gpio_write_edge_cause(mvchip, ~mask);
|
|
|
irq_gc_unlock(gc);
|
|
|
}
|
|
|
|
|
@@ -363,8 +407,7 @@ static void mvebu_gpio_edge_irq_mask(struct irq_data *d)
|
|
|
|
|
|
irq_gc_lock(gc);
|
|
|
ct->mask_cache_priv &= ~mask;
|
|
|
-
|
|
|
- writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_edge_mask(mvchip));
|
|
|
+ mvebu_gpio_write_edge_mask(mvchip, ct->mask_cache_priv);
|
|
|
irq_gc_unlock(gc);
|
|
|
}
|
|
|
|
|
@@ -377,7 +420,7 @@ static void mvebu_gpio_edge_irq_unmask(struct irq_data *d)
|
|
|
|
|
|
irq_gc_lock(gc);
|
|
|
ct->mask_cache_priv |= mask;
|
|
|
- writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_edge_mask(mvchip));
|
|
|
+ mvebu_gpio_write_edge_mask(mvchip, ct->mask_cache_priv);
|
|
|
irq_gc_unlock(gc);
|
|
|
}
|
|
|
|
|
@@ -390,7 +433,7 @@ static void mvebu_gpio_level_irq_mask(struct irq_data *d)
|
|
|
|
|
|
irq_gc_lock(gc);
|
|
|
ct->mask_cache_priv &= ~mask;
|
|
|
- writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_level_mask(mvchip));
|
|
|
+ mvebu_gpio_write_level_mask(mvchip, ct->mask_cache_priv);
|
|
|
irq_gc_unlock(gc);
|
|
|
}
|
|
|
|
|
@@ -403,7 +446,7 @@ static void mvebu_gpio_level_irq_unmask(struct irq_data *d)
|
|
|
|
|
|
irq_gc_lock(gc);
|
|
|
ct->mask_cache_priv |= mask;
|
|
|
- writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_level_mask(mvchip));
|
|
|
+ mvebu_gpio_write_level_mask(mvchip, ct->mask_cache_priv);
|
|
|
irq_gc_unlock(gc);
|
|
|
}
|
|
|
|
|
@@ -443,8 +486,8 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type)
|
|
|
|
|
|
pin = d->hwirq;
|
|
|
|
|
|
- u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & BIT(pin);
|
|
|
- if (!u)
|
|
|
+ regmap_read(mvchip->regs, GPIO_IO_CONF_OFF + mvchip->offset, &u);
|
|
|
+ if ((u & BIT(pin)) == 0)
|
|
|
return -EINVAL;
|
|
|
|
|
|
type &= IRQ_TYPE_SENSE_MASK;
|
|
@@ -462,31 +505,35 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type)
|
|
|
switch (type) {
|
|
|
case IRQ_TYPE_EDGE_RISING:
|
|
|
case IRQ_TYPE_LEVEL_HIGH:
|
|
|
- u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
|
|
|
- u &= ~BIT(pin);
|
|
|
- writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
|
|
|
+ regmap_update_bits(mvchip->regs,
|
|
|
+ GPIO_IN_POL_OFF + mvchip->offset,
|
|
|
+ BIT(pin), 0);
|
|
|
break;
|
|
|
case IRQ_TYPE_EDGE_FALLING:
|
|
|
case IRQ_TYPE_LEVEL_LOW:
|
|
|
- u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
|
|
|
- u |= BIT(pin);
|
|
|
- writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
|
|
|
+ regmap_update_bits(mvchip->regs,
|
|
|
+ GPIO_IN_POL_OFF + mvchip->offset,
|
|
|
+ BIT(pin), BIT(pin));
|
|
|
break;
|
|
|
case IRQ_TYPE_EDGE_BOTH: {
|
|
|
- u32 v;
|
|
|
+ u32 data_in, in_pol, val;
|
|
|
|
|
|
- v = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)) ^
|
|
|
- readl_relaxed(mvebu_gpioreg_data_in(mvchip));
|
|
|
+ regmap_read(mvchip->regs,
|
|
|
+ GPIO_IN_POL_OFF + mvchip->offset, &in_pol);
|
|
|
+ regmap_read(mvchip->regs,
|
|
|
+ GPIO_DATA_IN_OFF + mvchip->offset, &data_in);
|
|
|
|
|
|
/*
|
|
|
* set initial polarity based on current input level
|
|
|
*/
|
|
|
- u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
|
|
|
- if (v & BIT(pin))
|
|
|
- u |= BIT(pin); /* falling */
|
|
|
+ if ((data_in ^ in_pol) & BIT(pin))
|
|
|
+ val = BIT(pin); /* falling */
|
|
|
else
|
|
|
- u &= ~BIT(pin); /* rising */
|
|
|
- writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
|
|
|
+ val = 0; /* raising */
|
|
|
+
|
|
|
+ regmap_update_bits(mvchip->regs,
|
|
|
+ GPIO_IN_POL_OFF + mvchip->offset,
|
|
|
+ BIT(pin), val);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
@@ -497,7 +544,7 @@ static void mvebu_gpio_irq_handler(struct irq_desc *desc)
|
|
|
{
|
|
|
struct mvebu_gpio_chip *mvchip = irq_desc_get_handler_data(desc);
|
|
|
struct irq_chip *chip = irq_desc_get_chip(desc);
|
|
|
- u32 cause, type;
|
|
|
+ u32 cause, type, data_in, level_mask, edge_cause, edge_mask;
|
|
|
int i;
|
|
|
|
|
|
if (mvchip == NULL)
|
|
@@ -505,10 +552,12 @@ static void mvebu_gpio_irq_handler(struct irq_desc *desc)
|
|
|
|
|
|
chained_irq_enter(chip, desc);
|
|
|
|
|
|
- cause = readl_relaxed(mvebu_gpioreg_data_in(mvchip)) &
|
|
|
- readl_relaxed(mvebu_gpioreg_level_mask(mvchip));
|
|
|
- cause |= readl_relaxed(mvebu_gpioreg_edge_cause(mvchip)) &
|
|
|
- readl_relaxed(mvebu_gpioreg_edge_mask(mvchip));
|
|
|
+ regmap_read(mvchip->regs, GPIO_DATA_IN_OFF + mvchip->offset, &data_in);
|
|
|
+ level_mask = mvebu_gpio_read_level_mask(mvchip);
|
|
|
+ edge_cause = mvebu_gpio_read_edge_cause(mvchip);
|
|
|
+ edge_mask = mvebu_gpio_read_edge_mask(mvchip);
|
|
|
+
|
|
|
+ cause = (data_in ^ level_mask) | (edge_cause & edge_mask);
|
|
|
|
|
|
for (i = 0; i < mvchip->chip.ngpio; i++) {
|
|
|
int irq;
|
|
@@ -523,9 +572,13 @@ static void mvebu_gpio_irq_handler(struct irq_desc *desc)
|
|
|
/* Swap polarity (race with GPIO line) */
|
|
|
u32 polarity;
|
|
|
|
|
|
- polarity = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
|
|
|
+ regmap_read(mvchip->regs,
|
|
|
+ GPIO_IN_POL_OFF + mvchip->offset,
|
|
|
+ &polarity);
|
|
|
polarity ^= BIT(i);
|
|
|
- writel_relaxed(polarity, mvebu_gpioreg_in_pol(mvchip));
|
|
|
+ regmap_write(mvchip->regs,
|
|
|
+ GPIO_IN_POL_OFF + mvchip->offset,
|
|
|
+ polarity);
|
|
|
}
|
|
|
|
|
|
generic_handle_irq(irq);
|
|
@@ -628,7 +681,7 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip,
|
|
|
state->period = 1;
|
|
|
}
|
|
|
|
|
|
- u = readl_relaxed(mvebu_gpioreg_blink(mvchip));
|
|
|
+ regmap_read(mvchip->regs, GPIO_BLINK_EN_OFF + mvchip->offset, &u);
|
|
|
if (u)
|
|
|
state->enabled = true;
|
|
|
else
|
|
@@ -691,8 +744,8 @@ static void __maybe_unused mvebu_pwm_suspend(struct mvebu_gpio_chip *mvchip)
|
|
|
{
|
|
|
struct mvebu_pwm *mvpwm = mvchip->mvpwm;
|
|
|
|
|
|
- mvpwm->blink_select =
|
|
|
- readl_relaxed(mvebu_gpioreg_blink_counter_select(mvchip));
|
|
|
+ regmap_read(mvchip->regs, GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset,
|
|
|
+ &mvpwm->blink_select);
|
|
|
mvpwm->blink_on_duration =
|
|
|
readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm));
|
|
|
mvpwm->blink_off_duration =
|
|
@@ -703,8 +756,8 @@ static void __maybe_unused mvebu_pwm_resume(struct mvebu_gpio_chip *mvchip)
|
|
|
{
|
|
|
struct mvebu_pwm *mvpwm = mvchip->mvpwm;
|
|
|
|
|
|
- writel_relaxed(mvpwm->blink_select,
|
|
|
- mvebu_gpioreg_blink_counter_select(mvchip));
|
|
|
+ regmap_write(mvchip->regs, GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset,
|
|
|
+ mvpwm->blink_select);
|
|
|
writel_relaxed(mvpwm->blink_on_duration,
|
|
|
mvebu_pwmreg_blink_on_duration(mvpwm));
|
|
|
writel_relaxed(mvpwm->blink_off_duration,
|
|
@@ -747,7 +800,8 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
|
|
|
set = U32_MAX;
|
|
|
else
|
|
|
return -EINVAL;
|
|
|
- writel_relaxed(set, mvebu_gpioreg_blink_counter_select(mvchip));
|
|
|
+ regmap_write(mvchip->regs,
|
|
|
+ GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset, set);
|
|
|
|
|
|
mvpwm = devm_kzalloc(dev, sizeof(struct mvebu_pwm), GFP_KERNEL);
|
|
|
if (!mvpwm)
|
|
@@ -790,14 +844,14 @@ static void mvebu_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
|
|
u32 out, io_conf, blink, in_pol, data_in, cause, edg_msk, lvl_msk;
|
|
|
int i;
|
|
|
|
|
|
- out = readl_relaxed(mvebu_gpioreg_out(mvchip));
|
|
|
- io_conf = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
|
|
|
- blink = readl_relaxed(mvebu_gpioreg_blink(mvchip));
|
|
|
- in_pol = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
|
|
|
- data_in = readl_relaxed(mvebu_gpioreg_data_in(mvchip));
|
|
|
- cause = readl_relaxed(mvebu_gpioreg_edge_cause(mvchip));
|
|
|
- edg_msk = readl_relaxed(mvebu_gpioreg_edge_mask(mvchip));
|
|
|
- lvl_msk = readl_relaxed(mvebu_gpioreg_level_mask(mvchip));
|
|
|
+ regmap_read(mvchip->regs, GPIO_OUT_OFF + mvchip->offset, &out);
|
|
|
+ regmap_read(mvchip->regs, GPIO_IO_CONF_OFF + mvchip->offset, &io_conf);
|
|
|
+ regmap_read(mvchip->regs, GPIO_BLINK_EN_OFF + mvchip->offset, &blink);
|
|
|
+ regmap_read(mvchip->regs, GPIO_IN_POL_OFF + mvchip->offset, &in_pol);
|
|
|
+ regmap_read(mvchip->regs, GPIO_DATA_IN_OFF + mvchip->offset, &data_in);
|
|
|
+ cause = mvebu_gpio_read_edge_cause(mvchip);
|
|
|
+ edg_msk = mvebu_gpio_read_edge_mask(mvchip);
|
|
|
+ lvl_msk = mvebu_gpio_read_level_mask(mvchip);
|
|
|
|
|
|
for (i = 0; i < chip->ngpio; i++) {
|
|
|
const char *label;
|
|
@@ -855,6 +909,10 @@ static const struct of_device_id mvebu_gpio_of_match[] = {
|
|
|
.compatible = "marvell,armada-370-gpio",
|
|
|
.data = (void *) MVEBU_GPIO_SOC_VARIANT_ORION,
|
|
|
},
|
|
|
+ {
|
|
|
+ .compatible = "marvell,armada-8k-gpio",
|
|
|
+ .data = (void *) MVEBU_GPIO_SOC_VARIANT_A8K,
|
|
|
+ },
|
|
|
{
|
|
|
/* sentinel */
|
|
|
},
|
|
@@ -865,36 +923,41 @@ static int mvebu_gpio_suspend(struct platform_device *pdev, pm_message_t state)
|
|
|
struct mvebu_gpio_chip *mvchip = platform_get_drvdata(pdev);
|
|
|
int i;
|
|
|
|
|
|
- mvchip->out_reg = readl(mvebu_gpioreg_out(mvchip));
|
|
|
- mvchip->io_conf_reg = readl(mvebu_gpioreg_io_conf(mvchip));
|
|
|
- mvchip->blink_en_reg = readl(mvebu_gpioreg_blink(mvchip));
|
|
|
- mvchip->in_pol_reg = readl(mvebu_gpioreg_in_pol(mvchip));
|
|
|
+ regmap_read(mvchip->regs, GPIO_OUT_OFF + mvchip->offset,
|
|
|
+ &mvchip->out_reg);
|
|
|
+ regmap_read(mvchip->regs, GPIO_IO_CONF_OFF + mvchip->offset,
|
|
|
+ &mvchip->io_conf_reg);
|
|
|
+ regmap_read(mvchip->regs, GPIO_BLINK_EN_OFF + mvchip->offset,
|
|
|
+ &mvchip->blink_en_reg);
|
|
|
+ regmap_read(mvchip->regs, GPIO_IN_POL_OFF + mvchip->offset,
|
|
|
+ &mvchip->in_pol_reg);
|
|
|
|
|
|
switch (mvchip->soc_variant) {
|
|
|
case MVEBU_GPIO_SOC_VARIANT_ORION:
|
|
|
- mvchip->edge_mask_regs[0] =
|
|
|
- readl(mvchip->membase + GPIO_EDGE_MASK_OFF);
|
|
|
- mvchip->level_mask_regs[0] =
|
|
|
- readl(mvchip->membase + GPIO_LEVEL_MASK_OFF);
|
|
|
+ case MVEBU_GPIO_SOC_VARIANT_A8K:
|
|
|
+ regmap_read(mvchip->regs, GPIO_EDGE_MASK_OFF + mvchip->offset,
|
|
|
+ &mvchip->edge_mask_regs[0]);
|
|
|
+ regmap_read(mvchip->regs, GPIO_LEVEL_MASK_OFF + mvchip->offset,
|
|
|
+ &mvchip->level_mask_regs[0]);
|
|
|
break;
|
|
|
case MVEBU_GPIO_SOC_VARIANT_MV78200:
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
- mvchip->edge_mask_regs[i] =
|
|
|
- readl(mvchip->membase +
|
|
|
- GPIO_EDGE_MASK_MV78200_OFF(i));
|
|
|
- mvchip->level_mask_regs[i] =
|
|
|
- readl(mvchip->membase +
|
|
|
- GPIO_LEVEL_MASK_MV78200_OFF(i));
|
|
|
+ regmap_read(mvchip->regs,
|
|
|
+ GPIO_EDGE_MASK_MV78200_OFF(i),
|
|
|
+ &mvchip->edge_mask_regs[i]);
|
|
|
+ regmap_read(mvchip->regs,
|
|
|
+ GPIO_LEVEL_MASK_MV78200_OFF(i),
|
|
|
+ &mvchip->level_mask_regs[i]);
|
|
|
}
|
|
|
break;
|
|
|
case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
- mvchip->edge_mask_regs[i] =
|
|
|
- readl(mvchip->membase +
|
|
|
- GPIO_EDGE_MASK_ARMADAXP_OFF(i));
|
|
|
- mvchip->level_mask_regs[i] =
|
|
|
- readl(mvchip->membase +
|
|
|
- GPIO_LEVEL_MASK_ARMADAXP_OFF(i));
|
|
|
+ regmap_read(mvchip->regs,
|
|
|
+ GPIO_EDGE_MASK_ARMADAXP_OFF(i),
|
|
|
+ &mvchip->edge_mask_regs[i]);
|
|
|
+ regmap_read(mvchip->regs,
|
|
|
+ GPIO_LEVEL_MASK_ARMADAXP_OFF(i),
|
|
|
+ &mvchip->level_mask_regs[i]);
|
|
|
}
|
|
|
break;
|
|
|
default:
|
|
@@ -912,35 +975,41 @@ static int mvebu_gpio_resume(struct platform_device *pdev)
|
|
|
struct mvebu_gpio_chip *mvchip = platform_get_drvdata(pdev);
|
|
|
int i;
|
|
|
|
|
|
- writel(mvchip->out_reg, mvebu_gpioreg_out(mvchip));
|
|
|
- writel(mvchip->io_conf_reg, mvebu_gpioreg_io_conf(mvchip));
|
|
|
- writel(mvchip->blink_en_reg, mvebu_gpioreg_blink(mvchip));
|
|
|
- writel(mvchip->in_pol_reg, mvebu_gpioreg_in_pol(mvchip));
|
|
|
+ regmap_write(mvchip->regs, GPIO_OUT_OFF + mvchip->offset,
|
|
|
+ mvchip->out_reg);
|
|
|
+ regmap_write(mvchip->regs, GPIO_IO_CONF_OFF + mvchip->offset,
|
|
|
+ mvchip->io_conf_reg);
|
|
|
+ regmap_write(mvchip->regs, GPIO_BLINK_EN_OFF + mvchip->offset,
|
|
|
+ mvchip->blink_en_reg);
|
|
|
+ regmap_write(mvchip->regs, GPIO_IN_POL_OFF + mvchip->offset,
|
|
|
+ mvchip->in_pol_reg);
|
|
|
|
|
|
switch (mvchip->soc_variant) {
|
|
|
case MVEBU_GPIO_SOC_VARIANT_ORION:
|
|
|
- writel(mvchip->edge_mask_regs[0],
|
|
|
- mvchip->membase + GPIO_EDGE_MASK_OFF);
|
|
|
- writel(mvchip->level_mask_regs[0],
|
|
|
- mvchip->membase + GPIO_LEVEL_MASK_OFF);
|
|
|
+ case MVEBU_GPIO_SOC_VARIANT_A8K:
|
|
|
+ regmap_write(mvchip->regs, GPIO_EDGE_MASK_OFF + mvchip->offset,
|
|
|
+ mvchip->edge_mask_regs[0]);
|
|
|
+ regmap_write(mvchip->regs, GPIO_LEVEL_MASK_OFF + mvchip->offset,
|
|
|
+ mvchip->level_mask_regs[0]);
|
|
|
break;
|
|
|
case MVEBU_GPIO_SOC_VARIANT_MV78200:
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
- writel(mvchip->edge_mask_regs[i],
|
|
|
- mvchip->membase + GPIO_EDGE_MASK_MV78200_OFF(i));
|
|
|
- writel(mvchip->level_mask_regs[i],
|
|
|
- mvchip->membase +
|
|
|
- GPIO_LEVEL_MASK_MV78200_OFF(i));
|
|
|
+ regmap_write(mvchip->regs,
|
|
|
+ GPIO_EDGE_MASK_MV78200_OFF(i),
|
|
|
+ mvchip->edge_mask_regs[i]);
|
|
|
+ regmap_write(mvchip->regs,
|
|
|
+ GPIO_LEVEL_MASK_MV78200_OFF(i),
|
|
|
+ mvchip->level_mask_regs[i]);
|
|
|
}
|
|
|
break;
|
|
|
case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
- writel(mvchip->edge_mask_regs[i],
|
|
|
- mvchip->membase +
|
|
|
- GPIO_EDGE_MASK_ARMADAXP_OFF(i));
|
|
|
- writel(mvchip->level_mask_regs[i],
|
|
|
- mvchip->membase +
|
|
|
- GPIO_LEVEL_MASK_ARMADAXP_OFF(i));
|
|
|
+ regmap_write(mvchip->regs,
|
|
|
+ GPIO_EDGE_MASK_ARMADAXP_OFF(i),
|
|
|
+ mvchip->edge_mask_regs[i]);
|
|
|
+ regmap_write(mvchip->regs,
|
|
|
+ GPIO_LEVEL_MASK_ARMADAXP_OFF(i),
|
|
|
+ mvchip->level_mask_regs[i]);
|
|
|
}
|
|
|
break;
|
|
|
default:
|
|
@@ -953,12 +1022,73 @@ static int mvebu_gpio_resume(struct platform_device *pdev)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static const struct regmap_config mvebu_gpio_regmap_config = {
|
|
|
+ .reg_bits = 32,
|
|
|
+ .reg_stride = 4,
|
|
|
+ .val_bits = 32,
|
|
|
+ .fast_io = true,
|
|
|
+};
|
|
|
+
|
|
|
+static int mvebu_gpio_probe_raw(struct platform_device *pdev,
|
|
|
+ struct mvebu_gpio_chip *mvchip)
|
|
|
+{
|
|
|
+ struct resource *res;
|
|
|
+ void __iomem *base;
|
|
|
+
|
|
|
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
|
+ base = devm_ioremap_resource(&pdev->dev, res);
|
|
|
+ if (IS_ERR(base))
|
|
|
+ return PTR_ERR(base);
|
|
|
+
|
|
|
+ mvchip->regs = devm_regmap_init_mmio(&pdev->dev, base,
|
|
|
+ &mvebu_gpio_regmap_config);
|
|
|
+ if (IS_ERR(mvchip->regs))
|
|
|
+ return PTR_ERR(mvchip->regs);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * For the legacy SoCs, the regmap directly maps to the GPIO
|
|
|
+ * registers, so no offset is needed.
|
|
|
+ */
|
|
|
+ mvchip->offset = 0;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * The Armada XP has a second range of registers for the
|
|
|
+ * per-CPU registers
|
|
|
+ */
|
|
|
+ if (mvchip->soc_variant == MVEBU_GPIO_SOC_VARIANT_ARMADAXP) {
|
|
|
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
|
|
+ base = devm_ioremap_resource(&pdev->dev, res);
|
|
|
+ if (IS_ERR(base))
|
|
|
+ return PTR_ERR(base);
|
|
|
+
|
|
|
+ mvchip->percpu_regs =
|
|
|
+ devm_regmap_init_mmio(&pdev->dev, base,
|
|
|
+ &mvebu_gpio_regmap_config);
|
|
|
+ if (IS_ERR(mvchip->percpu_regs))
|
|
|
+ return PTR_ERR(mvchip->percpu_regs);
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int mvebu_gpio_probe_syscon(struct platform_device *pdev,
|
|
|
+ struct mvebu_gpio_chip *mvchip)
|
|
|
+{
|
|
|
+ mvchip->regs = syscon_node_to_regmap(pdev->dev.parent->of_node);
|
|
|
+ if (IS_ERR(mvchip->regs))
|
|
|
+ return PTR_ERR(mvchip->regs);
|
|
|
+
|
|
|
+ if (of_property_read_u32(pdev->dev.of_node, "offset", &mvchip->offset))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int mvebu_gpio_probe(struct platform_device *pdev)
|
|
|
{
|
|
|
struct mvebu_gpio_chip *mvchip;
|
|
|
const struct of_device_id *match;
|
|
|
struct device_node *np = pdev->dev.of_node;
|
|
|
- struct resource *res;
|
|
|
struct irq_chip_generic *gc;
|
|
|
struct irq_chip_type *ct;
|
|
|
unsigned int ngpios;
|
|
@@ -1016,53 +1146,47 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
|
|
|
mvchip->chip.of_node = np;
|
|
|
mvchip->chip.dbg_show = mvebu_gpio_dbg_show;
|
|
|
|
|
|
- spin_lock_init(&mvchip->lock);
|
|
|
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
|
- mvchip->membase = devm_ioremap_resource(&pdev->dev, res);
|
|
|
- if (IS_ERR(mvchip->membase))
|
|
|
- return PTR_ERR(mvchip->membase);
|
|
|
+ if (soc_variant == MVEBU_GPIO_SOC_VARIANT_A8K)
|
|
|
+ err = mvebu_gpio_probe_syscon(pdev, mvchip);
|
|
|
+ else
|
|
|
+ err = mvebu_gpio_probe_raw(pdev, mvchip);
|
|
|
|
|
|
- /*
|
|
|
- * The Armada XP has a second range of registers for the
|
|
|
- * per-CPU registers
|
|
|
- */
|
|
|
- if (soc_variant == MVEBU_GPIO_SOC_VARIANT_ARMADAXP) {
|
|
|
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
|
|
- mvchip->percpu_membase = devm_ioremap_resource(&pdev->dev,
|
|
|
- res);
|
|
|
- if (IS_ERR(mvchip->percpu_membase))
|
|
|
- return PTR_ERR(mvchip->percpu_membase);
|
|
|
- }
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
|
|
|
/*
|
|
|
* Mask and clear GPIO interrupts.
|
|
|
*/
|
|
|
switch (soc_variant) {
|
|
|
case MVEBU_GPIO_SOC_VARIANT_ORION:
|
|
|
- writel_relaxed(0, mvchip->membase + GPIO_EDGE_CAUSE_OFF);
|
|
|
- writel_relaxed(0, mvchip->membase + GPIO_EDGE_MASK_OFF);
|
|
|
- writel_relaxed(0, mvchip->membase + GPIO_LEVEL_MASK_OFF);
|
|
|
+ case MVEBU_GPIO_SOC_VARIANT_A8K:
|
|
|
+ regmap_write(mvchip->regs,
|
|
|
+ GPIO_EDGE_CAUSE_OFF + mvchip->offset, 0);
|
|
|
+ regmap_write(mvchip->regs,
|
|
|
+ GPIO_EDGE_MASK_OFF + mvchip->offset, 0);
|
|
|
+ regmap_write(mvchip->regs,
|
|
|
+ GPIO_LEVEL_MASK_OFF + mvchip->offset, 0);
|
|
|
break;
|
|
|
case MVEBU_GPIO_SOC_VARIANT_MV78200:
|
|
|
- writel_relaxed(0, mvchip->membase + GPIO_EDGE_CAUSE_OFF);
|
|
|
+ regmap_write(mvchip->regs, GPIO_EDGE_CAUSE_OFF, 0);
|
|
|
for (cpu = 0; cpu < 2; cpu++) {
|
|
|
- writel_relaxed(0, mvchip->membase +
|
|
|
- GPIO_EDGE_MASK_MV78200_OFF(cpu));
|
|
|
- writel_relaxed(0, mvchip->membase +
|
|
|
- GPIO_LEVEL_MASK_MV78200_OFF(cpu));
|
|
|
+ regmap_write(mvchip->regs,
|
|
|
+ GPIO_EDGE_MASK_MV78200_OFF(cpu), 0);
|
|
|
+ regmap_write(mvchip->regs,
|
|
|
+ GPIO_LEVEL_MASK_MV78200_OFF(cpu), 0);
|
|
|
}
|
|
|
break;
|
|
|
case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
|
|
|
- writel_relaxed(0, mvchip->membase + GPIO_EDGE_CAUSE_OFF);
|
|
|
- writel_relaxed(0, mvchip->membase + GPIO_EDGE_MASK_OFF);
|
|
|
- writel_relaxed(0, mvchip->membase + GPIO_LEVEL_MASK_OFF);
|
|
|
+ regmap_write(mvchip->regs, GPIO_EDGE_CAUSE_OFF, 0);
|
|
|
+ regmap_write(mvchip->regs, GPIO_EDGE_MASK_OFF, 0);
|
|
|
+ regmap_write(mvchip->regs, GPIO_LEVEL_MASK_OFF, 0);
|
|
|
for (cpu = 0; cpu < 4; cpu++) {
|
|
|
- writel_relaxed(0, mvchip->percpu_membase +
|
|
|
- GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu));
|
|
|
- writel_relaxed(0, mvchip->percpu_membase +
|
|
|
- GPIO_EDGE_MASK_ARMADAXP_OFF(cpu));
|
|
|
- writel_relaxed(0, mvchip->percpu_membase +
|
|
|
- GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu));
|
|
|
+ regmap_write(mvchip->percpu_regs,
|
|
|
+ GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu), 0);
|
|
|
+ regmap_write(mvchip->percpu_regs,
|
|
|
+ GPIO_EDGE_MASK_ARMADAXP_OFF(cpu), 0);
|
|
|
+ regmap_write(mvchip->percpu_regs,
|
|
|
+ GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu), 0);
|
|
|
}
|
|
|
break;
|
|
|
default:
|