[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1495717952-9762-2-git-send-email-david.wu@rock-chips.com>
Date: Thu, 25 May 2017 21:12:29 +0800
From: David Wu <david.wu@...k-chips.com>
To: heiko@...ech.de, linus.walleij@...aro.org
Cc: huangtao@...k-chips.com, dianders@...omium.org,
linux-rockchip@...ts.infradead.org, linux-gpio@...r.kernel.org,
linux-kernel@...r.kernel.org, David Wu <david.wu@...k-chips.com>
Subject: [PATCH 1/4] pinctrl: rockchip: Add iomux-route switching support
On the some rockchip soc, some things like one specific uart can use
multiple pins, but control of that seems to be split. Somewhere between
the pin io-cells and the uart it seems to have some sort of switch to
decide to which pin to actually route the data.
+-------+ +--------+ /- GPIO4_B0 (pinmux 2)
| uart2 | -- | switch | --- GPIO4_C0 (pinmux 2)
+-------+ +--------+ \- GPIO4_C3 (pinmux 2)
(switch selects one of the 3 pins base on the GRF_SOC_CON7[BIT0, BIT1])
The routing switch is determined by one pin of a specific group to be set
to its special pinmux function. If the pinmux setting is wrong for that
pin the ip block won't work correctly anyway.
Signed-off-by: David Wu <david.wu@...k-chips.com>
---
drivers/pinctrl/pinctrl-rockchip.c | 31 ++++++++++++++++++++++++++++++-
1 file changed, 30 insertions(+), 1 deletion(-)
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index f141aa0..f5dd1c3 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -146,6 +146,7 @@ struct rockchip_drv {
* @irq_lock: bus lock for irq chip
* @new_irqs: newly configured irqs which must be muxed as GPIOs in
* irq_bus_sync_unlock()
+ * @route_mask: bits describing the routing pins of per bank
*/
struct rockchip_pin_bank {
void __iomem *reg_base;
@@ -170,6 +171,7 @@ struct rockchip_pin_bank {
u32 toggle_edge_mode;
struct mutex irq_lock;
u32 new_irqs;
+ u32 route_mask;
};
#define PIN_BANK(id, pins, label) \
@@ -316,6 +318,8 @@ struct rockchip_pin_ctrl {
int (*schmitt_calc_reg)(struct rockchip_pin_bank *bank,
int pin_num, struct regmap **regmap,
int *reg, u8 *bit);
+ bool (*iomux_route)(u8 bank_num, int pin, int mux,
+ u32 *reg, u32 *value);
};
struct rockchip_pin_config {
@@ -383,6 +387,22 @@ struct rockchip_mux_recalced_data {
u8 mask;
};
+/**
+ * struct rockchip_mux_recalced_data: represent a pin iomux data.
+ * @bank: bank number.
+ * @pin: index at register or used to calc index.
+ * @func: the min pin.
+ * @route_offset: the max pin.
+ * @route_val: the register offset.
+ */
+struct rockchip_mux_route_data {
+ u8 bank;
+ u8 pin;
+ u8 func;
+ u32 route_offset;
+ u32 route_val;
+};
+
static struct regmap_config rockchip_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
@@ -683,7 +703,7 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
struct regmap *regmap;
int reg, ret, mask, mux_type;
u8 bit;
- u32 data, rmask;
+ u32 data, rmask, route_reg, route_val;
ret = rockchip_verify_mux(bank, pin, mux);
if (ret < 0)
@@ -719,6 +739,15 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
if (ctrl->iomux_recalc && (mux_type & IOMUX_RECALCED))
ctrl->iomux_recalc(bank->bank_num, pin, ®, &bit, &mask);
+ if (ctrl->iomux_route && (bank->route_mask & BIT(pin))) {
+ if (ctrl->iomux_route(bank->bank_num, pin, mux,
+ &route_reg, &route_val)) {
+ ret = regmap_write(regmap, route_reg, route_val);
+ if (ret)
+ return ret;
+ }
+ }
+
data = (mask << (bit + 16));
rmask = data | (data >> 16);
data |= (mux & mask) << bit;
--
1.9.1
Powered by blists - more mailing lists