Thread (12 messages) 12 messages, 4 authors, 2016-02-11

[PATCH v2] pinctrl: rockchip: add support for the rk3399

From: heiko@sntech.de (Heiko Stübner)
Date: 2016-01-28 16:56:55
Also in: linux-gpio, linux-rockchip, lkml

Hi David,

Am Donnerstag, 7. Januar 2016, 15:41:38 schrieb David Wu:
quoted hunk ↗ jump to hunk
From: David Wu <redacted>

The pinctrl of rk3399 is much different from other's,
especially the 3bits of drive strength.

Signed-off-by: David Wu <redacted>
---
change from v1:
- need spin_unlock_irqrestore for set drive default case

 .../bindings/pinctrl/rockchip,pinctrl.txt          |   1 +
 drivers/pinctrl/pinctrl-rockchip.c                 | 339
++++++++++++++++++++- 2 files changed, 326 insertions(+), 14 deletions(-)
diff --git a/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt
b/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt index
391ef4b..3bb9456 100644
--- a/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt
@@ -22,6 +22,7 @@ Required properties for iomux controller:
   - compatible: one of "rockchip,rk2928-pinctrl",
"rockchip,rk3066a-pinctrl" "rockchip,rk3066b-pinctrl",
"rockchip,rk3188-pinctrl"
 		       "rockchip,rk3288-pinctrl", "rockchip,rk3368-pinctrl"
+		       "rockchip,rk3399-pinctrl"
   - rockchip,grf: phandle referencing a syscon providing the
 	 "general register files"
diff --git a/drivers/pinctrl/pinctrl-rockchip.c
b/drivers/pinctrl/pinctrl-rockchip.c index a065112..9d61c6e 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
[...]
quoted hunk ↗ jump to hunk
@@ -685,19 +821,60 @@ static int rockchip_get_drive_perpin(struct
rockchip_pin_bank *bank, struct rockchip_pin_ctrl *ctrl = info->ctrl;
 	struct regmap *regmap;
 	int reg, ret;
-	u32 data;
+	u32 data, temp, rmask_bits;
 	u8 bit;
+	int drv_type = bank->drv[pin_num / 8].drv_type;

 	ctrl->drv_calc_reg(bank, pin_num, &regmap, &reg, &bit);

+	switch (drv_type) {
+	case DRV_TYPE_IO_1V8_3V0_AUTO:
+	case DRV_TYPE_IO_3V3_ONLY:
+		if (RK3399_DRV_3BITS_PER_PIN + bit >= 16) {
According to the doc excerpts, wouldn't the big special handling only be 
necessary for for gpio3b5 alone (+ other banks) ... i.e. the one setting being 
split over both registers?
If so I think doing something like the following might be easier to 
understand? Same of course for the set-counterpart. [Beware if I missed up the 
indices somewhere :-) ]

rmask_bits = RK3399_DRV_3BITS_PER_PIN;
switch(bit) {
case 0 ... 12:
	/* regular case, nothing to do */
	break;
case 15:
	/* drive-strength offset is special, as it is spread over 2 registers */
	ret = regmap_read(regmap, reg, &data);
	if (ret)
		return ret;

	ret = regmap_read(regmap, reg + 0x4, &temp);
	if (ret)
		return ret;

	/*
	 * the bit data[15] contains bit 0 of the value
	 * while temp[1:0] containts bits 2 and 1
	 */
	data >>= 15;
	temp &= 0x3;
	temp <<= 1;
	data |= temp;

	return rockchip_perpin_drv_list[drv_type][data];
case 18 ... 21:
	/* setting fully enclosed in the second register */
	rmask_bits = RK3399_DRV_3BITS_PER_PIN;
	reg += 4;
	bit -= 18;
}
+			/* need to read regs twice */
+			ret = regmap_read(regmap, reg, &temp);
+			if (ret)
+				return ret;
+
+			temp >>= bit;
+			rmask_bits = 16 - bit;
+			temp &= (1 << rmask_bits) - 1;
+
+			reg = reg + 0x4;
+			ret = regmap_read(regmap, reg, &data);
+			if (ret)
+				return ret;
+
+			rmask_bits = RK3399_DRV_3BITS_PER_PIN
+				+ bit - 16;
+			data &= (1 << rmask_bits) - 1;
+			data <<= 16 - bit;
+			data |= temp;
+
+			return rockchip_perpin_drv_list[drv_type][data];
+		}
+
+		rmask_bits = RK3399_DRV_3BITS_PER_PIN;
+		break;
+	case DRV_TYPE_IO_DEFAULT:
+	case DRV_TYPE_IO_1V8_OR_3V0:
+	case DRV_TYPE_IO_1V8_ONLY:
+		rmask_bits = RK3288_DRV_BITS_PER_PIN;
+		break;
+	default:
+		dev_err(info->dev, "unsupported pinctrl drive type: %d\n",
+			drv_type);
+		return -EINVAL;
+	}
+
 	ret = regmap_read(regmap, reg, &data);
 	if (ret)
 		return ret;

 	data >>= bit;
