From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1424057AbdEYNK0 (ORCPT ); Thu, 25 May 2017 09:10:26 -0400 Received: from lucky1.263xmail.com ([211.157.147.132]:52075 "EHLO lucky1.263xmail.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933967AbdEYNJd (ORCPT ); Thu, 25 May 2017 09:09:33 -0400 X-263anti-spam: KSV:0; X-MAIL-GRAY: 1 X-MAIL-DELIVERY: 0 X-KSVirus-check: 0 X-ABS-CHECKED: 4 X-RL-SENDER: david.wu@rock-chips.com X-FST-TO: heiko@sntech.de X-SENDER-IP: 58.22.7.114 X-LOGIN-NAME: david.wu@rock-chips.com X-UNIQUE-TAG: <1d6486b1df82f3d2fe6c66b05c3c9110> X-ATTACHMENT-NUM: 0 X-DNS-TYPE: 0 From: David Wu To: heiko@sntech.de, linus.walleij@linaro.org Cc: huangtao@rock-chips.com, dianders@chromium.org, linux-rockchip@lists.infradead.org, linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, David Wu Subject: [PATCH 1/4] pinctrl: rockchip: Add iomux-route switching support Date: Thu, 25 May 2017 21:12:29 +0800 Message-Id: <1495717952-9762-2-git-send-email-david.wu@rock-chips.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1495717952-9762-1-git-send-email-david.wu@rock-chips.com> References: <1495717952-9762-1-git-send-email-david.wu@rock-chips.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 --- 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