pinctrl: samsung: Remove hardcoded register offsets
authorTomasz Figa <tomasz.figa@gmail.com>
Mon, 18 Mar 2013 21:31:53 +0000 (22:31 +0100)
committerLinus Walleij <linus.walleij@linaro.org>
Tue, 9 Apr 2013 07:42:25 +0000 (09:42 +0200)
This patch replaces statically hardcoded register offsets of Exynos SoCs
with an array of register offsets in samsung_pin_bank_type struct.

Thanks to this change, support for SoCs with other set and order of
registers can be added (e.g. S3C24xx and S3C64xx).

Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
drivers/pinctrl/pinctrl-exynos.c
drivers/pinctrl/pinctrl-samsung.c
drivers/pinctrl/pinctrl-samsung.h

index b5dbb87800fd05c4b1bf3e2ab96080ffe5a00e3b..8b10b1ac9071374b557ece6c38eaf0b927e53812 100644 (file)
 
 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 */
@@ -126,7 +128,7 @@ 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;
+       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;
 
@@ -309,7 +311,7 @@ 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;
+       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;
 
index 97dd56024e3381c27a4b656e09cb4d76bbc8d5e3..b917ed36fb65e640ab15791a0b7abf7bdc62a30c 100644 (file)
@@ -275,10 +275,6 @@ static void pin_to_reg_bank(struct samsung_pinctrl_drv_data *drvdata,
        *offset = pin - b->pin_base;
        if (bank)
                *bank = b;
-
-       /* some banks have two config registers in a single bank */
-       if (*offset * b->func_width > BITS_PER_LONG)
-               *reg += 4;
 }
 
 /* enable or disable a pinmux function */
@@ -310,11 +306,11 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
 
                spin_lock_irqsave(&bank->slock, flags);
 
-               data = readl(reg);
+               data = readl(reg + type->reg_offset[PINCFG_TYPE_FUNC]);
                data &= ~(mask << shift);
                if (enable)
                        data |= drvdata->pin_groups[group].func << shift;
-               writel(data, reg);
+               writel(data, reg + type->reg_offset[PINCFG_TYPE_FUNC]);
 
                spin_unlock_irqrestore(&bank->slock, flags);
        }
@@ -355,7 +351,8 @@ static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
        drvdata = pinctrl_dev_get_drvdata(pctldev);
 
        pin_offset = offset - bank->pin_base;
-       reg = drvdata->virt_base + bank->pctl_offset;
+       reg = drvdata->virt_base + bank->pctl_offset +
+                                       type->reg_offset[PINCFG_TYPE_FUNC];
 
        mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1;
        shift = pin_offset * type->fld_width[PINCFG_TYPE_FUNC];
@@ -401,28 +398,11 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
                                        &pin_offset, &bank);
        type = bank->type;
 
-       switch (cfg_type) {
-       case PINCFG_TYPE_PUD:
-               cfg_reg = PUD_REG;
-               break;
-       case PINCFG_TYPE_DRV:
-               cfg_reg = DRV_REG;
-               break;
-       case PINCFG_TYPE_CON_PDN:
-               cfg_reg = CONPDN_REG;
-               break;
-       case PINCFG_TYPE_PUD_PDN:
-               cfg_reg = PUDPDN_REG;
-               break;
-       default:
-               WARN_ON(1);
-               return -EINVAL;
-       }
-
        if (cfg_type >= PINCFG_TYPE_NUM || !type->fld_width[cfg_type])
                return -EINVAL;
 
        width = type->fld_width[cfg_type];
+       cfg_reg = type->reg_offset[cfg_type];
 
        spin_lock_irqsave(&bank->slock, flags);
 
@@ -511,11 +491,11 @@ static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
 
        spin_lock_irqsave(&bank->slock, flags);
 
-       data = readl(reg + DAT_REG);
+       data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]);
        data &= ~(1 << offset);
        if (value)
                data |= 1 << offset;
-       writel(data, reg + DAT_REG);
+       writel(data, reg + type->reg_offset[PINCFG_TYPE_DAT]);
 
        spin_unlock_irqrestore(&bank->slock, flags);
 }
@@ -526,10 +506,11 @@ static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset)
        void __iomem *reg;
        u32 data;
        struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
+       struct samsung_pin_bank_type *type = bank->type;
 
        reg = bank->drvdata->virt_base + bank->pctl_offset;
 
-       data = readl(reg + DAT_REG);
+       data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]);
        data >>= offset;
        data &= 1;
        return data;
index 1c590f7e95dd869b96c1b568c221e32b25c263ab..9efeee862e0dcd9a3ce18302d305591fe84b2c00 100644 (file)
 
 #include <linux/gpio.h>
 
-/* register offsets within a pin bank */
-#define DAT_REG                0x4
-#define PUD_REG                0x8
-#define DRV_REG                0xC
-#define CONPDN_REG     0x10
-#define PUDPDN_REG     0x14
-
 /* pinmux function number for pin as gpio output line */
 #define FUNC_OUTPUT    0x1
 
@@ -111,9 +104,11 @@ struct samsung_pinctrl_drv_data;
 /**
  * struct samsung_pin_bank_type: pin bank type description
  * @fld_width: widths of configuration bitfields (0 if unavailable)
+ * @reg_offset: offsets of configuration registers (don't care of width is 0)
  */
 struct samsung_pin_bank_type {
        u8 fld_width[PINCFG_TYPE_NUM];
+       u8 reg_offset[PINCFG_TYPE_NUM];
 };
 
 /**