From patchwork Fri May 8 12:44:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eugeniy Paltsev X-Patchwork-Id: 245315 List-Id: U-Boot discussion From: Eugeniy.Paltsev at synopsys.com (Eugeniy Paltsev) Date: Fri, 8 May 2020 15:44:13 +0300 Subject: [PATCH 1/8] CLK: ARC: HSDK: avoid code duplication In-Reply-To: <20200508124420.31788-1-Eugeniy.Paltsev@synopsys.com> References: <20200508124420.31788-1-Eugeniy.Paltsev@synopsys.com> Message-ID: <20200508124420.31788-2-Eugeniy.Paltsev@synopsys.com> hsdk_axi_clk_cfg and hsdk_tun_clk_cfg clock divider structures and functions for their processing are almost the same so merge them to avoid code duplication. Signed-off-by: Eugeniy Paltsev --- drivers/clk/clk-hsdk-cgu.c | 112 +++++++++++++------------------------ 1 file changed, 40 insertions(+), 72 deletions(-) diff --git a/drivers/clk/clk-hsdk-cgu.c b/drivers/clk/clk-hsdk-cgu.c index 3035c5fb38e..a51e78071a9 100644 --- a/drivers/clk/clk-hsdk-cgu.c +++ b/drivers/clk/clk-hsdk-cgu.c @@ -126,45 +126,31 @@ #define PARENT_RATE_27 27000000 /* fixed clock - xtal */ #define CGU_MAX_CLOCKS 27 -#define CGU_SYS_CLOCKS 16 -#define MAX_AXI_CLOCKS 4 +#define MAX_FREQ_VARIATIONS 6 -#define CGU_TUN_CLOCKS 4 -#define MAX_TUN_CLOCKS 6 - -struct hsdk_tun_idiv_cfg { +struct hsdk_idiv_cfg { u32 oft; - u8 val[MAX_TUN_CLOCKS]; + u8 val[MAX_FREQ_VARIATIONS]; }; -struct hsdk_tun_clk_cfg { - const u32 clk_rate[MAX_TUN_CLOCKS]; - const u32 pll_rate[MAX_TUN_CLOCKS]; - const struct hsdk_tun_idiv_cfg idiv[CGU_TUN_CLOCKS]; +struct hsdk_div_full_cfg { + const u32 clk_rate[MAX_FREQ_VARIATIONS]; + const u32 pll_rate[MAX_FREQ_VARIATIONS]; + const struct hsdk_idiv_cfg idiv[]; }; -static const struct hsdk_tun_clk_cfg tun_clk_cfg = { +static const struct hsdk_div_full_cfg tun_clk_cfg = { { 25000000, 50000000, 75000000, 100000000, 125000000, 150000000 }, { 600000000, 600000000, 600000000, 600000000, 750000000, 600000000 }, { { CGU_TUN_IDIV_TUN, { 24, 12, 8, 6, 6, 4 } }, { CGU_TUN_IDIV_ROM, { 4, 4, 4, 4, 5, 4 } }, { CGU_TUN_IDIV_PWM, { 8, 8, 8, 8, 10, 8 } }, - { CGU_TUN_IDIV_TIMER, { 12, 12, 12, 12, 15, 12 } } + { CGU_TUN_IDIV_TIMER, { 12, 12, 12, 12, 15, 12 } }, + { /* last one */ } } }; -struct hsdk_sys_idiv_cfg { - u32 oft; - u8 val[MAX_AXI_CLOCKS]; -}; - -struct hsdk_axi_clk_cfg { - const u32 clk_rate[MAX_AXI_CLOCKS]; - const u32 pll_rate[MAX_AXI_CLOCKS]; - const struct hsdk_sys_idiv_cfg idiv[CGU_SYS_CLOCKS]; -}; - -static const struct hsdk_axi_clk_cfg axi_clk_cfg = { +static const struct hsdk_div_full_cfg axi_clk_cfg = { { 200000000, 400000000, 600000000, 800000000 }, { 800000000, 800000000, 600000000, 800000000 }, { { CGU_SYS_IDIV_APB, { 4, 4, 3, 4 } }, /* APB */ @@ -182,7 +168,8 @@ static const struct hsdk_axi_clk_cfg axi_clk_cfg = { { CGU_SYS_IDIV_SPI_REF, { 24, 24, 18, 24 } }, /* SPI-REF */ { CGU_SYS_IDIV_I2C_REF, { 4, 4, 3, 4 } }, /* I2C-REF */ { CGU_SYS_IDIV_UART_REF, { 24, 24, 18, 24 } }, /* UART-REF */ - { CGU_SYS_IDIV_EBI_REF, { 16, 16, 12, 16 } } /* EBI-REF */ + { CGU_SYS_IDIV_EBI_REF, { 16, 16, 12, 16 } }, /* EBI-REF */ + { /* last one */ } } }; @@ -546,8 +533,13 @@ static ulong cpu_clk_set(struct clk *sclk, ulong rate) return ret; } -/* Special behavior: wen we set this clock we set both idiv and pll and all pll dividers */ -static ulong axi_clk_set(struct clk *sclk, ulong rate) +/* + * Special behavior: + * when we set these clocks we set both PLL and all idiv dividers related to + * this PLL domain. + */ +static ulong common_div_clk_set(struct clk *sclk, ulong rate, + const struct hsdk_div_full_cfg *cfg) { struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); ulong pll_rate; @@ -556,71 +548,47 @@ static ulong axi_clk_set(struct clk *sclk, ulong rate) pll_rate = pll_get(sclk); - for (i = 0; i < MAX_AXI_CLOCKS; i++) { - if (axi_clk_cfg.clk_rate[i] == rate) { + for (i = 0; i < MAX_FREQ_VARIATIONS; i++) { + /* unused freq variations are filled with 0 */ + if (!cfg->clk_rate[i]) + break; + + if (cfg->clk_rate[i] == rate) { freq_idx = i; break; } } if (freq_idx < 0) { - pr_err("axi clk: invalid rate=%ld Hz\n", rate); + pr_err("clk: invalid rate=%ld Hz\n", rate); return -EINVAL; } /* configure PLL before dividers */ - if (axi_clk_cfg.pll_rate[freq_idx] < pll_rate) - ret = pll_set(sclk, axi_clk_cfg.pll_rate[freq_idx]); + if (cfg->pll_rate[freq_idx] < pll_rate) + ret = pll_set(sclk, cfg->pll_rate[freq_idx]); /* configure SYS dividers */ - for (i = 0; i < CGU_SYS_CLOCKS; i++) { - clk->idiv_regs = clk->cgu_regs + axi_clk_cfg.idiv[i].oft; - hsdk_idiv_write(clk, axi_clk_cfg.idiv[i].val[freq_idx]); + for (i = 0; cfg->idiv[i].oft != 0; i++) { + clk->idiv_regs = clk->cgu_regs + cfg->idiv[i].oft; + hsdk_idiv_write(clk, cfg->idiv[i].val[freq_idx]); } /* configure PLL after dividers */ - if (axi_clk_cfg.pll_rate[freq_idx] >= pll_rate) - ret = pll_set(sclk, axi_clk_cfg.pll_rate[freq_idx]); + if (cfg->pll_rate[freq_idx] >= pll_rate) + ret = pll_set(sclk, cfg->pll_rate[freq_idx]); return ret; } -static ulong tun_clk_set(struct clk *sclk, ulong rate) +static ulong axi_clk_set(struct clk *sclk, ulong rate) { - struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); - ulong pll_rate; - int i, freq_idx = -1; - ulong ret = 0; - - pll_rate = pll_get(sclk); - - for (i = 0; i < MAX_TUN_CLOCKS; i++) { - if (tun_clk_cfg.clk_rate[i] == rate) { - freq_idx = i; - break; - } - } - - if (freq_idx < 0) { - pr_err("tun clk: invalid rate=%ld Hz\n", rate); - return -EINVAL; - } - - /* configure PLL before dividers */ - if (tun_clk_cfg.pll_rate[freq_idx] < pll_rate) - ret = pll_set(sclk, tun_clk_cfg.pll_rate[freq_idx]); - - /* configure SYS dividers */ - for (i = 0; i < CGU_TUN_CLOCKS; i++) { - clk->idiv_regs = clk->cgu_regs + tun_clk_cfg.idiv[i].oft; - hsdk_idiv_write(clk, tun_clk_cfg.idiv[i].val[freq_idx]); - } - - /* configure PLL after dividers */ - if (tun_clk_cfg.pll_rate[freq_idx] >= pll_rate) - ret = pll_set(sclk, tun_clk_cfg.pll_rate[freq_idx]); + return common_div_clk_set(sclk, rate, &axi_clk_cfg); +} - return ret; +static ulong tun_clk_set(struct clk *sclk, ulong rate) +{ + return common_div_clk_set(sclk, rate, &tun_clk_cfg); } static ulong idiv_set(struct clk *sclk, ulong rate) From patchwork Fri May 8 12:44:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eugeniy Paltsev X-Patchwork-Id: 245312 List-Id: U-Boot discussion From: Eugeniy.Paltsev at synopsys.com (Eugeniy Paltsev) Date: Fri, 8 May 2020 15:44:14 +0300 Subject: [PATCH 2/8] CLK: ARC: HSDK: drop unused offset In-Reply-To: <20200508124420.31788-1-Eugeniy.Paltsev@synopsys.com> References: <20200508124420.31788-1-Eugeniy.Paltsev@synopsys.com> Message-ID: <20200508124420.31788-3-Eugeniy.Paltsev@synopsys.com> Drop creg_div_oft offset as it doesn't vary (due to it is used for CPU PLL only). Signed-off-by: Eugeniy Paltsev --- drivers/clk/clk-hsdk-cgu.c | 57 +++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/drivers/clk/clk-hsdk-cgu.c b/drivers/clk/clk-hsdk-cgu.c index a51e78071a9..ad0b74fbdb9 100644 --- a/drivers/clk/clk-hsdk-cgu.c +++ b/drivers/clk/clk-hsdk-cgu.c @@ -272,7 +272,6 @@ static ulong pll_get(struct clk *); struct hsdk_cgu_clock_map { u32 cgu_pll_oft; - u32 creg_div_oft; u32 cgu_div_oft; const struct hsdk_pll_devdata *pll_devdata; ulong (*get_rate)(struct clk *clk); @@ -281,33 +280,33 @@ struct hsdk_cgu_clock_map { }; static const struct hsdk_cgu_clock_map clock_map[] = { - { CGU_ARC_PLL, 0, 0, &core_pll_dat, pll_get, pll_set, NULL }, - { CGU_ARC_PLL, 0, CGU_ARC_IDIV, &core_pll_dat, idiv_get, cpu_clk_set, idiv_off }, - { CGU_DDR_PLL, 0, 0, &sdt_pll_dat, pll_get, pll_set, NULL }, - { CGU_SYS_PLL, 0, 0, &sdt_pll_dat, pll_get, pll_set, NULL }, - { CGU_SYS_PLL, 0, CGU_SYS_IDIV_APB, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, 0, CGU_SYS_IDIV_AXI, &sdt_pll_dat, idiv_get, axi_clk_set, idiv_off }, - { CGU_SYS_PLL, 0, CGU_SYS_IDIV_ETH, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, 0, CGU_SYS_IDIV_USB, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, 0, CGU_SYS_IDIV_SDIO, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, 0, CGU_SYS_IDIV_HDMI, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, 0, CGU_SYS_IDIV_GFX_CORE, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, 0, CGU_SYS_IDIV_GFX_DMA, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, 0, CGU_SYS_IDIV_GFX_CFG, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, 0, CGU_SYS_IDIV_DMAC_CORE, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, 0, CGU_SYS_IDIV_DMAC_CFG, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, 0, CGU_SYS_IDIV_SDIO_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, 0, CGU_SYS_IDIV_SPI_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, 0, CGU_SYS_IDIV_I2C_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, 0, CGU_SYS_IDIV_UART_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, 0, CGU_SYS_IDIV_EBI_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_TUN_PLL, 0, 0, &sdt_pll_dat, pll_get, pll_set, NULL }, - { CGU_TUN_PLL, 0, CGU_TUN_IDIV_TUN, &sdt_pll_dat, idiv_get, tun_clk_set, idiv_off }, - { CGU_TUN_PLL, 0, CGU_TUN_IDIV_ROM, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_TUN_PLL, 0, CGU_TUN_IDIV_PWM, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_TUN_PLL, 0, CGU_TUN_IDIV_TIMER, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_HDMI_PLL, 0, 0, &hdmi_pll_dat, pll_get, pll_set, NULL }, - { CGU_HDMI_PLL, 0, CGU_HDMI_IDIV_APB, &hdmi_pll_dat, idiv_get, idiv_set, idiv_off } + { CGU_ARC_PLL, 0, &core_pll_dat, pll_get, pll_set, NULL }, + { CGU_ARC_PLL, CGU_ARC_IDIV, &core_pll_dat, idiv_get, cpu_clk_set, idiv_off }, + { CGU_DDR_PLL, 0, &sdt_pll_dat, pll_get, pll_set, NULL }, + { CGU_SYS_PLL, 0, &sdt_pll_dat, pll_get, pll_set, NULL }, + { CGU_SYS_PLL, CGU_SYS_IDIV_APB, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + { CGU_SYS_PLL, CGU_SYS_IDIV_AXI, &sdt_pll_dat, idiv_get, axi_clk_set, idiv_off }, + { CGU_SYS_PLL, CGU_SYS_IDIV_ETH, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + { CGU_SYS_PLL, CGU_SYS_IDIV_USB, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + { CGU_SYS_PLL, CGU_SYS_IDIV_SDIO, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + { CGU_SYS_PLL, CGU_SYS_IDIV_HDMI, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + { CGU_SYS_PLL, CGU_SYS_IDIV_GFX_CORE, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + { CGU_SYS_PLL, CGU_SYS_IDIV_GFX_DMA, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + { CGU_SYS_PLL, CGU_SYS_IDIV_GFX_CFG, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + { CGU_SYS_PLL, CGU_SYS_IDIV_DMAC_CORE, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + { CGU_SYS_PLL, CGU_SYS_IDIV_DMAC_CFG, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + { CGU_SYS_PLL, CGU_SYS_IDIV_SDIO_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + { CGU_SYS_PLL, CGU_SYS_IDIV_SPI_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + { CGU_SYS_PLL, CGU_SYS_IDIV_I2C_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + { CGU_SYS_PLL, CGU_SYS_IDIV_UART_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + { CGU_SYS_PLL, CGU_SYS_IDIV_EBI_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + { CGU_TUN_PLL, 0, &sdt_pll_dat, pll_get, pll_set, NULL }, + { CGU_TUN_PLL, CGU_TUN_IDIV_TUN, &sdt_pll_dat, idiv_get, tun_clk_set, idiv_off }, + { CGU_TUN_PLL, CGU_TUN_IDIV_ROM, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + { CGU_TUN_PLL, CGU_TUN_IDIV_PWM, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + { CGU_TUN_PLL, CGU_TUN_IDIV_TIMER, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + { CGU_HDMI_PLL, 0, &hdmi_pll_dat, pll_get, pll_set, NULL }, + { CGU_HDMI_PLL, CGU_HDMI_IDIV_APB, &hdmi_pll_dat, idiv_get, idiv_set, idiv_off } }; static inline void hsdk_idiv_write(struct hsdk_cgu_clk *clk, u32 val) @@ -631,7 +630,7 @@ static int hsdk_prepare_clock_tree_branch(struct clk *sclk) clk->pll_devdata = clock_map[sclk->id].pll_devdata; clk->regs = clk->cgu_regs + clock_map[sclk->id].cgu_pll_oft; - clk->spec_regs = clk->creg_regs + clock_map[sclk->id].creg_div_oft; + clk->spec_regs = clk->creg_regs; clk->idiv_regs = clk->cgu_regs + clock_map[sclk->id].cgu_div_oft; return 0; From patchwork Fri May 8 12:44:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eugeniy Paltsev X-Patchwork-Id: 245317 List-Id: U-Boot discussion From: Eugeniy.Paltsev at synopsys.com (Eugeniy Paltsev) Date: Fri, 8 May 2020 15:44:15 +0300 Subject: [PATCH 3/8] CLK: ARC: HSDK: use appropriate config data types In-Reply-To: <20200508124420.31788-1-Eugeniy.Paltsev@synopsys.com> References: <20200508124420.31788-1-Eugeniy.Paltsev@synopsys.com> Message-ID: <20200508124420.31788-4-Eugeniy.Paltsev@synopsys.com> * constify clocks config data where is possible * use more appropriate data types for clocks config Signed-off-by: Eugeniy Paltsev --- drivers/clk/clk-hsdk-cgu.c | 41 +++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/drivers/clk/clk-hsdk-cgu.c b/drivers/clk/clk-hsdk-cgu.c index ad0b74fbdb9..30690b72f3c 100644 --- a/drivers/clk/clk-hsdk-cgu.c +++ b/drivers/clk/clk-hsdk-cgu.c @@ -129,8 +129,8 @@ #define MAX_FREQ_VARIATIONS 6 struct hsdk_idiv_cfg { - u32 oft; - u8 val[MAX_FREQ_VARIATIONS]; + const u32 oft; + const u8 val[MAX_FREQ_VARIATIONS]; }; struct hsdk_div_full_cfg { @@ -174,11 +174,11 @@ static const struct hsdk_div_full_cfg axi_clk_cfg = { }; struct hsdk_pll_cfg { - u32 rate; - u32 idiv; - u32 fbdiv; - u32 odiv; - u32 band; + const u32 rate; + const u8 idiv; + const u8 fbdiv; + const u8 odiv; + const u8 band; }; static const struct hsdk_pll_cfg asdt_pll_cfg[] = { @@ -233,9 +233,10 @@ struct hsdk_cgu_clk { struct hsdk_pll_devdata { const u32 parent_rate; - const struct hsdk_pll_cfg *pll_cfg; - int (*update_rate)(struct hsdk_cgu_clk *clk, unsigned long rate, - const struct hsdk_pll_cfg *cfg); + const struct hsdk_pll_cfg *const pll_cfg; + const int (*const update_rate)(struct hsdk_cgu_clk *clk, + unsigned long rate, + const struct hsdk_pll_cfg *cfg); }; static int hsdk_pll_core_update_rate(struct hsdk_cgu_clk *, unsigned long, @@ -271,12 +272,12 @@ static ulong pll_set(struct clk *, ulong); static ulong pll_get(struct clk *); struct hsdk_cgu_clock_map { - u32 cgu_pll_oft; - u32 cgu_div_oft; - const struct hsdk_pll_devdata *pll_devdata; - ulong (*get_rate)(struct clk *clk); - ulong (*set_rate)(struct clk *clk, ulong rate); - int (*disable)(struct clk *clk); + const u32 cgu_pll_oft; + const u32 cgu_div_oft; + const struct hsdk_pll_devdata *const pll_devdata; + const ulong (*const get_rate)(struct clk *clk); + const ulong (*const set_rate)(struct clk *clk, ulong rate); + const int (*const disable)(struct clk *clk); }; static const struct hsdk_cgu_clock_map clock_map[] = { @@ -345,10 +346,10 @@ static inline void hsdk_pll_set_cfg(struct hsdk_cgu_clk *clk, u32 val = 0; /* Powerdown and Bypass bits should be cleared */ - val |= cfg->idiv << CGU_PLL_CTRL_IDIV_SHIFT; - val |= cfg->fbdiv << CGU_PLL_CTRL_FBDIV_SHIFT; - val |= cfg->odiv << CGU_PLL_CTRL_ODIV_SHIFT; - val |= cfg->band << CGU_PLL_CTRL_BAND_SHIFT; + val |= (u32)cfg->idiv << CGU_PLL_CTRL_IDIV_SHIFT; + val |= (u32)cfg->fbdiv << CGU_PLL_CTRL_FBDIV_SHIFT; + val |= (u32)cfg->odiv << CGU_PLL_CTRL_ODIV_SHIFT; + val |= (u32)cfg->band << CGU_PLL_CTRL_BAND_SHIFT; pr_debug("write configurarion: %#x\n", val); From patchwork Fri May 8 12:44:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eugeniy Paltsev X-Patchwork-Id: 245313 List-Id: U-Boot discussion From: Eugeniy.Paltsev at synopsys.com (Eugeniy Paltsev) Date: Fri, 8 May 2020 15:44:16 +0300 Subject: [PATCH 4/8] CLK: ARC: HSDK: driver cleanup In-Reply-To: <20200508124420.31788-1-Eugeniy.Paltsev@synopsys.com> References: <20200508124420.31788-1-Eugeniy.Paltsev@synopsys.com> Message-ID: <20200508124420.31788-5-Eugeniy.Paltsev@synopsys.com> Minor code cleanup to improve readability. No functional change intended. Signed-off-by: Eugeniy Paltsev --- drivers/clk/clk-hsdk-cgu.c | 75 ++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/drivers/clk/clk-hsdk-cgu.c b/drivers/clk/clk-hsdk-cgu.c index 30690b72f3c..d7cb4f46242 100644 --- a/drivers/clk/clk-hsdk-cgu.c +++ b/drivers/clk/clk-hsdk-cgu.c @@ -214,23 +214,28 @@ static const struct hsdk_pll_cfg hdmi_pll_cfg[] = { {} }; -struct hsdk_cgu_clk { - /* CGU block register */ - void __iomem *cgu_regs; - /* CREG block register */ - void __iomem *creg_regs; - +struct hsdk_cgu_domain { /* PLLs registers */ - void __iomem *regs; + void __iomem *pll_regs; /* PLLs special registers */ void __iomem *spec_regs; /* PLLs devdata */ - const struct hsdk_pll_devdata *pll_devdata; + const struct hsdk_pll_devdata *pll; /* Dividers registers */ void __iomem *idiv_regs; }; +struct hsdk_cgu_clk { + /* CGU block register */ + void __iomem *cgu_regs; + /* CREG block register */ + void __iomem *creg_regs; + + /* The domain we are working with */ + struct hsdk_cgu_domain curr_domain; +}; + struct hsdk_pll_devdata { const u32 parent_rate; const struct hsdk_pll_cfg *const pll_cfg; @@ -271,7 +276,7 @@ static int idiv_off(struct clk *); static ulong pll_set(struct clk *, ulong); static ulong pll_get(struct clk *); -struct hsdk_cgu_clock_map { +struct cgu_clk_map { const u32 cgu_pll_oft; const u32 cgu_div_oft; const struct hsdk_pll_devdata *const pll_devdata; @@ -280,7 +285,7 @@ struct hsdk_cgu_clock_map { const int (*const disable)(struct clk *clk); }; -static const struct hsdk_cgu_clock_map clock_map[] = { +static const struct cgu_clk_map clock_map[] = { { CGU_ARC_PLL, 0, &core_pll_dat, pll_get, pll_set, NULL }, { CGU_ARC_PLL, CGU_ARC_IDIV, &core_pll_dat, idiv_get, cpu_clk_set, idiv_off }, { CGU_DDR_PLL, 0, &sdt_pll_dat, pll_get, pll_set, NULL }, @@ -312,32 +317,32 @@ static const struct hsdk_cgu_clock_map clock_map[] = { static inline void hsdk_idiv_write(struct hsdk_cgu_clk *clk, u32 val) { - iowrite32(val, clk->idiv_regs); + iowrite32(val, clk->curr_domain.idiv_regs); } static inline u32 hsdk_idiv_read(struct hsdk_cgu_clk *clk) { - return ioread32(clk->idiv_regs); + return ioread32(clk->curr_domain.idiv_regs); } static inline void hsdk_pll_write(struct hsdk_cgu_clk *clk, u32 reg, u32 val) { - iowrite32(val, clk->regs + reg); + iowrite32(val, clk->curr_domain.pll_regs + reg); } static inline u32 hsdk_pll_read(struct hsdk_cgu_clk *clk, u32 reg) { - return ioread32(clk->regs + reg); + return ioread32(clk->curr_domain.pll_regs + reg); } static inline void hsdk_pll_spcwrite(struct hsdk_cgu_clk *clk, u32 reg, u32 val) { - iowrite32(val, clk->spec_regs + reg); + iowrite32(val, clk->curr_domain.spec_regs + reg); } static inline u32 hsdk_pll_spcread(struct hsdk_cgu_clk *clk, u32 reg) { - return ioread32(clk->spec_regs + reg); + return ioread32(clk->curr_domain.spec_regs + reg); } static inline void hsdk_pll_set_cfg(struct hsdk_cgu_clk *clk, @@ -372,7 +377,7 @@ static ulong pll_get(struct clk *sclk) u64 rate; u32 idiv, fbdiv, odiv; struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); - u32 parent_rate = clk->pll_devdata->parent_rate; + u32 parent_rate = clk->curr_domain.pll->parent_rate; val = hsdk_pll_read(clk, CGU_PLL_CTRL); @@ -404,7 +409,7 @@ static unsigned long hsdk_pll_round_rate(struct clk *sclk, unsigned long rate) int i; unsigned long best_rate; struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); - const struct hsdk_pll_cfg *pll_cfg = clk->pll_devdata->pll_cfg; + const struct hsdk_pll_cfg *pll_cfg = clk->curr_domain.pll->pll_cfg; if (pll_cfg[0].rate == 0) return -EINVAL; @@ -480,19 +485,17 @@ static ulong pll_set(struct clk *sclk, ulong rate) int i; unsigned long best_rate; struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); - const struct hsdk_pll_cfg *pll_cfg = clk->pll_devdata->pll_cfg; + const struct hsdk_pll_devdata *pll = clk->curr_domain.pll; + const struct hsdk_pll_cfg *pll_cfg = pll->pll_cfg; best_rate = hsdk_pll_round_rate(sclk, rate); - for (i = 0; pll_cfg[i].rate != 0; i++) { - if (pll_cfg[i].rate == best_rate) { - return clk->pll_devdata->update_rate(clk, best_rate, - &pll_cfg[i]); - } - } + for (i = 0; pll_cfg[i].rate != 0; i++) + if (pll_cfg[i].rate == best_rate) + return pll->update_rate(clk, best_rate, &pll_cfg[i]); pr_err("invalid rate=%ld Hz, parent_rate=%d Hz\n", best_rate, - clk->pll_devdata->parent_rate); + pll->parent_rate); return -EINVAL; } @@ -570,7 +573,7 @@ static ulong common_div_clk_set(struct clk *sclk, ulong rate, /* configure SYS dividers */ for (i = 0; cfg->idiv[i].oft != 0; i++) { - clk->idiv_regs = clk->cgu_regs + cfg->idiv[i].oft; + clk->curr_domain.idiv_regs = clk->cgu_regs + cfg->idiv[i].oft; hsdk_idiv_write(clk, cfg->idiv[i].val[freq_idx]); } @@ -629,10 +632,10 @@ static int hsdk_prepare_clock_tree_branch(struct clk *sclk) if (sclk->id >= CGU_MAX_CLOCKS) return -EINVAL; - clk->pll_devdata = clock_map[sclk->id].pll_devdata; - clk->regs = clk->cgu_regs + clock_map[sclk->id].cgu_pll_oft; - clk->spec_regs = clk->creg_regs; - clk->idiv_regs = clk->cgu_regs + clock_map[sclk->id].cgu_div_oft; + clk->curr_domain.pll = clock_map[sclk->id].pll_devdata; + clk->curr_domain.pll_regs = clk->cgu_regs + clock_map[sclk->id].cgu_pll_oft; + clk->curr_domain.spec_regs = clk->creg_regs; + clk->curr_domain.idiv_regs = clk->cgu_regs + clock_map[sclk->id].cgu_div_oft; return 0; } @@ -672,16 +675,16 @@ static const struct clk_ops hsdk_cgu_ops = { static int hsdk_cgu_clk_probe(struct udevice *dev) { - struct hsdk_cgu_clk *pll_clk = dev_get_priv(dev); + struct hsdk_cgu_clk *hsdk_clk = dev_get_priv(dev); BUILD_BUG_ON(ARRAY_SIZE(clock_map) != CGU_MAX_CLOCKS); - pll_clk->cgu_regs = (void __iomem *)devfdt_get_addr_index(dev, 0); - if (!pll_clk->cgu_regs) + hsdk_clk->cgu_regs = (void __iomem *)devfdt_get_addr_index(dev, 0); + if (!hsdk_clk->cgu_regs) return -EINVAL; - pll_clk->creg_regs = (void __iomem *)devfdt_get_addr_index(dev, 1); - if (!pll_clk->creg_regs) + hsdk_clk->creg_regs = (void __iomem *)devfdt_get_addr_index(dev, 1); + if (!hsdk_clk->creg_regs) return -EINVAL; return 0; From patchwork Fri May 8 12:44:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eugeniy Paltsev X-Patchwork-Id: 245318 List-Id: U-Boot discussion From: Eugeniy.Paltsev at synopsys.com (Eugeniy Paltsev) Date: Fri, 8 May 2020 15:44:17 +0300 Subject: [PATCH 5/8] CLK: ARC: HSDK: prepare for multiple clock maps support In-Reply-To: <20200508124420.31788-1-Eugeniy.Paltsev@synopsys.com> References: <20200508124420.31788-1-Eugeniy.Paltsev@synopsys.com> Message-ID: <20200508124420.31788-6-Eugeniy.Paltsev@synopsys.com> The clock trees of HSDK and HSDK-4xD vary so we need to prepare CGU driver for multiple clock maps support. Signed-off-by: Eugeniy Paltsev --- drivers/clk/clk-hsdk-cgu.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/drivers/clk/clk-hsdk-cgu.c b/drivers/clk/clk-hsdk-cgu.c index d7cb4f46242..6aba4587a44 100644 --- a/drivers/clk/clk-hsdk-cgu.c +++ b/drivers/clk/clk-hsdk-cgu.c @@ -227,6 +227,7 @@ struct hsdk_cgu_domain { }; struct hsdk_cgu_clk { + const struct cgu_clk_map *map; /* CGU block register */ void __iomem *cgu_regs; /* CREG block register */ @@ -632,37 +633,47 @@ static int hsdk_prepare_clock_tree_branch(struct clk *sclk) if (sclk->id >= CGU_MAX_CLOCKS) return -EINVAL; - clk->curr_domain.pll = clock_map[sclk->id].pll_devdata; - clk->curr_domain.pll_regs = clk->cgu_regs + clock_map[sclk->id].cgu_pll_oft; + /* clocks missing in current map have their entry zeroed */ + if (!clk->map[sclk->id].pll_devdata) + return -EINVAL; + + clk->curr_domain.pll = clk->map[sclk->id].pll_devdata; + clk->curr_domain.pll_regs = clk->cgu_regs + clk->map[sclk->id].cgu_pll_oft; clk->curr_domain.spec_regs = clk->creg_regs; - clk->curr_domain.idiv_regs = clk->cgu_regs + clock_map[sclk->id].cgu_div_oft; + clk->curr_domain.idiv_regs = clk->cgu_regs + clk->map[sclk->id].cgu_div_oft; return 0; } static ulong hsdk_cgu_get_rate(struct clk *sclk) { + struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); + if (hsdk_prepare_clock_tree_branch(sclk)) return -EINVAL; - return clock_map[sclk->id].get_rate(sclk); + return clk->map[sclk->id].get_rate(sclk); } static ulong hsdk_cgu_set_rate(struct clk *sclk, ulong rate) { + struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); + if (hsdk_prepare_clock_tree_branch(sclk)) return -EINVAL; - return clock_map[sclk->id].set_rate(sclk, rate); + return clk->map[sclk->id].set_rate(sclk, rate); } static int hsdk_cgu_disable(struct clk *sclk) { + struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); + if (hsdk_prepare_clock_tree_branch(sclk)) return -EINVAL; - if (clock_map[sclk->id].disable) - return clock_map[sclk->id].disable(sclk); + if (clk->map[sclk->id].disable) + return clk->map[sclk->id].disable(sclk); return -ENOTSUPP; } @@ -679,6 +690,8 @@ static int hsdk_cgu_clk_probe(struct udevice *dev) BUILD_BUG_ON(ARRAY_SIZE(clock_map) != CGU_MAX_CLOCKS); + hsdk_clk->map = clock_map; + hsdk_clk->cgu_regs = (void __iomem *)devfdt_get_addr_index(dev, 0); if (!hsdk_clk->cgu_regs) return -EINVAL; From patchwork Fri May 8 12:44:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eugeniy Paltsev X-Patchwork-Id: 245316 List-Id: U-Boot discussion From: Eugeniy.Paltsev at synopsys.com (Eugeniy Paltsev) Date: Fri, 8 May 2020 15:44:18 +0300 Subject: [PATCH 6/8] CLK: ARC: HSDK: make set_clock optional In-Reply-To: <20200508124420.31788-1-Eugeniy.Paltsev@synopsys.com> References: <20200508124420.31788-1-Eugeniy.Paltsev@synopsys.com> Message-ID: <20200508124420.31788-7-Eugeniy.Paltsev@synopsys.com> We don't want to allow change some clocks, i.e. DDR clock. So allow to have set_clock to be unset in clock map. Signed-off-by: Eugeniy Paltsev --- drivers/clk/clk-hsdk-cgu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk-hsdk-cgu.c b/drivers/clk/clk-hsdk-cgu.c index 6aba4587a44..dd665b13587 100644 --- a/drivers/clk/clk-hsdk-cgu.c +++ b/drivers/clk/clk-hsdk-cgu.c @@ -662,7 +662,10 @@ static ulong hsdk_cgu_set_rate(struct clk *sclk, ulong rate) if (hsdk_prepare_clock_tree_branch(sclk)) return -EINVAL; - return clk->map[sclk->id].set_rate(sclk, rate); + if (clk->map[sclk->id].set_rate) + return clk->map[sclk->id].set_rate(sclk, rate); + + return -ENOTSUPP; } static int hsdk_cgu_disable(struct clk *sclk) From patchwork Fri May 8 12:44:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eugeniy Paltsev X-Patchwork-Id: 245320 List-Id: U-Boot discussion From: Eugeniy.Paltsev at synopsys.com (Eugeniy Paltsev) Date: Fri, 8 May 2020 15:44:19 +0300 Subject: [PATCH 7/8] CLK: ARC: HSDK: define clock map with DT binding constants In-Reply-To: <20200508124420.31788-1-Eugeniy.Paltsev@synopsys.com> References: <20200508124420.31788-1-Eugeniy.Paltsev@synopsys.com> Message-ID: <20200508124420.31788-8-Eugeniy.Paltsev@synopsys.com> Define clock map with DT binding constants so clock map can be discontinuous. Signed-off-by: Eugeniy Paltsev --- drivers/clk/clk-hsdk-cgu.c | 56 ++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/drivers/clk/clk-hsdk-cgu.c b/drivers/clk/clk-hsdk-cgu.c index dd665b13587..a44382d9586 100644 --- a/drivers/clk/clk-hsdk-cgu.c +++ b/drivers/clk/clk-hsdk-cgu.c @@ -15,6 +15,8 @@ #include #include +#include + /* * Synopsys ARC HSDK clock tree. * @@ -287,33 +289,33 @@ struct cgu_clk_map { }; static const struct cgu_clk_map clock_map[] = { - { CGU_ARC_PLL, 0, &core_pll_dat, pll_get, pll_set, NULL }, - { CGU_ARC_PLL, CGU_ARC_IDIV, &core_pll_dat, idiv_get, cpu_clk_set, idiv_off }, - { CGU_DDR_PLL, 0, &sdt_pll_dat, pll_get, pll_set, NULL }, - { CGU_SYS_PLL, 0, &sdt_pll_dat, pll_get, pll_set, NULL }, - { CGU_SYS_PLL, CGU_SYS_IDIV_APB, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, CGU_SYS_IDIV_AXI, &sdt_pll_dat, idiv_get, axi_clk_set, idiv_off }, - { CGU_SYS_PLL, CGU_SYS_IDIV_ETH, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, CGU_SYS_IDIV_USB, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, CGU_SYS_IDIV_SDIO, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, CGU_SYS_IDIV_HDMI, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, CGU_SYS_IDIV_GFX_CORE, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, CGU_SYS_IDIV_GFX_DMA, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, CGU_SYS_IDIV_GFX_CFG, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, CGU_SYS_IDIV_DMAC_CORE, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, CGU_SYS_IDIV_DMAC_CFG, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, CGU_SYS_IDIV_SDIO_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, CGU_SYS_IDIV_SPI_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, CGU_SYS_IDIV_I2C_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, CGU_SYS_IDIV_UART_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_SYS_PLL, CGU_SYS_IDIV_EBI_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_TUN_PLL, 0, &sdt_pll_dat, pll_get, pll_set, NULL }, - { CGU_TUN_PLL, CGU_TUN_IDIV_TUN, &sdt_pll_dat, idiv_get, tun_clk_set, idiv_off }, - { CGU_TUN_PLL, CGU_TUN_IDIV_ROM, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_TUN_PLL, CGU_TUN_IDIV_PWM, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_TUN_PLL, CGU_TUN_IDIV_TIMER, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, - { CGU_HDMI_PLL, 0, &hdmi_pll_dat, pll_get, pll_set, NULL }, - { CGU_HDMI_PLL, CGU_HDMI_IDIV_APB, &hdmi_pll_dat, idiv_get, idiv_set, idiv_off } + [CLK_ARC_PLL] = { CGU_ARC_PLL, 0, &core_pll_dat, pll_get, pll_set, NULL }, + [CLK_ARC] = { CGU_ARC_PLL, CGU_ARC_IDIV, &core_pll_dat, idiv_get, cpu_clk_set, idiv_off }, + [CLK_DDR_PLL] = { CGU_DDR_PLL, 0, &sdt_pll_dat, pll_get, pll_set, NULL }, + [CLK_SYS_PLL] = { CGU_SYS_PLL, 0, &sdt_pll_dat, pll_get, pll_set, NULL }, + [CLK_SYS_APB] = { CGU_SYS_PLL, CGU_SYS_IDIV_APB, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_AXI] = { CGU_SYS_PLL, CGU_SYS_IDIV_AXI, &sdt_pll_dat, idiv_get, axi_clk_set, idiv_off }, + [CLK_SYS_ETH] = { CGU_SYS_PLL, CGU_SYS_IDIV_ETH, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_USB] = { CGU_SYS_PLL, CGU_SYS_IDIV_USB, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_SDIO] = { CGU_SYS_PLL, CGU_SYS_IDIV_SDIO, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_HDMI] = { CGU_SYS_PLL, CGU_SYS_IDIV_HDMI, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_GFX_CORE] = { CGU_SYS_PLL, CGU_SYS_IDIV_GFX_CORE, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_GFX_DMA] = { CGU_SYS_PLL, CGU_SYS_IDIV_GFX_DMA, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_GFX_CFG] = { CGU_SYS_PLL, CGU_SYS_IDIV_GFX_CFG, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_DMAC_CORE] = { CGU_SYS_PLL, CGU_SYS_IDIV_DMAC_CORE, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_DMAC_CFG] = { CGU_SYS_PLL, CGU_SYS_IDIV_DMAC_CFG, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_SDIO_REF] = { CGU_SYS_PLL, CGU_SYS_IDIV_SDIO_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_SPI_REF] = { CGU_SYS_PLL, CGU_SYS_IDIV_SPI_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_I2C_REF] = { CGU_SYS_PLL, CGU_SYS_IDIV_I2C_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_UART_REF] = { CGU_SYS_PLL, CGU_SYS_IDIV_UART_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_EBI_REF] = { CGU_SYS_PLL, CGU_SYS_IDIV_EBI_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_TUN_PLL] = { CGU_TUN_PLL, 0, &sdt_pll_dat, pll_get, pll_set, NULL }, + [CLK_TUN_TUN] = { CGU_TUN_PLL, CGU_TUN_IDIV_TUN, &sdt_pll_dat, idiv_get, tun_clk_set, idiv_off }, + [CLK_TUN_ROM] = { CGU_TUN_PLL, CGU_TUN_IDIV_ROM, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_TUN_PWM] = { CGU_TUN_PLL, CGU_TUN_IDIV_PWM, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_TUN_TIMER] = { CGU_TUN_PLL, CGU_TUN_IDIV_TIMER, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_HDMI_PLL] = { CGU_HDMI_PLL, 0, &hdmi_pll_dat, pll_get, pll_set, NULL }, + [CLK_HDMI] = { CGU_HDMI_PLL, CGU_HDMI_IDIV_APB, &hdmi_pll_dat, idiv_get, idiv_set, idiv_off } }; static inline void hsdk_idiv_write(struct hsdk_cgu_clk *clk, u32 val) From patchwork Fri May 8 12:44:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eugeniy Paltsev X-Patchwork-Id: 245319 List-Id: U-Boot discussion From: Eugeniy.Paltsev at synopsys.com (Eugeniy Paltsev) Date: Fri, 8 May 2020 15:44:20 +0300 Subject: [PATCH 8/8] CLK: ARC: HSDK: add separate clock map for HSDK-4xD In-Reply-To: <20200508124420.31788-1-Eugeniy.Paltsev@synopsys.com> References: <20200508124420.31788-1-Eugeniy.Paltsev@synopsys.com> Message-ID: <20200508124420.31788-9-Eugeniy.Paltsev@synopsys.com> HSDK and HSDK-4xD clock trees are slightly different. commit 1dfb2ec0d7fb ("ARC: HSDK: CGU: add support for timer clock") introduce regression for HSDK board cause crash when setting tunnel clock. Fix that. Fixes: 1dfb2ec0d7fb ("ARC: HSDK: CGU: add support for timer clock") Signed-off-by: Eugeniy Paltsev --- drivers/clk/Kconfig | 7 ++-- drivers/clk/clk-hsdk-cgu.c | 68 +++++++++++++++++++++++++++++++++----- 2 files changed, 64 insertions(+), 11 deletions(-) diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 1992d4a4b47..8b8b7199995 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -100,10 +100,11 @@ config CLK_TI_SCI managed by the TI System Controller, say Y here. Otherwise, say N. config CLK_HSDK - bool "Enable cgu clock driver for HSDK" - depends on CLK + bool "Enable cgu clock driver for HSDK boards" + depends on CLK && TARGET_HSDK help - Enable this to support the cgu clocks on Synopsys ARC HSDK + Enable this to support the cgu clocks on Synopsys ARC HSDK and + Synopsys ARC HSDK-4xD boards config CLK_VERSAL bool "Enable clock driver support for Versal" diff --git a/drivers/clk/clk-hsdk-cgu.c b/drivers/clk/clk-hsdk-cgu.c index a44382d9586..2de3a6a30b0 100644 --- a/drivers/clk/clk-hsdk-cgu.c +++ b/drivers/clk/clk-hsdk-cgu.c @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -141,7 +142,7 @@ struct hsdk_div_full_cfg { const struct hsdk_idiv_cfg idiv[]; }; -static const struct hsdk_div_full_cfg tun_clk_cfg = { +static const struct hsdk_div_full_cfg hsdk_4xd_tun_clk_cfg = { { 25000000, 50000000, 75000000, 100000000, 125000000, 150000000 }, { 600000000, 600000000, 600000000, 600000000, 750000000, 600000000 }, { { CGU_TUN_IDIV_TUN, { 24, 12, 8, 6, 6, 4 } }, @@ -152,6 +153,16 @@ static const struct hsdk_div_full_cfg tun_clk_cfg = { } }; +static const struct hsdk_div_full_cfg hsdk_tun_clk_cfg = { + { 25000000, 50000000, 75000000, 100000000, 125000000, 150000000 }, + { 600000000, 600000000, 600000000, 600000000, 750000000, 600000000 }, { + { CGU_TUN_IDIV_TUN, { 24, 12, 8, 6, 6, 4 } }, + { CGU_TUN_IDIV_ROM, { 4, 4, 4, 4, 5, 4 } }, + { CGU_TUN_IDIV_PWM, { 8, 8, 8, 8, 10, 8 } }, + { /* last one */ } + } +}; + static const struct hsdk_div_full_cfg axi_clk_cfg = { { 200000000, 400000000, 600000000, 800000000 }, { 800000000, 800000000, 600000000, 800000000 }, { @@ -273,7 +284,8 @@ static const struct hsdk_pll_devdata hdmi_pll_dat = { static ulong idiv_set(struct clk *, ulong); static ulong cpu_clk_set(struct clk *, ulong); static ulong axi_clk_set(struct clk *, ulong); -static ulong tun_clk_set(struct clk *, ulong); +static ulong tun_hsdk_set(struct clk *, ulong); +static ulong tun_h4xd_set(struct clk *, ulong); static ulong idiv_get(struct clk *); static int idiv_off(struct clk *); static ulong pll_set(struct clk *, ulong); @@ -288,7 +300,7 @@ struct cgu_clk_map { const int (*const disable)(struct clk *clk); }; -static const struct cgu_clk_map clock_map[] = { +static const struct cgu_clk_map hsdk_clk_map[] = { [CLK_ARC_PLL] = { CGU_ARC_PLL, 0, &core_pll_dat, pll_get, pll_set, NULL }, [CLK_ARC] = { CGU_ARC_PLL, CGU_ARC_IDIV, &core_pll_dat, idiv_get, cpu_clk_set, idiv_off }, [CLK_DDR_PLL] = { CGU_DDR_PLL, 0, &sdt_pll_dat, pll_get, pll_set, NULL }, @@ -310,7 +322,37 @@ static const struct cgu_clk_map clock_map[] = { [CLK_SYS_UART_REF] = { CGU_SYS_PLL, CGU_SYS_IDIV_UART_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, [CLK_SYS_EBI_REF] = { CGU_SYS_PLL, CGU_SYS_IDIV_EBI_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, [CLK_TUN_PLL] = { CGU_TUN_PLL, 0, &sdt_pll_dat, pll_get, pll_set, NULL }, - [CLK_TUN_TUN] = { CGU_TUN_PLL, CGU_TUN_IDIV_TUN, &sdt_pll_dat, idiv_get, tun_clk_set, idiv_off }, + [CLK_TUN_TUN] = { CGU_TUN_PLL, CGU_TUN_IDIV_TUN, &sdt_pll_dat, idiv_get, tun_hsdk_set, idiv_off }, + [CLK_TUN_ROM] = { CGU_TUN_PLL, CGU_TUN_IDIV_ROM, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_TUN_PWM] = { CGU_TUN_PLL, CGU_TUN_IDIV_PWM, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_TUN_TIMER] = { /* missing in HSDK */ }, + [CLK_HDMI_PLL] = { CGU_HDMI_PLL, 0, &hdmi_pll_dat, pll_get, pll_set, NULL }, + [CLK_HDMI] = { CGU_HDMI_PLL, CGU_HDMI_IDIV_APB, &hdmi_pll_dat, idiv_get, idiv_set, idiv_off } +}; + +static const struct cgu_clk_map hsdk_4xd_clk_map[] = { + [CLK_ARC_PLL] = { CGU_ARC_PLL, 0, &core_pll_dat, pll_get, pll_set, NULL }, + [CLK_ARC] = { CGU_ARC_PLL, CGU_ARC_IDIV, &core_pll_dat, idiv_get, cpu_clk_set, idiv_off }, + [CLK_DDR_PLL] = { CGU_DDR_PLL, 0, &sdt_pll_dat, pll_get, pll_set, NULL }, + [CLK_SYS_PLL] = { CGU_SYS_PLL, 0, &sdt_pll_dat, pll_get, pll_set, NULL }, + [CLK_SYS_APB] = { CGU_SYS_PLL, CGU_SYS_IDIV_APB, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_AXI] = { CGU_SYS_PLL, CGU_SYS_IDIV_AXI, &sdt_pll_dat, idiv_get, axi_clk_set, idiv_off }, + [CLK_SYS_ETH] = { CGU_SYS_PLL, CGU_SYS_IDIV_ETH, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_USB] = { CGU_SYS_PLL, CGU_SYS_IDIV_USB, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_SDIO] = { CGU_SYS_PLL, CGU_SYS_IDIV_SDIO, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_HDMI] = { CGU_SYS_PLL, CGU_SYS_IDIV_HDMI, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_GFX_CORE] = { CGU_SYS_PLL, CGU_SYS_IDIV_GFX_CORE, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_GFX_DMA] = { /* missing in HSDK-4xD */ }, + [CLK_SYS_GFX_CFG] = { /* missing in HSDK-4xD */ }, + [CLK_SYS_DMAC_CORE] = { CGU_SYS_PLL, CGU_SYS_IDIV_DMAC_CORE, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_DMAC_CFG] = { CGU_SYS_PLL, CGU_SYS_IDIV_DMAC_CFG, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_SDIO_REF] = { CGU_SYS_PLL, CGU_SYS_IDIV_SDIO_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_SPI_REF] = { CGU_SYS_PLL, CGU_SYS_IDIV_SPI_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_I2C_REF] = { CGU_SYS_PLL, CGU_SYS_IDIV_I2C_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_UART_REF] = { CGU_SYS_PLL, CGU_SYS_IDIV_UART_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_SYS_EBI_REF] = { CGU_SYS_PLL, CGU_SYS_IDIV_EBI_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + [CLK_TUN_PLL] = { CGU_TUN_PLL, 0, &sdt_pll_dat, pll_get, pll_set, NULL }, + [CLK_TUN_TUN] = { CGU_TUN_PLL, CGU_TUN_IDIV_TUN, &sdt_pll_dat, idiv_get, tun_h4xd_set, idiv_off }, [CLK_TUN_ROM] = { CGU_TUN_PLL, CGU_TUN_IDIV_ROM, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, [CLK_TUN_PWM] = { CGU_TUN_PLL, CGU_TUN_IDIV_PWM, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, [CLK_TUN_TIMER] = { CGU_TUN_PLL, CGU_TUN_IDIV_TIMER, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, @@ -592,9 +634,14 @@ static ulong axi_clk_set(struct clk *sclk, ulong rate) return common_div_clk_set(sclk, rate, &axi_clk_cfg); } -static ulong tun_clk_set(struct clk *sclk, ulong rate) +static ulong tun_hsdk_set(struct clk *sclk, ulong rate) +{ + return common_div_clk_set(sclk, rate, &hsdk_tun_clk_cfg); +} + +static ulong tun_h4xd_set(struct clk *sclk, ulong rate) { - return common_div_clk_set(sclk, rate, &tun_clk_cfg); + return common_div_clk_set(sclk, rate, &hsdk_4xd_tun_clk_cfg); } static ulong idiv_set(struct clk *sclk, ulong rate) @@ -693,9 +740,14 @@ static int hsdk_cgu_clk_probe(struct udevice *dev) { struct hsdk_cgu_clk *hsdk_clk = dev_get_priv(dev); - BUILD_BUG_ON(ARRAY_SIZE(clock_map) != CGU_MAX_CLOCKS); + BUILD_BUG_ON(ARRAY_SIZE(hsdk_clk_map) != CGU_MAX_CLOCKS); + BUILD_BUG_ON(ARRAY_SIZE(hsdk_4xd_clk_map) != CGU_MAX_CLOCKS); - hsdk_clk->map = clock_map; + /* Choose which clock map to use in runtime */ + if ((read_aux_reg(ARC_AUX_IDENTITY) & 0xFF) == 0x52) + hsdk_clk->map = hsdk_clk_map; + else + hsdk_clk->map = hsdk_4xd_clk_map; hsdk_clk->cgu_regs = (void __iomem *)devfdt_get_addr_index(dev, 0); if (!hsdk_clk->cgu_regs)