aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/pinctrl/sunxi/pinctrl-sunxi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pinctrl/sunxi/pinctrl-sunxi.c')
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sunxi.c54
1 files changed, 37 insertions, 17 deletions
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index bde67ee31417..f1c5a991cf7b 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -58,13 +58,29 @@ static struct irq_chip sunxi_pinctrl_level_irq_chip;
* The following functions calculate the register and the bit offset to access.
* They take a pin number which is relative to the start of the current device.
*/
+
+/*
+ * When using the extended register layout, Bank K does not fit into the
+ * space used for the other banks. Instead it lives at offset 0x500.
+ */
+static u32 sunxi_bank_offset(const struct sunxi_pinctrl *pctl, u32 pin)
+{
+ u32 offset = 0;
+
+ if (pin >= PK_BASE) {
+ pin -= PK_BASE;
+ offset = PIO_BANK_K_OFFSET;
+ }
+
+ return offset + (pin / PINS_PER_BANK) * pctl->bank_mem_size;
+}
+
static void sunxi_mux_reg(const struct sunxi_pinctrl *pctl,
u32 pin, u32 *reg, u32 *shift, u32 *mask)
{
- u32 bank = pin / PINS_PER_BANK;
u32 offset = pin % PINS_PER_BANK * MUX_FIELD_WIDTH;
- *reg = bank * pctl->bank_mem_size + MUX_REGS_OFFSET +
+ *reg = sunxi_bank_offset(pctl, pin) + MUX_REGS_OFFSET +
offset / BITS_PER_TYPE(u32) * sizeof(u32);
*shift = offset % BITS_PER_TYPE(u32);
*mask = (BIT(MUX_FIELD_WIDTH) - 1) << *shift;
@@ -73,10 +89,9 @@ static void sunxi_mux_reg(const struct sunxi_pinctrl *pctl,
static void sunxi_data_reg(const struct sunxi_pinctrl *pctl,
u32 pin, u32 *reg, u32 *shift, u32 *mask)
{
- u32 bank = pin / PINS_PER_BANK;
u32 offset = pin % PINS_PER_BANK * DATA_FIELD_WIDTH;
- *reg = bank * pctl->bank_mem_size + DATA_REGS_OFFSET +
+ *reg = sunxi_bank_offset(pctl, pin) + DATA_REGS_OFFSET +
offset / BITS_PER_TYPE(u32) * sizeof(u32);
*shift = offset % BITS_PER_TYPE(u32);
*mask = (BIT(DATA_FIELD_WIDTH) - 1) << *shift;
@@ -85,10 +100,9 @@ static void sunxi_data_reg(const struct sunxi_pinctrl *pctl,
static void sunxi_dlevel_reg(const struct sunxi_pinctrl *pctl,
u32 pin, u32 *reg, u32 *shift, u32 *mask)
{
- u32 bank = pin / PINS_PER_BANK;
u32 offset = pin % PINS_PER_BANK * pctl->dlevel_field_width;
- *reg = bank * pctl->bank_mem_size + DLEVEL_REGS_OFFSET +
+ *reg = sunxi_bank_offset(pctl, pin) + DLEVEL_REGS_OFFSET +
offset / BITS_PER_TYPE(u32) * sizeof(u32);
*shift = offset % BITS_PER_TYPE(u32);
*mask = (BIT(pctl->dlevel_field_width) - 1) << *shift;
@@ -97,10 +111,9 @@ static void sunxi_dlevel_reg(const struct sunxi_pinctrl *pctl,
static void sunxi_pull_reg(const struct sunxi_pinctrl *pctl,
u32 pin, u32 *reg, u32 *shift, u32 *mask)
{
- u32 bank = pin / PINS_PER_BANK;
u32 offset = pin % PINS_PER_BANK * PULL_FIELD_WIDTH;
- *reg = bank * pctl->bank_mem_size + pctl->pull_regs_offset +
+ *reg = sunxi_bank_offset(pctl, pin) + pctl->pull_regs_offset +
offset / BITS_PER_TYPE(u32) * sizeof(u32);
*shift = offset % BITS_PER_TYPE(u32);
*mask = (BIT(PULL_FIELD_WIDTH) - 1) << *shift;
@@ -723,9 +736,11 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl,
val = uV > 1800000 && uV <= 2500000 ? BIT(bank) : 0;
raw_spin_lock_irqsave(&pctl->lock, flags);
- reg = readl(pctl->membase + PIO_POW_MOD_CTL_REG);
+ reg = readl(pctl->membase + pctl->pow_mod_sel_offset +
+ PIO_POW_MOD_CTL_OFS);
reg &= ~BIT(bank);
- writel(reg | val, pctl->membase + PIO_POW_MOD_CTL_REG);
+ writel(reg | val, pctl->membase + pctl->pow_mod_sel_offset +
+ PIO_POW_MOD_CTL_OFS);
raw_spin_unlock_irqrestore(&pctl->lock, flags);
fallthrough;
@@ -733,9 +748,10 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl,
val = uV <= 1800000 ? 1 : 0;
raw_spin_lock_irqsave(&pctl->lock, flags);
- reg = readl(pctl->membase + PIO_POW_MOD_SEL_REG);
+ reg = readl(pctl->membase + pctl->pow_mod_sel_offset);
reg &= ~(1 << bank);
- writel(reg | val << bank, pctl->membase + PIO_POW_MOD_SEL_REG);
+ writel(reg | val << bank,
+ pctl->membase + pctl->pow_mod_sel_offset);
raw_spin_unlock_irqrestore(&pctl->lock, flags);
return 0;
default:
@@ -1472,9 +1488,9 @@ static int sunxi_pinctrl_setup_debounce(struct sunxi_pinctrl *pctl,
return 0;
}
-int sunxi_pinctrl_init_with_variant(struct platform_device *pdev,
- const struct sunxi_pinctrl_desc *desc,
- unsigned long variant)
+int sunxi_pinctrl_init_with_flags(struct platform_device *pdev,
+ const struct sunxi_pinctrl_desc *desc,
+ unsigned long flags)
{
struct device_node *node = pdev->dev.of_node;
struct pinctrl_desc *pctrl_desc;
@@ -1497,8 +1513,8 @@ int sunxi_pinctrl_init_with_variant(struct platform_device *pdev,
pctl->dev = &pdev->dev;
pctl->desc = desc;
- pctl->variant = variant;
- if (pctl->variant >= PINCTRL_SUN20I_D1) {
+ pctl->variant = flags & SUNXI_PINCTRL_VARIANT_MASK;
+ if (flags & SUNXI_PINCTRL_NEW_REG_LAYOUT) {
pctl->bank_mem_size = D1_BANK_MEM_SIZE;
pctl->pull_regs_offset = D1_PULL_REGS_OFFSET;
pctl->dlevel_field_width = D1_DLEVEL_FIELD_WIDTH;
@@ -1507,6 +1523,10 @@ int sunxi_pinctrl_init_with_variant(struct platform_device *pdev,
pctl->pull_regs_offset = PULL_REGS_OFFSET;
pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH;
}
+ if (flags & SUNXI_PINCTRL_ELEVEN_BANKS)
+ pctl->pow_mod_sel_offset = PIO_11B_POW_MOD_SEL_REG;
+ else
+ pctl->pow_mod_sel_offset = PIO_POW_MOD_SEL_REG;
pctl->irq_array = devm_kcalloc(&pdev->dev,
IRQ_PER_BANK * pctl->desc->irq_banks,