From patchwork Thu Mar 10 04:31:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sam Shih X-Patchwork-Id: 1603665 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4KDbmk0FBQz9sGD for ; Thu, 10 Mar 2022 15:33:57 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id B4B35839D7; Thu, 10 Mar 2022 05:33:27 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=fail (p=quarantine dis=none) header.from=mediatek.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by phobos.denx.de (Postfix, from userid 109) id 869C0839CB; Thu, 10 Mar 2022 05:33:12 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RDNS_NONE, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE,UNPARSEABLE_RELAY autolearn=no autolearn_force=no version=3.4.2 Received: from mailgw01.mediatek.com (unknown [60.244.123.138]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 72590839C9 for ; Thu, 10 Mar 2022 05:33:01 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sam.shih@mediatek.com X-UUID: 4d51b11db2d049ca8e54564b2c456c73-20220310 X-UUID: 4d51b11db2d049ca8e54564b2c456c73-20220310 Received: from mtkmbs10n2.mediatek.inc [(172.21.101.183)] by mailgw01.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 924164767; Thu, 10 Mar 2022 12:32:08 +0800 Received: from mtkexhb01.mediatek.inc (172.21.101.102) by mtkmbs10n1.mediatek.inc (172.21.101.34) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.2.792.15; Thu, 10 Mar 2022 12:32:07 +0800 Received: from mtkcas11.mediatek.inc (172.21.101.40) by mtkexhb01.mediatek.inc (172.21.101.102) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Thu, 10 Mar 2022 12:32:06 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkcas11.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Thu, 10 Mar 2022 12:32:06 +0800 From: Sam Shih To: Tom Rini , Ryder Lee , "Weijie Gao" , Chunfeng Yun , GSS_MTK_Uboot_upstream , CC: Sam Shih Subject: [2/3] pinctrl: mediatek: introduce multiple memory bases support Date: Thu, 10 Mar 2022 12:31:44 +0800 Message-ID: <20220310043145.7690-3-sam.shih@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20220310043145.7690-1-sam.shih@mediatek.com> References: <20220310043145.7690-1-sam.shih@mediatek.com> MIME-Version: 1.0 X-MTK: N X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.5 at phobos.denx.de X-Virus-Status: Clean Pinctrl design of some mediatek SoC need to access registers that distribute in multiple memory base address. this patch introduce new mechanism in mediatek pinctrl driver to support the chips which have the new design. This patch add a member 'base_calc' in pinctrl private data, and changed original 'base' private data to an array of *iomem. When 'base_calc' attribute is set, it will requests multiplue regs base from the DT, if 'base_calc' attribute is not set, it only use legacy way to request single reg resource from the DT. Signed-off-by: Sam Shih --- drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 52 ++++++++++++------- drivers/pinctrl/mediatek/pinctrl-mtk-common.h | 23 ++++++-- 2 files changed, 53 insertions(+), 22 deletions(-) diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c index 4ae328699e..623c5e103c 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c @@ -45,18 +45,18 @@ static const struct mtk_drive_desc mtk_drive[] = { static const char *mtk_pinctrl_dummy_name = "_dummy"; -static void mtk_w32(struct udevice *dev, u32 reg, u32 val) +static void mtk_w32(struct udevice *dev, u8 i, u32 reg, u32 val) { struct mtk_pinctrl_priv *priv = dev_get_priv(dev); - __raw_writel(val, priv->base + reg); + __raw_writel(val, priv->base[i] + reg); } -static u32 mtk_r32(struct udevice *dev, u32 reg) +static u32 mtk_r32(struct udevice *dev, u8 i, u32 reg) { struct mtk_pinctrl_priv *priv = dev_get_priv(dev); - return __raw_readl(priv->base + reg); + return __raw_readl(priv->base[i] + reg); } static inline int get_count_order(unsigned int count) @@ -69,22 +69,24 @@ static inline int get_count_order(unsigned int count) return order; } -void mtk_rmw(struct udevice *dev, u32 reg, u32 mask, u32 set) +void mtk_rmw(struct udevice *dev, u8 i, u32 reg, u32 mask, u32 set) { u32 val; - val = mtk_r32(dev, reg); + val = mtk_r32(dev, i, reg); val &= ~mask; val |= set; - mtk_w32(dev, reg, val); + mtk_w32(dev, i, reg, val); } static int mtk_hw_pin_field_lookup(struct udevice *dev, int pin, const struct mtk_pin_reg_calc *rc, struct mtk_pin_field *pfd) { + struct mtk_pinctrl_priv *priv = dev_get_priv(dev); const struct mtk_pin_field_calc *c, *e; u32 bits; + u32 base_calc = priv->soc->base_calc; c = rc->range; e = c + rc->nranges; @@ -111,6 +113,11 @@ static int mtk_hw_pin_field_lookup(struct udevice *dev, int pin, pfd->bitpos = bits % c->sz_reg; pfd->mask = (1 << c->x_bits) - 1; + if (base_calc) + pfd->index = c->i_base; + else + pfd->index = 0; + /* pfd->next is used for indicating that bit wrapping-around happens * which requires the manipulation for bit 0 starting in the next * register to form the complete field read/write. @@ -150,10 +157,10 @@ static void mtk_hw_write_cross_field(struct udevice *dev, mtk_hw_bits_part(pf, &nbits_h, &nbits_l); - mtk_rmw(dev, pf->offset, pf->mask << pf->bitpos, + mtk_rmw(dev, pf->index, pf->offset, pf->mask << pf->bitpos, (value & pf->mask) << pf->bitpos); - mtk_rmw(dev, pf->offset + pf->next, BIT(nbits_h) - 1, + mtk_rmw(dev, pf->index, pf->offset + pf->next, BIT(nbits_h) - 1, (value & pf->mask) >> nbits_l); } @@ -164,8 +171,8 @@ static void mtk_hw_read_cross_field(struct udevice *dev, mtk_hw_bits_part(pf, &nbits_h, &nbits_l); - l = (mtk_r32(dev, pf->offset) >> pf->bitpos) & (BIT(nbits_l) - 1); - h = (mtk_r32(dev, pf->offset + pf->next)) & (BIT(nbits_h) - 1); + l = (mtk_r32(dev, pf->index, pf->offset) >> pf->bitpos) & (BIT(nbits_l) - 1); + h = (mtk_r32(dev, pf->index, pf->offset + pf->next)) & (BIT(nbits_h) - 1); *value = (h << nbits_l) | l; } @@ -181,7 +188,7 @@ static int mtk_hw_set_value(struct udevice *dev, int pin, int field, return err; if (!pf.next) - mtk_rmw(dev, pf.offset, pf.mask << pf.bitpos, + mtk_rmw(dev, pf.index, pf.offset, pf.mask << pf.bitpos, (value & pf.mask) << pf.bitpos); else mtk_hw_write_cross_field(dev, &pf, value); @@ -200,7 +207,7 @@ static int mtk_hw_get_value(struct udevice *dev, int pin, int field, return err; if (!pf.next) - *value = (mtk_r32(dev, pf.offset) >> pf.bitpos) & pf.mask; + *value = (mtk_r32(dev, pf.index, pf.offset) >> pf.bitpos) & pf.mask; else mtk_hw_read_cross_field(dev, &pf, value); @@ -236,7 +243,6 @@ static int mtk_get_pin_muxing(struct udevice *dev, unsigned int selector, char *buf, int size) { int val, err; - err = mtk_hw_get_value(dev, selector, PINCTRL_PIN_REG_MODE, &val); if (err) return err; @@ -722,13 +728,23 @@ int mtk_pinctrl_common_probe(struct udevice *dev, { struct mtk_pinctrl_priv *priv = dev_get_priv(dev); int ret = 0; - - priv->base = dev_read_addr_ptr(dev); - if (!priv->base) - return -EINVAL; + u32 i = 0; + fdt_addr_t addr; + u32 base_calc = soc->base_calc; + u32 nbase_names = soc->nbase_names; priv->soc = soc; + if (!base_calc) + nbase_names = 1; + + for (i = 0; i < nbase_names; i++) { + addr = devfdt_get_addr_index(dev, i); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + priv->base[i] = (void __iomem *)addr; + } + #if CONFIG_IS_ENABLED(DM_GPIO) || \ (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_GPIO)) ret = mtk_gpiochip_register(dev); --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h @@ -8,6 +8,8 @@ #define MTK_PINCTRL_V0 0x0 #define MTK_PINCTRL_V1 0x1 +#define BASE_CALC_NONE 0 +#define MAX_BASE_CALC 10 #define MTK_RANGE(_a) { .range = (_a), .nranges = ARRAY_SIZE(_a), } #define MTK_PIN(_number, _name, _drv_n) { \ @@ -24,10 +26,11 @@ id##_funcs, \ } -#define PIN_FIELD_CALC(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, \ - _x_bits, _sz_reg, _fixed) { \ +#define PIN_FIELD_BASE_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, \ + _s_bit, _x_bits, _sz_reg, _fixed) { \ .s_pin = _s_pin, \ .e_pin = _e_pin, \ + .i_base = _i_base, \ .s_addr = _s_addr, \ .x_addrs = _x_addrs, \ .s_bit = _s_bit, \ @@ -36,6 +39,11 @@ .fixed = _fixed, \ } +#define PIN_FIELD_CALC(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, \ + _x_bits, _sz_reg, _fixed) \ + PIN_FIELD_BASE_CALC(_s_pin, _e_pin, BASE_CALC_NONE, _s_addr, \ + _x_addrs, _s_bit, _x_bits, _sz_reg, _fixed) + /* List these attributes which could be modified for the pin */ enum { PINCTRL_PIN_REG_MODE, @@ -70,6 +78,7 @@ enum { /** * struct mtk_pin_field - the structure that holds the information of the field * used to describe the attribute for the pin + * @index: the index pointing to the entry in base address list * @offset: the register offset relative to the base address * @mask: the mask used to filter out the field from the register * @bitpos: the start bit relative to the register @@ -77,6 +86,7 @@ enum { next register */ struct mtk_pin_field { + u8 index; u32 offset; u32 mask; u8 bitpos; @@ -88,6 +98,7 @@ struct mtk_pin_field { * the guide used to look up the relevant field * @s_pin: the start pin within the range * @e_pin: the end pin within the range + * @i_base: the index pointing to the entry in base address list * @s_addr: the start address for the range * @x_addrs: the address distance between two consecutive registers * within the range @@ -101,6 +112,7 @@ struct mtk_pin_field { struct mtk_pin_field_calc { u16 s_pin; u16 e_pin; + u8 i_base; u32 s_addr; u8 x_addrs; u8 s_bit; @@ -171,7 +183,10 @@ struct mtk_pinctrl_soc { const struct mtk_function_desc *funcs; int nfuncs; int gpio_mode; + const char * const *base_names; + unsigned int nbase_names; int rev; + int base_calc; }; /** @@ -181,14 +196,14 @@ struct mtk_pinctrl_soc { * @soc: SoC specific data */ struct mtk_pinctrl_priv { - void __iomem *base; + void __iomem *base[MAX_BASE_CALC]; struct mtk_pinctrl_soc *soc; }; extern const struct pinctrl_ops mtk_pinctrl_ops; /* A common read-modify-write helper for MediaTek chips */ -void mtk_rmw(struct udevice *dev, u32 reg, u32 mask, u32 set); +void mtk_rmw(struct udevice *dev, u8 i, u32 reg, u32 mask, u32 set); int mtk_pinctrl_common_probe(struct udevice *dev, struct mtk_pinctrl_soc *soc);