From 46d295f362587524e95bef81cf880d3dff602fcd Mon Sep 17 00:00:00 2001 From: Eugeniy Paltsev Date: Thu, 7 May 2020 16:59:54 +0300 Subject: [PATCH 01/11] CLK: ARC: HSDK: avoid code duplication 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 Signed-off-by: Alexey Brodkin --- 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 3035c5fb38..a51e78071a 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 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) { - 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 ret; + return common_div_clk_set(sclk, rate, &tun_clk_cfg); } static ulong idiv_set(struct clk *sclk, ulong rate) From 5a2706524cead82a58432e094d5d840c24a464a7 Mon Sep 17 00:00:00 2001 From: Eugeniy Paltsev Date: Thu, 7 May 2020 17:37:37 +0300 Subject: [PATCH 02/11] CLK: ARC: HSDK: drop unused offset Drop creg_div_oft offset as it doesn't vary (due to it is used for CPU PLL only). Signed-off-by: Eugeniy Paltsev Signed-off-by: Alexey Brodkin --- 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 a51e78071a..ad0b74fbdb 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 731f12f382d6b93feb12457410ad3a3eba057e65 Mon Sep 17 00:00:00 2001 From: Eugeniy Paltsev Date: Thu, 7 May 2020 17:52:11 +0300 Subject: [PATCH 03/11] CLK: ARC: HSDK: use appropriate config data types * constify clocks config data where is possible * use more appropriate data types for clocks config Signed-off-by: Eugeniy Paltsev Signed-off-by: Alexey Brodkin --- 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 ad0b74fbdb..30690b72f3 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 9b67ebd250e0a772c52f88a24bb53e42d9819f40 Mon Sep 17 00:00:00 2001 From: Eugeniy Paltsev Date: Thu, 7 May 2020 19:00:08 +0300 Subject: [PATCH 04/11] CLK: ARC: HSDK: driver cleanup Minor code cleanup to improve readability. No functional change intended. Signed-off-by: Eugeniy Paltsev Signed-off-by: Alexey Brodkin --- drivers/clk/clk-hsdk-cgu.c | 77 ++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/drivers/clk/clk-hsdk-cgu.c b/drivers/clk/clk-hsdk-cgu.c index 30690b72f3..d7cb4f4624 100644 --- a/drivers/clk/clk-hsdk-cgu.c +++ b/drivers/clk/clk-hsdk-cgu.c @@ -214,21 +214,26 @@ static const struct hsdk_pll_cfg hdmi_pll_cfg[] = { {} }; +struct hsdk_cgu_domain { + /* PLLs registers */ + void __iomem *pll_regs; + /* PLLs special registers */ + void __iomem *spec_regs; + /* PLLs 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; - /* PLLs registers */ - void __iomem *regs; - /* PLLs special registers */ - void __iomem *spec_regs; - /* PLLs devdata */ - const struct hsdk_pll_devdata *pll_devdata; - - /* Dividers registers */ - void __iomem *idiv_regs; + /* The domain we are working with */ + struct hsdk_cgu_domain curr_domain; }; struct hsdk_pll_devdata { @@ -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 debfe3844502d3a2d7a10c6bb21b5f43a3f1d249 Mon Sep 17 00:00:00 2001 From: Eugeniy Paltsev Date: Thu, 7 May 2020 20:10:30 +0300 Subject: [PATCH 05/11] CLK: ARC: HSDK: prepare for multiple clock maps support 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 Signed-off-by: Alexey Brodkin --- 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 d7cb4f4624..6aba4587a4 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 c6988688eefe985e4aca78488c424b9e09263da1 Mon Sep 17 00:00:00 2001 From: Eugeniy Paltsev Date: Thu, 7 May 2020 20:18:41 +0300 Subject: [PATCH 06/11] CLK: ARC: HSDK: make set_clock optional 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 Signed-off-by: Alexey Brodkin --- 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 6aba4587a4..dd665b1358 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 96b2142a543b93a065b157cceea81145ee205b64 Mon Sep 17 00:00:00 2001 From: Eugeniy Paltsev Date: Thu, 7 May 2020 20:31:01 +0300 Subject: [PATCH 07/11] CLK: ARC: HSDK: define clock map with DT binding constants Define clock map with DT binding constants so clock map can be discontinuous. Signed-off-by: Eugeniy Paltsev Signed-off-by: Alexey Brodkin --- 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 dd665b1358..a44382d958 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 80a7674ef9cb07ffa04d390a5eaf2ae001b1efe0 Mon Sep 17 00:00:00 2001 From: Eugeniy Paltsev Date: Thu, 7 May 2020 22:20:10 +0300 Subject: [PATCH 08/11] CLK: ARC: HSDK: add separate clock map for HSDK-4xD 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 Signed-off-by: Alexey Brodkin --- 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 1992d4a4b4..8b8b719999 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 a44382d958..2de3a6a30b 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, &tun_clk_cfg); + 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, &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) From d82ed6788edff59287f60ceaa54062cbd85943d9 Mon Sep 17 00:00:00 2001 From: Eugeniy Paltsev Date: Wed, 13 May 2020 18:15:12 +0300 Subject: [PATCH 09/11] ARC: DTS: cleanup USB node names Remove redundant '0x' from node names. Signed-off-by: Eugeniy Paltsev Signed-off-by: Alexey Brodkin --- arch/arc/dts/axs10x_mb.dtsi | 4 ++-- arch/arc/dts/hsdk-common.dtsi | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arc/dts/axs10x_mb.dtsi b/arch/arc/dts/axs10x_mb.dtsi index 5b77642b8d..33b0593438 100644 --- a/arch/arc/dts/axs10x_mb.dtsi +++ b/arch/arc/dts/axs10x_mb.dtsi @@ -62,12 +62,12 @@ max-speed = <100>; }; - ehci@0x40000 { + ehci@40000 { compatible = "generic-ehci"; reg = < 0x40000 0x100 >; }; - ohci@0x60000 { + ohci@60000 { compatible = "generic-ohci"; reg = < 0x60000 0x100 >; }; diff --git a/arch/arc/dts/hsdk-common.dtsi b/arch/arc/dts/hsdk-common.dtsi index fd4245e164..3b2ae8635d 100644 --- a/arch/arc/dts/hsdk-common.dtsi +++ b/arch/arc/dts/hsdk-common.dtsi @@ -84,12 +84,12 @@ phy-mode = "gmii"; }; - ehci@0xf0040000 { + ehci@f0040000 { compatible = "generic-ehci"; reg = <0xf0040000 0x100>; }; - ohci@0xf0060000 { + ohci@f0060000 { compatible = "generic-ohci"; reg = <0xf0060000 0x100>; }; From a8eb9b2672a623c61dcc2ed88033321a53f270d0 Mon Sep 17 00:00:00 2001 From: Eugeniy Paltsev Date: Wed, 29 Apr 2020 21:36:44 +0300 Subject: [PATCH 10/11] ARC: HSDK: anounce state of BIM switch Anounce state of BIM switch which defines if U-boot is loaded and started by preloader or not. Signed-off-by: Eugeniy Paltsev Signed-off-by: Alexey Brodkin --- board/synopsys/hsdk/hsdk.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/board/synopsys/hsdk/hsdk.c b/board/synopsys/hsdk/hsdk.c index a3e0563ff4..8ccd84ca60 100644 --- a/board/synopsys/hsdk/hsdk.c +++ b/board/synopsys/hsdk/hsdk.c @@ -42,6 +42,8 @@ DECLARE_GLOBAL_DATA_PTR; #define CREG_CPU_START_MASK 0xF #define CREG_CPU_START_POL BIT(4) +#define CREG_CORE_BOOT_IMAGE GENMASK(5, 4) + #define CREG_CPU_0_ENTRY (CREG_BASE + 0x404) #define SDIO_BASE (ARC_PERIPHERAL_BASE + 0xA000) @@ -1241,11 +1243,16 @@ int board_late_init(void) int checkboard(void) { + u32 reg; + printf("Board: Synopsys %s\n", board_name(get_board_type_runtime())); if (board_mismatch()) printf("WARN: U-boot is configured NOT for this board but for %s!\n", board_name(get_board_type_config())); + reg = readl(CREG_AXI_M_HS_CORE_BOOT) & CREG_CORE_BOOT_IMAGE; + printf("U-boot autostart: %s\n", reg ? "enabled" : "disabled"); + return 0; }; From bed6481940b1b9a2f3b48afeeced550dd84e2932 Mon Sep 17 00:00:00 2001 From: Eugeniy Paltsev Date: Wed, 13 May 2020 18:18:09 +0300 Subject: [PATCH 11/11] ARC: HSDK: add reset for EHCI Add reset phandle to EHCI device tree node to make on-chip reset controller usable with EHCI. Signed-off-by: Eugeniy Paltsev Signed-off-by: Alexey Brodkin --- arch/arc/dts/hsdk-common.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arc/dts/hsdk-common.dtsi b/arch/arc/dts/hsdk-common.dtsi index 3b2ae8635d..9aa10e4b25 100644 --- a/arch/arc/dts/hsdk-common.dtsi +++ b/arch/arc/dts/hsdk-common.dtsi @@ -87,6 +87,13 @@ ehci@f0040000 { compatible = "generic-ehci"; reg = <0xf0040000 0x100>; + + /* + * OHCI and EHCI have reset line shared so we don't add + * reset property to OHCI node as it is probed later and + * it will reset sucessfuly probed and configured EHCI HW. + */ + resets = <&cgu_rst HSDK_USB_RESET>; }; ohci@f0060000 {