From nobody Thu Dec 18 06:14:43 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9558FC433EF for ; Wed, 22 Jun 2022 13:24:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243556AbiFVNYL (ORCPT ); Wed, 22 Jun 2022 09:24:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44022 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1355672AbiFVNXN (ORCPT ); Wed, 22 Jun 2022 09:23:13 -0400 Received: from maillog.nuvoton.com (maillog.nuvoton.com [202.39.227.15]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 9FBB227B01; Wed, 22 Jun 2022 06:23:09 -0700 (PDT) Received: from NTHCCAS01.nuvoton.com (NTHCCAS01.nuvoton.com [10.1.8.28]) by maillog.nuvoton.com (Postfix) with ESMTP id 7C8BC1C811EA; Wed, 22 Jun 2022 21:23:06 +0800 (CST) Received: from NTHCCAS01.nuvoton.com (10.1.8.28) by NTHCCAS01.nuvoton.com (10.1.8.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.7; Wed, 22 Jun 2022 21:23:06 +0800 Received: from taln60.nuvoton.co.il (10.191.1.180) by NTHCCAS01.nuvoton.com (10.1.12.25) with Microsoft SMTP Server id 15.1.2375.7 via Frontend Transport; Wed, 22 Jun 2022 21:23:05 +0800 Received: by taln60.nuvoton.co.il (Postfix, from userid 10070) id 4752163A4D; Wed, 22 Jun 2022 16:23:04 +0300 (IDT) From: Tomer Maimon To: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , CC: , , , , , , Tomer Maimon Subject: [PATCH v5 11/18] reset: npcm: Add NPCM8XX support Date: Wed, 22 Jun 2022 16:22:55 +0300 Message-ID: <20220622132302.267010-12-tmaimon77@gmail.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20220622132302.267010-1-tmaimon77@gmail.com> References: <20220622132302.267010-1-tmaimon77@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Updated the NPCM reset driver to add support for Nuvoton BMC NPCM8XX SoC. As part of adding NPCM8XX support - Add NPCM8XX specific compatible string. - Add NPCM8XX USB reset. - Add data to handle architecture-specific reset parameters. - Some of the Reset Id and number of resets are different from NPCM7XX. Signed-off-by: Tomer Maimon --- drivers/reset/reset-npcm.c | 205 +++++++++++++++++++++++++++++++------ 1 file changed, 172 insertions(+), 33 deletions(-) diff --git a/drivers/reset/reset-npcm.c b/drivers/reset/reset-npcm.c index 431ff2b602c5..e4801f2950fd 100644 --- a/drivers/reset/reset-npcm.c +++ b/drivers/reset/reset-npcm.c @@ -17,13 +17,20 @@ =20 /* NPCM7xx GCR registers */ #define NPCM_MDLR_OFFSET 0x7C -#define NPCM_MDLR_USBD0 BIT(9) -#define NPCM_MDLR_USBD1 BIT(8) -#define NPCM_MDLR_USBD2_4 BIT(21) -#define NPCM_MDLR_USBD5_9 BIT(22) +#define NPCM7XX_MDLR_USBD0 BIT(9) +#define NPCM7XX_MDLR_USBD1 BIT(8) +#define NPCM7XX_MDLR_USBD2_4 BIT(21) +#define NPCM7XX_MDLR_USBD5_9 BIT(22) + +/* NPCM8xx MDLR bits */ +#define NPCM8XX_MDLR_USBD0_3 BIT(9) +#define NPCM8XX_MDLR_USBD4_7 BIT(22) +#define NPCM8XX_MDLR_USBD8 BIT(24) +#define NPCM8XX_MDLR_USBD9 BIT(21) =20 #define NPCM_USB1PHYCTL_OFFSET 0x140 #define NPCM_USB2PHYCTL_OFFSET 0x144 +#define NPCM_USB3PHYCTL_OFFSET 0x148 #define NPCM_USBXPHYCTL_RS BIT(28) =20 /* NPCM7xx Reset registers */ @@ -49,12 +56,38 @@ #define NPCM_IPSRST3_USBPHY1 BIT(24) #define NPCM_IPSRST3_USBPHY2 BIT(25) =20 +#define NPCM_IPSRST4 0x74 +#define NPCM_IPSRST4_USBPHY3 BIT(25) +#define NPCM_IPSRST4_USB_HOST2 BIT(31) + #define NPCM_RC_RESETS_PER_REG 32 #define NPCM_MASK_RESETS GENMASK(4, 0) =20 +enum { + BMC_NPCM7XX =3D 0, + BMC_NPCM8XX, +}; + +static const u32 npxm7xx_ipsrst[] =3D {NPCM_IPSRST1, NPCM_IPSRST2, NPCM_IP= SRST3}; +static const u32 npxm8xx_ipsrst[] =3D {NPCM_IPSRST1, NPCM_IPSRST2, NPCM_IP= SRST3, + NPCM_IPSRST4}; + +struct npcm_reset_info { + u32 bmc_id; + u32 num_ipsrst; + const u32 *ipsrst; +}; + +static const struct npcm_reset_info npxm7xx_reset_info[] =3D { + {.bmc_id =3D BMC_NPCM7XX, .num_ipsrst =3D 3, .ipsrst =3D npxm7xx_ipsrst}}; +static const struct npcm_reset_info npxm8xx_reset_info[] =3D { + {.bmc_id =3D BMC_NPCM8XX, .num_ipsrst =3D 4, .ipsrst =3D npxm8xx_ipsrst}}; + struct npcm_rc_data { struct reset_controller_dev rcdev; struct notifier_block restart_nb; + const struct npcm_reset_info *info; + struct regmap *gcr_regmap; u32 sw_reset_number; void __iomem *base; spinlock_t lock; @@ -120,14 +153,24 @@ static int npcm_rc_status(struct reset_controller_dev= *rcdev, static int npcm_reset_xlate(struct reset_controller_dev *rcdev, const struct of_phandle_args *reset_spec) { + struct npcm_rc_data *rc =3D to_rc_data(rcdev); unsigned int offset, bit; + bool offset_found =3D false; + int off_num; =20 offset =3D reset_spec->args[0]; - if (offset !=3D NPCM_IPSRST1 && offset !=3D NPCM_IPSRST2 && - offset !=3D NPCM_IPSRST3) { + for (off_num =3D 0 ; off_num < rc->info->num_ipsrst ; off_num++) { + if (offset =3D=3D rc->info->ipsrst[off_num]) { + offset_found =3D true; + break; + } + } + + if (!offset_found) { dev_err(rcdev->dev, "Error reset register (0x%x)\n", offset); return -EINVAL; } + bit =3D reset_spec->args[1]; if (bit >=3D NPCM_RC_RESETS_PER_REG) { dev_err(rcdev->dev, "Error reset number (%d)\n", bit); @@ -138,44 +181,29 @@ static int npcm_reset_xlate(struct reset_controller_d= ev *rcdev, } =20 static const struct of_device_id npcm_rc_match[] =3D { - { .compatible =3D "nuvoton,npcm750-reset"}, + { .compatible =3D "nuvoton,npcm750-reset", .data =3D &npxm7xx_reset_info}, + { .compatible =3D "nuvoton,npcm845-reset", .data =3D &npxm8xx_reset_info}, { } }; =20 -/* - * The following procedure should be observed in USB PHY, USB device and - * USB host initialization at BMC boot - */ -static int npcm_usb_reset(struct platform_device *pdev, struct npcm_rc_dat= a *rc) +static void npcm_usb_reset_npcm7xx(struct npcm_rc_data *rc) { u32 mdlr, iprst1, iprst2, iprst3; - struct device *dev =3D &pdev->dev; - struct regmap *gcr_regmap; u32 ipsrst1_bits =3D 0; u32 ipsrst2_bits =3D NPCM_IPSRST2_USB_HOST; u32 ipsrst3_bits =3D 0; =20 - gcr_regmap =3D syscon_regmap_lookup_by_phandle(dev->of_node, "nuvoton,sys= gcr"); - if (IS_ERR(gcr_regmap)) { - dev_warn(&pdev->dev, "Failed to find nuvoton,sysgcr search for nuvoton,n= pcm750-gcr for Poleg backward compatibility"); - gcr_regmap =3D syscon_regmap_lookup_by_compatible("nuvoton,npcm750-gcr"); - if (IS_ERR(gcr_regmap)) { - dev_err(&pdev->dev, "Failed to find nuvoton,npcm750-gcr"); - return PTR_ERR(gcr_regmap); - } - } - /* checking which USB device is enabled */ - regmap_read(gcr_regmap, NPCM_MDLR_OFFSET, &mdlr); - if (!(mdlr & NPCM_MDLR_USBD0)) + regmap_read(rc->gcr_regmap, NPCM_MDLR_OFFSET, &mdlr); + if (!(mdlr & NPCM7XX_MDLR_USBD0)) ipsrst3_bits |=3D NPCM_IPSRST3_USBD0; - if (!(mdlr & NPCM_MDLR_USBD1)) + if (!(mdlr & NPCM7XX_MDLR_USBD1)) ipsrst1_bits |=3D NPCM_IPSRST1_USBD1; - if (!(mdlr & NPCM_MDLR_USBD2_4)) + if (!(mdlr & NPCM7XX_MDLR_USBD2_4)) ipsrst1_bits |=3D (NPCM_IPSRST1_USBD2 | NPCM_IPSRST1_USBD3 | NPCM_IPSRST1_USBD4); - if (!(mdlr & NPCM_MDLR_USBD0)) { + if (!(mdlr & NPCM7XX_MDLR_USBD0)) { ipsrst1_bits |=3D (NPCM_IPSRST1_USBD5 | NPCM_IPSRST1_USBD6); ipsrst3_bits |=3D (NPCM_IPSRST3_USBD7 | @@ -198,9 +226,9 @@ static int npcm_usb_reset(struct platform_device *pdev,= struct npcm_rc_data *rc) writel(iprst3, rc->base + NPCM_IPSRST3); =20 /* clear USB PHY RS bit */ - regmap_update_bits(gcr_regmap, NPCM_USB1PHYCTL_OFFSET, + regmap_update_bits(rc->gcr_regmap, NPCM_USB1PHYCTL_OFFSET, NPCM_USBXPHYCTL_RS, 0); - regmap_update_bits(gcr_regmap, NPCM_USB2PHYCTL_OFFSET, + regmap_update_bits(rc->gcr_regmap, NPCM_USB2PHYCTL_OFFSET, NPCM_USBXPHYCTL_RS, 0); =20 /* deassert reset USB PHY */ @@ -210,19 +238,130 @@ static int npcm_usb_reset(struct platform_device *pd= ev, struct npcm_rc_data *rc) udelay(50); =20 /* set USB PHY RS bit */ - regmap_update_bits(gcr_regmap, NPCM_USB1PHYCTL_OFFSET, + regmap_update_bits(rc->gcr_regmap, NPCM_USB1PHYCTL_OFFSET, + NPCM_USBXPHYCTL_RS, NPCM_USBXPHYCTL_RS); + regmap_update_bits(rc->gcr_regmap, NPCM_USB2PHYCTL_OFFSET, + NPCM_USBXPHYCTL_RS, NPCM_USBXPHYCTL_RS); + + /* deassert reset USB devices*/ + iprst1 &=3D ~ipsrst1_bits; + iprst2 &=3D ~ipsrst2_bits; + iprst3 &=3D ~ipsrst3_bits; + + writel(iprst1, rc->base + NPCM_IPSRST1); + writel(iprst2, rc->base + NPCM_IPSRST2); + writel(iprst3, rc->base + NPCM_IPSRST3); +} + +static void npcm_usb_reset_npcm8xx(struct npcm_rc_data *rc) +{ + u32 mdlr, iprst1, iprst2, iprst3, iprst4; + u32 ipsrst1_bits =3D 0; + u32 ipsrst2_bits =3D NPCM_IPSRST2_USB_HOST; + u32 ipsrst3_bits =3D 0; + u32 ipsrst4_bits =3D NPCM_IPSRST4_USB_HOST2 | NPCM_IPSRST4_USBPHY3; + + /* checking which USB device is enabled */ + regmap_read(rc->gcr_regmap, NPCM_MDLR_OFFSET, &mdlr); + if (!(mdlr & NPCM8XX_MDLR_USBD0_3)) { + ipsrst3_bits |=3D NPCM_IPSRST3_USBD0; + ipsrst1_bits |=3D (NPCM_IPSRST1_USBD1 | + NPCM_IPSRST1_USBD2 | + NPCM_IPSRST1_USBD3); + } + if (!(mdlr & NPCM8XX_MDLR_USBD4_7)) { + ipsrst1_bits |=3D (NPCM_IPSRST1_USBD4 | + NPCM_IPSRST1_USBD5 | + NPCM_IPSRST1_USBD6); + ipsrst3_bits |=3D NPCM_IPSRST3_USBD7; + } + + if (!(mdlr & NPCM8XX_MDLR_USBD8)) + ipsrst3_bits |=3D NPCM_IPSRST3_USBD8; + if (!(mdlr & NPCM8XX_MDLR_USBD9)) + ipsrst3_bits |=3D NPCM_IPSRST3_USBD9; + + /* assert reset USB PHY and USB devices */ + iprst1 =3D readl(rc->base + NPCM_IPSRST1); + iprst2 =3D readl(rc->base + NPCM_IPSRST2); + iprst3 =3D readl(rc->base + NPCM_IPSRST3); + iprst4 =3D readl(rc->base + NPCM_IPSRST4); + + iprst1 |=3D ipsrst1_bits; + iprst2 |=3D ipsrst2_bits; + iprst3 |=3D (ipsrst3_bits | NPCM_IPSRST3_USBPHY1 | + NPCM_IPSRST3_USBPHY2); + iprst2 |=3D ipsrst4_bits; + + writel(iprst1, rc->base + NPCM_IPSRST1); + writel(iprst2, rc->base + NPCM_IPSRST2); + writel(iprst3, rc->base + NPCM_IPSRST3); + writel(iprst4, rc->base + NPCM_IPSRST4); + + /* clear USB PHY RS bit */ + regmap_update_bits(rc->gcr_regmap, NPCM_USB1PHYCTL_OFFSET, + NPCM_USBXPHYCTL_RS, 0); + regmap_update_bits(rc->gcr_regmap, NPCM_USB2PHYCTL_OFFSET, + NPCM_USBXPHYCTL_RS, 0); + regmap_update_bits(rc->gcr_regmap, NPCM_USB3PHYCTL_OFFSET, + NPCM_USBXPHYCTL_RS, 0); + + /* deassert reset USB PHY */ + iprst3 &=3D ~(NPCM_IPSRST3_USBPHY1 | NPCM_IPSRST3_USBPHY2); + writel(iprst3, rc->base + NPCM_IPSRST3); + iprst4 &=3D ~NPCM_IPSRST4_USBPHY3; + writel(iprst4, rc->base + NPCM_IPSRST4); + + /* set USB PHY RS bit */ + regmap_update_bits(rc->gcr_regmap, NPCM_USB1PHYCTL_OFFSET, NPCM_USBXPHYCTL_RS, NPCM_USBXPHYCTL_RS); - regmap_update_bits(gcr_regmap, NPCM_USB2PHYCTL_OFFSET, + regmap_update_bits(rc->gcr_regmap, NPCM_USB2PHYCTL_OFFSET, + NPCM_USBXPHYCTL_RS, NPCM_USBXPHYCTL_RS); + regmap_update_bits(rc->gcr_regmap, NPCM_USB3PHYCTL_OFFSET, NPCM_USBXPHYCTL_RS, NPCM_USBXPHYCTL_RS); =20 /* deassert reset USB devices*/ iprst1 &=3D ~ipsrst1_bits; iprst2 &=3D ~ipsrst2_bits; iprst3 &=3D ~ipsrst3_bits; + iprst4 &=3D ~ipsrst4_bits; =20 writel(iprst1, rc->base + NPCM_IPSRST1); writel(iprst2, rc->base + NPCM_IPSRST2); writel(iprst3, rc->base + NPCM_IPSRST3); + writel(iprst4, rc->base + NPCM_IPSRST4); +} + +/* + * The following procedure should be observed in USB PHY, USB device and + * USB host initialization at BMC boot + */ +static int npcm_usb_reset(struct platform_device *pdev, struct npcm_rc_dat= a *rc) +{ + struct device *dev =3D &pdev->dev; + + rc->gcr_regmap =3D syscon_regmap_lookup_by_phandle(dev->of_node, "nuvoton= ,sysgcr"); + if (IS_ERR(rc->gcr_regmap)) { + dev_warn(&pdev->dev, "Failed to find nuvoton,sysgcr search for nuvoton,n= pcm750-gcr for Poleg backward compatibility"); + rc->gcr_regmap =3D syscon_regmap_lookup_by_compatible("nuvoton,npcm750-g= cr"); + if (IS_ERR(rc->gcr_regmap)) { + dev_err(&pdev->dev, "Failed to find nuvoton,npcm750-gcr"); + return PTR_ERR(rc->gcr_regmap); + } + } + + rc->info =3D (const struct npcm_reset_info *) + of_match_device(dev->driver->of_match_table, dev)->data; + switch (rc->info->bmc_id) { + case BMC_NPCM7XX: + npcm_usb_reset_npcm7xx(rc); + break; + case BMC_NPCM8XX: + npcm_usb_reset_npcm8xx(rc); + break; + default: + return -ENODEV; + } =20 return 0; } --=20 2.33.0