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: > 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 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
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