diff options
Diffstat (limited to 'drivers/pinctrl/pinctrl-exynos.c')
| -rw-r--r-- | drivers/pinctrl/pinctrl-exynos.c | 695 |
1 files changed, 663 insertions, 32 deletions
diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c index 538b9ddaadf..9609c23834c 100644 --- a/drivers/pinctrl/pinctrl-exynos.c +++ b/drivers/pinctrl/pinctrl-exynos.c @@ -23,64 +23,98 @@ #include <linux/interrupt.h> #include <linux/irqdomain.h> #include <linux/irq.h> +#include <linux/irqchip/chained_irq.h> #include <linux/of_irq.h> #include <linux/io.h> #include <linux/slab.h> +#include <linux/spinlock.h> #include <linux/err.h> -#include <asm/mach/irq.h> - #include "pinctrl-samsung.h" #include "pinctrl-exynos.h" + +static struct samsung_pin_bank_type bank_type_off = { + .fld_width = { 4, 1, 2, 2, 2, 2, }, + .reg_offset = { 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, }, +}; + +static struct samsung_pin_bank_type bank_type_alive = { + .fld_width = { 4, 1, 2, 2, }, + .reg_offset = { 0x00, 0x04, 0x08, 0x0c, }, +}; + /* list of external wakeup controllers supported */ static const struct of_device_id exynos_wkup_irq_ids[] = { { .compatible = "samsung,exynos4210-wakeup-eint", }, { } }; -static void exynos_gpio_irq_unmask(struct irq_data *irqd) +static void exynos_gpio_irq_mask(struct irq_data *irqd) { struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); struct samsung_pinctrl_drv_data *d = bank->drvdata; unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset; unsigned long mask; + unsigned long flags; + + spin_lock_irqsave(&bank->slock, flags); mask = readl(d->virt_base + reg_mask); - mask &= ~(1 << irqd->hwirq); + mask |= 1 << irqd->hwirq; writel(mask, d->virt_base + reg_mask); + + spin_unlock_irqrestore(&bank->slock, flags); } -static void exynos_gpio_irq_mask(struct irq_data *irqd) +static void exynos_gpio_irq_ack(struct irq_data *irqd) { struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); struct samsung_pinctrl_drv_data *d = bank->drvdata; - unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset; - unsigned long mask; + unsigned long reg_pend = d->ctrl->geint_pend + bank->eint_offset; - mask = readl(d->virt_base + reg_mask); - mask |= 1 << irqd->hwirq; - writel(mask, d->virt_base + reg_mask); + writel(1 << irqd->hwirq, d->virt_base + reg_pend); } -static void exynos_gpio_irq_ack(struct irq_data *irqd) +static void exynos_gpio_irq_unmask(struct irq_data *irqd) { struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); struct samsung_pinctrl_drv_data *d = bank->drvdata; - unsigned long reg_pend = d->ctrl->geint_pend + bank->eint_offset; + unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset; + unsigned long mask; + unsigned long flags; - writel(1 << irqd->hwirq, d->virt_base + reg_pend); + /* + * Ack level interrupts right before unmask + * + * If we don't do this we'll get a double-interrupt. Level triggered + * interrupts must not fire an interrupt if the level is not + * _currently_ active, even if it was active while the interrupt was + * masked. + */ + if (irqd_get_trigger_type(irqd) & IRQ_TYPE_LEVEL_MASK) + exynos_gpio_irq_ack(irqd); + + spin_lock_irqsave(&bank->slock, flags); + + mask = readl(d->virt_base + reg_mask); + mask &= ~(1 << irqd->hwirq); + writel(mask, d->virt_base + reg_mask); + + spin_unlock_irqrestore(&bank->slock, flags); } static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) { struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); + struct samsung_pin_bank_type *bank_type = bank->type; struct samsung_pinctrl_drv_data *d = bank->drvdata; struct samsung_pin_ctrl *ctrl = d->ctrl; unsigned int pin = irqd->hwirq; unsigned int shift = EXYNOS_EINT_CON_LEN * pin; unsigned int con, trig_type; unsigned long reg_con = ctrl->geint_con + bank->eint_offset; + unsigned long flags; unsigned int mask; switch (type) { @@ -114,15 +148,19 @@ static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) con |= trig_type << shift; writel(con, d->virt_base + reg_con); - reg_con = bank->pctl_offset; - shift = pin * bank->func_width; - mask = (1 << bank->func_width) - 1; + reg_con = bank->pctl_offset + bank_type->reg_offset[PINCFG_TYPE_FUNC]; + shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC]; + mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1; + + spin_lock_irqsave(&bank->slock, flags); con = readl(d->virt_base + reg_con); con &= ~(mask << shift); con |= EXYNOS_EINT_FUNC << shift; writel(con, d->virt_base + reg_con); + spin_unlock_irqrestore(&bank->slock, flags); + return 0; } @@ -179,6 +217,12 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data) return IRQ_HANDLED; } +struct exynos_eint_gpio_save { + u32 eint_con; + u32 eint_fltcon0; + u32 eint_fltcon1; +}; + /* * exynos_eint_gpio_init() - setup handling of external gpio interrupts. * @d: driver data of samsung pinctrl driver. @@ -187,8 +231,8 @@ static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d) { struct samsung_pin_bank *bank; struct device *dev = d->dev; - unsigned int ret; - unsigned int i; + int ret; + int i; if (!d->irq) { dev_err(dev, "irq number not available\n"); @@ -210,23 +254,29 @@ static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d) bank->nr_pins, &exynos_gpio_irqd_ops, bank); if (!bank->irq_domain) { dev_err(dev, "gpio irq domain add failed\n"); - return -ENXIO; + ret = -ENXIO; + goto err_domains; + } + + bank->soc_priv = devm_kzalloc(d->dev, + sizeof(struct exynos_eint_gpio_save), GFP_KERNEL); + if (!bank->soc_priv) { + irq_domain_remove(bank->irq_domain); + ret = -ENOMEM; + goto err_domains; } } return 0; -} -static void exynos_wkup_irq_unmask(struct irq_data *irqd) -{ - struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd); - struct samsung_pinctrl_drv_data *d = b->drvdata; - unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset; - unsigned long mask; +err_domains: + for (--i, --bank; i >= 0; --i, --bank) { + if (bank->eint_type != EINT_TYPE_GPIO) + continue; + irq_domain_remove(bank->irq_domain); + } - mask = readl(d->virt_base + reg_mask); - mask &= ~(1 << irqd->hwirq); - writel(mask, d->virt_base + reg_mask); + return ret; } static void exynos_wkup_irq_mask(struct irq_data *irqd) @@ -235,10 +285,15 @@ static void exynos_wkup_irq_mask(struct irq_data *irqd) struct samsung_pinctrl_drv_data *d = b->drvdata; unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset; unsigned long mask; + unsigned long flags; + + spin_lock_irqsave(&b->slock, flags); mask = readl(d->virt_base + reg_mask); mask |= 1 << irqd->hwirq; writel(mask, d->virt_base + reg_mask); + + spin_unlock_irqrestore(&b->slock, flags); } static void exynos_wkup_irq_ack(struct irq_data *irqd) @@ -250,14 +305,44 @@ static void exynos_wkup_irq_ack(struct irq_data *irqd) writel(1 << irqd->hwirq, d->virt_base + pend); } +static void exynos_wkup_irq_unmask(struct irq_data *irqd) +{ + struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd); + struct samsung_pinctrl_drv_data *d = b->drvdata; + unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset; + unsigned long mask; + unsigned long flags; + + /* + * Ack level interrupts right before unmask + * + * If we don't do this we'll get a double-interrupt. Level triggered + * interrupts must not fire an interrupt if the level is not + * _currently_ active, even if it was active while the interrupt was + * masked. + */ + if (irqd_get_trigger_type(irqd) & IRQ_TYPE_LEVEL_MASK) + exynos_wkup_irq_ack(irqd); + + spin_lock_irqsave(&b->slock, flags); + + mask = readl(d->virt_base + reg_mask); + mask &= ~(1 << irqd->hwirq); + writel(mask, d->virt_base + reg_mask); + + spin_unlock_irqrestore(&b->slock, flags); +} + static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type) { struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); + struct samsung_pin_bank_type *bank_type = bank->type; struct samsung_pinctrl_drv_data *d = bank->drvdata; unsigned int pin = irqd->hwirq; unsigned long reg_con = d->ctrl->weint_con + bank->eint_offset; unsigned long shift = EXYNOS_EINT_CON_LEN * pin; unsigned long con, trig_type; + unsigned long flags; unsigned int mask; switch (type) { @@ -291,15 +376,41 @@ static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type) con |= trig_type << shift; writel(con, d->virt_base + reg_con); - reg_con = bank->pctl_offset; - shift = pin * bank->func_width; - mask = (1 << bank->func_width) - 1; + reg_con = bank->pctl_offset + bank_type->reg_offset[PINCFG_TYPE_FUNC]; + shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC]; + mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1; + + spin_lock_irqsave(&bank->slock, flags); con = readl(d->virt_base + reg_con); con &= ~(mask << shift); con |= EXYNOS_EINT_FUNC << shift; writel(con, d->virt_base + reg_con); + spin_unlock_irqrestore(&bank->slock, flags); + + return 0; +} + +static u32 exynos_eint_wake_mask = 0xffffffff; + +u32 exynos_get_eint_wake_mask(void) +{ + return exynos_eint_wake_mask; +} + +static int exynos_wkup_irq_set_wake(struct irq_data *irqd, unsigned int on) +{ + struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); + unsigned long bit = 1UL << (2 * bank->eint_offset + irqd->hwirq); + + pr_info("wake %s for irq %d\n", on ? "enabled" : "disabled", irqd->irq); + + if (!on) + exynos_eint_wake_mask |= bit; + else + exynos_eint_wake_mask &= ~bit; + return 0; } @@ -312,6 +423,7 @@ static struct irq_chip exynos_wkup_irq_chip = { .irq_mask = exynos_wkup_irq_mask, .irq_ack = exynos_wkup_irq_ack, .irq_set_type = exynos_wkup_irq_set_type, + .irq_set_wake = exynos_wkup_irq_set_wake, }; /* interrupt handler for wakeup interrupts 0..15 */ @@ -482,6 +594,197 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d) return 0; } +static void exynos_pinctrl_suspend_bank( + struct samsung_pinctrl_drv_data *drvdata, + struct samsung_pin_bank *bank) +{ + struct exynos_eint_gpio_save *save = bank->soc_priv; + void __iomem *regs = drvdata->virt_base; + + save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET + + bank->eint_offset); + save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET + + 2 * bank->eint_offset); + save->eint_fltcon1 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET + + 2 * bank->eint_offset + 4); + + pr_debug("%s: save con %#010x\n", bank->name, save->eint_con); + pr_debug("%s: save fltcon0 %#010x\n", bank->name, save->eint_fltcon0); + pr_debug("%s: save fltcon1 %#010x\n", bank->name, save->eint_fltcon1); +} + +static void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata) +{ + struct samsung_pin_ctrl *ctrl = drvdata->ctrl; + struct samsung_pin_bank *bank = ctrl->pin_banks; + int i; + + for (i = 0; i < ctrl->nr_banks; ++i, ++bank) + if (bank->eint_type == EINT_TYPE_GPIO) + exynos_pinctrl_suspend_bank(drvdata, bank); +} + +static void exynos_pinctrl_resume_bank( + struct samsung_pinctrl_drv_data *drvdata, + struct samsung_pin_bank *bank) +{ + struct exynos_eint_gpio_save *save = bank->soc_priv; + void __iomem *regs = drvdata->virt_base; + + pr_debug("%s: con %#010x => %#010x\n", bank->name, + readl(regs + EXYNOS_GPIO_ECON_OFFSET + + bank->eint_offset), save->eint_con); + pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name, + readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET + + 2 * bank->eint_offset), save->eint_fltcon0); + pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name, + readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET + + 2 * bank->eint_offset + 4), save->eint_fltcon1); + + writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET + + bank->eint_offset); + writel(save->eint_fltcon0, regs + EXYNOS_GPIO_EFLTCON_OFFSET + + 2 * bank->eint_offset); + writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET + + 2 * bank->eint_offset + 4); +} + +static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata) +{ + struct samsung_pin_ctrl *ctrl = drvdata->ctrl; + struct samsung_pin_bank *bank = ctrl->pin_banks; + int i; + + for (i = 0; i < ctrl->nr_banks; ++i, ++bank) + if (bank->eint_type == EINT_TYPE_GPIO) + exynos_pinctrl_resume_bank(drvdata, bank); +} + +/* pin banks of s5pv210 pin-controller */ +static struct samsung_pin_bank s5pv210_pin_bank[] = { + EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00), + EXYNOS_PIN_BANK_EINTG(4, 0x020, "gpa1", 0x04), + EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb", 0x08), + EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0", 0x0c), + EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1", 0x10), + EXYNOS_PIN_BANK_EINTG(4, 0x0a0, "gpd0", 0x14), + EXYNOS_PIN_BANK_EINTG(6, 0x0c0, "gpd1", 0x18), + EXYNOS_PIN_BANK_EINTG(8, 0x0e0, "gpe0", 0x1c), + EXYNOS_PIN_BANK_EINTG(5, 0x100, "gpe1", 0x20), + EXYNOS_PIN_BANK_EINTG(8, 0x120, "gpf0", 0x24), + EXYNOS_PIN_BANK_EINTG(8, 0x140, "gpf1", 0x28), + EXYNOS_PIN_BANK_EINTG(8, 0x160, "gpf2", 0x2c), + EXYNOS_PIN_BANK_EINTG(6, 0x180, "gpf3", 0x30), + EXYNOS_PIN_BANK_EINTG(7, 0x1a0, "gpg0", 0x34), + EXYNOS_PIN_BANK_EINTG(7, 0x1c0, "gpg1", 0x38), + EXYNOS_PIN_BANK_EINTG(7, 0x1e0, "gpg2", 0x3c), + EXYNOS_PIN_BANK_EINTG(7, 0x200, "gpg3", 0x40), + EXYNOS_PIN_BANK_EINTN(7, 0x220, "gpi"), + EXYNOS_PIN_BANK_EINTG(8, 0x240, "gpj0", 0x44), + EXYNOS_PIN_BANK_EINTG(6, 0x260, "gpj1", 0x48), + EXYNOS_PIN_BANK_EINTG(8, 0x280, "gpj2", 0x4c), + EXYNOS_PIN_BANK_EINTG(8, 0x2a0, "gpj3", 0x50), + EXYNOS_PIN_BANK_EINTG(5, 0x2c0, "gpj4", 0x54), + EXYNOS_PIN_BANK_EINTN(8, 0x2e0, "mp01"), + EXYNOS_PIN_BANK_EINTN(4, 0x300, "mp02"), + EXYNOS_PIN_BANK_EINTN(8, 0x320, "mp03"), + EXYNOS_PIN_BANK_EINTN(8, 0x340, "mp04"), + EXYNOS_PIN_BANK_EINTN(8, 0x360, "mp05"), + EXYNOS_PIN_BANK_EINTN(8, 0x380, "mp06"), + EXYNOS_PIN_BANK_EINTN(8, 0x3a0, "mp07"), + EXYNOS_PIN_BANK_EINTW(8, 0xc00, "gph0", 0x00), + EXYNOS_PIN_BANK_EINTW(8, 0xc20, "gph1", 0x04), + EXYNOS_PIN_BANK_EINTW(8, 0xc40, "gph2", 0x08), + EXYNOS_PIN_BANK_EINTW(8, 0xc60, "gph3", 0x0c), +}; + +struct samsung_pin_ctrl s5pv210_pin_ctrl[] = { + { + /* pin-controller instance 0 data */ + .pin_banks = s5pv210_pin_bank, + .nr_banks = ARRAY_SIZE(s5pv210_pin_bank), + .geint_con = EXYNOS_GPIO_ECON_OFFSET, + .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, + .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, + .weint_con = EXYNOS_WKUP_ECON_OFFSET, + .weint_mask = EXYNOS_WKUP_EMASK_OFFSET, + .weint_pend = EXYNOS_WKUP_EPEND_OFFSET, + .svc = EXYNOS_SVC_OFFSET, + .eint_gpio_init = exynos_eint_gpio_init, + .eint_wkup_init = exynos_eint_wkup_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, + .label = "s5pv210-gpio-ctrl0", + }, +}; + +/* pin banks of exynos3250 pin-controller 0 */ +static struct samsung_pin_bank exynos3250_pin_banks0[] = { + EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00), + EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04), + EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb", 0x08), + EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0", 0x0c), + EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1", 0x10), + EXYNOS_PIN_BANK_EINTG(4, 0x0a0, "gpd0", 0x14), + EXYNOS_PIN_BANK_EINTG(4, 0x0c0, "gpd1", 0x18), +}; + +/* pin banks of exynos3250 pin-controller 1 */ +static struct samsung_pin_bank exynos3250_pin_banks1[] = { + EXYNOS_PIN_BANK_EINTN(8, 0x120, "gpe0"), + EXYNOS_PIN_BANK_EINTN(8, 0x140, "gpe1"), + EXYNOS_PIN_BANK_EINTN(3, 0x180, "gpe2"), + EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpk0", 0x08), + EXYNOS_PIN_BANK_EINTG(7, 0x060, "gpk1", 0x0c), + EXYNOS_PIN_BANK_EINTG(7, 0x080, "gpk2", 0x10), + EXYNOS_PIN_BANK_EINTG(4, 0x0c0, "gpl0", 0x18), + EXYNOS_PIN_BANK_EINTG(8, 0x260, "gpm0", 0x24), + EXYNOS_PIN_BANK_EINTG(7, 0x280, "gpm1", 0x28), + EXYNOS_PIN_BANK_EINTG(5, 0x2a0, "gpm2", 0x2c), + EXYNOS_PIN_BANK_EINTG(8, 0x2c0, "gpm3", 0x30), + EXYNOS_PIN_BANK_EINTG(8, 0x2e0, "gpm4", 0x34), + EXYNOS_PIN_BANK_EINTW(8, 0xc00, "gpx0", 0x00), + EXYNOS_PIN_BANK_EINTW(8, 0xc20, "gpx1", 0x04), + EXYNOS_PIN_BANK_EINTW(8, 0xc40, "gpx2", 0x08), + EXYNOS_PIN_BANK_EINTW(8, 0xc60, "gpx3", 0x0c), +}; + +/* + * Samsung pinctrl driver data for Exynos3250 SoC. Exynos3250 SoC includes + * two gpio/pin-mux/pinconfig controllers. + */ +struct samsung_pin_ctrl exynos3250_pin_ctrl[] = { + { + /* pin-controller instance 0 data */ + .pin_banks = exynos3250_pin_banks0, + .nr_banks = ARRAY_SIZE(exynos3250_pin_banks0), + .geint_con = EXYNOS_GPIO_ECON_OFFSET, + .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, + .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, + .svc = EXYNOS_SVC_OFFSET, + .eint_gpio_init = exynos_eint_gpio_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, + .label = "exynos3250-gpio-ctrl0", + }, { + /* pin-controller instance 1 data */ + .pin_banks = exynos3250_pin_banks1, + .nr_banks = ARRAY_SIZE(exynos3250_pin_banks1), + .geint_con = EXYNOS_GPIO_ECON_OFFSET, + .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, + .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, + .weint_con = EXYNOS_WKUP_ECON_OFFSET, + .weint_mask = EXYNOS_WKUP_EMASK_OFFSET, + .weint_pend = EXYNOS_WKUP_EPEND_OFFSET, + .svc = EXYNOS_SVC_OFFSET, + .eint_gpio_init = exynos_eint_gpio_init, + .eint_wkup_init = exynos_eint_wkup_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, + .label = "exynos3250-gpio-ctrl1", + }, +}; + /* pin banks of exynos4210 pin-controller 0 */ static struct samsung_pin_bank exynos4210_pin_banks0[] = { EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00), @@ -545,6 +848,8 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = { .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, .svc = EXYNOS_SVC_OFFSET, .eint_gpio_init = exynos_eint_gpio_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, .label = "exynos4210-gpio-ctrl0", }, { /* pin-controller instance 1 data */ @@ -559,6 +864,8 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = { .svc = EXYNOS_SVC_OFFSET, .eint_gpio_init = exynos_eint_gpio_init, .eint_wkup_init = exynos_eint_wkup_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, .label = "exynos4210-gpio-ctrl1", }, { /* pin-controller instance 2 data */ @@ -640,6 +947,8 @@ struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = { .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, .svc = EXYNOS_SVC_OFFSET, .eint_gpio_init = exynos_eint_gpio_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, .label = "exynos4x12-gpio-ctrl0", }, { /* pin-controller instance 1 data */ @@ -654,6 +963,8 @@ struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = { .svc = EXYNOS_SVC_OFFSET, .eint_gpio_init = exynos_eint_gpio_init, .eint_wkup_init = exynos_eint_wkup_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, .label = "exynos4x12-gpio-ctrl1", }, { /* pin-controller instance 2 data */ @@ -664,6 +975,8 @@ struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = { .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, .svc = EXYNOS_SVC_OFFSET, .eint_gpio_init = exynos_eint_gpio_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, .label = "exynos4x12-gpio-ctrl2", }, { /* pin-controller instance 3 data */ @@ -674,6 +987,324 @@ struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = { .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, .svc = EXYNOS_SVC_OFFSET, .eint_gpio_init = exynos_eint_gpio_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, .label = "exynos4x12-gpio-ctrl3", }, }; + +/* pin banks of exynos5250 pin-controller 0 */ +static struct samsung_pin_bank exynos5250_pin_banks0[] = { + EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00), + EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04), + EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpa2", 0x08), + EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpb0", 0x0c), + EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpb1", 0x10), + EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpb2", 0x14), + EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpb3", 0x18), + EXYNOS_PIN_BANK_EINTG(7, 0x0E0, "gpc0", 0x1c), + EXYNOS_PIN_BANK_EINTG(4, 0x100, "gpc1", 0x20), + EXYNOS_PIN_BANK_EINTG(7, 0x120, "gpc2", 0x24), + EXYNOS_PIN_BANK_EINTG(7, 0x140, "gpc3", 0x28), + EXYNOS_PIN_BANK_EINTG(4, 0x160, "gpd0", 0x2c), + EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpd1", 0x30), + EXYNOS_PIN_BANK_EINTG(7, 0x2E0, "gpc4", 0x34), + EXYNOS_PIN_BANK_EINTN(6, 0x1A0, "gpy0"), + EXYNOS_PIN_BANK_EINTN(4, 0x1C0, "gpy1"), + EXYNOS_PIN_BANK_EINTN(6, 0x1E0, "gpy2"), + EXYNOS_PIN_BANK_EINTN(8, 0x200, "gpy3"), + EXYNOS_PIN_BANK_EINTN(8, 0x220, "gpy4"), + EXYNOS_PIN_BANK_EINTN(8, 0x240, "gpy5"), + EXYNOS_PIN_BANK_EINTN(8, 0x260, "gpy6"), + EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00), + EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04), + EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08), + EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c), +}; + +/* pin banks of exynos5250 pin-controller 1 */ +static struct samsung_pin_bank exynos5250_pin_banks1[] = { + EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpe0", 0x00), + EXYNOS_PIN_BANK_EINTG(2, 0x020, "gpe1", 0x04), + EXYNOS_PIN_BANK_EINTG(4, 0x040, "gpf0", 0x08), + EXYNOS_PIN_BANK_EINTG(4, 0x060, "gpf1", 0x0c), + EXYNOS_PIN_BANK_EINTG(8, 0x080, "gpg0", 0x10), + EXYNOS_PIN_BANK_EINTG(8, 0x0A0, "gpg1", 0x14), + EXYNOS_PIN_BANK_EINTG(2, 0x0C0, "gpg2", 0x18), + EXYNOS_PIN_BANK_EINTG(4, 0x0E0, "gph0", 0x1c), + EXYNOS_PIN_BANK_EINTG(8, 0x100, "gph1", 0x20), +}; + +/* pin banks of exynos5250 pin-controller 2 */ +static struct samsung_pin_bank exynos5250_pin_banks2[] = { + EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpv0", 0x00), + EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpv1", 0x04), + EXYNOS_PIN_BANK_EINTG(8, 0x060, "gpv2", 0x08), + EXYNOS_PIN_BANK_EINTG(8, 0x080, "gpv3", 0x0c), + EXYNOS_PIN_BANK_EINTG(2, 0x0C0, "gpv4", 0x10), +}; + +/* pin banks of exynos5250 pin-controller 3 */ +static struct samsung_pin_bank exynos5250_pin_banks3[] = { + EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz", 0x00), +}; + +/* + * Samsung pinctrl driver data for Exynos5250 SoC. Exynos5250 SoC includes + * four gpio/pin-mux/pinconfig controllers. + */ +struct samsung_pin_ctrl exynos5250_pin_ctrl[] = { + { + /* pin-controller instance 0 data */ + .pin_banks = exynos5250_pin_banks0, + .nr_banks = ARRAY_SIZE(exynos5250_pin_banks0), + .geint_con = EXYNOS_GPIO_ECON_OFFSET, + .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, + .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, + .weint_con = EXYNOS_WKUP_ECON_OFFSET, + .weint_mask = EXYNOS_WKUP_EMASK_OFFSET, + .weint_pend = EXYNOS_WKUP_EPEND_OFFSET, + .svc = EXYNOS_SVC_OFFSET, + .eint_gpio_init = exynos_eint_gpio_init, + .eint_wkup_init = exynos_eint_wkup_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, + .label = "exynos5250-gpio-ctrl0", + }, { + /* pin-controller instance 1 data */ + .pin_banks = exynos5250_pin_banks1, + .nr_banks = ARRAY_SIZE(exynos5250_pin_banks1), + .geint_con = EXYNOS_GPIO_ECON_OFFSET, + .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, + .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, + .svc = EXYNOS_SVC_OFFSET, + .eint_gpio_init = exynos_eint_gpio_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, + .label = "exynos5250-gpio-ctrl1", + }, { + /* pin-controller instance 2 data */ + .pin_banks = exynos5250_pin_banks2, + .nr_banks = ARRAY_SIZE(exynos5250_pin_banks2), + .geint_con = EXYNOS_GPIO_ECON_OFFSET, + .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, + .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, + .svc = EXYNOS_SVC_OFFSET, + .eint_gpio_init = exynos_eint_gpio_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, + .label = "exynos5250-gpio-ctrl2", + }, { + /* pin-controller instance 3 data */ + .pin_banks = exynos5250_pin_banks3, + .nr_banks = ARRAY_SIZE(exynos5250_pin_banks3), + .geint_con = EXYNOS_GPIO_ECON_OFFSET, + .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, + .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, + .svc = EXYNOS_SVC_OFFSET, + .eint_gpio_init = exynos_eint_gpio_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, + .label = "exynos5250-gpio-ctrl3", + }, +}; + +/* pin banks of exynos5260 pin-controller 0 */ +static struct samsung_pin_bank exynos5260_pin_banks0[] = { + EXYNOS_PIN_BANK_EINTG(4, 0x000, "gpa0", 0x00), + EXYNOS_PIN_BANK_EINTG(7, 0x020, "gpa1", 0x04), + EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpa2", 0x08), + EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpb0", 0x0c), + EXYNOS_PIN_BANK_EINTG(4, 0x080, "gpb1", 0x10), + EXYNOS_PIN_BANK_EINTG(5, 0x0a0, "gpb2", 0x14), + EXYNOS_PIN_BANK_EINTG(8, 0x0c0, "gpb3", 0x18), + EXYNOS_PIN_BANK_EINTG(8, 0x0e0, "gpb4", 0x1c), + EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpb5", 0x20), + EXYNOS_PIN_BANK_EINTG(8, 0x120, "gpd0", 0x24), + EXYNOS_PIN_BANK_EINTG(7, 0x140, "gpd1", 0x28), + EXYNOS_PIN_BANK_EINTG(5, 0x160, "gpd2", 0x2c), + EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpe0", 0x30), + EXYNOS_PIN_BANK_EINTG(5, 0x1a0, "gpe1", 0x34), + EXYNOS_PIN_BANK_EINTG(4, 0x1c0, "gpf0", 0x38), + EXYNOS_PIN_BANK_EINTG(8, 0x1e0, "gpf1", 0x3c), + EXYNOS_PIN_BANK_EINTG(2, 0x200, "gpk0", 0x40), + EXYNOS_PIN_BANK_EINTW(8, 0xc00, "gpx0", 0x00), + EXYNOS_PIN_BANK_EINTW(8, 0xc20, "gpx1", 0x04), + EXYNOS_PIN_BANK_EINTW(8, 0xc40, "gpx2", 0x08), + EXYNOS_PIN_BANK_EINTW(8, 0xc60, "gpx3", 0x0c), +}; + +/* pin banks of exynos5260 pin-controller 1 */ +static struct samsung_pin_bank exynos5260_pin_banks1[] = { + EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpc0", 0x00), + EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpc1", 0x04), + EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpc2", 0x08), + EXYNOS_PIN_BANK_EINTG(4, 0x060, "gpc3", 0x0c), + EXYNOS_PIN_BANK_EINTG(4, 0x080, "gpc4", 0x10), +}; + +/* pin banks of exynos5260 pin-controller 2 */ +static struct samsung_pin_bank exynos5260_pin_banks2[] = { + EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz0", 0x00), + EXYNOS_PIN_BANK_EINTG(4, 0x020, "gpz1", 0x04), +}; + +/* + * Samsung pinctrl driver data for Exynos5260 SoC. Exynos5260 SoC includes + * three gpio/pin-mux/pinconfig controllers. + */ +struct samsung_pin_ctrl exynos5260_pin_ctrl[] = { + { + /* pin-controller instance 0 data */ + .pin_banks = exynos5260_pin_banks0, + .nr_banks = ARRAY_SIZE(exynos5260_pin_banks0), + .geint_con = EXYNOS_GPIO_ECON_OFFSET, + .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, + .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, + .weint_con = EXYNOS_WKUP_ECON_OFFSET, + .weint_mask = EXYNOS_WKUP_EMASK_OFFSET, + .weint_pend = EXYNOS_WKUP_EPEND_OFFSET, + .svc = EXYNOS_SVC_OFFSET, + .eint_gpio_init = exynos_eint_gpio_init, + .eint_wkup_init = exynos_eint_wkup_init, + .label = "exynos5260-gpio-ctrl0", + }, { + /* pin-controller instance 1 data */ + .pin_banks = exynos5260_pin_banks1, + .nr_banks = ARRAY_SIZE(exynos5260_pin_banks1), + .geint_con = EXYNOS_GPIO_ECON_OFFSET, + .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, + .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, + .svc = EXYNOS_SVC_OFFSET, + .eint_gpio_init = exynos_eint_gpio_init, + .label = "exynos5260-gpio-ctrl1", + }, { + /* pin-controller instance 2 data */ + .pin_banks = exynos5260_pin_banks2, + .nr_banks = ARRAY_SIZE(exynos5260_pin_banks2), + .geint_con = EXYNOS_GPIO_ECON_OFFSET, + .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, + .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, + .svc = EXYNOS_SVC_OFFSET, + .eint_gpio_init = exynos_eint_gpio_init, + .label = "exynos5260-gpio-ctrl2", + }, +}; + +/* pin banks of exynos5420 pin-controller 0 */ +static struct samsung_pin_bank exynos5420_pin_banks0[] = { + EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpy7", 0x00), + EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00), + EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04), + EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08), + EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c), +}; + +/* pin banks of exynos5420 pin-controller 1 */ +static struct samsung_pin_bank exynos5420_pin_banks1[] = { + EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpc0", 0x00), + EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpc1", 0x04), + EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpc2", 0x08), + EXYNOS_PIN_BANK_EINTG(4, 0x060, "gpc3", 0x0c), + EXYNOS_PIN_BANK_EINTG(2, 0x080, "gpc4", 0x10), + EXYNOS_PIN_BANK_EINTG(8, 0x0A0, "gpd1", 0x14), + EXYNOS_PIN_BANK_EINTN(6, 0x0C0, "gpy0"), + EXYNOS_PIN_BANK_EINTN(4, 0x0E0, "gpy1"), + EXYNOS_PIN_BANK_EINTN(6, 0x100, "gpy2"), + EXYNOS_PIN_BANK_EINTN(8, 0x120, "gpy3"), + EXYNOS_PIN_BANK_EINTN(8, 0x140, "gpy4"), + EXYNOS_PIN_BANK_EINTN(8, 0x160, "gpy5"), + EXYNOS_PIN_BANK_EINTN(8, 0x180, "gpy6"), +}; + +/* pin banks of exynos5420 pin-controller 2 */ +static struct samsung_pin_bank exynos5420_pin_banks2[] = { + EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpe0", 0x00), + EXYNOS_PIN_BANK_EINTG(2, 0x020, "gpe1", 0x04), + EXYNOS_PIN_BANK_EINTG(6, 0x040, "gpf0", 0x08), + EXYNOS_PIN_BANK_EINTG(8, 0x060, "gpf1", 0x0c), + EXYNOS_PIN_BANK_EINTG(8, 0x080, "gpg0", 0x10), + EXYNOS_PIN_BANK_EINTG(8, 0x0A0, "gpg1", 0x14), + EXYNOS_PIN_BANK_EINTG(2, 0x0C0, "gpg2", 0x18), + EXYNOS_PIN_BANK_EINTG(4, 0x0E0, "gpj4", 0x1c), +}; + +/* pin banks of exynos5420 pin-controller 3 */ +static struct samsung_pin_bank exynos5420_pin_banks3[] = { + EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00), + EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04), + EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpa2", 0x08), + EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpb0", 0x0c), + EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpb1", 0x10), + EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpb2", 0x14), + EXYNOS_PIN_BANK_EINTG(8, 0x0C0, "gpb3", 0x18), + EXYNOS_PIN_BANK_EINTG(2, 0x0E0, "gpb4", 0x1c), + EXYNOS_PIN_BANK_EINTG(8, 0x100, "gph0", 0x20), +}; + +/* pin banks of exynos5420 pin-controller 4 */ +static struct samsung_pin_bank exynos5420_pin_banks4[] = { + EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz", 0x00), +}; + +/* + * Samsung pinctrl driver data for Exynos5420 SoC. Exynos5420 SoC includes + * four gpio/pin-mux/pinconfig controllers. + */ +struct samsung_pin_ctrl exynos5420_pin_ctrl[] = { + { + /* pin-controller instance 0 data */ + .pin_banks = exynos5420_pin_banks0, + .nr_banks = ARRAY_SIZE(exynos5420_pin_banks0), + .geint_con = EXYNOS_GPIO_ECON_OFFSET, + .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, + .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, + .weint_con = EXYNOS_WKUP_ECON_OFFSET, + .weint_mask = EXYNOS_WKUP_EMASK_OFFSET, + .weint_pend = EXYNOS_WKUP_EPEND_OFFSET, + .svc = EXYNOS_SVC_OFFSET, + .eint_gpio_init = exynos_eint_gpio_init, + .eint_wkup_init = exynos_eint_wkup_init, + .label = "exynos5420-gpio-ctrl0", + }, { + /* pin-controller instance 1 data */ + .pin_banks = exynos5420_pin_banks1, + .nr_banks = ARRAY_SIZE(exynos5420_pin_banks1), + .geint_con = EXYNOS_GPIO_ECON_OFFSET, + .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, + .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, + .svc = EXYNOS_SVC_OFFSET, + .eint_gpio_init = exynos_eint_gpio_init, + .label = "exynos5420-gpio-ctrl1", + }, { + /* pin-controller instance 2 data */ + .pin_banks = exynos5420_pin_banks2, + .nr_banks = ARRAY_SIZE(exynos5420_pin_banks2), + .geint_con = EXYNOS_GPIO_ECON_OFFSET, + .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, + .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, + .svc = EXYNOS_SVC_OFFSET, + .eint_gpio_init = exynos_eint_gpio_init, + .label = "exynos5420-gpio-ctrl2", + }, { + /* pin-controller instance 3 data */ + .pin_banks = exynos5420_pin_banks3, + .nr_banks = ARRAY_SIZE(exynos5420_pin_banks3), + .geint_con = EXYNOS_GPIO_ECON_OFFSET, + .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, + .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, + .svc = EXYNOS_SVC_OFFSET, + .eint_gpio_init = exynos_eint_gpio_init, + .label = "exynos5420-gpio-ctrl3", + }, { + /* pin-controller instance 4 data */ + .pin_banks = exynos5420_pin_banks4, + .nr_banks = ARRAY_SIZE(exynos5420_pin_banks4), + .geint_con = EXYNOS_GPIO_ECON_OFFSET, + .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, + .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, + .svc = EXYNOS_SVC_OFFSET, + .eint_gpio_init = exynos_eint_gpio_init, + .label = "exynos5420-gpio-ctrl4", + }, +}; |