-	data &= (1 << RK3288_DRV_BITS_PER_PIN) - 1;
+	data &= (1 << rmask_bits) - 1;

-	return rockchip_perpin_drv_list[data];
+	return rockchip_perpin_drv_list[drv_type][data];
 }

 static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
[...]
quoted hunk ↗ jump to hunk
@@ -729,8 +913,45 @@ static int rockchip_set_drive_perpin(struct
rockchip_pin_bank *bank,

 	spin_lock_irqsave(&bank->slock, flags);

+	switch (drv_type) {
+	case DRV_TYPE_IO_1V8_3V0_AUTO:
+	case DRV_TYPE_IO_3V3_ONLY:
+		if (RK3399_DRV_3BITS_PER_PIN + bit >= 16) {
+			/* need to write regs twice */
+			rmask_bits = 16 - bit;
+			/* enable the write to the equivalent lower bits */
+			data = ((1 << rmask_bits) - 1) << (bit + 16);
+			rmask = data | (data >> 16);
+			ret &= (1 << rmask_bits) - 1;
+			data |= (ret << bit);
+
+			ret = regmap_update_bits(regmap, reg, rmask, data);
+			if (ret)
+				return ret;
+
+			ret = i >> rmask_bits;
+			rmask_bits = RK3399_DRV_3BITS_PER_PIN + bit - 16;
+			reg = reg + 0x4;
+			bit = 0;
Apart from a change similar to the above, should the setting maybe also 
directly return and not depend on the final write?
+		} else {
+			rmask_bits = RK3399_DRV_3BITS_PER_PIN;
+		}
+		break;
+	case DRV_TYPE_IO_DEFAULT:
+	case DRV_TYPE_IO_1V8_OR_3V0:
+	case DRV_TYPE_IO_1V8_ONLY:
+		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;
+
+	}
+
 	/* enable the write to the equivalent lower bits */
-	data = ((1 << RK3288_DRV_BITS_PER_PIN) - 1) << (bit + 16);
+	data = ((1 << rmask_bits) - 1) << (bit + 16);
 	rmask = data | (data >> 16);
 	data |= (ret << bit);
[...]
quoted hunk ↗ jump to hunk
@@ -2208,6 +2461,62 @@ static struct rockchip_pin_ctrl rk3368_pin_ctrl = {
 		.drv_calc_reg		= rk3368_calc_drv_reg_and_bit,
 };

+static struct rockchip_pin_bank rk3399_pin_banks[] = {
+	PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(0, 32, "gpio0", IOMUX_SOURCE_PMU,
+					IOMUX_SOURCE_PMU,
+					IOMUX_SOURCE_PMU,
+					IOMUX_SOURCE_PMU,
+					DRV_TYPE_IO_1V8_ONLY,
+					DRV_TYPE_IO_1V8_ONLY,
+					0,
+					0,
DRV_TYPE_IO_DEFAULT instead of 0 please.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help