#include <linux/uaccess.h>
#include <linux/spinlock.h>
-#define GPIO_EN 0xe0
-#define GPIO_IS_LOW 0xe4
-#define GPIO_IS_HIGH 0xe8
-#define GPIO_IBE_LOW 0xf4
-#define GPIO_IBE_HIGH 0xf8
-#define GPIO_IEV_LOW 0xfc
-#define GPIO_IEV_HIGH 0x100
-#define GPIO_IE_LOW 0x104
-#define GPIO_IE_HIGH 0x108
-#define GPIO_IC_LOW 0xec
-#define GPIO_IC_HIGH 0xf0
+#define GPIO_EN 0xdc
+#define GPIO_IS_LOW 0xe0
+#define GPIO_IS_HIGH 0xe4
+#define GPIO_IC_LOW 0xe8
+#define GPIO_IC_HIGH 0xec
+#define GPIO_IBE_LOW 0xf0
+#define GPIO_IBE_HIGH 0xf4
+#define GPIO_IEV_LOW 0xf8
+#define GPIO_IEV_HIGH 0xfc
+#define GPIO_IE_LOW 0x100
+#define GPIO_IE_HIGH 0x104
+
//read only
-#define GPIO_RIS_LOW 0x10c
-#define GPIO_RIS_HIGH 0x110
-#define GPIO_MIS_LOW 0x114
-#define GPIO_MIS_HIGH 0x118
-#define GPIO_DIN_LOW 0x11C
-#define GPIO_DIN_HIGH 0x120
+#define GPIO_RIS_LOW 0x108
+#define GPIO_RIS_HIGH 0x10c
+#define GPIO_MIS_LOW 0x110
+#define GPIO_MIS_HIGH 0x114
+#define GPIO_DIN_LOW 0x118
+#define GPIO_DIN_HIGH 0x11c
-#define GPIO_DOUT_X_REG 0x0
-#define GPIO_DOEN_X_REG 0x40
+#define GPIO_DOEN_X_REG 0x0
+#define GPIO_DOUT_X_REG 0x40
-#define GPIO_INPUT_ENABLE_X_REG 0x124
+#define GPIO_INPUT_ENABLE_X_REG 0x120
#define MAX_GPIO 64
if (offset >= gc->ngpio)
return -EINVAL;
-
+
raw_spin_lock_irqsave(&chip->lock, flags);
v = readl_relaxed(chip->base + GPIO_DOEN_X_REG + (offset & ~0x3));
v &= ~(0x3f << ((offset & 0x3) * 8));
if (offset >= gc->ngpio)
return -EINVAL;
+
raw_spin_lock_irqsave(&chip->lock, flags);
v = readl_relaxed(chip->base + GPIO_DOEN_X_REG + (offset & ~0x3));
v &= ~(0x3f << ((offset & 0x3) * 8));
writel_relaxed(v, chip->base + GPIO_DOEN_X_REG + (offset & ~0x3));
v = readl_relaxed(chip->base + GPIO_DOUT_X_REG + (offset & ~0x3));
- v &= ~(0x3f << ((offset & 0x3) * 8));
+ v &= ~(0x7f << ((offset & 0x3) * 8));
v |= value << ((offset & 0x3) * 8);
writel_relaxed(v, chip->base + GPIO_DOUT_X_REG + (offset & ~0x3));
raw_spin_unlock_irqrestore(&chip->lock, flags);
raw_spin_lock_irqsave(&chip->lock, flags);
v = readl_relaxed(chip->base + GPIO_DOUT_X_REG + (offset & ~0x3));
- v &= ~(0x3f << ((offset & 0x3) * 8));
+ v &= ~(0x7f << ((offset & 0x3) * 8));
v |= value << ((offset & 0x3) * 8);
writel_relaxed(v, chip->base + GPIO_DOUT_X_REG + (offset & ~0x3));
raw_spin_unlock_irqrestore(&chip->lock, flags);
reg_iev = readl_relaxed(chip->base + GPIO_IEV_LOW + reg_offset);
reg_is &= (~(0x1<< index));
reg_ibe &= (~(0x1<< index));
- reg_iev |= (0x1<< index);
- writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
- writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
+ reg_iev |= (~(0x1<< index));
writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
+ writel_relaxed(reg_ibe, chip->base + GPIO_IBE_LOW + reg_offset);
+ writel_relaxed(reg_iev, chip->base + GPIO_IEV_LOW + reg_offset);
break;
case IRQ_TYPE_LEVEL_LOW:
reg_is = readl_relaxed(chip->base + GPIO_IS_LOW + reg_offset);
reg_ibe &= (~(0x1<< index));
reg_iev &= (0x1<< index);
writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
- writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
- writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
+ writel_relaxed(reg_ibe, chip->base + GPIO_IBE_LOW + reg_offset);
+ writel_relaxed(reg_iev, chip->base + GPIO_IEV_LOW + reg_offset);
break;
case IRQ_TYPE_EDGE_BOTH:
reg_is = readl_relaxed(chip->base + GPIO_IS_LOW + reg_offset);
reg_ibe = readl_relaxed(chip->base + GPIO_IBE_LOW + reg_offset);
- //reg_iev = readl_relaxed(chip->base + GPIO_IEV_LOW + reg_offset);
- reg_is |= (~(0x1<< index));
- reg_ibe |= (~(0x1<< index));
- //reg_iev |= (0x1<< index);
- writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
+ reg_iev = readl_relaxed(chip->base + GPIO_IEV_LOW + reg_offset);
+ reg_is |= (0x1<< index);
+ reg_ibe |= (0x1<< index);
+ reg_iev |= (~(0x1<< index));
writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
- //writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
+ writel_relaxed(reg_ibe, chip->base + GPIO_IBE_LOW + reg_offset);
+ writel_relaxed(reg_iev, chip->base + GPIO_IEV_LOW + reg_offset);
break;
case IRQ_TYPE_EDGE_RISING:
reg_is = readl_relaxed(chip->base + GPIO_IS_LOW + reg_offset);
reg_ibe = readl_relaxed(chip->base + GPIO_IBE_LOW + reg_offset);
reg_iev = readl_relaxed(chip->base + GPIO_IEV_LOW + reg_offset);
- reg_is |= (~(0x1<< index));
+ reg_is |= (0x1<< index);
reg_ibe &= (~(0x1<< index));
reg_iev |= (0x1<< index);
writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
- writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
- writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
+ writel_relaxed(reg_ibe, chip->base + GPIO_IBE_LOW + reg_offset);
+ writel_relaxed(reg_iev, chip->base + GPIO_IEV_LOW + reg_offset);
break;
case IRQ_TYPE_EDGE_FALLING:
reg_is = readl_relaxed(chip->base + GPIO_IS_LOW + reg_offset);
reg_ibe = readl_relaxed(chip->base + GPIO_IBE_LOW + reg_offset);
reg_iev = readl_relaxed(chip->base + GPIO_IEV_LOW + reg_offset);
- reg_is |= (~(0x1<< index));
+ reg_is |= (0x1<< index);
reg_ibe &= (~(0x1<< index));
- reg_iev &= (0x1<< index);
- writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
- writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
+ reg_iev &= (~(0x1<< index));
writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
+ writel_relaxed(reg_ibe, chip->base + GPIO_IBE_LOW + reg_offset);
+ writel_relaxed(reg_iev, chip->base + GPIO_IEV_LOW + reg_offset);
break;
}
.irq_disable = sfvic7110_irq_disable,
};
-
-static int starfive_gpio_child_to_parent_hwirq(struct gpio_chip *gc,
- unsigned int child,
- unsigned int child_type,
- unsigned int *parent,
- unsigned int *parent_type)
-{
- struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
- struct irq_data *d = irq_get_irq_data(chip->irq_parent[child]);
-
- *parent_type = IRQ_TYPE_NONE;
- *parent = irqd_to_hwirq(d);
-
- return 0;
-}
-
static irqreturn_t sfvic7110_irq_handler(int irq, void *gc)
{
int offset;
spin_lock(&sfg_lock);
value = ioread32(gpio_base + offset);
- value &= ~(0x3f << ((offset & 0x3) * 8));
+ value &= ~(0x7f << ((offset & 0x3) * 8));
value |= (en & 0x1) << ((offset & 0x3) * 8);
iowrite32(value, gpio_base + offset);
spin_unlock(&sfg_lock);
spin_lock(&sfg_lock);
value = ioread32(gpio_base + offset);
- value &= ~(0x3f << ((offset & 0x3) * 8));
- value |= (v & 0x3f) << ((offset & 0x3) * 8);
+ value &= ~(0x7f << ((offset & 0x3) * 8));
+ value |= (v & 0x7f) << ((offset & 0x3) * 8);
iowrite32(value,gpio_base + offset);
spin_unlock(&sfg_lock);
}
struct resource *res;
int irq, ret, ngpio;
int loop;
- struct gpio_irq_chip *girq;
- struct device_node *node = pdev->dev.of_node;
- struct device_node *irq_parent;
- struct irq_domain *parent;
chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
if (!chip) {
chip->gc.parent = dev;
chip->gc.owner = THIS_MODULE;
- irq_parent = of_irq_find_parent(node);
- if (!irq_parent) {
- dev_err(dev, "no IRQ parent node\n");
- return -ENODEV;
- }
- parent = irq_find_host(irq_parent);
- if (!parent) {
- dev_err(dev, "no IRQ parent domain\n");
- return -ENODEV;
- }
-
- girq = &chip->gc.irq;
- girq->chip = &sfvic7110_irqchip;
- girq->fwnode = of_node_to_fwnode(node);
- girq->parent_domain = parent;
- girq->child_to_parent_hwirq = starfive_gpio_child_to_parent_hwirq;
- girq->handler = handle_simple_irq;
- girq->default_type = IRQ_TYPE_NONE;
-
- /* Disable all GPIO interrupts before enabling parent interrupts */
- iowrite32(0, chip->base + GPIO_IE_HIGH);
- iowrite32(0, chip->base + GPIO_IE_LOW);
- chip->enabled = 0;
-
- platform_set_drvdata(pdev, chip);
ret = gpiochip_add_data(&chip->gc, chip);
if (ret){
dev_err(dev, "gpiochip_add_data ret=%d!\n", ret);
return ret;
}
-
-#if 0
+
/* Disable all GPIO interrupts before enabling parent interrupts */
iowrite32(0, chip->base + GPIO_IE_HIGH);
iowrite32(0, chip->base + GPIO_IE_LOW);
chip->enabled = 0;
- ret = gpiochip_gpiochip_add(&chip->gc, &sfvic7110_irqchip, 0,
+ ret = gpiochip_irqchip_add(&chip->gc, &sfvic7110_irqchip, 0,
handle_simple_irq, IRQ_TYPE_NONE);
if (ret) {
dev_err(dev, "could not add irqchip\n");
gpiochip_remove(&chip->gc);
return ret;
}
-#endif
-
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "Cannot get IRQ resource\n");
return irq;
}
- chip->irq_parent[0] = irq;
-
ret = devm_request_irq(dev, irq, sfvic7110_irq_handler, IRQF_SHARED,
dev_name(dev), chip);
if (ret) {