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 */
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;
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;
*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 */
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);
}
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];
&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);
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);
}
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;
#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
/**
* 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];
};
/**