static int lnw_irq_type(struct irq_data *d, unsigned type) { struct lnw_gpio *lnw = irq_data_get_irq_chip_data(d); u32 gpio = irqd_to_hwirq(d); unsigned long flags; u32 value; void __iomem *grer = gpio_reg(&lnw->chip, gpio, GRER); void __iomem *gfer = gpio_reg(&lnw->chip, gpio, GFER); if (gpio >= lnw->chip.ngpio) return -EINVAL; if (lnw->pdev) pm_runtime_get(&lnw->pdev->dev); spin_lock_irqsave(&lnw->lock, flags); if (type & IRQ_TYPE_EDGE_RISING) value = readl(grer) | BIT(gpio % 32); else value = readl(grer) & (~BIT(gpio % 32)); writel(value, grer); if (type & IRQ_TYPE_EDGE_FALLING) value = readl(gfer) | BIT(gpio % 32); else value = readl(gfer) & (~BIT(gpio % 32)); writel(value, gfer); spin_unlock_irqrestore(&lnw->lock, flags); if (lnw->pdev) pm_runtime_put(&lnw->pdev->dev); return 0; }
static void lnw_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { void __iomem *gpsr, *gpcr; if (value) { gpsr = gpio_reg(chip, offset, GPSR); writel(BIT(offset % 32), gpsr); } else { gpcr = gpio_reg(chip, offset, GPCR); writel(BIT(offset % 32), gpcr); } }
static void intel_mid_irq_handler(struct irq_desc *desc) { struct gpio_chip *gc = irq_desc_get_handler_data(desc); struct intel_mid_gpio *priv = gpiochip_get_data(gc); struct irq_data *data = irq_desc_get_irq_data(desc); struct irq_chip *chip = irq_data_get_irq_chip(data); u32 base, gpio, mask; unsigned long pending; void __iomem *gedr; /* check GPIO controller to check which pin triggered the interrupt */ for (base = 0; base < priv->chip.ngpio; base += 32) { gedr = gpio_reg(&priv->chip, base, GEDR); while ((pending = readl(gedr))) { gpio = __ffs(pending); mask = BIT(gpio); /* Clear before handling so we can't lose an edge */ writel(mask, gedr); generic_handle_irq(irq_find_mapping(gc->irqdomain, base + gpio)); } } chip->irq_eoi(data); }
static void lnw_irq_init_hw(struct lnw_gpio *lnw) { void __iomem *reg; unsigned base; for (base = 0; base < lnw->chip.ngpio; base += 32) { /* Clear the rising-edge detect register */ reg = gpio_reg(&lnw->chip, base, GRER); writel(0, reg); /* Clear the falling-edge detect register */ reg = gpio_reg(&lnw->chip, base, GFER); writel(0, reg); /* Clear the edge detect status register */ reg = gpio_reg(&lnw->chip, base, GEDR); writel(~0, reg); } }
void lnw_gpio_set_alt(int gpio, int alt) { struct lnw_gpio *lnw; u32 __iomem *mem; int reg; int bit; u32 offset; u32 value; unsigned long flags; /* use this trick to get memio */ lnw = irq_get_chip_data(gpio_to_irq(gpio)); if (!lnw) { pr_err("langwell_gpio: can not find pin %d\n", gpio); return; } if (gpio < lnw->chip.base || gpio >= lnw->chip.base + lnw->chip.ngpio) { dev_err(lnw->chip.dev, "langwell_gpio: wrong pin %d to config alt\n", gpio); return; } #if 0 if (lnw->irq_base + gpio - lnw->chip.base != gpio_to_irq(gpio)) { dev_err(lnw->chip.dev, "langwell_gpio: wrong chip data for pin %d\n", gpio); return; } #endif gpio -= lnw->chip.base; if (lnw->type != TANGIER_GPIO) { reg = gpio / 16; bit = gpio % 16; mem = gpio_reg(&lnw->chip, 0, GAFR); spin_lock_irqsave(&lnw->lock, flags); value = readl(mem + reg); value &= ~(3 << (bit * 2)); value |= (alt & 3) << (bit * 2); writel(value, mem + reg); spin_unlock_irqrestore(&lnw->lock, flags); dev_dbg(lnw->chip.dev, "ALT: writing 0x%x to %p\n", value, mem + reg); } else { offset = lnw->get_flis_offset(gpio); if (WARN(offset == -EINVAL, "invalid pin %d\n", gpio)) return; if (!is_merr_i2c_flis(offset)) spin_lock_irqsave(&lnw->lock, flags); value = get_flis_value(offset); value &= ~7; value |= (alt & 7); set_flis_value(value, offset); if (!is_merr_i2c_flis(offset)) spin_unlock_irqrestore(&lnw->lock, flags); } }
static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { struct lnw_gpio *lnw = to_lnw_priv(chip); void __iomem *gpdr = gpio_reg(chip, offset, GPDR); u32 value; unsigned long flags; if (lnw->pdev) pm_runtime_get(&lnw->pdev->dev); spin_lock_irqsave(&lnw->lock, flags); value = readl(gpdr); value &= ~BIT(offset % 32); writel(value, gpdr); spin_unlock_irqrestore(&lnw->lock, flags); if (lnw->pdev) pm_runtime_put(&lnw->pdev->dev); return 0; }
int gpio_get_alt(int gpio) { struct lnw_gpio *lnw; u32 __iomem *mem; int reg; int bit; u32 value; u32 offset; /* use this trick to get memio */ lnw = irq_get_chip_data(gpio_to_irq(gpio)); if (!lnw) { pr_err("langwell_gpio: can not find pin %d\n", gpio); return -1; } if (gpio < lnw->chip.base || gpio >= lnw->chip.base + lnw->chip.ngpio) { dev_err(lnw->chip.dev, "langwell_gpio: wrong pin %d to config alt\n", gpio); return -1; } #if 0 if (lnw->irq_base + gpio - lnw->chip.base != gpio_to_irq(gpio)) { dev_err(lnw->chip.dev, "langwell_gpio: wrong chip data for pin %d\n", gpio); return -1; } #endif gpio -= lnw->chip.base; if (lnw->type != TANGIER_GPIO) { reg = gpio / 16; bit = gpio % 16; mem = gpio_reg(&lnw->chip, 0, GAFR); value = readl(mem + reg); value &= (3 << (bit * 2)); value >>= (bit * 2); } else {
static int intel_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { struct intel_mid_gpio *priv = gpiochip_get_data(chip); void __iomem *gpdr = gpio_reg(chip, offset, GPDR); unsigned long flags; intel_gpio_set(chip, offset, value); if (priv->pdev) pm_runtime_get(&priv->pdev->dev); spin_lock_irqsave(&priv->lock, flags); value = readl(gpdr); value |= BIT(offset % 32); writel(value, gpdr); spin_unlock_irqrestore(&priv->lock, flags); if (priv->pdev) pm_runtime_put(&priv->pdev->dev); return 0; }
static int lnw_gpio_get(struct gpio_chip *chip, unsigned offset) { void __iomem *gplr = gpio_reg(chip, offset, GPLR); return readl(gplr) & BIT(offset % 32); }