Message ID | 20220422170920.401914-1-sebastian.reichel@collabora.com |
---|---|
Headers | show |
Series | Basic RK3588 Support | expand |
On 22/04/2022 19:09, Sebastian Reichel wrote: > From: Elaine Zhang <zhangqing@rock-chips.com> > > Document the device tree bindings of the rockchip Rk3588 SoC > clock driver. > > Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com> > Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com> > --- > .../bindings/clock/rockchip,rk3588-cru.yaml | 63 +++++++++++++++++++ > 1 file changed, 63 insertions(+) > create mode 100644 Documentation/devicetree/bindings/clock/rockchip,rk3588-cru.yaml > > diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3588-cru.yaml b/Documentation/devicetree/bindings/clock/rockchip,rk3588-cru.yaml > new file mode 100644 > index 000000000000..dec2ae8c7970 > --- /dev/null > +++ b/Documentation/devicetree/bindings/clock/rockchip,rk3588-cru.yaml > @@ -0,0 +1,63 @@ > +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/clock/rockchip,rk3588-cru.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: ROCKCHIP rk3588 Family Clock Control Module Binding s/ROCKCHIP/Rockchip/ (that's the most common name used here and also on company website) s/Binding// > + > +maintainers: > + - Elaine Zhang <zhangqing@rock-chips.com> > + - Heiko Stuebner <heiko@sntech.de> > + > +description: | > + The RK3588 clock controller generates the clock and also implements a > + reset controller for SoC peripherals. > + (examples: provide SCLK_UART2\PCLK_UART2 and SRST_P_UART2\SRST_S_UART2 for UART module) > + Each clock is assigned an identifier and client nodes can use this identifier > + to specify the clock which they consume. All available clocks are defined as > + preprocessor macros in the dt-bindings/clock/rk3588-cru.h headers and can be > + used in device tree sources. > + > +properties: > + compatible: > + enum: > + - rockchip,rk3588-cru > + > + reg: > + maxItems: 1 > + > + "#clock-cells": > + const: 1 > + > + "#reset-cells": > + const: 1 > + > + clocks: true Need to define how many and what clocks are coming here. > + > + assigned-clocks: > + minItems: 1 > + > + assigned-clock-parents: > + minItems: 1 > + > + assigned-clock-rates: > + minItems: 1 You normally don't need these in the bindings, they come from the schema. > + > +required: > + - compatible > + - reg > + - "#clock-cells" > + - "#reset-cells" > + > +additionalProperties: false > + > +examples: > + # Clock Control Module node: > + - | > + cru: clock-controller@fd7c0000 { > + compatible = "rockchip,rk3588-cru"; > + reg = <0xfd7c0000 0x5c000>; > + #clock-cells = <1>; > + #reset-cells = <1>; > + }; Best regards, Krzysztof
On 22/04/2022 19:09, Sebastian Reichel wrote: > Add compatible value for the Rockchip rk3588 dwcmshc controller. > > Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com> Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> Best regards, Krzysztof
On 22/04/2022 19:09, Sebastian Reichel wrote: > Add compatible string for rk3588 pin controller. No other changes > are required, since the new controller can use the old binding. > > Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com> Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> Best regards, Krzysztof
On 22/04/2022 19:09, Sebastian Reichel wrote: > From: Kever Yang <kever.yang@rock-chips.com> > > Add board file for the RK3588 evaluation board. While the hardware > offers plenty of peripherals and connectivity this basic implementation > just handles things required to successfully boot Linux from eMMC > and connect via UART. > > Signed-off-by: Kever Yang <kever.yang@rock-chips.com> > [rebase, update commit message, use EVB1 for SoC bringup] > Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com> > --- > .../devicetree/bindings/arm/rockchip.yaml | 5 +++ > arch/arm64/boot/dts/rockchip/Makefile | 1 + > .../boot/dts/rockchip/rk3588-evb1-v10.dts | 34 +++++++++++++++++++ > 3 files changed, 40 insertions(+) > create mode 100644 arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts > > diff --git a/Documentation/devicetree/bindings/arm/rockchip.yaml b/Documentation/devicetree/bindings/arm/rockchip.yaml > index eece92f83a2d..b14d0c84c69b 100644 > --- a/Documentation/devicetree/bindings/arm/rockchip.yaml > +++ b/Documentation/devicetree/bindings/arm/rockchip.yaml > @@ -664,6 +664,11 @@ properties: > - const: rockchip,rk3568-bpi-r2pro > - const: rockchip,rk3568 > > + - description: Rockchip RK3588 Evaluation board > + items: > + - const: rockchip,rk3588-evb1-v10 > + - const: rockchip,rk3588 > + > additionalProperties: true > > ... > diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile > index 4ae9f35434b8..8a53ab6d37a1 100644 > --- a/arch/arm64/boot/dts/rockchip/Makefile > +++ b/arch/arm64/boot/dts/rockchip/Makefile > @@ -61,3 +61,4 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-pinenote-v1.2.dtb > dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-quartz64-a.dtb > dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-v10.dtb > dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-bpi-r2-pro.dtb > +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb1-v10.dtb > diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts > new file mode 100644 > index 000000000000..68b19acb1550 > --- /dev/null > +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts > @@ -0,0 +1,34 @@ > +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) > +/* > + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. > + * > + */ > + > +/dts-v1/; > + > +#include "rk3588.dtsi" > + > +/ { > + model = "Rockchip RK3588 EVB1 V10 Board"; > + compatible = "rockchip,rk3588-evb1-v10", "rockchip,rk3588"; > + > + chosen { > + stdout-path = "serial2:1500000n8"; > + }; > +}; > + > +&sdhci { > + bus-width = <8>; > + no-sdio; > + no-sd; > + non-removable; > + max-frequency = <200000000>; > + mmc-hs400-1_8v; > + mmc-hs400-enhanced-strobe; > + status = "ok"; > +}; > + > +&uart2 { > + status = "ok"; Usually status goes at the end of properties and rockchip sources use "okay" instead of "ok". It's a nit, so in any case: Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> Best regards, Krzysztof
On Sat, Apr 23, 2022 at 12:09:21PM +0200, Krzysztof Kozlowski wrote: > On 22/04/2022 19:09, Sebastian Reichel wrote: > > From: Kever Yang <kever.yang@rock-chips.com> > > > > Add board file for the RK3588 evaluation board. While the hardware > > offers plenty of peripherals and connectivity this basic implementation > > just handles things required to successfully boot Linux from eMMC > > and connect via UART. > > > > Signed-off-by: Kever Yang <kever.yang@rock-chips.com> > > [rebase, update commit message, use EVB1 for SoC bringup] > > Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com> > > --- > > .../devicetree/bindings/arm/rockchip.yaml | 5 +++ > > arch/arm64/boot/dts/rockchip/Makefile | 1 + > > .../boot/dts/rockchip/rk3588-evb1-v10.dts | 34 +++++++++++++++++++ > > 3 files changed, 40 insertions(+) > > create mode 100644 arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts > > > > diff --git a/Documentation/devicetree/bindings/arm/rockchip.yaml b/Documentation/devicetree/bindings/arm/rockchip.yaml > > index eece92f83a2d..b14d0c84c69b 100644 > > --- a/Documentation/devicetree/bindings/arm/rockchip.yaml > > +++ b/Documentation/devicetree/bindings/arm/rockchip.yaml > > @@ -664,6 +664,11 @@ properties: > > - const: rockchip,rk3568-bpi-r2pro > > - const: rockchip,rk3568 > > > > + - description: Rockchip RK3588 Evaluation board > > + items: > > + - const: rockchip,rk3588-evb1-v10 > > + - const: rockchip,rk3588 > > + > > additionalProperties: true > > > > ... > > diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile > > index 4ae9f35434b8..8a53ab6d37a1 100644 > > --- a/arch/arm64/boot/dts/rockchip/Makefile > > +++ b/arch/arm64/boot/dts/rockchip/Makefile > > @@ -61,3 +61,4 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-pinenote-v1.2.dtb > > dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-quartz64-a.dtb > > dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-v10.dtb > > dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-bpi-r2-pro.dtb > > +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb1-v10.dtb > > diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts > > new file mode 100644 > > index 000000000000..68b19acb1550 > > --- /dev/null > > +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts > > @@ -0,0 +1,34 @@ > > +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) > > +/* > > + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. > > + * > > + */ > > + > > +/dts-v1/; > > + > > +#include "rk3588.dtsi" > > + > > +/ { > > + model = "Rockchip RK3588 EVB1 V10 Board"; > > + compatible = "rockchip,rk3588-evb1-v10", "rockchip,rk3588"; > > + > > + chosen { > > + stdout-path = "serial2:1500000n8"; > > + }; > > +}; > > + > > +&sdhci { > > + bus-width = <8>; > > + no-sdio; > > + no-sd; > > + non-removable; > > + max-frequency = <200000000>; > > + mmc-hs400-1_8v; > > + mmc-hs400-enhanced-strobe; > > + status = "ok"; > > +}; > > + > > +&uart2 { > > + status = "ok"; > > Usually status goes at the end of properties and rockchip sources use > "okay" instead of "ok". "okay" is what's documented in the spec and in the schemas, so please fix. No need for reviewers to tell you this though, please run 'make dtbs_checks' on the dts file and don't add new warnings. Rob
On 22/04/22 20:09, Sebastian Reichel wrote: > From: Yifeng Zhao <yifeng.zhao@rock-chips.com> > > Add support for RK3588's DWCMSHC controller, which is used for > providing the rootfs on the RK3588 evaluation board. > > Signed-off-by: Yifeng Zhao <yifeng.zhao@rock-chips.com> > [port from vendor BSP] > Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com> One comment otherwise: Acked-by: Adrian Hunter <adrian.hunter@intel.com> > --- > drivers/mmc/host/sdhci-of-dwcmshc.c | 113 +++++++++++++++++++++++----- > 1 file changed, 96 insertions(+), 17 deletions(-) > > diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c > index 54ae0268e002..bc365767e66c 100644 > --- a/drivers/mmc/host/sdhci-of-dwcmshc.c > +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c > @@ -31,6 +31,7 @@ > /* Offset inside the vendor area 1 */ > #define DWCMSHC_HOST_CTRL3 0x8 > #define DWCMSHC_EMMC_CONTROL 0x2c > +#define DWCMSHC_CARD_IS_EMMC BIT(0) > #define DWCMSHC_ENHANCED_STROBE BIT(8) > #define DWCMSHC_EMMC_ATCTRL 0x40 > > @@ -39,7 +40,7 @@ > #define DWCMSHC_EMMC_DLL_RXCLK 0x804 > #define DWCMSHC_EMMC_DLL_TXCLK 0x808 > #define DWCMSHC_EMMC_DLL_STRBIN 0x80c > -#define DLL_STRBIN_TAPNUM_FROM_SW BIT(24) > +#define DECMSHC_EMMC_DLL_CMDOUT 0x810 > #define DWCMSHC_EMMC_DLL_STATUS0 0x840 > #define DWCMSHC_EMMC_DLL_START BIT(0) > #define DWCMSHC_EMMC_DLL_LOCKED BIT(8) > @@ -48,11 +49,21 @@ > #define DWCMSHC_EMMC_DLL_START_POINT 16 > #define DWCMSHC_EMMC_DLL_INC 8 > #define DWCMSHC_EMMC_DLL_DLYENA BIT(27) > -#define DLL_TXCLK_TAPNUM_DEFAULT 0x8 > -#define DLL_STRBIN_TAPNUM_DEFAULT 0x8 > +#define DLL_TXCLK_TAPNUM_DEFAULT 0x10 > +#define DLL_TXCLK_TAPNUM_90_DEGREES 0xA > #define DLL_TXCLK_TAPNUM_FROM_SW BIT(24) > +#define DLL_STRBIN_TAPNUM_DEFAULT 0x8 > +#define DLL_STRBIN_TAPNUM_FROM_SW BIT(24) > +#define DLL_STRBIN_DELAY_NUM_SEL BIT(26) > +#define DLL_STRBIN_DELAY_NUM_OFFSET 16 > +#define DLL_STRBIN_DELAY_NUM_DEFAULT 0x16 > #define DLL_RXCLK_NO_INVERTER 1 > #define DLL_RXCLK_INVERTER 0 > +#define DLL_CMDOUT_TAPNUM_90_DEGREES 0x8 > +#define DLL_CMDOUT_TAPNUM_FROM_SW BIT(24) > +#define DLL_CMDOUT_SRC_CLK_NEG BIT(28) > +#define DLL_CMDOUT_EN_SRC_CLK_NEG BIT(29) > + > #define DLL_LOCK_WO_TMOUT(x) \ > ((((x) & DWCMSHC_EMMC_DLL_LOCKED) == DWCMSHC_EMMC_DLL_LOCKED) && \ > (((x) & DWCMSHC_EMMC_DLL_TIMEOUT) == 0)) > @@ -61,10 +72,16 @@ > #define BOUNDARY_OK(addr, len) \ > ((addr | (SZ_128M - 1)) == ((addr + len - 1) | (SZ_128M - 1))) > > +enum dwcmshc_rk_type { > + DWCMSHC_RK3568, > + DWCMSHC_RK3588, > +}; > + > struct rk35xx_priv { > /* Rockchip specified optional clocks */ > struct clk_bulk_data rockchip_clks[RK35xx_MAX_CLKS]; > struct reset_control *reset; > + enum dwcmshc_rk_type devtype; > u8 txclk_tapnum; > }; > > @@ -133,7 +150,9 @@ static void dwcmshc_request(struct mmc_host *mmc, struct mmc_request *mrq) > static void dwcmshc_set_uhs_signaling(struct sdhci_host *host, > unsigned int timing) > { > - u16 ctrl_2; > + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); > + struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); > + u16 ctrl, ctrl_2; > > ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); > /* Select Bus Speed Mode for host */ > @@ -151,8 +170,15 @@ static void dwcmshc_set_uhs_signaling(struct sdhci_host *host, > else if ((timing == MMC_TIMING_UHS_DDR50) || > (timing == MMC_TIMING_MMC_DDR52)) > ctrl_2 |= SDHCI_CTRL_UHS_DDR50; > - else if (timing == MMC_TIMING_MMC_HS400) > + else if (timing == MMC_TIMING_MMC_HS400) { > + /* set CARD_IS_EMMC bit to enable Data Strobe for HS400 */ > + ctrl = sdhci_readw(host, priv->vendor_specific_area1 + DWCMSHC_EMMC_CONTROL); > + ctrl |= DWCMSHC_CARD_IS_EMMC; > + sdhci_writew(host, ctrl, priv->vendor_specific_area1 + DWCMSHC_EMMC_CONTROL); > + > ctrl_2 |= DWCMSHC_CTRL_HS400; > + } > + > sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); > } > > @@ -185,17 +211,11 @@ static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock > > host->mmc->actual_clock = 0; > > - /* > - * DO NOT TOUCH THIS SETTING. RX clk inverter unit is enabled > - * by default, but it shouldn't be enabled. We should anyway > - * disable it before issuing any cmds. > - */ > - extra = DWCMSHC_EMMC_DLL_DLYENA | > - DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL; > - sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK); > - > - if (clock == 0) > + if (clock == 0) { > + /* Disable interface clock at initial state. */ > + sdhci_set_clock(host, clock); > return; > + } > > /* Rockchip platform only support 375KHz for identify mode */ > if (clock <= 400000) > @@ -213,9 +233,21 @@ static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock > extra &= ~BIT(0); > sdhci_writel(host, extra, reg); > > - if (clock <= 400000) { > - /* Disable DLL to reset sample clock */ > + if (clock <= 52000000) { > + /* Disable DLL and reset both of sample and drive clock */ > sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL); > + sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_RXCLK); > + sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK); > + sdhci_writel(host, 0, DECMSHC_EMMC_DLL_CMDOUT); > + /* > + * Before switching to hs400es mode, the driver will enable > + * enhanced strobe first. PHY needs to configure the parameters > + * of enhanced strobe first. > + */ > + extra = DWCMSHC_EMMC_DLL_DLYENA | > + DLL_STRBIN_DELAY_NUM_SEL | > + DLL_STRBIN_DELAY_NUM_DEFAULT << DLL_STRBIN_DELAY_NUM_OFFSET; > + sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN); > return; > } > > @@ -224,6 +256,15 @@ static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock > udelay(1); > sdhci_writel(host, 0x0, DWCMSHC_EMMC_DLL_CTRL); > > + /* > + * We shouldn't set DLL_RXCLK_NO_INVERTER for identify mode but > + * we must set it in higher speed mode. > + */ > + extra = DWCMSHC_EMMC_DLL_DLYENA; > + if (priv->devtype == DWCMSHC_RK3568) > + extra |= DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL; > + sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK); > + > /* Init DLL settings */ > extra = 0x5 << DWCMSHC_EMMC_DLL_START_POINT | > 0x2 << DWCMSHC_EMMC_DLL_INC | > @@ -246,8 +287,20 @@ static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock > host->mmc->ios.timing == MMC_TIMING_MMC_HS400) > txclk_tapnum = priv->txclk_tapnum; > > + if ((priv->devtype == DWCMSHC_RK3588) && host->mmc->ios.timing == MMC_TIMING_MMC_HS400) { > + txclk_tapnum = DLL_TXCLK_TAPNUM_90_DEGREES; > + > + extra = DLL_CMDOUT_SRC_CLK_NEG | > + DLL_CMDOUT_EN_SRC_CLK_NEG | > + DWCMSHC_EMMC_DLL_DLYENA | > + DLL_CMDOUT_TAPNUM_90_DEGREES | > + DLL_CMDOUT_TAPNUM_FROM_SW; > + sdhci_writel(host, extra, DECMSHC_EMMC_DLL_CMDOUT); > + } > + > extra = DWCMSHC_EMMC_DLL_DLYENA | > DLL_TXCLK_TAPNUM_FROM_SW | > + DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL | > txclk_tapnum; > sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK); > > @@ -347,7 +400,25 @@ static int dwcmshc_rk35xx_init(struct sdhci_host *host, struct dwcmshc_priv *dwc > return 0; > } > > +static void dwcmshc_rk35xx_postinit(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv) > +{ > + /* > + * Don't support highspeed bus mode with low clk speed as we > + * cannot use DLL for this condition. > + */ > + if (host->mmc->f_max <= 52000000) { > + dev_info(mmc_dev(host->mmc), "Disabling HS200/HS400, frequency too low (%d)\n", > + host->mmc->f_max); > + host->mmc->caps2 &= ~(MMC_CAP2_HS200 | MMC_CAP2_HS400); > + host->mmc->caps &= ~(MMC_CAP_3_3V_DDR | MMC_CAP_1_8V_DDR); Ideally, this should be done before mmc_add_host(), for example by using sdhci_setup_host() + __sdhci_add_host() instead of sdhci_add_host(), and putting dwcmshc_rk35xx_postinit() between sdhci_setup_host() and __sdhci_add_host(). > + } > +} > + > static const struct of_device_id sdhci_dwcmshc_dt_ids[] = { > + { > + .compatible = "rockchip,rk3588-dwcmshc", > + .data = &sdhci_dwcmshc_rk35xx_pdata, > + }, > { > .compatible = "rockchip,rk3568-dwcmshc", > .data = &sdhci_dwcmshc_rk35xx_pdata, > @@ -435,6 +506,11 @@ static int dwcmshc_probe(struct platform_device *pdev) > goto err_clk; > } > > + if (of_device_is_compatible(pdev->dev.of_node, "rockchip,rk3588-dwcmshc")) > + rk_priv->devtype = DWCMSHC_RK3588; > + else > + rk_priv->devtype = DWCMSHC_RK3568; > + > priv->priv = rk_priv; > > err = dwcmshc_rk35xx_init(host, priv); > @@ -448,6 +524,9 @@ static int dwcmshc_probe(struct platform_device *pdev) > if (err) > goto err_clk; > > + if (rk_priv) > + dwcmshc_rk35xx_postinit(host, priv); > + > return 0; > > err_clk:
Le vendredi 22 avril 2022 à 19:09 +0200, Sebastian Reichel a écrit : > From: Elaine Zhang <zhangqing@rock-chips.com> > > Add RK3588 PLL support including calculation of PLL parameters > for arbitrary frequencies. > > Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com> > [rebase and partially rewrite code] > Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com> > --- > drivers/clk/rockchip/clk-pll.c | 287 ++++++++++++++++++++++++++++++++- > drivers/clk/rockchip/clk.h | 18 +++ > 2 files changed, 304 insertions(+), 1 deletion(-) > > diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c > index f7827b3b7fc1..010e47eb51b8 100644 > --- a/drivers/clk/rockchip/clk-pll.c > +++ b/drivers/clk/rockchip/clk-pll.c > @@ -15,6 +15,7 @@ > #include <linux/iopoll.h> > #include <linux/regmap.h> > #include <linux/clk.h> > +#include <linux/units.h> > #include "clk.h" > > #define PLL_MODE_MASK 0x3 > @@ -47,6 +48,67 @@ struct rockchip_clk_pll { > #define to_rockchip_clk_pll_nb(nb) \ > container_of(nb, struct rockchip_clk_pll, clk_nb) > > +static int > +rockchip_rk3588_get_pll_settings(struct rockchip_clk_pll *pll, > + unsigned long fin_hz, > + unsigned long fout_hz, > + struct rockchip_pll_rate_table *rate_table) > +{ > + u64 fvco_min = 2250 * HZ_PER_MHZ, fvco_max = 4500 * HZ_PER_MHZ; > + u64 fout_min = 37 * HZ_PER_MHZ, fout_max = 4500 * HZ_PER_MHZ; > + u32 p, m, s; > + u64 fvco, fref, fout, ffrac; > + > + if (fin_hz == 0 || fout_hz == 0 || fout_hz == fin_hz) > + return -EINVAL; > + > + if (fout_hz > fout_max || fout_hz < fout_min) > + return -EINVAL; > + > + if (fin_hz / HZ_PER_MHZ * HZ_PER_MHZ == fin_hz && > + fout_hz / HZ_PER_MHZ * HZ_PER_MHZ == fout_hz) { > + for (s = 0; s <= 6; s++) { > + fvco = fout_hz << s; > + if (fvco < fvco_min || fvco > fvco_max) > + continue; > + for (p = 2; p <= 4; p++) { > + for (m = 64; m <= 1023; m++) { > + if (fvco == m * fin_hz / p) { > + rate_table->p = p; > + rate_table->m = m; > + rate_table->s = s; > + rate_table->k = 0; > + return 0; > + } > + } > + } > + } > + } else { > + fout = (fout_hz / HZ_PER_MHZ) * HZ_PER_MHZ; > + ffrac = (fout_hz % HZ_PER_MHZ); > + for (s = 0; s <= 6; s++) { > + fvco = fout << s; > + if (fvco < fvco_min || fvco > fvco_max) > + continue; > + for (p = 1; p <= 4; p++) { > + for (m = 64; m <= 1023; m++) { > + if (fvco == m * fin_hz / p) { > + rate_table->p = p; > + rate_table->m = m; > + rate_table->s = s; > + fref = fin_hz / p; > + fout = (ffrac << s) * 65535; > + rate_table->k = fout / fref; > + return 0; > + } > + } > + } > + } > + } > + > + return -EINVAL; > +} > + > static const struct rockchip_pll_rate_table *rockchip_get_pll_settings( > struct rockchip_clk_pll *pll, unsigned long rate) > { > @@ -68,6 +130,14 @@ static long rockchip_pll_round_rate(struct clk_hw *hw, > const struct rockchip_pll_rate_table *rate_table = pll->rate_table; > int i; > > + if (pll->type == pll_rk3588 || pll->type == pll_rk3588_core) { > + long parent_rate = prate ? *prate : 24 * HZ_PER_MHZ; > + struct rockchip_pll_rate_table pll_settings; > + > + if (rockchip_rk3588_get_pll_settings(pll, parent_rate, drate, &pll_settings) >= 0) > + return pll_settings.rate; > + } > + I was reading some of previous backlog on why these formula have never been mainlines [0]. It looks like so far the statu quo was adopted. But if that was to change, I think this implementation is not aligned with the intent. If my understanding is right, the rate_table[] (if it exists) should be looked up first and the formula use as a fallback. [0] https://patchwork.kernel.org/project/linux-rockchip/patch/1470144852-20708-1-git-send-email-zhengxing@rock-chips.com/#19548765 > /* Assumming rate_table is in descending order */ > for (i = 0; i < pll->rate_count; i++) { > if (drate >= rate_table[i].rate) > @@ -842,6 +912,212 @@ static const struct clk_ops rockchip_rk3399_pll_clk_ops = { > .init = rockchip_rk3399_pll_init, > }; > > +/** > + * PLL used in RK3588 > + */ > + > +#define RK3588_PLLCON(i) (i * 0x4) > +#define RK3588_PLLCON0_M_MASK 0x3ff > +#define RK3588_PLLCON0_M_SHIFT 0 > +#define RK3588_PLLCON1_P_MASK 0x3f > +#define RK3588_PLLCON1_P_SHIFT 0 > +#define RK3588_PLLCON1_S_MASK 0x7 > +#define RK3588_PLLCON1_S_SHIFT 6 > +#define RK3588_PLLCON2_K_MASK 0xffff > +#define RK3588_PLLCON2_K_SHIFT 0 > +#define RK3588_PLLCON1_PWRDOWN BIT(13) > +#define RK3588_PLLCON6_LOCK_STATUS BIT(15) > + > +static int rockchip_rk3588_pll_wait_lock(struct rockchip_clk_pll *pll) > +{ > + u32 pllcon; > + int ret; > + > + /* > + * Lock time typical 250, max 500 input clock cycles @24MHz > + * So define a very safe maximum of 1000us, meaning 24000 cycles. > + */ > + ret = readl_relaxed_poll_timeout(pll->reg_base + RK3588_PLLCON(6), > + pllcon, > + pllcon & RK3588_PLLCON6_LOCK_STATUS, > + 0, 1000); > + if (ret) > + pr_err("%s: timeout waiting for pll to lock\n", __func__); > + > + return ret; > +} > + > +static void rockchip_rk3588_pll_get_params(struct rockchip_clk_pll *pll, > + struct rockchip_pll_rate_table *rate) > +{ > + u32 pllcon; > + > + pllcon = readl_relaxed(pll->reg_base + RK3588_PLLCON(0)); > + rate->m = ((pllcon >> RK3588_PLLCON0_M_SHIFT) & RK3588_PLLCON0_M_MASK); > + > + pllcon = readl_relaxed(pll->reg_base + RK3588_PLLCON(1)); > + rate->p = ((pllcon >> RK3588_PLLCON1_P_SHIFT) & RK3588_PLLCON1_P_MASK); > + rate->s = ((pllcon >> RK3588_PLLCON1_S_SHIFT) & RK3588_PLLCON1_S_MASK); > + > + pllcon = readl_relaxed(pll->reg_base + RK3588_PLLCON(2)); > + rate->k = ((pllcon >> RK3588_PLLCON2_K_SHIFT) & RK3588_PLLCON2_K_MASK); > +} > + > +static unsigned long rockchip_rk3588_pll_recalc_rate(struct clk_hw *hw, unsigned long prate) > +{ > + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); > + struct rockchip_pll_rate_table cur; > + u64 rate64 = prate, postdiv; > + > + rockchip_rk3588_pll_get_params(pll, &cur); > + > + rate64 *= cur.m; > + do_div(rate64, cur.p); > + > + if (cur.k) { > + /* fractional mode */ > + u64 frac_rate64 = prate * cur.k; > + > + postdiv = cur.p * 65535; > + do_div(frac_rate64, postdiv); > + rate64 += frac_rate64; > + } > + rate64 = rate64 >> cur.s; > + > + return (unsigned long)rate64; > +} > + > +static int rockchip_rk3588_pll_set_params(struct rockchip_clk_pll *pll, > + const struct rockchip_pll_rate_table *rate) > +{ > + const struct clk_ops *pll_mux_ops = pll->pll_mux_ops; > + struct clk_mux *pll_mux = &pll->pll_mux; > + struct rockchip_pll_rate_table cur; > + int rate_change_remuxed = 0; > + int cur_parent; > + int ret; > + > + pr_debug("%s: rate settings for %lu p: %d, m: %d, s: %d, k: %d\n", > + __func__, rate->rate, rate->p, rate->m, rate->s, rate->k); > + > + rockchip_rk3588_pll_get_params(pll, &cur); > + cur.rate = 0; > + > + if (pll->type == pll_rk3588) { > + cur_parent = pll_mux_ops->get_parent(&pll_mux->hw); > + if (cur_parent == PLL_MODE_NORM) { > + pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW); > + rate_change_remuxed = 1; > + } > + } > + > + /* set pll power down */ > + writel(HIWORD_UPDATE(RK3588_PLLCON1_PWRDOWN, > + RK3588_PLLCON1_PWRDOWN, 0), > + pll->reg_base + RK3399_PLLCON(1)); > + > + /* update pll values */ > + writel_relaxed(HIWORD_UPDATE(rate->m, RK3588_PLLCON0_M_MASK, RK3588_PLLCON0_M_SHIFT), > + pll->reg_base + RK3399_PLLCON(0)); > + > + writel_relaxed(HIWORD_UPDATE(rate->p, RK3588_PLLCON1_P_MASK, RK3588_PLLCON1_P_SHIFT) | > + HIWORD_UPDATE(rate->s, RK3588_PLLCON1_S_MASK, RK3588_PLLCON1_S_SHIFT), > + pll->reg_base + RK3399_PLLCON(1)); > + > + writel_relaxed(HIWORD_UPDATE(rate->k, RK3588_PLLCON2_K_MASK, RK3588_PLLCON2_K_SHIFT), > + pll->reg_base + RK3399_PLLCON(2)); > + > + /* set pll power up */ > + writel(HIWORD_UPDATE(0, RK3588_PLLCON1_PWRDOWN, 0), > + pll->reg_base + RK3588_PLLCON(1)); > + > + /* wait for the pll to lock */ > + ret = rockchip_rk3588_pll_wait_lock(pll); > + if (ret) { > + pr_warn("%s: pll update unsuccessful, trying to restore old params\n", > + __func__); > + rockchip_rk3588_pll_set_params(pll, &cur); > + } > + > + if ((pll->type == pll_rk3588) && rate_change_remuxed) > + pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM); > + > + return ret; > +} > + > +static int rockchip_rk3588_pll_set_rate(struct clk_hw *hw, unsigned long drate, > + unsigned long prate) > +{ > + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); > + struct rockchip_pll_rate_table rate; > + unsigned long old_rate = rockchip_rk3588_pll_recalc_rate(hw, prate); > + > + pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n", > + __func__, __clk_get_name(hw->clk), old_rate, drate, prate); > + > + if (rockchip_rk3588_get_pll_settings(pll, prate, drate, &rate) < 0) { > + pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, > + drate, __clk_get_name(hw->clk)); > + return -EINVAL; > + } > + > + return rockchip_rk3588_pll_set_params(pll, &rate); > +} > + > +static int rockchip_rk3588_pll_enable(struct clk_hw *hw) > +{ > + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); > + > + writel(HIWORD_UPDATE(0, RK3588_PLLCON1_PWRDOWN, 0), > + pll->reg_base + RK3588_PLLCON(1)); > + rockchip_rk3588_pll_wait_lock(pll); > + > + return 0; > +} > + > +static void rockchip_rk3588_pll_disable(struct clk_hw *hw) > +{ > + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); > + > + writel(HIWORD_UPDATE(RK3588_PLLCON1_PWRDOWN, RK3588_PLLCON1_PWRDOWN, 0), > + pll->reg_base + RK3588_PLLCON(1)); > +} > + > +static int rockchip_rk3588_pll_is_enabled(struct clk_hw *hw) > +{ > + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); > + u32 pllcon = readl(pll->reg_base + RK3588_PLLCON(1)); > + > + return !(pllcon & RK3588_PLLCON1_PWRDOWN); > +} > + > +static int rockchip_rk3588_pll_init(struct clk_hw *hw) > +{ > + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); > + > + if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE)) > + return 0; > + > + return 0; > +} > + > +static const struct clk_ops rockchip_rk3588_pll_clk_norate_ops = { > + .recalc_rate = rockchip_rk3588_pll_recalc_rate, > + .enable = rockchip_rk3588_pll_enable, > + .disable = rockchip_rk3588_pll_disable, > + .is_enabled = rockchip_rk3588_pll_is_enabled, > +}; > + > +static const struct clk_ops rockchip_rk3588_pll_clk_ops = { > + .recalc_rate = rockchip_rk3588_pll_recalc_rate, > + .round_rate = rockchip_pll_round_rate, > + .set_rate = rockchip_rk3588_pll_set_rate, > + .enable = rockchip_rk3588_pll_enable, > + .disable = rockchip_rk3588_pll_disable, > + .is_enabled = rockchip_rk3588_pll_is_enabled, > + .init = rockchip_rk3588_pll_init, > +}; > + > /* > * Common registering of pll clocks > */ > @@ -890,7 +1166,8 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx, > if (pll_type == pll_rk3036 || > pll_type == pll_rk3066 || > pll_type == pll_rk3328 || > - pll_type == pll_rk3399) > + pll_type == pll_rk3399 || > + pll_type == pll_rk3588) > pll_mux->flags |= CLK_MUX_HIWORD_MASK; > > /* the actual muxing is xin24m, pll-output, xin32k */ > @@ -957,6 +1234,14 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx, > else > init.ops = &rockchip_rk3399_pll_clk_ops; > break; > + case pll_rk3588: > + case pll_rk3588_core: > + if (!pll->rate_table) > + init.ops = &rockchip_rk3588_pll_clk_norate_ops; > + else > + init.ops = &rockchip_rk3588_pll_clk_ops; > + init.flags = flags; > + break; > default: > pr_warn("%s: Unknown pll type for pll clk %s\n", > __func__, name); > diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h > index 6aece7f07a7d..bf7c8d082fde 100644 > --- a/drivers/clk/rockchip/clk.h > +++ b/drivers/clk/rockchip/clk.h > @@ -221,6 +221,8 @@ enum rockchip_pll_type { > pll_rk3066, > pll_rk3328, > pll_rk3399, > + pll_rk3588, > + pll_rk3588_core, > }; > > #define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, \ > @@ -253,6 +255,15 @@ enum rockchip_pll_type { > .nb = _nb, \ > } > > +#define RK3588_PLL_RATE(_rate, _p, _m, _s, _k) \ > +{ \ > + .rate = _rate##U, \ > + .p = _p, \ > + .m = _m, \ > + .s = _s, \ > + .k = _k, \ > +} > + > /** > * struct rockchip_clk_provider - information about clock provider > * @reg_base: virtual address for the register base. > @@ -288,6 +299,13 @@ struct rockchip_pll_rate_table { > unsigned int dsmpd; > unsigned int frac; > }; > + struct { > + /* for RK3588 */ > + unsigned int m; > + unsigned int p; > + unsigned int s; > + unsigned int k; > + }; > }; > }; > > -- > 2.35.1 > >
On Fri, Apr 22, 2022 at 7:09 PM Sebastian Reichel <sebastian.reichel@collabora.com> wrote: > From: Jianqun Xu <jay.xu@rock-chips.com> > > Add pinctrl support for RK3588. > > Signed-off-by: Jianqun Xu <jay.xu@rock-chips.com> > [merged in downstream fixes, simplified register lookup logic for better > maintanence at the cost of a bit more static const memory and fixed some > incorrect registers] > Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com> Patch applied, unless Heiko does some loud protesting it stays in the tree. Yours, Linus Walleij
Hi, Am Freitag, 29. April 2022, 00:55:52 CEST schrieb Linus Walleij: > On Fri, Apr 22, 2022 at 7:09 PM Sebastian Reichel > <sebastian.reichel@collabora.com> wrote: > > > From: Jianqun Xu <jay.xu@rock-chips.com> > > > > Add pinctrl support for RK3588. > > > > Signed-off-by: Jianqun Xu <jay.xu@rock-chips.com> > > [merged in downstream fixes, simplified register lookup logic for better > > maintanence at the cost of a bit more static const memory and fixed some > > incorrect registers] > > Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com> > > Patch applied, unless Heiko does some loud protesting it stays > in the tree. I'm never loud ;-) Patch looked ok overall as well. I guess at some future point someone will need to refactor the small "if rk3588" but that can be done when another slightly different user appears and we have a feeling what the common approach could look like. Heiko
On Fri, 22 Apr 2022 at 19:09, Sebastian Reichel <sebastian.reichel@collabora.com> wrote: > > Add compatible value for the Rockchip rk3588 dwcmshc controller. > > Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com> Applied for next, thanks! Note that, I am expecting a new version of the other mmc patches that is a part of the series. Kind regards Uffe > --- > Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml > index f300ced4cdf3..71f8e726d641 100644 > --- a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml > +++ b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml > @@ -17,6 +17,7 @@ properties: > compatible: > enum: > - rockchip,rk3568-dwcmshc > + - rockchip,rk3588-dwcmshc > - snps,dwcmshc-sdhci > > reg: > -- > 2.35.1 >