Skip to content

Commit

Permalink
pinctrl: samsung: Remove hardcoded register offsets
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Tomasz Figa authored and Linus Walleij committed Apr 9, 2013
1 parent 499147c commit 43fc9e7
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 37 deletions.
6 changes: 4 additions & 2 deletions drivers/pinctrl/pinctrl-exynos.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,12 @@

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 */
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;

Expand Down
37 changes: 9 additions & 28 deletions drivers/pinctrl/pinctrl-samsung.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);
}
Expand All @@ -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;
Expand Down
9 changes: 2 additions & 7 deletions drivers/pinctrl/pinctrl-samsung.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,6 @@

#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

Expand Down Expand Up @@ -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];
};

/**
Expand Down

0 comments on commit 43fc9e7

Please sign in to comment.