summaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/pinctrl-rockchip.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pinctrl/pinctrl-rockchip.c')
-rw-r--r--drivers/pinctrl/pinctrl-rockchip.c443
1 files changed, 337 insertions, 106 deletions
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index 7813599..f141aa0 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -59,7 +59,7 @@
#define GPIO_LS_SYNC 0x60
enum rockchip_pinctrl_type {
- RK1108,
+ RV1108,
RK2928,
RK3066B,
RK3188,
@@ -75,6 +75,8 @@ enum rockchip_pinctrl_type {
#define IOMUX_WIDTH_4BIT BIT(1)
#define IOMUX_SOURCE_PMU BIT(2)
#define IOMUX_UNROUTED BIT(3)
+#define IOMUX_WIDTH_3BIT BIT(4)
+#define IOMUX_RECALCED BIT(5)
/**
* @type: iomux variant using IOMUX_* constants
@@ -141,6 +143,9 @@ struct rockchip_drv {
* @gpio_chip: gpiolib chip
* @grange: gpio range
* @slock: spinlock for the gpio bank
+ * @irq_lock: bus lock for irq chip
+ * @new_irqs: newly configured irqs which must be muxed as GPIOs in
+ * irq_bus_sync_unlock()
*/
struct rockchip_pin_bank {
void __iomem *reg_base;
@@ -161,8 +166,10 @@ struct rockchip_pin_bank {
struct irq_domain *domain;
struct gpio_chip gpio_chip;
struct pinctrl_gpio_range grange;
- spinlock_t slock;
+ raw_spinlock_t slock;
u32 toggle_edge_mode;
+ struct mutex irq_lock;
+ u32 new_irqs;
};
#define PIN_BANK(id, pins, label) \
@@ -304,6 +311,11 @@ struct rockchip_pin_ctrl {
void (*drv_calc_reg)(struct rockchip_pin_bank *bank,
int pin_num, struct regmap **regmap,
int *reg, u8 *bit);
+ void (*iomux_recalc)(u8 bank_num, int pin, int *reg,
+ u8 *bit, int *mask);
+ int (*schmitt_calc_reg)(struct rockchip_pin_bank *bank,
+ int pin_num, struct regmap **regmap,
+ int *reg, u8 *bit);
};
struct rockchip_pin_config {
@@ -355,6 +367,22 @@ struct rockchip_pinctrl {
unsigned int nfunctions;
};
+/**
+ * struct rockchip_mux_recalced_data: represent a pin iomux data.
+ * @num: bank number.
+ * @pin: pin number.
+ * @bit: index at register.
+ * @reg: register offset.
+ * @mask: mask bit
+ */
+struct rockchip_mux_recalced_data {
+ u8 num;
+ u8 pin;
+ u8 reg;
+ u8 bit;
+ u8 mask;
+};
+
static struct regmap_config rockchip_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
@@ -514,13 +542,57 @@ static const struct pinctrl_ops rockchip_pctrl_ops = {
* Hardware access
*/
+static const struct rockchip_mux_recalced_data rk3328_mux_recalced_data[] = {
+ {
+ .num = 2,
+ .pin = 12,
+ .reg = 0x24,
+ .bit = 8,
+ .mask = 0x3
+ }, {
+ .num = 2,
+ .pin = 15,
+ .reg = 0x28,
+ .bit = 0,
+ .mask = 0x7
+ }, {
+ .num = 2,
+ .pin = 23,
+ .reg = 0x30,
+ .bit = 14,
+ .mask = 0x3
+ },
+};
+
+static void rk3328_recalc_mux(u8 bank_num, int pin, int *reg,
+ u8 *bit, int *mask)
+{
+ const struct rockchip_mux_recalced_data *data = NULL;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(rk3328_mux_recalced_data); i++)
+ if (rk3328_mux_recalced_data[i].num == bank_num &&
+ rk3328_mux_recalced_data[i].pin == pin) {
+ data = &rk3328_mux_recalced_data[i];
+ break;
+ }
+
+ if (!data)
+ return;
+
+ *reg = data->reg;
+ *mask = data->mask;
+ *bit = data->bit;
+}
+
static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin)
{
struct rockchip_pinctrl *info = bank->drvdata;
+ struct rockchip_pin_ctrl *ctrl = info->ctrl;
int iomux_num = (pin / 8);
struct regmap *regmap;
unsigned int val;
- int reg, ret, mask;
+ int reg, ret, mask, mux_type;
u8 bit;
if (iomux_num > 3)
@@ -538,16 +610,26 @@ static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin)
? info->regmap_pmu : info->regmap_base;
/* get basic quadrupel of mux registers and the correct reg inside */
- mask = (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) ? 0xf : 0x3;
+ mux_type = bank->iomux[iomux_num].type;
reg = bank->iomux[iomux_num].offset;
- if (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) {
+ if (mux_type & IOMUX_WIDTH_4BIT) {
if ((pin % 8) >= 4)
reg += 0x4;
bit = (pin % 4) * 4;
+ mask = 0xf;
+ } else if (mux_type & IOMUX_WIDTH_3BIT) {
+ if ((pin % 8) >= 5)
+ reg += 0x4;
+ bit = (pin % 8 % 5) * 3;
+ mask = 0x7;
} else {
bit = (pin % 8) * 2;
+ mask = 0x3;
}
+ if (ctrl->iomux_recalc && (mux_type & IOMUX_RECALCED))
+ ctrl->iomux_recalc(bank->bank_num, pin, &reg, &bit, &mask);
+
ret = regmap_read(regmap, reg, &val);
if (ret)
return ret;
@@ -555,6 +637,31 @@ static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin)
return ((val >> bit) & mask);
}
+static int rockchip_verify_mux(struct rockchip_pin_bank *bank,
+ int pin, int mux)
+{
+ struct rockchip_pinctrl *info = bank->drvdata;
+ int iomux_num = (pin / 8);
+
+ if (iomux_num > 3)
+ return -EINVAL;
+
+ if (bank->iomux[iomux_num].type & IOMUX_UNROUTED) {
+ dev_err(info->dev, "pin %d is unrouted\n", pin);
+ return -EINVAL;
+ }
+
+ if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY) {
+ if (mux != RK_FUNC_GPIO) {
+ dev_err(info->dev,
+ "pin %d only supports a gpio mux\n", pin);
+ return -ENOTSUPP;
+ }
+ }
+
+ return 0;
+}
+
/*
* Set a new mux function for a pin.
*
@@ -571,30 +678,19 @@ static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin)
static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
{
struct rockchip_pinctrl *info = bank->drvdata;
+ struct rockchip_pin_ctrl *ctrl = info->ctrl;
int iomux_num = (pin / 8);
struct regmap *regmap;
- int reg, ret, mask;
- unsigned long flags;
+ int reg, ret, mask, mux_type;
u8 bit;
u32 data, rmask;
- if (iomux_num > 3)
- return -EINVAL;
-
- if (bank->iomux[iomux_num].type & IOMUX_UNROUTED) {
- dev_err(info->dev, "pin %d is unrouted\n", pin);
- return -EINVAL;
- }
+ ret = rockchip_verify_mux(bank, pin, mux);
+ if (ret < 0)
+ return ret;
- if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY) {
- if (mux != RK_FUNC_GPIO) {
- dev_err(info->dev,
- "pin %d only supports a gpio mux\n", pin);
- return -ENOTSUPP;
- } else {
- return 0;
- }
- }
+ if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY)
+ return 0;
dev_dbg(info->dev, "setting mux of GPIO%d-%d to %d\n",
bank->bank_num, pin, mux);
@@ -603,35 +699,41 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
? info->regmap_pmu : info->regmap_base;
/* get basic quadrupel of mux registers and the correct reg inside */
- mask = (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) ? 0xf : 0x3;
+ mux_type = bank->iomux[iomux_num].type;
reg = bank->iomux[iomux_num].offset;
- if (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) {
+ if (mux_type & IOMUX_WIDTH_4BIT) {
if ((pin % 8) >= 4)
reg += 0x4;
bit = (pin % 4) * 4;
+ mask = 0xf;
+ } else if (mux_type & IOMUX_WIDTH_3BIT) {
+ if ((pin % 8) >= 5)
+ reg += 0x4;
+ bit = (pin % 8 % 5) * 3;
+ mask = 0x7;
} else {
bit = (pin % 8) * 2;
+ mask = 0x3;
}
- spin_lock_irqsave(&bank->slock, flags);
+ if (ctrl->iomux_recalc && (mux_type & IOMUX_RECALCED))
+ ctrl->iomux_recalc(bank->bank_num, pin, &reg, &bit, &mask);
data = (mask << (bit + 16));
rmask = data | (data >> 16);
data |= (mux & mask) << bit;
ret = regmap_update_bits(regmap, reg, rmask, data);
- spin_unlock_irqrestore(&bank->slock, flags);
-
return ret;
}
-#define RK1108_PULL_PMU_OFFSET 0x10
-#define RK1108_PULL_OFFSET 0x110
-#define RK1108_PULL_PINS_PER_REG 8
-#define RK1108_PULL_BITS_PER_PIN 2
-#define RK1108_PULL_BANK_STRIDE 16
+#define RV1108_PULL_PMU_OFFSET 0x10
+#define RV1108_PULL_OFFSET 0x110
+#define RV1108_PULL_PINS_PER_REG 8
+#define RV1108_PULL_BITS_PER_PIN 2
+#define RV1108_PULL_BANK_STRIDE 16
-static void rk1108_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+static void rv1108_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
int pin_num, struct regmap **regmap,
int *reg, u8 *bit)
{
@@ -640,27 +742,27 @@ static void rk1108_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
/* The first 24 pins of the first bank are located in PMU */
if (bank->bank_num == 0) {
*regmap = info->regmap_pmu;
- *reg = RK1108_PULL_PMU_OFFSET;
+ *reg = RV1108_PULL_PMU_OFFSET;
} else {
- *reg = RK1108_PULL_OFFSET;
+ *reg = RV1108_PULL_OFFSET;
*regmap = info->regmap_base;
/* correct the offset, as we're starting with the 2nd bank */
*reg -= 0x10;
- *reg += bank->bank_num * RK1108_PULL_BANK_STRIDE;
+ *reg += bank->bank_num * RV1108_PULL_BANK_STRIDE;
}
- *reg += ((pin_num / RK1108_PULL_PINS_PER_REG) * 4);
- *bit = (pin_num % RK1108_PULL_PINS_PER_REG);
- *bit *= RK1108_PULL_BITS_PER_PIN;
+ *reg += ((pin_num / RV1108_PULL_PINS_PER_REG) * 4);
+ *bit = (pin_num % RV1108_PULL_PINS_PER_REG);
+ *bit *= RV1108_PULL_BITS_PER_PIN;
}
-#define RK1108_DRV_PMU_OFFSET 0x20
-#define RK1108_DRV_GRF_OFFSET 0x210
-#define RK1108_DRV_BITS_PER_PIN 2
-#define RK1108_DRV_PINS_PER_REG 8
-#define RK1108_DRV_BANK_STRIDE 16
+#define RV1108_DRV_PMU_OFFSET 0x20
+#define RV1108_DRV_GRF_OFFSET 0x210
+#define RV1108_DRV_BITS_PER_PIN 2
+#define RV1108_DRV_PINS_PER_REG 8
+#define RV1108_DRV_BANK_STRIDE 16
-static void rk1108_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+static void rv1108_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
int pin_num, struct regmap **regmap,
int *reg, u8 *bit)
{
@@ -669,19 +771,19 @@ static void rk1108_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
/* The first 24 pins of the first bank are located in PMU */
if (bank->bank_num == 0) {
*regmap = info->regmap_pmu;
- *reg = RK1108_DRV_PMU_OFFSET;
+ *reg = RV1108_DRV_PMU_OFFSET;
} else {
*regmap = info->regmap_base;
- *reg = RK1108_DRV_GRF_OFFSET;
+ *reg = RV1108_DRV_GRF_OFFSET;
/* correct the offset, as we're starting with the 2nd bank */
*reg -= 0x10;
- *reg += bank->bank_num * RK1108_DRV_BANK_STRIDE;
+ *reg += bank->bank_num * RV1108_DRV_BANK_STRIDE;
}
- *reg += ((pin_num / RK1108_DRV_PINS_PER_REG) * 4);
- *bit = pin_num % RK1108_DRV_PINS_PER_REG;
- *bit *= RK1108_DRV_BITS_PER_PIN;
+ *reg += ((pin_num / RV1108_DRV_PINS_PER_REG) * 4);
+ *bit = pin_num % RV1108_DRV_PINS_PER_REG;
+ *bit *= RV1108_DRV_BITS_PER_PIN;
}
#define RK2928_PULL_OFFSET 0x118
@@ -1047,7 +1149,6 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
struct rockchip_pinctrl *info = bank->drvdata;
struct rockchip_pin_ctrl *ctrl = info->ctrl;
struct regmap *regmap;
- unsigned long flags;
int reg, ret, i;
u32 data, rmask, rmask_bits, temp;
u8 bit;
@@ -1075,8 +1176,6 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
return ret;
}
- spin_lock_irqsave(&bank->slock, flags);
-
switch (drv_type) {
case DRV_TYPE_IO_1V8_3V0_AUTO:
case DRV_TYPE_IO_3V3_ONLY:
@@ -1097,17 +1196,14 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
rmask = BIT(15) | BIT(31);
data |= BIT(31);
ret = regmap_update_bits(regmap, reg, rmask, data);
- if (ret) {
- spin_unlock_irqrestore(&bank->slock, flags);
+ if (ret)
return ret;
- }
rmask = 0x3 | (0x3 << 16);
temp |= (0x3 << 16);
reg += 0x4;
ret = regmap_update_bits(regmap, reg, rmask, temp);
- spin_unlock_irqrestore(&bank->slock, flags);
return ret;
case 18 ... 21:
/* setting fully enclosed in the second register */
@@ -1115,7 +1211,6 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
bit -= 16;
break;
default:
- spin_unlock_irqrestore(&bank->slock, flags);
dev_err(info->dev, "unsupported bit: %d for pinctrl drive type: %d\n",
bit, drv_type);
return -EINVAL;
@@ -1127,7 +1222,6 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
rmask_bits = RK3288_DRV_BITS_PER_PIN;
break;
default:
- spin_unlock_irqrestore(&bank->slock, flags);
dev_err(info->dev, "unsupported pinctrl drive type: %d\n",
drv_type);
return -EINVAL;
@@ -1139,7 +1233,6 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
data |= (ret << bit);
ret = regmap_update_bits(regmap, reg, rmask, data);
- spin_unlock_irqrestore(&bank->slock, flags);
return ret;
}
@@ -1183,7 +1276,7 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
return !(data & BIT(bit))
? PIN_CONFIG_BIAS_PULL_PIN_DEFAULT
: PIN_CONFIG_BIAS_DISABLE;
- case RK1108:
+ case RV1108:
case RK3188:
case RK3288:
case RK3368:
@@ -1206,7 +1299,6 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
struct rockchip_pin_ctrl *ctrl = info->ctrl;
struct regmap *regmap;
int reg, ret, i, pull_type;
- unsigned long flags;
u8 bit;
u32 data, rmask;
@@ -1221,16 +1313,12 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
switch (ctrl->type) {
case RK2928:
- spin_lock_irqsave(&bank->slock, flags);
-
data = BIT(bit + 16);
if (pull == PIN_CONFIG_BIAS_DISABLE)
data |= BIT(bit);
ret = regmap_write(regmap, reg, data);
-
- spin_unlock_irqrestore(&bank->slock, flags);
break;
- case RK1108:
+ case RV1108:
case RK3188:
case RK3288:
case RK3368:
@@ -1251,16 +1339,12 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
return ret;
}
- spin_lock_irqsave(&bank->slock, flags);
-
/* enable the write to the equivalent lower bits */
data = ((1 << RK3188_PULL_BITS_PER_PIN) - 1) << (bit + 16);
rmask = data | (data >> 16);
data |= (ret << bit);
ret = regmap_update_bits(regmap, reg, rmask, data);
-
- spin_unlock_irqrestore(&bank->slock, flags);
break;
default:
dev_err(info->dev, "unsupported pinctrl type\n");
@@ -1270,6 +1354,73 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
return ret;
}
+#define RK3328_SCHMITT_BITS_PER_PIN 1
+#define RK3328_SCHMITT_PINS_PER_REG 16
+#define RK3328_SCHMITT_BANK_STRIDE 8
+#define RK3328_SCHMITT_GRF_OFFSET 0x380
+
+static int rk3328_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
+ int pin_num,
+ struct regmap **regmap,
+ int *reg, u8 *bit)
+{
+ struct rockchip_pinctrl *info = bank->drvdata;
+
+ *regmap = info->regmap_base;
+ *reg = RK3328_SCHMITT_GRF_OFFSET;
+
+ *reg += bank->bank_num * RK3328_SCHMITT_BANK_STRIDE;
+ *reg += ((pin_num / RK3328_SCHMITT_PINS_PER_REG) * 4);
+ *bit = pin_num % RK3328_SCHMITT_PINS_PER_REG;
+
+ return 0;
+}
+
+static int rockchip_get_schmitt(struct rockchip_pin_bank *bank, int pin_num)
+{
+ struct rockchip_pinctrl *info = bank->drvdata;
+ struct rockchip_pin_ctrl *ctrl = info->ctrl;
+ struct regmap *regmap;
+ int reg, ret;
+ u8 bit;
+ u32 data;
+
+ ret = ctrl->schmitt_calc_reg(bank, pin_num, &regmap, &reg, &bit);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(regmap, reg, &data);
+ if (ret)
+ return ret;
+
+ data >>= bit;
+ return data & 0x1;
+}
+
+static int rockchip_set_schmitt(struct rockchip_pin_bank *bank,
+ int pin_num, int enable)
+{
+ struct rockchip_pinctrl *info = bank->drvdata;
+ struct rockchip_pin_ctrl *ctrl = info->ctrl;
+ struct regmap *regmap;
+ int reg, ret;
+ u8 bit;
+ u32 data, rmask;
+
+ dev_dbg(info->dev, "setting input schmitt of GPIO%d-%d to %d\n",
+ bank->bank_num, pin_num, enable);
+
+ ret = ctrl->schmitt_calc_reg(bank, pin_num, &regmap, &reg, &bit);
+ if (ret)
+ return ret;
+
+ /* enable the write to the equivalent lower bits */
+ data = BIT(bit + 16) | (enable << bit);
+ rmask = BIT(bit + 16) | BIT(bit);
+
+ return regmap_update_bits(regmap, reg, rmask, data);
+}
+
/*
* Pinmux_ops handling
*/
@@ -1366,7 +1517,7 @@ static int _rockchip_pmx_gpio_set_direction(struct gpio_chip *chip,
return ret;
clk_enable(bank->clk);
- spin_lock_irqsave(&bank->slock, flags);
+ raw_spin_lock_irqsave(&bank->slock, flags);
data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
/* set bit to 1 for output, 0 for input */
@@ -1376,7 +1527,7 @@ static int _rockchip_pmx_gpio_set_direction(struct gpio_chip *chip,
data &= ~BIT(pin);
writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR);
- spin_unlock_irqrestore(&bank->slock, flags);
+ raw_spin_unlock_irqrestore(&bank->slock, flags);
clk_disable(bank->clk);
return 0;
@@ -1420,7 +1571,7 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl,
pull == PIN_CONFIG_BIAS_DISABLE);
case RK3066B:
return pull ? false : true;
- case RK1108:
+ case RV1108:
case RK3188:
case RK3288:
case RK3368:
@@ -1489,6 +1640,15 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
if (rc < 0)
return rc;
break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ if (!info->ctrl->schmitt_calc_reg)
+ return -ENOTSUPP;
+
+ rc = rockchip_set_schmitt(bank,
+ pin - bank->pin_base, arg);
+ if (rc < 0)
+ return rc;
+ break;
default:
return -ENOTSUPP;
break;
@@ -1549,6 +1709,16 @@ static int rockchip_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
arg = rc;
break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ if (!info->ctrl->schmitt_calc_reg)
+ return -ENOTSUPP;
+
+ rc = rockchip_get_schmitt(bank, pin - bank->pin_base);
+ if (rc < 0)
+ return rc;
+
+ arg = rc;
+ break;
default:
return -ENOTSUPP;
break;
@@ -1807,7 +1977,7 @@ static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
u32 data;
clk_enable(bank->clk);
- spin_lock_irqsave(&bank->slock, flags);
+ raw_spin_lock_irqsave(&bank->slock, flags);
data = readl(reg);
data &= ~BIT(offset);
@@ -1815,7 +1985,7 @@ static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
data |= BIT(offset);
writel(data, reg);
- spin_unlock_irqrestore(&bank->slock, flags);
+ raw_spin_unlock_irqrestore(&bank->slock, flags);
clk_disable(bank->clk);
}
@@ -1927,7 +2097,7 @@ static void rockchip_irq_demux(struct irq_desc *desc)
data = readl_relaxed(bank->reg_base + GPIO_EXT_PORT);
do {
- spin_lock_irqsave(&bank->slock, flags);
+ raw_spin_lock_irqsave(&bank->slock, flags);
polarity = readl_relaxed(bank->reg_base +
GPIO_INT_POLARITY);
@@ -1938,7 +2108,7 @@ static void rockchip_irq_demux(struct irq_desc *desc)
writel(polarity,
bank->reg_base + GPIO_INT_POLARITY);
- spin_unlock_irqrestore(&bank->slock, flags);
+ raw_spin_unlock_irqrestore(&bank->slock, flags);
data_old = data;
data = readl_relaxed(bank->reg_base +
@@ -1964,25 +2134,26 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
int ret;
/* make sure the pin is configured as gpio input */
- ret = rockchip_set_mux(bank, d->hwirq, RK_FUNC_GPIO);
+ ret = rockchip_verify_mux(bank, d->hwirq, RK_FUNC_GPIO);
if (ret < 0)
return ret;
- clk_enable(bank->clk);
- spin_lock_irqsave(&bank->slock, flags);
+ bank->new_irqs |= mask;
+
+ raw_spin_lock_irqsave(&bank->slock, flags);
data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
data &= ~mask;
writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR);
- spin_unlock_irqrestore(&bank->slock, flags);
+ raw_spin_unlock_irqrestore(&bank->slock, flags);
if (type & IRQ_TYPE_EDGE_BOTH)
irq_set_handler_locked(d, handle_edge_irq);
else
irq_set_handler_locked(d, handle_level_irq);
- spin_lock_irqsave(&bank->slock, flags);
+ raw_spin_lock_irqsave(&bank->slock, flags);
irq_gc_lock(gc);
level = readl_relaxed(gc->reg_base + GPIO_INTTYPE_LEVEL);
@@ -2025,8 +2196,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
break;
default:
irq_gc_unlock(gc);
- spin_unlock_irqrestore(&bank->slock, flags);
- clk_disable(bank->clk);
+ raw_spin_unlock_irqrestore(&bank->slock, flags);
return -EINVAL;
}
@@ -2034,8 +2204,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
writel_relaxed(polarity, gc->reg_base + GPIO_INT_POLARITY);
irq_gc_unlock(gc);
- spin_unlock_irqrestore(&bank->slock, flags);
- clk_disable(bank->clk);
+ raw_spin_unlock_irqrestore(&bank->slock, flags);
return 0;
}
@@ -2061,7 +2230,7 @@ static void rockchip_irq_resume(struct irq_data *d)
clk_disable(bank->clk);
}
-static void rockchip_irq_gc_mask_clr_bit(struct irq_data *d)
+static void rockchip_irq_enable(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct rockchip_pin_bank *bank = gc->private;
@@ -2070,7 +2239,7 @@ static void rockchip_irq_gc_mask_clr_bit(struct irq_data *d)
irq_gc_mask_clr_bit(d);
}
-static void rockchip_irq_gc_mask_set_bit(struct irq_data *d)
+static void rockchip_irq_disable(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct rockchip_pin_bank *bank = gc->private;
@@ -2079,6 +2248,34 @@ static void rockchip_irq_gc_mask_set_bit(struct irq_data *d)
clk_disable(bank->clk);
}
+static void rockchip_irq_bus_lock(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct rockchip_pin_bank *bank = gc->private;
+
+ clk_enable(bank->clk);
+ mutex_lock(&bank->irq_lock);
+}
+
+static void rockchip_irq_bus_sync_unlock(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct rockchip_pin_bank *bank = gc->private;
+
+ while (bank->new_irqs) {
+ unsigned int irq = __ffs(bank->new_irqs);
+ int ret;
+
+ ret = rockchip_set_mux(bank, irq, RK_FUNC_GPIO);
+ WARN_ON(ret < 0);
+
+ bank->new_irqs &= ~BIT(irq);
+ }
+
+ mutex_unlock(&bank->irq_lock);
+ clk_disable(bank->clk);
+}
+
static int rockchip_interrupts_register(struct platform_device *pdev,
struct rockchip_pinctrl *info)
{
@@ -2137,13 +2334,17 @@ static int rockchip_interrupts_register(struct platform_device *pdev,
gc->chip_types[0].regs.mask = GPIO_INTMASK;
gc->chip_types[0].regs.ack = GPIO_PORTS_EOI;
gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit;
- gc->chip_types[0].chip.irq_mask = rockchip_irq_gc_mask_set_bit;
- gc->chip_types[0].chip.irq_unmask =
- rockchip_irq_gc_mask_clr_bit;
+ gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit;
+ gc->chip_types[0].chip.irq_unmask = irq_gc_mask_clr_bit;
+ gc->chip_types[0].chip.irq_enable = rockchip_irq_enable;
+ gc->chip_types[0].chip.irq_disable = rockchip_irq_disable;
gc->chip_types[0].chip.irq_set_wake = irq_gc_set_wake;
gc->chip_types[0].chip.irq_suspend = rockchip_irq_suspend;
gc->chip_types[0].chip.irq_resume = rockchip_irq_resume;
gc->chip_types[0].chip.irq_set_type = rockchip_irq_set_type;
+ gc->chip_types[0].chip.irq_bus_lock = rockchip_irq_bus_lock;
+ gc->chip_types[0].chip.irq_bus_sync_unlock =
+ rockchip_irq_bus_sync_unlock;
gc->wake_enabled = IRQ_MSK(bank->nr_pins);
irq_set_chained_handler_and_data(bank->irq,
@@ -2316,7 +2517,8 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(
for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
int bank_pins = 0;
- spin_lock_init(&bank->slock);
+ raw_spin_lock_init(&bank->slock);
+ mutex_init(&bank->irq_lock);
bank->drvdata = d;
bank->pin_base = ctrl->nr_pins;
ctrl->nr_pins += bank->nr_pins;
@@ -2359,7 +2561,8 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(
* Increase offset according to iomux width.
* 4bit iomux'es are spread over two registers.
*/
- inc = (iom->type & IOMUX_WIDTH_4BIT) ? 8 : 4;
+ inc = (iom->type & (IOMUX_WIDTH_4BIT |
+ IOMUX_WIDTH_3BIT)) ? 8 : 4;
if (iom->type & IOMUX_SOURCE_PMU)
pmu_offs += inc;
else
@@ -2518,7 +2721,7 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
return 0;
}
-static struct rockchip_pin_bank rk1108_pin_banks[] = {
+static struct rockchip_pin_bank rv1108_pin_banks[] = {
PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU,
IOMUX_SOURCE_PMU,
IOMUX_SOURCE_PMU,
@@ -2528,15 +2731,15 @@ static struct rockchip_pin_bank rk1108_pin_banks[] = {
PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", 0, 0, 0, 0),
};
-static struct rockchip_pin_ctrl rk1108_pin_ctrl = {
- .pin_banks = rk1108_pin_banks,
- .nr_banks = ARRAY_SIZE(rk1108_pin_banks),
- .label = "RK1108-GPIO",
- .type = RK1108,
+static struct rockchip_pin_ctrl rv1108_pin_ctrl = {
+ .pin_banks = rv1108_pin_banks,
+ .nr_banks = ARRAY_SIZE(rv1108_pin_banks),
+ .label = "RV1108-GPIO",
+ .type = RV1108,
.grf_mux_offset = 0x10,
.pmu_mux_offset = 0x0,
- .pull_calc_reg = rk1108_calc_pull_reg_and_bit,
- .drv_calc_reg = rk1108_calc_drv_reg_and_bit,
+ .pull_calc_reg = rv1108_calc_pull_reg_and_bit,
+ .drv_calc_reg = rv1108_calc_drv_reg_and_bit,
};
static struct rockchip_pin_bank rk2928_pin_banks[] = {
@@ -2679,6 +2882,32 @@ static struct rockchip_pin_ctrl rk3288_pin_ctrl = {
.drv_calc_reg = rk3288_calc_drv_reg_and_bit,
};
+static struct rockchip_pin_bank rk3328_pin_banks[] = {
+ PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", 0, 0, 0, 0),
+ PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", 0, 0, 0, 0),
+ PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0,
+ IOMUX_WIDTH_3BIT | IOMUX_RECALCED,
+ IOMUX_WIDTH_3BIT | IOMUX_RECALCED,
+ 0),
+ PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3",
+ IOMUX_WIDTH_3BIT,
+ IOMUX_WIDTH_3BIT | IOMUX_RECALCED,
+ 0,
+ 0),
+};
+
+static struct rockchip_pin_ctrl rk3328_pin_ctrl = {
+ .pin_banks = rk3328_pin_banks,
+ .nr_banks = ARRAY_SIZE(rk3328_pin_banks),
+ .label = "RK3328-GPIO",
+ .type = RK3288,
+ .grf_mux_offset = 0x0,
+ .pull_calc_reg = rk3228_calc_pull_reg_and_bit,
+ .drv_calc_reg = rk3228_calc_drv_reg_and_bit,
+ .iomux_recalc = rk3328_recalc_mux,
+ .schmitt_calc_reg = rk3328_calc_schmitt_reg_and_bit,
+};
+
static struct rockchip_pin_bank rk3368_pin_banks[] = {
PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU,
IOMUX_SOURCE_PMU,
@@ -2768,8 +2997,8 @@ static struct rockchip_pin_ctrl rk3399_pin_ctrl = {
};
static const struct of_device_id rockchip_pinctrl_dt_match[] = {
- { .compatible = "rockchip,rk1108-pinctrl",
- .data = (void *)&rk1108_pin_ctrl },
+ { .compatible = "rockchip,rv1108-pinctrl",
+ .data = (void *)&rv1108_pin_ctrl },
{ .compatible = "rockchip,rk2928-pinctrl",
.data = (void *)&rk2928_pin_ctrl },
{ .compatible = "rockchip,rk3036-pinctrl",
@@ -2784,6 +3013,8 @@ static const struct of_device_id rockchip_pinctrl_dt_match[] = {
.data = (void *)&rk3228_pin_ctrl },
{ .compatible = "rockchip,rk3288-pinctrl",
.data = (void *)&rk3288_pin_ctrl },
+ { .compatible = "rockchip,rk3328-pinctrl",
+ .data = (void *)&rk3328_pin_ctrl },
{ .compatible = "rockchip,rk3368-pinctrl",
.data = (void *)&rk3368_pin_ctrl },
{ .compatible = "rockchip,rk3399-pinctrl",
OpenPOWER on IntegriCloud