Commit aab58ace authored by Stephen Boyd's avatar Stephen Boyd

Merge tag 'v5.9-rockchip-clk1' of...

Merge tag 'v5.9-rockchip-clk1' of git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip into clk-rockchip

Pull Rockchip clk driver updates from Heiko Stuebner:

Use poll_timeout functions for pll lock-waiting and move the rk3036 to use
the available lock-status in pll-registers instead of reading it from the
General Register Files. Handle the clock variants on the rk3288w, revert
the mmc sample shift change on rk3328 and make the mac_lbtest clock
critical on rk3188.

* tag 'v5.9-rockchip-clk1' of git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip:
  clk: rockchip: add sclk_mac_lbtest to rk3188_critical_clocks
  clk: rockchip: Revert "fix wrong mmc sample phase shift for rk3328"
  clk: rockchip: use separate compatibles for rk3288w-cru
  dt-bindings: clocks: add rk3288w variant compatible
  clk: rockchip: Handle clock tree for rk3288w variant
  clk: rockchip: convert rk3036 pll type to use internal lock status
  clk: rockchip: convert basic pll lock_wait to use regmap_read_poll_timeout
  clk: rockchip: convert rk3399 pll type to use readl_relaxed_poll_timeout
parents b3a9e3b9 ef990bca
...@@ -4,9 +4,15 @@ The RK3288 clock controller generates and supplies clock to various ...@@ -4,9 +4,15 @@ The RK3288 clock controller generates and supplies clock to various
controllers within the SoC and also implements a reset controller for SoC controllers within the SoC and also implements a reset controller for SoC
peripherals. peripherals.
A revision of this SoC is available: rk3288w. The clock tree is a bit
different so another dt-compatible is available. Noticed that it is only
setting the difference but there is no automatic revision detection. This
should be performed by bootloaders.
Required Properties: Required Properties:
- compatible: should be "rockchip,rk3288-cru" - compatible: should be "rockchip,rk3288-cru" or "rockchip,rk3288w-cru" in
case of this revision of Rockchip rk3288.
- reg: physical base address of the controller and length of memory mapped - reg: physical base address of the controller and length of memory mapped
region. region.
- #clock-cells: should be 1. - #clock-cells: should be 1.
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/iopoll.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/clk.h> #include <linux/clk.h>
#include "clk.h" #include "clk.h"
...@@ -86,23 +87,14 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) ...@@ -86,23 +87,14 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll)
{ {
struct regmap *grf = pll->ctx->grf; struct regmap *grf = pll->ctx->grf;
unsigned int val; unsigned int val;
int delay = 24000000, ret; int ret;
while (delay > 0) {
ret = regmap_read(grf, pll->lock_offset, &val);
if (ret) {
pr_err("%s: failed to read pll lock status: %d\n",
__func__, ret);
return ret;
}
if (val & BIT(pll->lock_shift)) ret = regmap_read_poll_timeout(grf, pll->lock_offset, val,
return 0; val & BIT(pll->lock_shift), 0, 1000);
delay--; if (ret)
} pr_err("%s: timeout waiting for pll to lock\n", __func__);
pr_err("%s: timeout waiting for pll to lock\n", __func__); return ret;
return -ETIMEDOUT;
} }
/** /**
...@@ -118,12 +110,31 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) ...@@ -118,12 +110,31 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll)
#define RK3036_PLLCON1_REFDIV_SHIFT 0 #define RK3036_PLLCON1_REFDIV_SHIFT 0
#define RK3036_PLLCON1_POSTDIV2_MASK 0x7 #define RK3036_PLLCON1_POSTDIV2_MASK 0x7
#define RK3036_PLLCON1_POSTDIV2_SHIFT 6 #define RK3036_PLLCON1_POSTDIV2_SHIFT 6
#define RK3036_PLLCON1_LOCK_STATUS BIT(10)
#define RK3036_PLLCON1_DSMPD_MASK 0x1 #define RK3036_PLLCON1_DSMPD_MASK 0x1
#define RK3036_PLLCON1_DSMPD_SHIFT 12 #define RK3036_PLLCON1_DSMPD_SHIFT 12
#define RK3036_PLLCON1_PWRDOWN BIT(13)
#define RK3036_PLLCON2_FRAC_MASK 0xffffff #define RK3036_PLLCON2_FRAC_MASK 0xffffff
#define RK3036_PLLCON2_FRAC_SHIFT 0 #define RK3036_PLLCON2_FRAC_SHIFT 0
#define RK3036_PLLCON1_PWRDOWN (1 << 13) static int rockchip_rk3036_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 + RK3036_PLLCON(1),
pllcon,
pllcon & RK3036_PLLCON1_LOCK_STATUS,
0, 1000);
if (ret)
pr_err("%s: timeout waiting for pll to lock\n", __func__);
return ret;
}
static void rockchip_rk3036_pll_get_params(struct rockchip_clk_pll *pll, static void rockchip_rk3036_pll_get_params(struct rockchip_clk_pll *pll,
struct rockchip_pll_rate_table *rate) struct rockchip_pll_rate_table *rate)
...@@ -221,7 +232,7 @@ static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll, ...@@ -221,7 +232,7 @@ static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll,
writel_relaxed(pllcon, pll->reg_base + RK3036_PLLCON(2)); writel_relaxed(pllcon, pll->reg_base + RK3036_PLLCON(2));
/* wait for the pll to lock */ /* wait for the pll to lock */
ret = rockchip_pll_wait_lock(pll); ret = rockchip_rk3036_pll_wait_lock(pll);
if (ret) { if (ret) {
pr_warn("%s: pll update unsuccessful, trying to restore old params\n", pr_warn("%s: pll update unsuccessful, trying to restore old params\n",
__func__); __func__);
...@@ -260,7 +271,7 @@ static int rockchip_rk3036_pll_enable(struct clk_hw *hw) ...@@ -260,7 +271,7 @@ static int rockchip_rk3036_pll_enable(struct clk_hw *hw)
writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 0), writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 0),
pll->reg_base + RK3036_PLLCON(1)); pll->reg_base + RK3036_PLLCON(1));
rockchip_pll_wait_lock(pll); rockchip_rk3036_pll_wait_lock(pll);
return 0; return 0;
} }
...@@ -589,19 +600,20 @@ static const struct clk_ops rockchip_rk3066_pll_clk_ops = { ...@@ -589,19 +600,20 @@ static const struct clk_ops rockchip_rk3066_pll_clk_ops = {
static int rockchip_rk3399_pll_wait_lock(struct rockchip_clk_pll *pll) static int rockchip_rk3399_pll_wait_lock(struct rockchip_clk_pll *pll)
{ {
u32 pllcon; u32 pllcon;
int delay = 24000000; int ret;
/* poll check the lock status in rk3399 xPLLCON2 */
while (delay > 0) {
pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2));
if (pllcon & RK3399_PLLCON2_LOCK_STATUS)
return 0;
delay--; /*
} * 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 + RK3399_PLLCON(2),
pllcon,
pllcon & RK3399_PLLCON2_LOCK_STATUS,
0, 1000);
if (ret)
pr_err("%s: timeout waiting for pll to lock\n", __func__);
pr_err("%s: timeout waiting for pll to lock\n", __func__); return ret;
return -ETIMEDOUT;
} }
static void rockchip_rk3399_pll_get_params(struct rockchip_clk_pll *pll, static void rockchip_rk3399_pll_get_params(struct rockchip_clk_pll *pll,
......
...@@ -751,6 +751,7 @@ static const char *const rk3188_critical_clocks[] __initconst = { ...@@ -751,6 +751,7 @@ static const char *const rk3188_critical_clocks[] __initconst = {
"pclk_peri", "pclk_peri",
"hclk_cpubus", "hclk_cpubus",
"hclk_vio_bus", "hclk_vio_bus",
"sclk_mac_lbtest",
}; };
static struct rockchip_clk_provider *__init rk3188_common_clk_init(struct device_node *np) static struct rockchip_clk_provider *__init rk3188_common_clk_init(struct device_node *np)
......
...@@ -15,6 +15,11 @@ ...@@ -15,6 +15,11 @@
#define RK3288_GRF_SOC_CON(x) (0x244 + x * 4) #define RK3288_GRF_SOC_CON(x) (0x244 + x * 4)
#define RK3288_GRF_SOC_STATUS1 0x284 #define RK3288_GRF_SOC_STATUS1 0x284
enum rk3288_variant {
RK3288_CRU,
RK3288W_CRU,
};
enum rk3288_plls { enum rk3288_plls {
apll, dpll, cpll, gpll, npll, apll, dpll, cpll, gpll, npll,
}; };
...@@ -425,8 +430,6 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { ...@@ -425,8 +430,6 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
COMPOSITE(0, "aclk_vio0", mux_pll_src_cpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, COMPOSITE(0, "aclk_vio0", mux_pll_src_cpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
RK3288_CLKSEL_CON(31), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3288_CLKSEL_CON(31), 6, 2, MFLAGS, 0, 5, DFLAGS,
RK3288_CLKGATE_CON(3), 0, GFLAGS), RK3288_CLKGATE_CON(3), 0, GFLAGS),
DIV(0, "hclk_vio", "aclk_vio0", 0,
RK3288_CLKSEL_CON(28), 8, 5, DFLAGS),
COMPOSITE(0, "aclk_vio1", mux_pll_src_cpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, COMPOSITE(0, "aclk_vio1", mux_pll_src_cpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
RK3288_CLKSEL_CON(31), 14, 2, MFLAGS, 8, 5, DFLAGS, RK3288_CLKSEL_CON(31), 14, 2, MFLAGS, 8, 5, DFLAGS,
RK3288_CLKGATE_CON(3), 2, GFLAGS), RK3288_CLKGATE_CON(3), 2, GFLAGS),
...@@ -819,6 +822,16 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { ...@@ -819,6 +822,16 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
INVERTER(0, "pclk_isp", "pclk_isp_in", RK3288_CLKSEL_CON(29), 3, IFLAGS), INVERTER(0, "pclk_isp", "pclk_isp_in", RK3288_CLKSEL_CON(29), 3, IFLAGS),
}; };
static struct rockchip_clk_branch rk3288w_hclkvio_branch[] __initdata = {
DIV(0, "hclk_vio", "aclk_vio1", 0,
RK3288_CLKSEL_CON(28), 8, 5, DFLAGS),
};
static struct rockchip_clk_branch rk3288_hclkvio_branch[] __initdata = {
DIV(0, "hclk_vio", "aclk_vio0", 0,
RK3288_CLKSEL_CON(28), 8, 5, DFLAGS),
};
static const char *const rk3288_critical_clocks[] __initconst = { static const char *const rk3288_critical_clocks[] __initconst = {
"aclk_cpu", "aclk_cpu",
"aclk_peri", "aclk_peri",
...@@ -914,7 +927,8 @@ static struct syscore_ops rk3288_clk_syscore_ops = { ...@@ -914,7 +927,8 @@ static struct syscore_ops rk3288_clk_syscore_ops = {
.resume = rk3288_clk_resume, .resume = rk3288_clk_resume,
}; };
static void __init rk3288_clk_init(struct device_node *np) static void __init rk3288_common_init(struct device_node *np,
enum rk3288_variant soc)
{ {
struct rockchip_clk_provider *ctx; struct rockchip_clk_provider *ctx;
...@@ -936,6 +950,14 @@ static void __init rk3288_clk_init(struct device_node *np) ...@@ -936,6 +950,14 @@ static void __init rk3288_clk_init(struct device_node *np)
RK3288_GRF_SOC_STATUS1); RK3288_GRF_SOC_STATUS1);
rockchip_clk_register_branches(ctx, rk3288_clk_branches, rockchip_clk_register_branches(ctx, rk3288_clk_branches,
ARRAY_SIZE(rk3288_clk_branches)); ARRAY_SIZE(rk3288_clk_branches));
if (soc == RK3288W_CRU)
rockchip_clk_register_branches(ctx, rk3288w_hclkvio_branch,
ARRAY_SIZE(rk3288w_hclkvio_branch));
else
rockchip_clk_register_branches(ctx, rk3288_hclkvio_branch,
ARRAY_SIZE(rk3288_hclkvio_branch));
rockchip_clk_protect_critical(rk3288_critical_clocks, rockchip_clk_protect_critical(rk3288_critical_clocks,
ARRAY_SIZE(rk3288_critical_clocks)); ARRAY_SIZE(rk3288_critical_clocks));
...@@ -954,4 +976,15 @@ static void __init rk3288_clk_init(struct device_node *np) ...@@ -954,4 +976,15 @@ static void __init rk3288_clk_init(struct device_node *np)
rockchip_clk_of_add_provider(np, ctx); rockchip_clk_of_add_provider(np, ctx);
} }
static void __init rk3288_clk_init(struct device_node *np)
{
rk3288_common_init(np, RK3288_CRU);
}
CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init); CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init);
static void __init rk3288w_clk_init(struct device_node *np)
{
rk3288_common_init(np, RK3288W_CRU);
}
CLK_OF_DECLARE(rk3288w_cru, "rockchip,rk3288w-cru", rk3288w_clk_init);
...@@ -808,22 +808,22 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = { ...@@ -808,22 +808,22 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "clk_sdmmc", MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "clk_sdmmc",
RK3328_SDMMC_CON0, 1), RK3328_SDMMC_CON0, 1),
MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "clk_sdmmc", MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "clk_sdmmc",
RK3328_SDMMC_CON1, 0), RK3328_SDMMC_CON1, 1),
MMC(SCLK_SDIO_DRV, "sdio_drv", "clk_sdio", MMC(SCLK_SDIO_DRV, "sdio_drv", "clk_sdio",
RK3328_SDIO_CON0, 1), RK3328_SDIO_CON0, 1),
MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "clk_sdio", MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "clk_sdio",
RK3328_SDIO_CON1, 0), RK3328_SDIO_CON1, 1),
MMC(SCLK_EMMC_DRV, "emmc_drv", "clk_emmc", MMC(SCLK_EMMC_DRV, "emmc_drv", "clk_emmc",
RK3328_EMMC_CON0, 1), RK3328_EMMC_CON0, 1),
MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "clk_emmc", MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "clk_emmc",
RK3328_EMMC_CON1, 0), RK3328_EMMC_CON1, 1),
MMC(SCLK_SDMMC_EXT_DRV, "sdmmc_ext_drv", "clk_sdmmc_ext", MMC(SCLK_SDMMC_EXT_DRV, "sdmmc_ext_drv", "clk_sdmmc_ext",
RK3328_SDMMC_EXT_CON0, 1), RK3328_SDMMC_EXT_CON0, 1),
MMC(SCLK_SDMMC_EXT_SAMPLE, "sdmmc_ext_sample", "clk_sdmmc_ext", MMC(SCLK_SDMMC_EXT_SAMPLE, "sdmmc_ext_sample", "clk_sdmmc_ext",
RK3328_SDMMC_EXT_CON1, 0), RK3328_SDMMC_EXT_CON1, 1),
}; };
static const char *const rk3328_critical_clocks[] __initconst = { static const char *const rk3328_critical_clocks[] __initconst = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment