diff options
author | Eugeniy Paltsev | 2020-05-07 22:20:10 +0300 |
---|---|---|
committer | Alexey Brodkin | 2020-05-13 18:09:27 +0300 |
commit | 80a7674ef9cb07ffa04d390a5eaf2ae001b1efe0 (patch) | |
tree | ca2c09b68df330800735189748b5926b372481b1 /drivers/clk | |
parent | 96b2142a543b93a065b157cceea81145ee205b64 (diff) |
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 <Eugeniy.Paltsev@synopsys.com>
Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
Diffstat (limited to 'drivers/clk')
-rw-r--r-- | drivers/clk/Kconfig | 7 | ||||
-rw-r--r-- | 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 <div64.h> #include <dm.h> #include <linux/io.h> +#include <asm/arcregs.h> #include <dt-bindings/clock/snps,hsdk-cgu.h> @@ -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) |