[PATCH] 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 --- 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 a3e0563ff45..8ccd84ca600 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_MASK0xF #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; }; -- 2.21.1
[PATCH] 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 --- 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 fd4245e1646..ea6cc468f83 100644 --- a/arch/arc/dts/hsdk-common.dtsi +++ b/arch/arc/dts/hsdk-common.dtsi @@ -87,6 +87,13 @@ ehci@0xf004 { compatible = "generic-ehci"; reg = <0xf004 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@0xf006 { -- 2.21.3
[PATCH] ARC: DTS: cleanup USB node names
Remove redundant '0x' from node names. Signed-off-by: Eugeniy Paltsev --- 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 5b77642b8d7..33b05934387 100644 --- a/arch/arc/dts/axs10x_mb.dtsi +++ b/arch/arc/dts/axs10x_mb.dtsi @@ -62,12 +62,12 @@ max-speed = <100>; }; - ehci@0x4 { + ehci@4 { compatible = "generic-ehci"; reg = < 0x4 0x100 >; }; - ohci@0x6 { + ohci@6 { compatible = "generic-ohci"; reg = < 0x6 0x100 >; }; diff --git a/arch/arc/dts/hsdk-common.dtsi b/arch/arc/dts/hsdk-common.dtsi index ea6cc468f83..9aa10e4b25d 100644 --- a/arch/arc/dts/hsdk-common.dtsi +++ b/arch/arc/dts/hsdk-common.dtsi @@ -84,7 +84,7 @@ phy-mode = "gmii"; }; - ehci@0xf004 { + ehci@f004 { compatible = "generic-ehci"; reg = <0xf004 0x100>; @@ -96,7 +96,7 @@ resets = <&cgu_rst HSDK_USB_RESET>; }; - ohci@0xf006 { + ohci@f006 { compatible = "generic-ohci"; reg = <0xf006 0x100>; }; -- 2.21.3
[PATCH 2/8] 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 --- 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_p
[PATCH 0/8] 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 and do required code cleanup. Eugeniy Paltsev (8): CLK: ARC: HSDK: avoid code duplication CLK: ARC: HSDK: drop unused offset CLK: ARC: HSDK: use appropriate config data types CLK: ARC: HSDK: driver cleanup CLK: ARC: HSDK: prepare for multiple clock maps support CLK: ARC: HSDK: make set_clock optional CLK: ARC: HSDK: define clock map with DT binding constants CLK: ARC: HSDK: add separate clock map for HSDK-4xD drivers/clk/Kconfig| 7 +- drivers/clk/clk-hsdk-cgu.c | 355 + 2 files changed, 202 insertions(+), 160 deletions(-) -- 2.21.3
[PATCH 4/8] CLK: ARC: HSDK: driver cleanup
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++) +
[PATCH 3/8] 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 --- 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_VARIATIONS6 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); -- 2.21.3
[PATCH 5/8] 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 --- 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; -- 2.21.3
[PATCH 6/8] 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 --- 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) -- 2.21.3
[PATCH 1/8] 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 --- 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 2700 /* fixed clock - xtal */ #define CGU_MAX_CLOCKS 27 -#define CGU_SYS_CLOCKS 16 -#define MAX_AXI_CLOCKS 4 +#define MAX_FREQ_VARIATIONS6 -#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 = { { 2500, 5000, 7500, 1, 12500, 15000 }, { 6, 6, 6, 6, 75000, 6 }, { { 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 = { { 2,4, 6, 8 }, { 8,8, 6, 8 }, { { 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; -
[PATCH 8/8] 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 --- 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..8b8b715 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 = { { 2500, 5000, 7500, 1, 12500, 15000 }, { 6, 6, 6, 6, 75000, 6 }, { { 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 = { + { 2500, 5000, 7500, 1, 12500, 15000 }, + { 6, 6, 6, 6, 75000, 6 }, { + { 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 = { { 2,4, 6, 8 }, { 8,8, 6, 8 }, { @@ -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_ID
[PATCH 7/8] 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 --- 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
[PATCH] CMD: random: fix return code
As of today 'random' command return 1 (CMD_RET_FAILURE) in case of successful execution and 0 (CMD_RET_SUCCESS) in case of bad arguments. Fix that. NOTE: we remove printing usage information from command body so it won't print twice. Signed-off-by: Eugeniy Paltsev --- cmd/mem.c | 9 - 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cmd/mem.c b/cmd/mem.c index 6d54f195272..6b4897dfd94 100644 --- a/cmd/mem.c +++ b/cmd/mem.c @@ -1102,10 +1102,8 @@ static int do_random(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) unsigned char *buf8; unsigned int i; - if (argc < 3 || argc > 4) { - printf("usage: %s []\n", argv[0]); - return 0; - } + if (argc < 3 || argc > 4) + return CMD_RET_USAGE; len = simple_strtoul(argv[2], NULL, 16); addr = simple_strtoul(argv[1], NULL, 16); @@ -1132,7 +1130,8 @@ static int do_random(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) unmap_sysmem(start); printf("%lu bytes filled with random data\n", len); - return 1; + + return CMD_RET_SUCCESS; } #endif -- 2.21.1
[PATCH] ARC: fix up memory accessors
Commit 07906b3dad15 ("ARC: Switch to generic accessors") introduces a regression as it removes compiler barriers from __raw_readX \ __raw_writeX accessors. It breaks DW SPI driver (and possibly others) Let's fix that and return compiler barriers back. However that's not all. Let's add read/write barriers to __raw_readX \ __raw_writeX accessors as lots of drivers use them instead of regular readX \ writeX accessors. It will save us from lot's of debugging in the future and it is OK as U-Boot is not that performance oriented as real run-time software like OS or user bare-metal app so we may afford being not super fast as we only being executed once. Signed-off-by: Eugeniy Paltsev --- arch/arc/include/asm/io.h | 49 ++- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h index 70d050590de..46cf11ff893 100644 --- a/arch/arc/include/asm/io.h +++ b/arch/arc/include/asm/io.h @@ -64,21 +64,28 @@ static inline void sync(void) #define __arch_putl(v, a) (*(unsigned int *)(a) = (v)) #define __arch_putq(v, a) (*(unsigned long long *)(a) = (v)) -#define __raw_writeb(v, a) __arch_putb(v, a) -#define __raw_writew(v, a) __arch_putw(v, a) -#define __raw_writel(v, a) __arch_putl(v, a) -#define __raw_writeq(v, a) __arch_putq(v, a) +/* + * We add memory barriers for __raw_* operations as lots of U-boot driver uses + * then instead of proper accessor with barrier. + */ +#define __raw_writeb(v, c) ({ __iowmb(); __arch_putb(v, c); }) +#define __raw_writew(v, c) ({ __iowmb(); __arch_putw(v, c); }) +#define __raw_writel(v, c) ({ __iowmb(); __arch_putl(v, c); }) +#define __raw_writeq(v, c) ({ __iowmb(); __arch_putq(v, c); }) + +#define __raw_readb(c) ({ u8 __v = __arch_getb(c); __iormb(); __v; }) +#define __raw_readw(c) ({ u16 __v = __arch_getw(c); __iormb(); __v; }) +#define __raw_readl(c) ({ u32 __v = __arch_getl(c); __iormb(); __v; }) +#define __raw_readq(c) ({ u64 __v = __arch_getq(c); __iormb(); __v; }) -#define __raw_readb(a) __arch_getb(a) -#define __raw_readw(a) __arch_getw(a) -#define __raw_readl(a) __arch_getl(a) -#define __raw_readq(a) __arch_getq(a) static inline void __raw_writesb(unsigned long addr, const void *data, int bytelen) { u8 *buf = (uint8_t *)data; + __iowmb(); + while (bytelen--) __arch_putb(*buf++, addr); } @@ -88,6 +95,8 @@ static inline void __raw_writesw(unsigned long addr, const void *data, { u16 *buf = (uint16_t *)data; + __iowmb(); + while (wordlen--) __arch_putw(*buf++, addr); } @@ -97,6 +106,8 @@ static inline void __raw_writesl(unsigned long addr, const void *data, { u32 *buf = (uint32_t *)data; + __iowmb(); + while (longlen--) __arch_putl(*buf++, addr); } @@ -107,6 +118,8 @@ static inline void __raw_readsb(unsigned long addr, void *data, int bytelen) while (bytelen--) *buf++ = __arch_getb(addr); + + __iormb(); } static inline void __raw_readsw(unsigned long addr, void *data, int wordlen) @@ -115,6 +128,8 @@ static inline void __raw_readsw(unsigned long addr, void *data, int wordlen) while (wordlen--) *buf++ = __arch_getw(addr); + + __iormb(); } static inline void __raw_readsl(unsigned long addr, void *data, int longlen) @@ -123,6 +138,8 @@ static inline void __raw_readsl(unsigned long addr, void *data, int longlen) while (longlen--) *buf++ = __arch_getl(addr); + + __iormb(); } /* @@ -130,20 +147,20 @@ static inline void __raw_readsl(unsigned long addr, void *data, int longlen) * ordering rules but do not guarantee any ordering relative to Normal memory * accesses. */ -#define readb_relaxed(c) ({ u8 __r = __raw_readb(c); __r; }) +#define readb_relaxed(c) ({ u8 __r = __arch_getb(c); __r; }) #define readw_relaxed(c) ({ u16 __r = le16_to_cpu((__force __le16) \ - __raw_readw(c)); __r; }) + __arch_getw(c)); __r; }) #define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \ - __raw_readl(c)); __r; }) + __arch_getl(c)); __r; }) #define readq_relaxed(c) ({ u64 __r = le64_to_cpu((__force __le64) \ - __raw_readq(c)); __r; }) + __arch_getq(c)); __r; }) -#define writeb_relaxed(v, c) ((void)__raw_writeb((v), (c))) -#define writew_relaxed(v, c) ((void)__raw_writew((__force u16) \ +#define writeb_relaxed(v, c) ((void)__arch_putb((v), (c))) +#define writew_rela
[PATCH v2 0/3] ARC: IO: rework IO accessors
Fixing of DW SPI which was broken by commit 07906b3dad15 ("ARC: Switch to generic accessors") lead me to several fixes in ARC IO accessors code. Eugeniy Paltsev (3): ARC: IO: add volatile to accessors ARC: IO: add compiler barriers to IO accessors ARC: IO: add MB for __raw_* memory accessors arch/arc/include/asm/io.h | 93 +-- 1 file changed, 60 insertions(+), 33 deletions(-) -- 2.21.1
[PATCH v2 3/3] ARC: IO: add MB for __raw_* memory accessors
We add memory barriers for __raw_readX / __raw_writeX accessors same way as it is done for readX and writeX accessors as lots of U-boot driver uses __raw_readX / __raw_writeX instead of proper accessor with barrier. It will save us from lot's of debugging in the future and it is OK as U-Boot is not that performance oriented as real run-time software like OS or user bare-metal app so we may afford being not super fast as we only being executed once. Signed-off-by: Eugeniy Paltsev --- arch/arc/include/asm/io.h | 58 +++ 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h index 50c88456002..e770a1fe4b8 100644 --- a/arch/arc/include/asm/io.h +++ b/arch/arc/include/asm/io.h @@ -79,21 +79,29 @@ static inline void sync(void) #define __arch_putq(v, a) ({ __comp_b(); *(volatile u64 *)(a) = (v); __comp_b(); }) -#define __raw_writeb(v, a) __arch_putb(v, a) -#define __raw_writew(v, a) __arch_putw(v, a) -#define __raw_writel(v, a) __arch_putl(v, a) -#define __raw_writeq(v, a) __arch_putq(v, a) +/* + * We add memory barriers for __raw_readX / __raw_writeX accessors same way as + * it is done for readX and writeX accessors as lots of U-boot driver uses + * __raw_readX / __raw_writeX instead of proper accessor with barrier. + */ +#define __raw_writeb(v, c) ({ __iowmb(); __arch_putb(v, c); }) +#define __raw_writew(v, c) ({ __iowmb(); __arch_putw(v, c); }) +#define __raw_writel(v, c) ({ __iowmb(); __arch_putl(v, c); }) +#define __raw_writeq(v, c) ({ __iowmb(); __arch_putq(v, c); }) + +#define __raw_readb(c) ({ u8 __v = __arch_getb(c); __iormb(); __v; }) +#define __raw_readw(c) ({ u16 __v = __arch_getw(c); __iormb(); __v; }) +#define __raw_readl(c) ({ u32 __v = __arch_getl(c); __iormb(); __v; }) +#define __raw_readq(c) ({ u64 __v = __arch_getq(c); __iormb(); __v; }) -#define __raw_readb(a) __arch_getb(a) -#define __raw_readw(a) __arch_getw(a) -#define __raw_readl(a) __arch_getl(a) -#define __raw_readq(a) __arch_getq(a) static inline void __raw_writesb(unsigned long addr, const void *data, int bytelen) { u8 *buf = (uint8_t *)data; + __iowmb(); + while (bytelen--) __arch_putb(*buf++, addr); } @@ -103,6 +111,8 @@ static inline void __raw_writesw(unsigned long addr, const void *data, { u16 *buf = (uint16_t *)data; + __iowmb(); + while (wordlen--) __arch_putw(*buf++, addr); } @@ -112,6 +122,8 @@ static inline void __raw_writesl(unsigned long addr, const void *data, { u32 *buf = (uint32_t *)data; + __iowmb(); + while (longlen--) __arch_putl(*buf++, addr); } @@ -122,6 +134,8 @@ static inline void __raw_readsb(unsigned long addr, void *data, int bytelen) while (bytelen--) *buf++ = __arch_getb(addr); + + __iormb(); } static inline void __raw_readsw(unsigned long addr, void *data, int wordlen) @@ -130,6 +144,8 @@ static inline void __raw_readsw(unsigned long addr, void *data, int wordlen) while (wordlen--) *buf++ = __arch_getw(addr); + + __iormb(); } static inline void __raw_readsl(unsigned long addr, void *data, int longlen) @@ -138,6 +154,8 @@ static inline void __raw_readsl(unsigned long addr, void *data, int longlen) while (longlen--) *buf++ = __arch_getl(addr); + + __iormb(); } /* @@ -145,21 +163,15 @@ static inline void __raw_readsl(unsigned long addr, void *data, int longlen) * ordering rules but do not guarantee any ordering relative to Normal memory * accesses. */ -#define readb_relaxed(c) ({ u8 __r = __raw_readb(c); __r; }) -#define readw_relaxed(c) ({ u16 __r = le16_to_cpu((__force __le16) \ - __raw_readw(c)); __r; }) -#define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \ - __raw_readl(c)); __r; }) -#define readq_relaxed(c) ({ u64 __r = le64_to_cpu((__force __le64) \ - __raw_readq(c)); __r; }) - -#define writeb_relaxed(v, c) ((void)__raw_writeb((v), (c))) -#define writew_relaxed(v, c) ((void)__raw_writew((__force u16) \ - cpu_to_le16(v), (c))) -#define writel_relaxed(v, c) ((void)__raw_writel((__force u32) \ - cpu_to_le32(v), (c))) -#define writeq_relaxed(v, c) ((void)__raw_writeq((__force u64) \ - cpu_to_le64(v), (c))) +#define readb_relaxed(c) ({ u8 __r = __arch_getb(c); __r; }) +#define readw_relaxed(c) ({ u16 __r = le16_to_cpu((__force __le16)__arch_getw(c)); __r; }) +#d
[PATCH v2 1/3] ARC: IO: add volatile to accessors
We must use 'volatile' in C-version read/write IO accessors implementation to avoid merging several reads (writes) into one read (write), or optimizing them out by compiler. Fixes commit 07906b3dad15 ("ARC: Switch to generic accessors") Signed-off-by: Eugeniy Paltsev --- arch/arc/include/asm/io.h | 24 +++- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h index 70d050590de..1f1ae889f3a 100644 --- a/arch/arc/include/asm/io.h +++ b/arch/arc/include/asm/io.h @@ -54,15 +54,21 @@ static inline void sync(void) /* Not yet implemented */ } -#define __arch_getb(a) (*(unsigned char *)(a)) -#define __arch_getw(a) (*(unsigned short *)(a)) -#define __arch_getl(a) (*(unsigned int *)(a)) -#define __arch_getq(a) (*(unsigned long long *)(a)) - -#define __arch_putb(v, a) (*(unsigned char *)(a) = (v)) -#define __arch_putw(v, a) (*(unsigned short *)(a) = (v)) -#define __arch_putl(v, a) (*(unsigned int *)(a) = (v)) -#define __arch_putq(v, a) (*(unsigned long long *)(a) = (v)) +/* + * We must use 'volatile' in C-version read/write IO accessors implementation + * to avoid merging several reads (writes) into one read (write), or optimizing + * them out by compiler. + */ +#define __arch_getb(a) (*(volatile u8 *)(a)) +#define __arch_getw(a) (*(volatile u16 *)(a)) +#define __arch_getl(a) (*(volatile u32 *)(a)) +#define __arch_getq(a) (*(volatile u64 *)(a)) + +#define __arch_putb(v, a) (*(volatile u8 *)(a) = (v)) +#define __arch_putw(v, a) (*(volatile u16 *)(a) = (v)) +#define __arch_putl(v, a) (*(volatile u32 *)(a) = (v)) +#define __arch_putq(v, a) (*(volatile u64 *)(a) = (v)) + #define __raw_writeb(v, a) __arch_putb(v, a) #define __raw_writew(v, a) __arch_putw(v, a) -- 2.21.1
[PATCH v2 2/3] ARC: IO: add compiler barriers to IO accessors
We must use compiler barriers in C-version read/write IO accessors before and after operation (read or write) so it won't be reordered by compiler. Fixes commit 07906b3dad15 ("ARC: Switch to generic accessors") Signed-off-by: Eugeniy Paltsev --- arch/arc/include/asm/io.h | 31 --- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h index 1f1ae889f3a..50c88456002 100644 --- a/arch/arc/include/asm/io.h +++ b/arch/arc/include/asm/io.h @@ -9,6 +9,13 @@ #include #include + +/* + * Compiler barrier. It prevents compiler from reordering instructions before + * and after it. It doesn't prevent HW (CPU) from any reordering though. + */ +#define __comp_b() asm volatile("" : : : "memory") + #ifdef __ARCHS__ /* @@ -45,8 +52,8 @@ #define __iormb() rmb() #define __iowmb() wmb() #else -#define __iormb() asm volatile("" : : : "memory") -#define __iowmb() asm volatile("" : : : "memory") +#define __iormb() __comp_b() +#define __iowmb() __comp_b() #endif static inline void sync(void) @@ -58,16 +65,18 @@ static inline void sync(void) * We must use 'volatile' in C-version read/write IO accessors implementation * to avoid merging several reads (writes) into one read (write), or optimizing * them out by compiler. + * We must use compiler barriers before and after operation (read or write) so + * it won't be reordered by compiler. */ -#define __arch_getb(a) (*(volatile u8 *)(a)) -#define __arch_getw(a) (*(volatile u16 *)(a)) -#define __arch_getl(a) (*(volatile u32 *)(a)) -#define __arch_getq(a) (*(volatile u64 *)(a)) - -#define __arch_putb(v, a) (*(volatile u8 *)(a) = (v)) -#define __arch_putw(v, a) (*(volatile u16 *)(a) = (v)) -#define __arch_putl(v, a) (*(volatile u32 *)(a) = (v)) -#define __arch_putq(v, a) (*(volatile u64 *)(a) = (v)) +#define __arch_getb(a) ({ u8 __v; __comp_b(); __v = *(volatile u8 *)(a); __comp_b(); __v; }) +#define __arch_getw(a) ({ u16 __v; __comp_b(); __v = *(volatile u16 *)(a); __comp_b(); __v; }) +#define __arch_getl(a) ({ u32 __v; __comp_b(); __v = *(volatile u32 *)(a); __comp_b(); __v; }) +#define __arch_getq(a) ({ u64 __v; __comp_b(); __v = *(volatile u64 *)(a); __comp_b(); __v; }) + +#define __arch_putb(v, a) ({ __comp_b(); *(volatile u8 *)(a) = (v); __comp_b(); }) +#define __arch_putw(v, a) ({ __comp_b(); *(volatile u16 *)(a) = (v); __comp_b(); }) +#define __arch_putl(v, a) ({ __comp_b(); *(volatile u32 *)(a) = (v); __comp_b(); }) +#define __arch_putq(v, a) ({ __comp_b(); *(volatile u64 *)(a) = (v); __comp_b(); }) #define __raw_writeb(v, a) __arch_putb(v, a) -- 2.21.1
Re: [PATCH v1 6/8] spi: dw: Add mem_ops
Hi Sean, do you have branch with this code (all dw spi changes) in some public repo? I would like to test it with our board (which have DW SPI). --- Eugeniy Paltsev From: Sean Anderson Sent: Thursday, March 5, 2020 22:19 To: u-boot@lists.denx.de Cc: Simon Glass; Jagan Teki; Sean Anderson; Eugeniy Paltsev Subject: [PATCH v1 6/8] spi: dw: Add mem_ops The designware ssi device has "broken" chip select behaviour [1], and needs specific manipulation to use the built-in chip select. The existing fix is to use an external GPIO for chip select, but typically the K210 has SPI3 directly connected to a flash chip with dedicated pins. This makes it impossible to use the spi_xfer function to use spi, since the CS is de-asserted in between calls. This patch adds an implementation of exec_op, which gives correct behaviour when reading/writing spi flash. Work on this device has been difficult because the only example code I have to work off is Kendryte's sdk, and I do not have access to the datasheet (if anyone does, I would love to have a look!). The MMC device is still not working, but I have been making progress. [1] https://urldefense.proofpoint.com/v2/url?u=https-3A__lkml.org_lkml_2015_12_23_132&d=DwIDAg&c=DPL6_X_6JkXFx7AXWqB0tg&r=ZlJN1MriPUTkBKCrPSx67GmaplEUGcAEk9yPtCLdUXI&m=WVwKMzBXasdUvVoschXNTC5C7t39Ta0E7Ly3uEPRT_0&s=7dEhNfWpefL5yAqFi1Ztrve9SBPM_n3OoIJoH40hgpQ&e= Signed-off-by: Sean Anderson --- drivers/spi/designware_spi.c | 128 ++- 1 file changed, 126 insertions(+), 2 deletions(-) diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c index 613eb0d0e6..298d1dbab5 100644 --- a/drivers/spi/designware_spi.c +++ b/drivers/spi/designware_spi.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -108,8 +109,8 @@ struct dw_spi_priv { int len; u32 fifo_len; /* depth of the FIFO buffer */ - void *tx; - void *tx_end; + const void *tx; + const void *tx_end; void *rx; void *rx_end; @@ -471,6 +472,124 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen, return ret; } +/* + * This function is necessary for reading SPI flash with the native CS + * c.f. https://urldefense.proofpoint.com/v2/url?u=https-3A__lkml.org_lkml_2015_12_23_132&d=DwIDAg&c=DPL6_X_6JkXFx7AXWqB0tg&r=ZlJN1MriPUTkBKCrPSx67GmaplEUGcAEk9yPtCLdUXI&m=WVwKMzBXasdUvVoschXNTC5C7t39Ta0E7Ly3uEPRT_0&s=7dEhNfWpefL5yAqFi1Ztrve9SBPM_n3OoIJoH40hgpQ&e= + */ +static int dw_spi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op) +{ + bool read = op->data.dir == SPI_MEM_DATA_IN; + int pos, i, ret = 0; + struct udevice *bus = slave->dev->parent; + struct dw_spi_platdata *plat = dev_get_platdata(bus); + struct dw_spi_priv *priv = dev_get_priv(bus); + u8 op_len = sizeof(op->cmd.opcode) + op->addr.nbytes + op->dummy.nbytes; + u8 op_buf[op_len]; + u32 cr0; + + if (read) + priv->tmode = SPI_TMOD_EPROMREAD; + else + priv->tmode = SPI_TMOD_TO; + + debug("%s: buf=%p len=%u [bytes]\n", + __func__, op->data.buf.in, op->data.nbytes); + + cr0 = GEN_CTRL0(priv, plat); + debug("%s: cr0=%08x\n", __func__, cr0); + + spi_enable_chip(priv, 0); + dw_write(priv, DW_SPI_CTRL0, cr0); + if (read) + dw_write(priv, DW_SPI_CTRL1, op->data.nbytes - 1); + spi_enable_chip(priv, 1); + + /* From spi_mem_exec_op */ + pos = 0; + op_buf[pos++] = op->cmd.opcode; + if (op->addr.nbytes) { + for (i = 0; i < op->addr.nbytes; i++) + op_buf[pos + i] = op->addr.val >> + (8 * (op->addr.nbytes - i - 1)); + + pos += op->addr.nbytes; + } + if (op->dummy.nbytes) + memset(op_buf + pos, 0xff, op->dummy.nbytes); + + priv->tx = &op_buf; + priv->tx_end = priv->tx + op_len; + priv->rx = NULL; + priv->rx_end = NULL; + while (priv->tx != priv->tx_end) { + dw_writer(priv); + /* This loop needs a delay otherwise we can hang */ + udelay(1); + } + + /* +* XXX: The following are tight loops! Enabling debug messages may cause +* them to fail because we are not reading/writing the fifo fast enough. +* +* We heuristically break out of the loop when we stop getting data. +* This is to stop us from hanging if the device doesn't send any data +* (either at all, or after sending a response). For example, one flash +* chip I tested did not send anything back after the first 64K of data. +
Re: [PATCH v1 6/8] spi: dw: Add mem_ops
Hi Sean, I've tested the SPI (with SPI flash) on HSDK board (which have DW SPI) with your changes. It completely break SPI on HSDK: ->8-- # sf probe unrecognized JEDEC id bytes: ff, ff, ff Failed to initialize SPI flash at 0:0 (error -2) ->8-- Tested from maix_spi HEAD (e338571bf528f58b3ced7fbd0c1f5d923caa1cfd) --- Eugeniy Paltsev From: Sean Anderson Sent: Friday, March 6, 2020 03:48 To: Eugeniy Paltsev; u-boot@lists.denx.de Cc: Simon Glass; Jagan Teki; Alexey Brodkin Subject: Re: [PATCH v1 6/8] spi: dw: Add mem_ops On 3/5/20 5:15 PM, Eugeniy Paltsev wrote: > Hi Sean, > > do you have branch with this code (all dw spi changes) in some public repo? > I would like to test it with our board (which have DW SPI). > > --- > Eugeniy Paltsev A full tree is available at https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_Forty-2DBot_u-2Dboot_tree_maix-5Fspi&d=DwICaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=ZlJN1MriPUTkBKCrPSx67GmaplEUGcAEk9yPtCLdUXI&m=EmfUzvFjhqLxmNa2GVtV9Ph9bW4C8gFi0EhXqFqucSU&s=23UJFSwfnLIPXRyp6h_whXzJJJCbiceE8X6ydfb11_A&e= --Sean
[PATCH 0/2] ARC cache subsystem updates
Eugeniy Paltsev (2): ARC: CACHE: add support for SL$ disable ARC: CACHE: mark IOC helper functions as inlined_cachefunc arch/arc/include/asm/cache.h | 7 +++ arch/arc/lib/cache.c | 118 --- 2 files changed, 116 insertions(+), 9 deletions(-) -- 2.21.1
[PATCH 2/2] ARC: CACHE: mark IOC helper functions as inlined_cachefunc
Force inlining of IOC related functions used in other cache functions. This is preventive change. Signed-off-by: Eugeniy Paltsev --- arch/arc/lib/cache.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index c42723daeb2..8a1d67870a8 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -179,7 +179,7 @@ DECLARE_GLOBAL_DATA_PTR; static inlined_cachefunc void __ic_entire_invalidate(void); static inlined_cachefunc void __dc_entire_op(const int cacheop); static inlined_cachefunc void __slc_entire_op(const int op); -static inline bool ioc_enabled(void); +static inlined_cachefunc bool ioc_enabled(void); static inline bool pae_exists(void) { @@ -346,7 +346,7 @@ void slc_disable(void) __slc_disable(); } -static inline bool ioc_exists(void) +static inlined_cachefunc bool ioc_exists(void) { if (is_isa_arcv2()) { union bcr_clust_cfg cbcr; @@ -358,7 +358,7 @@ static inline bool ioc_exists(void) return false; } -static inline bool ioc_enabled(void) +static inlined_cachefunc bool ioc_enabled(void) { /* * We check only CONFIG option instead of IOC HW state check as IOC -- 2.21.1
[PATCH 1/2] ARC: CACHE: add support for SL$ disable
Since version 3.0 ARC HS supports SL$ (L2 system level cache) disable. So add support for SL$ disable/enable to code. Signed-off-by: Eugeniy Paltsev --- arch/arc/include/asm/cache.h | 7 +++ arch/arc/lib/cache.c | 114 --- 2 files changed, 114 insertions(+), 7 deletions(-) diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h index 0fdcf2d2dd5..ab61846b5ab 100644 --- a/arch/arc/include/asm/cache.h +++ b/arch/arc/include/asm/cache.h @@ -40,6 +40,13 @@ static const inline int is_ioc_enabled(void) return IS_ENABLED(CONFIG_ARC_DBG_IOC_ENABLE); } +/* + * We export SLC control functions to use them in platform configuration code. + * They maust not be used in any generic code! + */ +void slc_enable(void); +void slc_disable(void); + #endif /* __ASSEMBLY__ */ #endif /* __ASM_ARC_CACHE_H */ diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index 1340776c669..c42723daeb2 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -89,8 +89,7 @@ * * [ NOTE 2 ]: * As of today we only support the following cache configurations on ARC. - * Other configurations may exist in HW (for example, since version 3.0 HS - * supports SL$ (L2 system level cache) disable) but we don't support it in SW. + * Other configurations may exist in HW but we don't support it in SW. * Configuration 1: *__ * | | @@ -120,7 +119,8 @@ * | | * | L2 (SL$) | * |__| - * always must be on + * always on (ARCv2, HS < 3.0) + * on/off(ARCv2, HS >= 3.0) *___|__| * | | * | main memory| @@ -178,6 +178,8 @@ DECLARE_GLOBAL_DATA_PTR; static inlined_cachefunc void __ic_entire_invalidate(void); static inlined_cachefunc void __dc_entire_op(const int cacheop); +static inlined_cachefunc void __slc_entire_op(const int op); +static inline bool ioc_enabled(void); static inline bool pae_exists(void) { @@ -238,6 +240,70 @@ static inlined_cachefunc bool slc_exists(void) return false; } +enum slc_dis_status { + ST_SLC_MISSING = 0, + ST_SLC_NO_DISABLE_CTRL, + ST_SLC_DISABLE_CTRL +}; + +/* + * ARCv1 -> ST_SLC_MISSING + * ARCv2 && SLC absent -> ST_SLC_MISSING + * ARCv2 && SLC exists && SLC version <= 2 -> ST_SLC_NO_DISABLE_CTRL + * ARCv2 && SLC exists && SLC version > 2-> ST_SLC_DISABLE_CTRL + */ +static inlined_cachefunc enum slc_dis_status slc_disable_supported(void) +{ + if (is_isa_arcv2()) { + union bcr_generic sbcr; + + sbcr.word = read_aux_reg(ARC_BCR_SLC); + if (sbcr.fields.ver == 0) + return ST_SLC_MISSING; + else if (sbcr.fields.ver <= 2) + return ST_SLC_NO_DISABLE_CTRL; + else + return ST_SLC_DISABLE_CTRL; + } + + return ST_SLC_MISSING; +} + +static inlined_cachefunc bool __slc_enabled(void) +{ + return !(read_aux_reg(ARC_AUX_SLC_CTRL) & SLC_CTRL_DIS); +} + +static inlined_cachefunc void __slc_enable(void) +{ + unsigned int ctrl; + + ctrl = read_aux_reg(ARC_AUX_SLC_CTRL); + ctrl &= ~SLC_CTRL_DIS; + write_aux_reg(ARC_AUX_SLC_CTRL, ctrl); +} + +static inlined_cachefunc void __slc_disable(void) +{ + unsigned int ctrl; + + ctrl = read_aux_reg(ARC_AUX_SLC_CTRL); + ctrl |= SLC_CTRL_DIS; + write_aux_reg(ARC_AUX_SLC_CTRL, ctrl); +} + +static inlined_cachefunc bool slc_enabled(void) +{ + enum slc_dis_status slc_status = slc_disable_supported(); + + if (slc_status == ST_SLC_MISSING) + return false; + else if (slc_status == ST_SLC_NO_DISABLE_CTRL) + return true; + else + return __slc_enabled(); +} + static inlined_cachefunc bool slc_data_bypass(void) { /* @@ -247,6 +313,39 @@ static inlined_cachefunc bool slc_data_bypass(void) return !dcache_enabled(); } +void slc_enable(void) +{ + if (slc_disable_supported() != ST_SLC_DISABLE_CTRL) + return; + + if (__slc_enabled()) + return; + + __slc_enable(); +} + +/* TODO: warn if we are not able to disable SLC */ +void slc_disable(void) +{ + if (slc_disable_supported() != ST_SLC_DISABLE_CTRL) + return; + + /* we don't support SLC disabling if we use IOC */ + if (ioc_enabled()) + return; + + if (!__slc_enabled()) + return; + + /* +* We need to flush L1D$ to guarantee that we won't have any +* writeback operations during SLC disabling. +*/ + __dc_entire_op(OP_FLUSH); + __s
[PATCH] ARC: HSDK: Enable on-chip reset controller
As the driver of on-chip reset controller became available we are ready to enable it. Signed-off-by: Eugeniy Paltsev --- arch/arc/dts/hsdk.dts | 7 +++ configs/hsdk_defconfig | 1 + 2 files changed, 8 insertions(+) diff --git a/arch/arc/dts/hsdk.dts b/arch/arc/dts/hsdk.dts index 34ef3a620a3..cf2ce8a1f6c 100644 --- a/arch/arc/dts/hsdk.dts +++ b/arch/arc/dts/hsdk.dts @@ -6,6 +6,7 @@ #include "skeleton.dtsi" #include "dt-bindings/clock/snps,hsdk-cgu.h" +#include "dt-bindings/reset/snps,hsdk-reset.h" / { model = "snps,hsdk"; @@ -62,6 +63,12 @@ #clock-cells = <1>; }; + cgu_rst: reset-controller@f8a0 { + compatible = "snps,hsdk-reset"; + #reset-cells = <1>; + reg = <0xf8a0 0x4>, <0xfff0 0x4>; + }; + uart0: serial0@f0005000 { compatible = "snps,dw-apb-uart"; reg = <0xf0005000 0x1000>; diff --git a/configs/hsdk_defconfig b/configs/hsdk_defconfig index 4830158d55a..84b22ed7c04 100644 --- a/configs/hsdk_defconfig +++ b/configs/hsdk_defconfig @@ -47,6 +47,7 @@ CONFIG_SPI_FLASH_SST=y CONFIG_DM_ETH=y CONFIG_ETH_DESIGNWARE=y CONFIG_MII=y +CONFIG_DM_RESET=y CONFIG_DM_SERIAL=y CONFIG_DEBUG_UART_SHIFT=2 CONFIG_DEBUG_UART_ANNOUNCE=y -- 2.21.1
Re: [PATCH v1 6/8] spi: dw: Add mem_ops
Hi Sean, even after fixing build errors with this patch I still have issues with communications to flash IC. Now it is detected correctly (JEDEC id is valid) but I have issues with read or write. I need to look to that more intently. --- Eugeniy Paltsev From: Sean Anderson Sent: Saturday, March 7, 2020 00:20 To: Eugeniy Paltsev; u-boot@lists.denx.de Cc: Simon Glass; Jagan Teki; Alexey Brodkin Subject: Re: [PATCH v1 6/8] spi: dw: Add mem_ops On 3/6/20 12:03 PM, Eugeniy Paltsev wrote: > Hi Sean, > > I've tested the SPI (with SPI flash) on HSDK board (which have DW SPI) with > your changes. > It completely break SPI on HSDK: > > ->8-- > # sf probe > unrecognized JEDEC id bytes: ff, ff, ff > Failed to initialize SPI flash at 0:0 (error -2) > ->8-- > > Tested from maix_spi HEAD (e338571bf528f58b3ced7fbd0c1f5d923caa1cfd) > > --- > Eugeniy Paltsev Actually, it just occured to me that I did not add support for a gpio cs to the xfer function, so it's likely that the chip is not enabling the cs. Can you try testing with the following patch --- drivers/spi/designware_spi.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c index 298d1dbab5..a4e3dbd948 100644 --- a/drivers/spi/designware_spi.c +++ b/drivers/spi/designware_spi.c @@ -517,6 +517,8 @@ static int dw_spi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op) if (op->dummy.nbytes) memset(op_buf + pos, 0xff, op->dummy.nbytes); + external_cs_manage(dev, false); + priv->tx = &op_buf; priv->tx_end = priv->tx + op_len; priv->rx = NULL; @@ -586,6 +588,8 @@ static int dw_spi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op) } dw_write(priv, DW_SPI_SER, 0); + external_cs_manage(dev, true); + debug("%s: %u bytes xfered\n", __func__, op->data.nbytes); return ret; } -- 2.25.0
[U-Boot] [PATCH] ARC: enable unit tests on development platforms
Enable unit tests on HSDK and AXS103 development platforms to run it in verification flow. Signed-off-by: Eugeniy Paltsev --- configs/axs103_defconfig | 2 ++ configs/hsdk_defconfig | 2 ++ 2 files changed, 4 insertions(+) diff --git a/configs/axs103_defconfig b/configs/axs103_defconfig index 8255d9fa068..73a224fa145 100644 --- a/configs/axs103_defconfig +++ b/configs/axs103_defconfig @@ -59,3 +59,5 @@ CONFIG_USB_OHCI_HCD=y CONFIG_USB_OHCI_GENERIC=y CONFIG_USB_STORAGE=y CONFIG_USE_PRIVATE_LIBGCC=y +CONFIG_UNIT_TEST=y +CONFIG_UT_TIME=y diff --git a/configs/hsdk_defconfig b/configs/hsdk_defconfig index e28ceae289c..c0b45513afd 100644 --- a/configs/hsdk_defconfig +++ b/configs/hsdk_defconfig @@ -63,3 +63,5 @@ CONFIG_USB_OHCI_GENERIC=y CONFIG_USB_STORAGE=y CONFIG_USE_PRIVATE_LIBGCC=y CONFIG_PANIC_HANG=y +CONFIG_UNIT_TEST=y +CONFIG_UT_TIME=y -- 2.21.0 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[PATCH] ARC: HSDK: CGU: fix tunnel clock calculation
We set wrong tunnel PLL frequency when we request 125MHz tunnel clock. Fix that. Signed-off-by: Eugeniy Paltsev --- drivers/clk/clk-hsdk-cgu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk-hsdk-cgu.c b/drivers/clk/clk-hsdk-cgu.c index 4637b9fdf15..6eaafdeaf99 100644 --- a/drivers/clk/clk-hsdk-cgu.c +++ b/drivers/clk/clk-hsdk-cgu.c @@ -144,7 +144,7 @@ struct hsdk_tun_clk_cfg { static const struct hsdk_tun_clk_cfg tun_clk_cfg = { { 2500, 5000, 7500, 1, 12500, 15000 }, - { 6, 6, 6, 6, 7, 6 }, { + { 6, 6, 6, 6, 75000, 6 }, { { 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 } } @@ -205,6 +205,7 @@ static const struct hsdk_pll_cfg asdt_pll_cfg[] = { { 5, 0, 14, 1, 0 }, { 6, 0, 17, 1, 0 }, { 7, 0, 20, 1, 0 }, + { 75000, 1, 44, 1, 0 }, { 8, 0, 23, 1, 0 }, { 9, 1, 26, 0, 0 }, { 10, 1, 29, 0, 0 }, -- 2.21.1
[PATCH] ARC: AXS10x: cleanup kconfig
As we've dropped NAND support for AXS101 and AXS103 see commit 4f5e552d95bb ("ARC: AXS10x: drop NAND support") we don't need bounce buffer anymore. Signed-off-by: Eugeniy Paltsev --- arch/arc/Kconfig | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index ea875711e70..6ff201fa816 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -164,11 +164,9 @@ config TARGET_NSIM config TARGET_AXS101 bool "Support Synopsys Designware SDP board AXS101" - select BOUNCE_BUFFER if CMD_NAND config TARGET_AXS103 bool "Support Synopsys Designware SDP board AXS103" - select BOUNCE_BUFFER if CMD_NAND config TARGET_EMSDP bool "Synopsys EM Software Development Platform" -- 2.21.1
[PATCH 00/14] ARC: add HSDK-4xD board support
Eugeniy Paltsev (14): ARC: ARCv2: handle DSP presence in HW ARC: HSDK: CGU: add support for timer clock ARC: HSDK-4xD: add initial board support ARC: HSDK: split HSDK and HSDK-4xD DTS ARC: HSDK-4xD: use active low polarity of cpu_start pulse ARC: HSDK-4xD: fix headerize script for HSDK-4xD compatibility ARC: HSDK-4xD: print info about HDMI clocks ARC: HSDK-4xD: drop additional GPU clock info ARC: HSDK-4xD: print timer clock value ARC: HSDK-4xD: add support for SLC enable/disable ARC: HSDK-4xD: add CSM configuration support ARC: HSDK-4xD: tweak memory map ARC: HSDK-4xD: use separate config file ARC: HSDK-4xD: make init status resistant to U-boot reloading arch/arc/Kconfig | 2 +- arch/arc/dts/Makefile | 2 +- arch/arc/dts/hsdk-4xd.dts | 12 ++ arch/arc/dts/hsdk-common.dtsi | 152 + arch/arc/dts/hsdk.dts | 145 + arch/arc/include/asm/arcregs.h| 4 + arch/arc/lib/start.S | 15 ++ board/synopsys/hsdk/Kconfig | 20 +- board/synopsys/hsdk/MAINTAINERS | 5 +- board/synopsys/hsdk/config.mk | 16 ++ board/synopsys/hsdk/headerize-hsdk.py | 2 +- board/synopsys/hsdk/hsdk.c| 251 -- configs/hsdk_4xd_defconfig| 67 ++ drivers/clk/clk-hsdk-cgu.c| 9 +- include/configs/hsdk-4xd.h| 120 +++ include/dt-bindings/clock/snps,hsdk-cgu.h | 5 +- 16 files changed, 657 insertions(+), 170 deletions(-) create mode 100644 arch/arc/dts/hsdk-4xd.dts create mode 100644 arch/arc/dts/hsdk-common.dtsi create mode 100644 configs/hsdk_4xd_defconfig create mode 100644 include/configs/hsdk-4xd.h -- 2.21.1
[PATCH 01/14] ARC: ARCv2: handle DSP presence in HW
In case of DSP extension presence in HW some instructions (related to integer multiply, multiply-accumulate, and divide operation) executes on this DSP execution unit. So their execution will depend on dsp configuration register (DSP_CTRL) As we want these instructions to execute the same way regardless of DSP presence we need to set DSP_CTRL properly. NOTE: we do the same adjustments in Linux kernel, see in kernel tree: commit 4827d0cf744e ("ARC: handle DSP presence in HW") Signed-off-by: Eugeniy Paltsev --- arch/arc/include/asm/arcregs.h | 1 + arch/arc/lib/start.S | 15 +++ 2 files changed, 16 insertions(+) diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h index fff6591c681..f3cd4a889ac 100644 --- a/arch/arc/include/asm/arcregs.h +++ b/arch/arc/include/asm/arcregs.h @@ -100,6 +100,7 @@ /* DSP-extensions related auxiliary registers */ #define ARC_AUX_DSP_BUILD 0x7A +#define ARC_AUX_DSP_CTRL 0x59F /* ARC Subsystems related auxiliary registers */ #define ARC_AUX_SUBSYS_BUILD 0xF0 diff --git a/arch/arc/lib/start.S b/arch/arc/lib/start.S index 8c744f5be7f..016ae85be23 100644 --- a/arch/arc/lib/start.S +++ b/arch/arc/lib/start.S @@ -61,6 +61,21 @@ ENTRY(_start) 1: #endif +#ifdef CONFIG_ISA_ARCV2 + ; In case of DSP extension presence in HW some instructions + ; (related to integer multiply, multiply-accumulate, and divide + ; operation) executes on this DSP execution unit. So their + ; execution will depend on dsp configuration register (DSP_CTRL) + ; As we want these instructions to execute the same way regardless + ; of DSP presence we need to set DSP_CTRL properly. + lr r5, [ARC_AUX_DSP_BUILD] + bmskr5, r5, 7 + breqr5, 0, 1f + mov r5, 0 + sr r5, [ARC_AUX_DSP_CTRL] +1: +#endif + #ifdef __ARC_UNALIGNED__ /* * Enable handling of unaligned access in the CPU as by default -- 2.21.1
[PATCH 03/14] ARC: HSDK-4xD: add initial board support
Add initial HSDK-4xD board support. The ARC HS4x/HS4xD Development Kit includes a multicore ARC HS4xD-based chip that integrates a wide range of interfaces including Ethernet, HDMI, WiFi, Bluetooth, USB, SDIO, I2C, SPI, UART, I2S, ADC, PWM and GPIO, as well as a Think Silicon GPU. Signed-off-by: Eugeniy Paltsev --- arch/arc/Kconfig| 2 +- board/synopsys/hsdk/Kconfig | 17 board/synopsys/hsdk/MAINTAINERS | 3 +- board/synopsys/hsdk/config.mk | 8 board/synopsys/hsdk/hsdk.c | 71 - configs/hsdk_4xd_defconfig | 67 +++ 6 files changed, 164 insertions(+), 4 deletions(-) create mode 100644 configs/hsdk_4xd_defconfig diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 63413d90bb2..6ff201fa816 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -173,7 +173,7 @@ config TARGET_EMSDP select CPU_ARCEM6 config TARGET_HSDK - bool "Support Synpsys HS DevelopmentKit board" + bool "Support Synopsys HSDK or HSDK-4xD board" config TARGET_IOT_DEVKIT bool "Synopsys Brite IoT Development kit" diff --git a/board/synopsys/hsdk/Kconfig b/board/synopsys/hsdk/Kconfig index e8c00a6e7d0..5e23b3229a9 100644 --- a/board/synopsys/hsdk/Kconfig +++ b/board/synopsys/hsdk/Kconfig @@ -9,4 +9,21 @@ config SYS_VENDOR config SYS_CONFIG_NAME default "hsdk" +choice + prompt "HSDK board type" + default BOARD_HSDK + +config BOARD_HSDK + bool "ARC HS Development Kit" + help + ARC HS Development Kit based on quard core ARC HS38 processor + +config BOARD_HSDK_4XD + bool "ARC HS4x/HS4xD Development Kit" + help + ARC HS4x/HS4xD Development Kit based on quard core ARC HS48/HS47D + processor + +endchoice + endif diff --git a/board/synopsys/hsdk/MAINTAINERS b/board/synopsys/hsdk/MAINTAINERS index e22bd1e40b2..d385951048f 100644 --- a/board/synopsys/hsdk/MAINTAINERS +++ b/board/synopsys/hsdk/MAINTAINERS @@ -1,5 +1,6 @@ -HSDK BOARD +HSDK BOARDs M: Eugeniy Paltsev S: Maintained F: board/synopsys/hsdk/ F: configs/hsdk_defconfig +F: configs/hsdk_4xd_defconfig diff --git a/board/synopsys/hsdk/config.mk b/board/synopsys/hsdk/config.mk index 5ae22fa2b75..1d01ef50379 100644 --- a/board/synopsys/hsdk/config.mk +++ b/board/synopsys/hsdk/config.mk @@ -2,9 +2,17 @@ # # Copyright (C) 2018 Synopsys, Inc. All rights reserved. +ifdef CONFIG_BOARD_HSDK PLATFORM_CPPFLAGS += -mcpu=hs38_linux -mlittle-endian -matomic -mll64 \ -mdiv-rem -mswap -mnorm -mmpy-option=9 -mbarrel-shifter \ -mfpu=fpud_all +endif + +ifdef CONFIG_BOARD_HSDK_4XD +PLATFORM_CPPFLAGS += -mcpu=hs4x_rel31 -mlittle-endian -matomic -mll64 \ + -mdiv-rem -mswap -mnorm -mmpy-option=9 -mbarrel-shifter \ + -mfpu=fpud_all +endif bsp-generate: u-boot u-boot.bin $(Q)python3 $(srctree)/board/$(BOARDDIR)/headerize-hsdk.py \ diff --git a/board/synopsys/hsdk/hsdk.c b/board/synopsys/hsdk/hsdk.c index 67a29e334d7..771f7bbf886 100644 --- a/board/synopsys/hsdk/hsdk.c +++ b/board/synopsys/hsdk/hsdk.c @@ -154,6 +154,56 @@ static const struct env_map_percpu env_map_go[] = { {} }; +enum board_type { + T_BOARD_NONE, + T_BOARD_HSDK, + T_BOARD_HSDK_4XD +}; + +static inline enum board_type get_board_type_runtime(void) +{ + u32 arc_id = read_aux_reg(ARC_AUX_IDENTITY) & 0xFF; + + if (arc_id == 0x52) + return T_BOARD_HSDK; + else if (arc_id == 0x54) + return T_BOARD_HSDK_4XD; + else + return T_BOARD_NONE; +} + +static inline enum board_type get_board_type_config(void) +{ + if (IS_ENABLED(CONFIG_BOARD_HSDK)) + return T_BOARD_HSDK; + else if (IS_ENABLED(CONFIG_BOARD_HSDK_4XD)) + return T_BOARD_HSDK_4XD; + else + return T_BOARD_NONE; +} + +static bool is_board_match_runtime(enum board_type type_req) +{ + return get_board_type_runtime() == type_req; +} + +static const char * board_name(enum board_type type) +{ + switch (type) { + case T_BOARD_HSDK: + return "ARC HS Development Kit"; + case T_BOARD_HSDK_4XD: + return "ARC HS4x/HS4xD Development Kit"; + default: + return "?"; + } +} + +static bool board_mismatch(void) +{ + return get_board_type_config() != get_board_type_runtime(); +} + static void sync_cross_cpu_data(void) { u32 value; @@ -221,7 +271,9 @@ static void init_cluster_nvlim(void) flush_dcache_all(); write_aux_reg(ARC_AUX_NON_VOLATILE_LIMIT, val); - write_aux_reg(AUX_AUX_CACHE_LIMIT, val); + /* AUX_AUX_CACHE_LIMIT reg is missing starting from HS48 */
[PATCH 05/14] ARC: HSDK-4xD: use active low polarity of cpu_start pulse
Add quirk for HSDK-4xD - due to HW issues HSDK can use any pulse polarity but HSDK-4xD require active low polarity of cpu_start pulse. So use low polarity of cpu_start pulse for both board. Signed-off-by: Eugeniy Paltsev --- board/synopsys/hsdk/hsdk.c | 26 +++--- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/board/synopsys/hsdk/hsdk.c b/board/synopsys/hsdk/hsdk.c index 771f7bbf886..577893de2a1 100644 --- a/board/synopsys/hsdk/hsdk.c +++ b/board/synopsys/hsdk/hsdk.c @@ -40,6 +40,7 @@ DECLARE_GLOBAL_DATA_PTR; #define CREG_BASE (ARC_PERIPHERAL_BASE + 0x1000) #define CREG_CPU_START (CREG_BASE + 0x400) #define CREG_CPU_START_MASK0xF +#define CREG_CPU_START_POL BIT(4) #define SDIO_BASE (ARC_PERIPHERAL_BASE + 0xA000) #define SDIO_UHS_REG_EXT (SDIO_BASE + 0x108) @@ -331,25 +332,36 @@ static inline void halt_this_cpu(void) __builtin_arc_flag(1); } -static void smp_kick_cpu_x(u32 cpu_id) +static u32 get_masked_cpu_ctart_reg(void) { int cmd = readl((void __iomem *)CREG_CPU_START); + /* +* Quirk for HSDK-4xD - due to HW issues HSDK can use any pulse polarity +* and HSDK-4xD require active low polarity of cpu_start pulse. +*/ + cmd &= ~CREG_CPU_START_POL; + + cmd &= ~CREG_CPU_START_MASK; + + return cmd; +} + +static void smp_kick_cpu_x(u32 cpu_id) +{ + int cmd; + if (cpu_id > NR_CPUS) return; - cmd &= ~CREG_CPU_START_MASK; + cmd = get_masked_cpu_ctart_reg(); cmd |= (1 << cpu_id); writel(cmd, (void __iomem *)CREG_CPU_START); } static u32 prepare_cpu_ctart_reg(void) { - int cmd = readl((void __iomem *)CREG_CPU_START); - - cmd &= ~CREG_CPU_START_MASK; - - return cmd | env_common.core_mask.val; + return get_masked_cpu_ctart_reg() | env_common.core_mask.val; } /* slave CPU entry for configuration */ -- 2.21.1
[PATCH 02/14] ARC: HSDK: CGU: add support for timer clock
Add support for additional timer clock which belongs to tunnel domain. Signed-off-by: Eugeniy Paltsev --- drivers/clk/clk-hsdk-cgu.c| 9 ++--- include/dt-bindings/clock/snps,hsdk-cgu.h | 5 +++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/clk/clk-hsdk-cgu.c b/drivers/clk/clk-hsdk-cgu.c index 6eaafdeaf99..3035c5fb38e 100644 --- a/drivers/clk/clk-hsdk-cgu.c +++ b/drivers/clk/clk-hsdk-cgu.c @@ -67,6 +67,7 @@ #define CGU_TUN_IDIV_TUN 0x380 #define CGU_TUN_IDIV_ROM 0x390 #define CGU_TUN_IDIV_PWM 0x3A0 +#define CGU_TUN_IDIV_TIMER 0x3B0 #define CGU_HDMI_IDIV_APB 0x480 #define CGU_SYS_IDIV_APB 0x180 #define CGU_SYS_IDIV_AXI 0x190 @@ -123,12 +124,12 @@ #define MIN_PLL_RATE 1 /* 100 MHz */ #define PARENT_RATE_33 /* fixed clock - xtal */ #define PARENT_RATE_27 2700 /* fixed clock - xtal */ -#define CGU_MAX_CLOCKS 26 +#define CGU_MAX_CLOCKS 27 #define CGU_SYS_CLOCKS 16 #define MAX_AXI_CLOCKS 4 -#define CGU_TUN_CLOCKS 3 +#define CGU_TUN_CLOCKS 4 #define MAX_TUN_CLOCKS 6 struct hsdk_tun_idiv_cfg { @@ -147,7 +148,8 @@ static const struct hsdk_tun_clk_cfg tun_clk_cfg = { { 6, 6, 6, 6, 75000, 6 }, { { 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_PWM, { 8,8, 8, 8, 10, 8 } }, + { CGU_TUN_IDIV_TIMER, { 12, 12, 12, 12, 15, 12 } } } }; @@ -316,6 +318,7 @@ static const struct hsdk_cgu_clock_map clock_map[] = { { 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 } }; diff --git a/include/dt-bindings/clock/snps,hsdk-cgu.h b/include/dt-bindings/clock/snps,hsdk-cgu.h index 2cfe34eb35f..1ce7661cd93 100644 --- a/include/dt-bindings/clock/snps,hsdk-cgu.h +++ b/include/dt-bindings/clock/snps,hsdk-cgu.h @@ -36,7 +36,8 @@ #define CLK_TUN_TUN21 #define CLK_TUN_ROM22 #define CLK_TUN_PWM23 -#define CLK_HDMI_PLL 24 -#define CLK_HDMI 25 +#define CLK_TUN_TIMER 24 +#define CLK_HDMI_PLL 25 +#define CLK_HDMI 26 #endif /* __DT_BINDINGS_CLK_HSDK_CGU_H_ */ -- 2.21.1
[PATCH 09/14] ARC: HSDK-4xD: print timer clock value
Print timer clock value in hsdk_clock print_all command. Signed-off-by: Eugeniy Paltsev --- arch/arc/dts/hsdk-common.dtsi | 6 -- board/synopsys/hsdk/hsdk.c| 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arc/dts/hsdk-common.dtsi b/arch/arc/dts/hsdk-common.dtsi index 7292a8da514..fd4245e1646 100644 --- a/arch/arc/dts/hsdk-common.dtsi +++ b/arch/arc/dts/hsdk-common.dtsi @@ -40,7 +40,8 @@ <&cgu_clk CLK_SYS_DMAC_CFG>, <&cgu_clk CLK_SYS_SDIO_REF>, <&cgu_clk CLK_SYS_SPI_REF>, <&cgu_clk CLK_SYS_I2C_REF>, <&cgu_clk CLK_SYS_UART_REF>, <&cgu_clk CLK_SYS_EBI_REF>, -<&cgu_clk CLK_TUN_ROM>, <&cgu_clk CLK_TUN_PWM>; +<&cgu_clk CLK_TUN_ROM>, <&cgu_clk CLK_TUN_PWM>, +<&cgu_clk CLK_TUN_TIMER>; clock-names = "cpu-pll", "sys-pll", "tun-pll", "ddr-clk", "cpu-clk", "hdmi-pll", @@ -53,7 +54,8 @@ "dmac-cfg-clk", "sdio-ref-clk", "spi-clk", "i2c-clk", "uart-clk", "ebi-clk", - "rom-clk", "pwm-clk"; + "rom-clk", "pwm-clk", + "timer-clk"; }; cgu_clk: cgu-clk@f000 { diff --git a/board/synopsys/hsdk/hsdk.c b/board/synopsys/hsdk/hsdk.c index 7ba2a56c331..b8b995db47d 100644 --- a/board/synopsys/hsdk/hsdk.c +++ b/board/synopsys/hsdk/hsdk.c @@ -1017,6 +1017,8 @@ static int do_hsdk_clock_print_all(cmd_tbl_t *cmdtp, int flag, int argc, soc_clk_ctl("tun-clk", NULL, CLK_PRINT | CLK_MHZ); soc_clk_ctl("rom-clk", NULL, CLK_PRINT | CLK_MHZ); soc_clk_ctl("pwm-clk", NULL, CLK_PRINT | CLK_MHZ); + if (is_board_match_runtime(T_BOARD_HSDK_4XD)) + soc_clk_ctl("timer-clk", NULL, CLK_PRINT | CLK_MHZ); printf("\n"); return CMD_RET_SUCCESS; -- 2.21.1
[PATCH 08/14] ARC: HSDK-4xD: drop additional GPU clock info
HSDK-4xD has other GPU type so it consumes only GPU core clock. Even we have additional GPU clock dividers they are not routed to anything. So drop information about those additional clocks in hsdk_clock print_all command. Signed-off-by: Eugeniy Paltsev --- board/synopsys/hsdk/hsdk.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/board/synopsys/hsdk/hsdk.c b/board/synopsys/hsdk/hsdk.c index 45bc5ebe7db..7ba2a56c331 100644 --- a/board/synopsys/hsdk/hsdk.c +++ b/board/synopsys/hsdk/hsdk.c @@ -988,8 +988,10 @@ static int do_hsdk_clock_print_all(cmd_tbl_t *cmdtp, int flag, int argc, if (is_board_match_runtime(T_BOARD_HSDK_4XD)) soc_clk_ctl("hdmi-sys-clk", NULL, CLK_PRINT | CLK_MHZ); soc_clk_ctl("gfx-core-clk", NULL, CLK_PRINT | CLK_MHZ); - soc_clk_ctl("gfx-dma-clk", NULL, CLK_PRINT | CLK_MHZ); - soc_clk_ctl("gfx-cfg-clk", NULL, CLK_PRINT | CLK_MHZ); + if (is_board_match_runtime(T_BOARD_HSDK)) { + soc_clk_ctl("gfx-dma-clk", NULL, CLK_PRINT | CLK_MHZ); + soc_clk_ctl("gfx-cfg-clk", NULL, CLK_PRINT | CLK_MHZ); + } soc_clk_ctl("dmac-core-clk", NULL, CLK_PRINT | CLK_MHZ); soc_clk_ctl("dmac-cfg-clk", NULL, CLK_PRINT | CLK_MHZ); soc_clk_ctl("sdio-ref-clk", NULL, CLK_PRINT | CLK_MHZ); -- 2.21.1
[PATCH 06/14] ARC: HSDK-4xD: fix headerize script for HSDK-4xD compatibility
ARC HS CPU in HSDK-4xD has ARC ID = 0x54, so fix headerize script accordingly. Signed-off-by: Eugeniy Paltsev --- board/synopsys/hsdk/config.mk | 12 ++-- board/synopsys/hsdk/headerize-hsdk.py | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/board/synopsys/hsdk/config.mk b/board/synopsys/hsdk/config.mk index 1d01ef50379..def944aad2b 100644 --- a/board/synopsys/hsdk/config.mk +++ b/board/synopsys/hsdk/config.mk @@ -6,18 +6,26 @@ ifdef CONFIG_BOARD_HSDK PLATFORM_CPPFLAGS += -mcpu=hs38_linux -mlittle-endian -matomic -mll64 \ -mdiv-rem -mswap -mnorm -mmpy-option=9 -mbarrel-shifter \ -mfpu=fpud_all + +bsp-generate: u-boot u-boot.bin + $(Q)python3 $(srctree)/board/$(BOARDDIR)/headerize-hsdk.py \ + --arc-id 0x52 --image $(srctree)/u-boot.bin \ + --elf $(srctree)/u-boot + $(Q)tools/mkimage -T script -C none -n 'uboot update script' \ + -d $(srctree)/u-boot-update.txt \ + $(srctree)/u-boot-update.scr &> /dev/null endif ifdef CONFIG_BOARD_HSDK_4XD PLATFORM_CPPFLAGS += -mcpu=hs4x_rel31 -mlittle-endian -matomic -mll64 \ -mdiv-rem -mswap -mnorm -mmpy-option=9 -mbarrel-shifter \ -mfpu=fpud_all -endif bsp-generate: u-boot u-boot.bin $(Q)python3 $(srctree)/board/$(BOARDDIR)/headerize-hsdk.py \ - --arc-id 0x52 --image $(srctree)/u-boot.bin \ + --arc-id 0x54 --image $(srctree)/u-boot.bin \ --elf $(srctree)/u-boot $(Q)tools/mkimage -T script -C none -n 'uboot update script' \ -d $(srctree)/u-boot-update.txt \ $(srctree)/u-boot-update.scr &> /dev/null +endif diff --git a/board/synopsys/hsdk/headerize-hsdk.py b/board/synopsys/hsdk/headerize-hsdk.py index fce749723ed..7b047cf4a38 100644 --- a/board/synopsys/hsdk/headerize-hsdk.py +++ b/board/synopsys/hsdk/headerize-hsdk.py @@ -27,7 +27,7 @@ def calc_check_sum(filename): def arg_verify(uboot_bin_filename, uboot_elf_filename, arc_id): -if arc_id not in [0x52, 0x53]: +if arc_id not in [0x52, 0x53, 0x54]: print("unknown ARC ID: " + hex(arc_id)) sys.exit(2) -- 2.21.1
[PATCH 04/14] ARC: HSDK: split HSDK and HSDK-4xD DTS
Split HSDK and HSDK-4xD device tree files so they can have different model names. Signed-off-by: Eugeniy Paltsev --- arch/arc/dts/Makefile | 2 +- arch/arc/dts/hsdk-4xd.dts | 12 +++ arch/arc/dts/hsdk-common.dtsi | 150 ++ arch/arc/dts/hsdk.dts | 145 +--- configs/hsdk_4xd_defconfig| 2 +- 5 files changed, 167 insertions(+), 144 deletions(-) create mode 100644 arch/arc/dts/hsdk-4xd.dts create mode 100644 arch/arc/dts/hsdk-common.dtsi diff --git a/arch/arc/dts/Makefile b/arch/arc/dts/Makefile index 4f1e4637ce9..515fe1fe535 100644 --- a/arch/arc/dts/Makefile +++ b/arch/arc/dts/Makefile @@ -5,7 +5,7 @@ dtb-$(CONFIG_TARGET_AXS103) += axs103.dtb dtb-$(CONFIG_TARGET_NSIM) += nsim.dtb dtb-$(CONFIG_TARGET_TB100) += abilis_tb100.dtb dtb-$(CONFIG_TARGET_EMSDP) += emsdp.dtb -dtb-$(CONFIG_TARGET_HSDK) += hsdk.dtb +dtb-$(CONFIG_TARGET_HSDK) += hsdk.dtb hsdk-4xd.dtb dtb-$(CONFIG_TARGET_IOT_DEVKIT) += iot_devkit.dtb targets += $(dtb-y) diff --git a/arch/arc/dts/hsdk-4xd.dts b/arch/arc/dts/hsdk-4xd.dts new file mode 100644 index 000..b245eea7692 --- /dev/null +++ b/arch/arc/dts/hsdk-4xd.dts @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Synopsys, Inc. All rights reserved. + * Author: Eugeniy Paltsev + */ +/dts-v1/; + +#include "hsdk-common.dtsi" + +/ { + model = "snps,hsdk-4xd"; +}; diff --git a/arch/arc/dts/hsdk-common.dtsi b/arch/arc/dts/hsdk-common.dtsi new file mode 100644 index 000..7292a8da514 --- /dev/null +++ b/arch/arc/dts/hsdk-common.dtsi @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017-2020 Synopsys, Inc. All rights reserved. + * Author: Eugeniy Paltsev + */ +/dts-v1/; + +#include "skeleton.dtsi" +#include "dt-bindings/clock/snps,hsdk-cgu.h" +#include "dt-bindings/reset/snps,hsdk-reset.h" + +/ { + #address-cells = <1>; + #size-cells = <1>; + + aliases { + console = &uart0; + spi0 = &spi0; + }; + + cpu_card { + core_clk: core_clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <5>; + u-boot,dm-pre-reloc; + }; + }; + + clk-fmeas { + clocks = <&cgu_clk CLK_ARC_PLL>, <&cgu_clk CLK_SYS_PLL>, +<&cgu_clk CLK_TUN_PLL>, <&cgu_clk CLK_DDR_PLL>, +<&cgu_clk CLK_ARC>, <&cgu_clk CLK_HDMI_PLL>, +<&cgu_clk CLK_TUN_TUN>, <&cgu_clk CLK_HDMI>, +<&cgu_clk CLK_SYS_APB>, <&cgu_clk CLK_SYS_AXI>, +<&cgu_clk CLK_SYS_ETH>, <&cgu_clk CLK_SYS_USB>, +<&cgu_clk CLK_SYS_SDIO>, <&cgu_clk CLK_SYS_HDMI>, +<&cgu_clk CLK_SYS_GFX_CORE>, <&cgu_clk CLK_SYS_GFX_DMA>, +<&cgu_clk CLK_SYS_GFX_CFG>, <&cgu_clk CLK_SYS_DMAC_CORE>, +<&cgu_clk CLK_SYS_DMAC_CFG>, <&cgu_clk CLK_SYS_SDIO_REF>, +<&cgu_clk CLK_SYS_SPI_REF>, <&cgu_clk CLK_SYS_I2C_REF>, +<&cgu_clk CLK_SYS_UART_REF>, <&cgu_clk CLK_SYS_EBI_REF>, +<&cgu_clk CLK_TUN_ROM>, <&cgu_clk CLK_TUN_PWM>; + clock-names = "cpu-pll", "sys-pll", + "tun-pll", "ddr-clk", + "cpu-clk", "hdmi-pll", + "tun-clk", "hdmi-clk", + "apb-clk", "axi-clk", + "eth-clk", "usb-clk", + "sdio-clk", "hdmi-sys-clk", + "gfx-core-clk", "gfx-dma-clk", + "gfx-cfg-clk", "dmac-core-clk", + "dmac-cfg-clk", "sdio-ref-clk", + "spi-clk", "i2c-clk", + "uart-clk", "ebi-clk", + "rom-clk", "pwm-clk"; + }; + + cgu_clk: cgu-clk@f000 { + compatible = "snps,hsdk-cgu-clock"; + reg = <0xf000 0x10>, <0xf00014B8 0x4>; + #clock-cells = <1>; + }; + + cgu_rst: reset-controller@f8a0 { +
[PATCH 10/14] ARC: HSDK-4xD: add support for SLC enable/disable
Add support for SLC enable/disable via hsdk_init command. Signed-off-by: Eugeniy Paltsev --- board/synopsys/hsdk/hsdk.c | 22 ++ 1 file changed, 22 insertions(+) diff --git a/board/synopsys/hsdk/hsdk.c b/board/synopsys/hsdk/hsdk.c index b8b995db47d..b25b1331874 100644 --- a/board/synopsys/hsdk/hsdk.c +++ b/board/synopsys/hsdk/hsdk.c @@ -80,6 +80,7 @@ struct hsdk_env_common_ctl { u32_env nvlim; u32_env icache; u32_env dcache; + u32_env l2_cache; }; /* @@ -129,6 +130,9 @@ static const struct env_map_common env_map_common[] = { { "non_volatile_limit", ENV_HEX, true, 0, 0xF, &env_common.nvlim }, { "icache_ena", ENV_HEX, true, 0, 1, &env_common.icache }, { "dcache_ena", ENV_HEX, true, 0, 1, &env_common.dcache }, +#if defined(CONFIG_BOARD_HSDK_4XD) + { "l2_cache_ena", ENV_HEX, true, 0, 1, &env_common.l2_cache }, +#endif /* CONFIG_BOARD_HSDK_4XD */ {} }; @@ -188,6 +192,11 @@ static bool is_board_match_runtime(enum board_type type_req) return get_board_type_runtime() == type_req; } +static bool is_board_match_config(enum board_type type_req) +{ + return get_board_type_config() == type_req; +} + static const char * board_name(enum board_type type) { switch (type) { @@ -278,6 +287,18 @@ static void init_cluster_nvlim(void) flush_n_invalidate_dcache_all(); } +static void init_cluster_slc(void) +{ + /* ARC HS38 doesn't support SLC disabling */ + if (!is_board_match_config(T_BOARD_HSDK_4XD)) + return; + + if (env_common.l2_cache.val) + slc_enable(); + else + slc_disable(); +} + static void init_master_icache(void) { if (icache_status()) { @@ -657,6 +678,7 @@ static void do_init_cluster(void) * cores. */ init_cluster_nvlim(); + init_cluster_slc(); } static int check_master_cpu_id(void) -- 2.21.1
[PATCH 12/14] ARC: HSDK-4xD: tweak memory map
For HSDK-4xD we do additional AXI bridge tweaking while doing hsdk_init command: - we shrink IOC region. - we configure ARC HS CORE SLV1 aperture depending on haps_apb_location environment variable. Signed-off-by: Eugeniy Paltsev --- board/synopsys/hsdk/hsdk.c | 58 ++ 1 file changed, 58 insertions(+) diff --git a/board/synopsys/hsdk/hsdk.c b/board/synopsys/hsdk/hsdk.c index 2cbb59d8092..329427ed4ba 100644 --- a/board/synopsys/hsdk/hsdk.c +++ b/board/synopsys/hsdk/hsdk.c @@ -82,6 +82,7 @@ struct hsdk_env_common_ctl { u32_env dcache; u32_env csm_location; u32_env l2_cache; + u32_env haps_apb; }; /* @@ -134,6 +135,7 @@ static const struct env_map_common env_map_common[] = { #if defined(CONFIG_BOARD_HSDK_4XD) { "l2_cache_ena", ENV_HEX, true, 0, 1, &env_common.l2_cache }, { "csm_location", ENV_HEX, true, 0, NO_CCM, &env_common.csm_location }, + { "haps_apb_location", ENV_HEX, true, 0, 1, &env_common.haps_apb }, #endif /* CONFIG_BOARD_HSDK_4XD */ {} }; @@ -671,6 +673,61 @@ void init_memory_bridge(void) writel(UPDATE_VAL, CREG_PAE_UPDT); } +/* + * For HSDK-4xD we do additional AXI bridge tweaking in hsdk_init command: + * - we shrink IOC region. + * - we configure HS CORE SLV1 aperture depending on haps_apb_location + * environment variable. + * + * As we've already configured AXI bridge in init_memory_bridge we don't + * do full configuration here but reconfigure changed part. + * + * m master AXI_M_m_SLV0AXI_M_m_SLV1AXI_M_m_OFFSET0 AXI_M_m_OFFSET1 + * 0 HS (CBU)0x 0x6311 0xFEDCBA98 0x0E543210 [haps_apb_location = 0] + * 0 HS (CBU)0x 0x6111 0xFEDCBA98 0x06543210 [haps_apb_location = 1] + * 1 HS (RTT)0x 0x 0xFEDCBA98 0x76543210 + * 2 AXI Tunnel 0x 0x 0xFEDCBA98 0x76543210 + * 3 HDMI-VIDEO 0x 0x 0xFEDCBA98 0x76543210 + * 4 HDMI-ADUIO 0x 0x 0xFEDCBA98 0x76543210 + * 5 USB-HOST0x 0x 0xFEDCBA98 0x7654BA98 + * 6 ETHERNET0x 0x 0xFEDCBA98 0x7654BA98 + * 7 SDIO0x 0x 0xFEDCBA98 0x7654BA98 + * 8 GPU 0x 0x 0xFEDCBA98 0x76543210 + * 9 DMAC (port #1) 0x 0x 0xFEDCBA98 0x76543210 + * 10 DMAC (port #2) 0x 0x 0xFEDCBA98 0x76543210 + * 11 DVFS0x 0x6000 0x 0x + */ +void tweak_memory_bridge_cfg(void) +{ + /* +* Only HSDK-4xD requre additional AXI bridge tweaking depending on +* haps_apb_location environment variable +*/ + if (!is_board_match_config(T_BOARD_HSDK_4XD)) + return; + + if (env_common.haps_apb.val) { + writel(0x6111, CREG_AXI_M_SLV1(M_HS_CORE)); + writel(0x06543210, CREG_AXI_M_OFT1(M_HS_CORE)); + } else { + writel(0x6311, CREG_AXI_M_SLV1(M_HS_CORE)); + writel(0x0E543210, CREG_AXI_M_OFT1(M_HS_CORE)); + } + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HS_CORE)); + + writel(0x, CREG_AXI_M_SLV1(M_USB_HOST)); + writel(0x7654BA98, CREG_AXI_M_OFT1(M_USB_HOST)); + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_USB_HOST)); + + writel(0x, CREG_AXI_M_SLV1(M_ETHERNET));; + writel(0x7654BA98, CREG_AXI_M_OFT1(M_ETHERNET)); + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_ETHERNET)); + + writel(0x, CREG_AXI_M_SLV1(M_SDIO)); + writel(0x7654BA98, CREG_AXI_M_OFT1(M_SDIO)); + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_SDIO)); +} + static void setup_clocks(void) { ulong rate; @@ -706,6 +763,7 @@ static void do_init_cluster(void) init_cluster_nvlim(); init_cluster_csm(); init_cluster_slc(); + tweak_memory_bridge_cfg(); } static int check_master_cpu_id(void) -- 2.21.1
[PATCH 07/14] ARC: HSDK-4xD: print info about HDMI clocks
HSDK-4xD has HDMI working so let's print info about HDMI clocks. Signed-off-by: Eugeniy Paltsev --- board/synopsys/hsdk/hsdk.c | 11 +++ 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/board/synopsys/hsdk/hsdk.c b/board/synopsys/hsdk/hsdk.c index 577893de2a1..45bc5ebe7db 100644 --- a/board/synopsys/hsdk/hsdk.c +++ b/board/synopsys/hsdk/hsdk.c @@ -985,7 +985,8 @@ static int do_hsdk_clock_print_all(cmd_tbl_t *cmdtp, int flag, int argc, soc_clk_ctl("eth-clk", NULL, CLK_PRINT | CLK_MHZ); soc_clk_ctl("usb-clk", NULL, CLK_PRINT | CLK_MHZ); soc_clk_ctl("sdio-clk", NULL, CLK_PRINT | CLK_MHZ); -/* soc_clk_ctl("hdmi-sys-clk", NULL, CLK_PRINT | CLK_MHZ); */ + if (is_board_match_runtime(T_BOARD_HSDK_4XD)) + soc_clk_ctl("hdmi-sys-clk", NULL, CLK_PRINT | CLK_MHZ); soc_clk_ctl("gfx-core-clk", NULL, CLK_PRINT | CLK_MHZ); soc_clk_ctl("gfx-dma-clk", NULL, CLK_PRINT | CLK_MHZ); soc_clk_ctl("gfx-cfg-clk", NULL, CLK_PRINT | CLK_MHZ); @@ -1003,9 +1004,11 @@ static int do_hsdk_clock_print_all(cmd_tbl_t *cmdtp, int flag, int argc, printf("\n"); /* HDMI clock domain */ -/* soc_clk_ctl("hdmi-pll", NULL, CLK_PRINT | CLK_MHZ); */ -/* soc_clk_ctl("hdmi-clk", NULL, CLK_PRINT | CLK_MHZ); */ -/* printf("\n"); */ + if (is_board_match_runtime(T_BOARD_HSDK_4XD)) { + soc_clk_ctl("hdmi-pll", NULL, CLK_PRINT | CLK_MHZ); + soc_clk_ctl("hdmi-clk", NULL, CLK_PRINT | CLK_MHZ); + printf("\n"); + } /* TUN clock domain */ soc_clk_ctl("tun-pll", NULL, CLK_PRINT | CLK_MHZ); -- 2.21.1
[PATCH 11/14] ARC: HSDK-4xD: add CSM configuration support
Add support for CSM enable/disable and CSM relocation via hsdk_init command. We allow to relocate CSM to the beginning of any aperture even if HW support finer granularity. Signed-off-by: Eugeniy Paltsev --- arch/arc/include/asm/arcregs.h | 3 +++ board/synopsys/hsdk/hsdk.c | 27 +++ 2 files changed, 30 insertions(+) diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h index f3cd4a889ac..516c14e105b 100644 --- a/arch/arc/include/asm/arcregs.h +++ b/arch/arc/include/asm/arcregs.h @@ -51,6 +51,9 @@ #define ARC_AUX_DCCM_BASE 0x18/* DCCM Base Addr ARCv2 */ #define ARC_AUX_ICCM_BASE 0x208 /* ICCM Base Addr ARCv2 */ +/* CSM auxiliary registers */ +#define ARC_AUX_CSM_ENABLE 0x9A0 + /* Timer related auxiliary registers */ #define ARC_AUX_TIMER0_CNT 0x21/* Timer 0 count */ #define ARC_AUX_TIMER0_CTRL0x22/* Timer 0 control */ diff --git a/board/synopsys/hsdk/hsdk.c b/board/synopsys/hsdk/hsdk.c index b25b1331874..2cbb59d8092 100644 --- a/board/synopsys/hsdk/hsdk.c +++ b/board/synopsys/hsdk/hsdk.c @@ -80,6 +80,7 @@ struct hsdk_env_common_ctl { u32_env nvlim; u32_env icache; u32_env dcache; + u32_env csm_location; u32_env l2_cache; }; @@ -132,6 +133,7 @@ static const struct env_map_common env_map_common[] = { { "dcache_ena", ENV_HEX, true, 0, 1, &env_common.dcache }, #if defined(CONFIG_BOARD_HSDK_4XD) { "l2_cache_ena", ENV_HEX, true, 0, 1, &env_common.l2_cache }, + { "csm_location", ENV_HEX, true, 0, NO_CCM, &env_common.csm_location }, #endif /* CONFIG_BOARD_HSDK_4XD */ {} }; @@ -299,6 +301,30 @@ static void init_cluster_slc(void) slc_disable(); } +#define CREG_CSM_BASE (CREG_BASE + 0x210) + +static void init_cluster_csm(void) +{ + /* ARC HS38 in HSDK SoC doesn't include CSM */ + if (!is_board_match_config(T_BOARD_HSDK_4XD)) + return; + + if (env_common.csm_location.val == NO_CCM) { + write_aux_reg(ARC_AUX_CSM_ENABLE, 0); + } else { + /* +* CSM base address is 256kByte aligned but we allow to map +* CSM only to aperture start (256MByte aligned) +* The field in CREG_CSM_BASE is in 17:2 bits itself so we need +* to shift it. +*/ + u32 csm_base = (env_common.csm_location.val * SZ_1K) << 2; + + write_aux_reg(ARC_AUX_CSM_ENABLE, 1); + writel(csm_base, (void __iomem *)CREG_CSM_BASE); + } +} + static void init_master_icache(void) { if (icache_status()) { @@ -678,6 +704,7 @@ static void do_init_cluster(void) * cores. */ init_cluster_nvlim(); + init_cluster_csm(); init_cluster_slc(); } -- 2.21.1
[PATCH 13/14] ARC: HSDK-4xD: use separate config file
HSDK-4xD has quite different environment so let's split HSDK and HSDK-4xD configs file. Signed-off-by: Eugeniy Paltsev --- board/synopsys/hsdk/Kconfig | 3 +- board/synopsys/hsdk/MAINTAINERS | 2 + include/configs/hsdk-4xd.h | 120 3 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 include/configs/hsdk-4xd.h diff --git a/board/synopsys/hsdk/Kconfig b/board/synopsys/hsdk/Kconfig index 5e23b3229a9..d9c0e27a41d 100644 --- a/board/synopsys/hsdk/Kconfig +++ b/board/synopsys/hsdk/Kconfig @@ -7,7 +7,8 @@ config SYS_VENDOR default "synopsys" config SYS_CONFIG_NAME - default "hsdk" + default "hsdk" if BOARD_HSDK + default "hsdk-4xd" if BOARD_HSDK_4XD choice prompt "HSDK board type" diff --git a/board/synopsys/hsdk/MAINTAINERS b/board/synopsys/hsdk/MAINTAINERS index d385951048f..73f71fd06bc 100644 --- a/board/synopsys/hsdk/MAINTAINERS +++ b/board/synopsys/hsdk/MAINTAINERS @@ -4,3 +4,5 @@ S: Maintained F: board/synopsys/hsdk/ F: configs/hsdk_defconfig F: configs/hsdk_4xd_defconfig +F: include/configs/hsdk-4xd.h +F: include/configs/hsdk.h diff --git a/include/configs/hsdk-4xd.h b/include/configs/hsdk-4xd.h new file mode 100644 index 000..4628108075e --- /dev/null +++ b/include/configs/hsdk-4xd.h @@ -0,0 +1,120 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2020 Synopsys, Inc. All rights reserved. + * Author: Eugeniy Paltsev + */ + +#ifndef _CONFIG_HSDK_H_ +#define _CONFIG_HSDK_H_ + +#include + +/* + * CPU configuration + */ +#define NR_CPUS4 +#define ARC_PERIPHERAL_BASE0xF000 +#define ARC_DWMMC_BASE (ARC_PERIPHERAL_BASE + 0xA000) +#define ARC_DWGMAC_BASE(ARC_PERIPHERAL_BASE + 0x18000) + +/* + * Memory configuration + */ +#define CONFIG_SYS_MONITOR_BASECONFIG_SYS_TEXT_BASE + +#define CONFIG_SYS_DDR_SDRAM_BASE 0x8000 +#define CONFIG_SYS_SDRAM_BASE CONFIG_SYS_DDR_SDRAM_BASE +#define CONFIG_SYS_SDRAM_SIZE SZ_1G + +#define CONFIG_SYS_INIT_SP_ADDR\ + (CONFIG_SYS_SDRAM_BASE + 0x1000 - GENERATED_GBL_DATA_SIZE) + +#define CONFIG_SYS_MALLOC_LEN SZ_2M +#define CONFIG_SYS_BOOTM_LEN SZ_128M +#define CONFIG_SYS_LOAD_ADDR 0x8200 + +/* + * UART configuration + */ +#define CONFIG_SYS_NS16550_SERIAL +#define CONFIG_SYS_NS16550_CLK +#define CONFIG_SYS_NS16550_MEM32 + +/* + * Ethernet PHY configuration + */ + +/* + * USB 1.1 configuration + */ +#define CONFIG_USB_OHCI_NEW +#define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 1 + +/* + * Environment settings + */ +#define CONFIG_EXTRA_ENV_SETTINGS \ + "upgrade=if mmc rescan && " \ + "fatload mmc 0:1 ${loadaddr} u-boot-update.scr && " \ + "iminfo ${loadaddr} && source ${loadaddr}; then; else echo " \ + "\"Fail to upgrade.\n" \ + "Do you have u-boot-update.scr and u-boot.head on first (FAT) SD card partition?\"" \ + "; fi\0" \ + "core_mask=0xF\0" \ + "hsdk_hs45d=setenv core_mask 0x2; setenv haps_apb_location 0x1; \ +setenv l2_cache_ena 0x0; setenv icache_ena 0x0; setenv csm_location 0x10; \ +setenv dcache_ena 0x0; setenv core_iccm_1 0x7; \ +setenv core_dccm_1 0x8; setenv non_volatile_limit 0xF;\0" \ + "hsdk_hs47d=setenv core_mask 0x1; setenv haps_apb_location 0x1; \ +setenv l2_cache_ena 0x0; setenv icache_ena 0x1; setenv csm_location 0x10; \ +setenv dcache_ena 0x1; setenv core_iccm_0 0x10; \ +setenv core_dccm_0 0x10; setenv non_volatile_limit 0xF;\0" \ + "hsdk_hs47d_ccm=setenv core_mask 0x2; setenv haps_apb_location 0x1; \ +setenv l2_cache_ena 0x0; setenv icache_ena 0x1; setenv csm_location 0x10; \ +setenv dcache_ena 0x1; setenv core_iccm_1 0x7; \ +setenv core_dccm_1 0x8; setenv non_volatile_limit 0xF;\0" \ + "hsdk_hs48=setenv core_mask 0x1; setenv haps_apb_location 0x1; \ +setenv l2_cache_ena 0x1; setenv icache_ena 0x1; setenv csm_location 0x10; \ +setenv dcache_ena 0x1; setenv core_iccm_0 0x10; \ +setenv core_dccm_0 0x10; setenv non_volatile_limit 0xF;\0" \ + "hsdk_hs48_ccm=setenv core_mask 0x2; setenv haps_apb_location 0x1; \ +setenv l2_cache_ena 0x1; setenv icache_ena 0x1; setenv csm_location 0x10; \ +setenv dcache_ena 0x1; setenv core_iccm_1 0x7; \ +setenv core_dccm_1 0x8; setenv non_volatile_limit 0xF;\0" \ + "hsdk_hs48x2=run hsdk_hs47dx2;\0" \ + "hsdk_hs47dx2=setenv core_mask 0x3; setenv haps_apb_location 0x1; \ +setenv l2_cache_ena 0x1; setenv icache_ena 0x1; setenv csm_location 0x10; \ +setenv dcache_ena 0x1; setenv core_iccm_0 0x10; \ +setenv core_dccm_0 0x10; setenv non_vola
[PATCH 14/14] ARC: HSDK-4xD: make init status resistant to U-boot reloading
Use register instead of static variable to store HSDK init status as we want to avoid the situation when we reload U-boot via MDB after previous init is done but HW reset (board reset) isn't done. So let's store the init status in unused register - CREG_CPU_0_ENTRY so status will survive after U-boot is reloaded via MDB. Signed-off-by: Eugeniy Paltsev --- board/synopsys/hsdk/hsdk.c | 28 +--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/board/synopsys/hsdk/hsdk.c b/board/synopsys/hsdk/hsdk.c index 329427ed4ba..a3e0563ff45 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_MASK0xF #define CREG_CPU_START_POL BIT(4) +#define CREG_CPU_0_ENTRY (CREG_BASE + 0x404) + #define SDIO_BASE (ARC_PERIPHERAL_BASE + 0xA000) #define SDIO_UHS_REG_EXT (SDIO_BASE + 0x108) #define SDIO_UHS_REG_EXT_DIV_2 (2 << 30) @@ -969,9 +971,29 @@ U_BOOT_CMD( "hsdk_go halt - Boot stand-alone application on HSDK, halt CPU just before application run\n" ); +/* + * We may simply use static variable here to store init status, but we also want + * to avoid the situation when we reload U-boot via MDB after previous + * init is done but HW reset (board reset) isn't done. So let's store the + * init status in any unused register (i.e CREG_CPU_0_ENTRY) so status will + * survive after U-boot is reloaded via MDB. + */ +#define INIT_MARKER_REGISTER ((void __iomem *)CREG_CPU_0_ENTRY) +/* must be equal to INIT_MARKER_REGISTER reset value */ +#define INIT_MARKER_PENDING0 + +static bool init_marker_get(void) +{ + return readl(INIT_MARKER_REGISTER) != INIT_MARKER_PENDING; +} + +static void init_mark_done(void) +{ + writel(~INIT_MARKER_PENDING, INIT_MARKER_REGISTER); +} + static int do_hsdk_init(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { - static bool done = false; int ret; if (board_mismatch()) { @@ -980,14 +1002,14 @@ static int do_hsdk_init(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[] } /* hsdk_init can be run only once */ - if (done) { + if (init_marker_get()) { printf("HSDK HW is already initialized! Please reset the board if you want to change the configuration.\n"); return CMD_RET_FAILURE; } ret = prepare_cpus(); if (!ret) - done = true; + init_mark_done(); return ret ? CMD_RET_FAILURE : CMD_RET_SUCCESS; } -- 2.21.1
[PATCH] BDINFO: ARC: print info about relocations
Print relocation information in bdinfo. NOTE: this patch changes only ARC part of bdinfo code. Signed-off-by: Eugeniy Paltsev --- cmd/bdinfo.c | 4 1 file changed, 4 insertions(+) diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c index d6a7175b379..31ec4615641 100644 --- a/cmd/bdinfo.c +++ b/cmd/bdinfo.c @@ -439,20 +439,24 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 0; } #elif defined(CONFIG_ARC) int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { bd_t *bd = gd->bd; print_bi_mem(bd); + if (!(gd->flags & GD_FLG_SKIP_RELOC)) { + print_num("relocaddr", gd->relocaddr); + print_num("reloc off", gd->reloc_off); + } print_eth_ip_addr(); print_baudrate(); return 0; } #elif defined(CONFIG_XTENSA) int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { -- 2.21.1
Re: [PATCH] CMD: random: fix return code
Hi Simon, Tom, I guess it's perfect time to apply this patch. Thanks! --- Eugeniy Paltsev From: Simon Glass Sent: Monday, March 23, 2020 18:37 To: Eugeniy Paltsev Cc: Tom Rini; U-Boot Mailing List; uboot-snps-...@synopsys.com; Alexey Brodkin; linux-snps-...@lists.infradead.org Subject: Re: [PATCH] CMD: random: fix return code On Fri, 20 Mar 2020 at 10:38, Eugeniy Paltsev wrote: > > As of today 'random' command return 1 (CMD_RET_FAILURE) in case > of successful execution and 0 (CMD_RET_SUCCESS) in case of bad > arguments. Fix that. > > NOTE: we remove printing usage information from command body > so it won't print twice. > > Signed-off-by: Eugeniy Paltsev > --- > cmd/mem.c | 9 - > 1 file changed, 4 insertions(+), 5 deletions(-) > Reviewed-by: Simon Glass
Re: [PATCH v2 00/10] riscv: Add SPI support for Kendryte K210
Hi Sean, do you have any public git branch with this patch series? I want to test these changes on our board with DW SPI controller. Thanks. --- Eugeniy Paltsev From: Sean Anderson Sent: Friday, August 7, 2020 17:43 To: u-boot@lists.denx.de; uboot-snps-...@synopsys.com Cc: Heinrich Schuchardt; Jagan Teki; Eugeniy Paltsev; Horatiu Vultur; Marek Vasut; Sean Anderson; Alexey Brodkin; Alexey Brodkin; Daniel Schwierzeck; Gregory CLEMENT; Lars Povlsen; Ley Foon Tan; Rick Chen; Simon Goldschmidt Subject: [PATCH v2 00/10] riscv: Add SPI support for Kendryte K210 This series adds support for SPI on the Kendryte K210. This covers the MMC slot (currently broken) and SPI flash on the Sipeed Maix Bit. This series makes significant changes to the designware SPI driver. I would really appreciate if the maintainers I CC'd could test this series and ensure that SPI still works on all their devices. I have tried my best not to affect existing devices, but I'd rather find out if this breaks stuff now rather than later. In particular: Ley Foon Tan, can you try using dw_spi_dw32_init with the Stratix 10 and Agilex SoCFPGAs? From their documentation, it is unclear whether one should use the DFS or DFS_32 field. I have used dw_spi_dw16_init for these devices, since that keeps the same behavior as before this series, but I am interested in seeing whether the DFS_32 works. Gregory Clement, Lars Povlsen, and Horatiu Vultur, can you confirm the register layout of ctrlr0 and version of the device on the MSCC Ocelot and Jaguar 2? I couldn't find any documentation for the device on those SoCs online. Alexey Brodkin and Eugeniy Paltsev, can you confirm the register layout of ctrlr0 and version of the device on ARC SoCs? I couldn't find any documentation for the device on those SoCs online. In addition, can you clarify the nature of SSI_MAX_XFER_SIZE? Is it set once before the device is fabricated, or is it set at runtime? Is there any way to detect it at runtime? Is my supposition that it was introduced in version 3.23 correct? Have there been any other breaking changes which I have overlooked? I tried investigating some of this, but I was unable to find any definitive ruling on the matter. All I could find was this forum post which doesn't really explain anything [1]. [1] https://urldefense.com/v3/__https://community.intel.com/t5/Intel-Makers/D2000-SPI-word-frame-size/td-p/276520__;!!A4F2R9G_pg!PEqqmGgI-XfH0K6kaLF8oIuYYMfBugTtH4ysThH7wyY4Q01OMi_rGRiRi2hs0S7bdAf8nWI$ This series was previously part of https://urldefense.com/v3/__https://patchwork.ozlabs.org/project/uboot/list/?series=161576__;!!A4F2R9G_pg!PEqqmGgI-XfH0K6kaLF8oIuYYMfBugTtH4ysThH7wyY4Q01OMi_rGRiRi2hs0S7bo-OeOVc$ This series depends on https://urldefense.com/v3/__https://patchwork.ozlabs.org/project/uboot/list/?series=185489__;!!A4F2R9G_pg!PEqqmGgI-XfH0K6kaLF8oIuYYMfBugTtH4ysThH7wyY4Q01OMi_rGRiRi2hs0S7b478gncg$ Known bugs: - The MMC cannot be accessed with the dw_spi driver Changes in v2: - Add Gigadevice SPI chips to dependencies - Add external gpio cs support - Clean up exec_op - Configure ctrlr0 register layout based on compatible string - Convert debug calls to log_ instead of removing the ones which affect timing - Document new compatible strings - Limit data transfers to 64k - Remove broken-wp property (implicit due to no wp gpio) - Remove ctrl0 field offsets from device tree - Switch to new compatible strings - Switch to new pinmux binding style Sean Anderson (10): spi: dw: Convert calls to debug to log_* spi: dw: Rename "cs-gpio" to "cs-gpios" spi: dw: Use generic function to read reg address spi: dw: Rearrange struct dw_spi_priv spi: dw: Add SoC-specific compatible strings spi: dw: Configure ctrlr0 layout based on compatible string spi: dw: Document devicetree binding spi: dw: Add mem_ops riscv: Add device tree bindings for SPI riscv: Add support for SPI on Kendryte K210 arch/arc/dts/axs10x_mb.dtsi | 5 +- arch/arc/dts/hsdk-common.dtsi | 5 +- arch/arm/dts/socfpga.dtsi | 6 +- arch/arm/dts/socfpga_agilex.dtsi | 6 +- arch/arm/dts/socfpga_arria10.dtsi | 6 +- arch/arm/dts/socfpga_stratix10.dtsi | 6 +- arch/mips/dts/mscc,jr2.dtsi | 2 +- arch/mips/dts/mscc,ocelot.dtsi| 2 +- arch/riscv/dts/k210-maix-bit.dts | 46 ++- arch/riscv/dts/k210.dtsi | 15 +- board/sipeed/maix/Kconfig | 11 + configs/sipeed_maix_bitm_defconfig| 8 + doc/board/sipeed/maix.rst | 94 +++-- .../spi/snps,dw-apb-ssi.txt | 56 +++ drivers/spi/designware_spi.c | 381 ++ 15 files changed, 528 insertions(+), 121 deletions(-) create mode 100644 doc/device-tree-bindings/spi/snps,dw-apb-ssi.txt -- 2.28.0
Re: [PATCH v2 00/10] riscv: Add SPI support for Kendryte K210
FYI: I've tested on commit aa68b00a8259aa026591475f21a5c51311252ef2 (current branch head) and I don't see any build/runtime issues. Tested-by Eugeniy Paltsev --- Eugeniy Paltsev From: Sean Anderson Sent: Monday, August 10, 2020 14:13 To: Eugeniy Paltsev; u-boot@lists.denx.de; uboot-snps-...@synopsys.com Cc: Heinrich Schuchardt; Jagan Teki; Horatiu Vultur; Marek Vasut; Alexey Brodkin; Daniel Schwierzeck; Gregory CLEMENT; Lars Povlsen; Ley Foon Tan; Rick Chen; Simon Goldschmidt Subject: Re: [PATCH v2 00/10] riscv: Add SPI support for Kendryte K210 On 8/10/20 6:49 AM, Eugeniy Paltsev wrote: > Hi Sean, > > do you have any public git branch with this patch series? > I want to test these changes on our board with DW SPI controller. https://urldefense.com/v3/__https://github.com/Forty-Bot/u-boot/tree/maix_spi__;!!A4F2R9G_pg!JnihRPoojBUo2j8mMgJNH_K5dis6o-g7c2YGmb0SYh2wBkWGASlPXxMFW-TPbdSOtlYUiTs$ --Sean
[PATCH 1/2] CLK: HSDK: Check for PLL bypass firstly
Pll bypass has priority over enable/disable. Signed-off-by: Eugeniy Paltsev --- drivers/clk/clk-hsdk-cgu.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/clk/clk-hsdk-cgu.c b/drivers/clk/clk-hsdk-cgu.c index 56ef08c032b..69e6b24b66c 100644 --- a/drivers/clk/clk-hsdk-cgu.c +++ b/drivers/clk/clk-hsdk-cgu.c @@ -377,14 +377,14 @@ static ulong pll_get(struct clk *sclk) pr_debug("current configurarion: %#x\n", val); - /* Check if PLL is disabled */ - if (val & CGU_PLL_CTRL_PD) - return 0; - /* Check if PLL is bypassed */ if (val & CGU_PLL_CTRL_BYPASS) return PARENT_RATE; + /* Check if PLL is disabled */ + if (val & CGU_PLL_CTRL_PD) + return 0; + /* input divider = reg.idiv + 1 */ idiv = 1 + ((val & CGU_PLL_CTRL_IDIV_MASK) >> CGU_PLL_CTRL_IDIV_SHIFT); /* fb divider = 2*(reg.fbdiv + 1) */ -- 2.21.0
[PATCH 2/2] CLK: HSDK: fix HDMI clock calculation
HDMI PLL has its own xtal with 27 MHz output but we treat it the same way as other PLLs with 33.33 MHz input. Fix that. Signed-off-by: Eugeniy Paltsev --- drivers/clk/clk-hsdk-cgu.c | 31 +-- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/clk/clk-hsdk-cgu.c b/drivers/clk/clk-hsdk-cgu.c index 69e6b24b66c..4637b9fdf15 100644 --- a/drivers/clk/clk-hsdk-cgu.c +++ b/drivers/clk/clk-hsdk-cgu.c @@ -46,17 +46,21 @@ *||-->|CGU_TUN_IDIV_ROM|---> *||-->|CGU_TUN_IDIV_PWM|---> *| - *| - *|-->| HDMI PLL | - *| - *|| - *||-->|CGU_HDMI_IDIV_APB|--> - *| *| --- *|-->| DDR PLL | *--- * | * |> + * + * -- + * | 27.00 MHz xtal | + * -- + *| + *| + *|-->| HDMI PLL | + * + * | + * |-->|CGU_HDMI_IDIV_APB|--> */ #define CGU_ARC_IDIV 0x080 @@ -117,7 +121,8 @@ #define CREG_CORE_IF_CLK_DIV_2 0x1 #define MIN_PLL_RATE 1 /* 100 MHz */ -#define PARENT_RATE /* fixed clock - xtal */ +#define PARENT_RATE_33 /* fixed clock - xtal */ +#define PARENT_RATE_27 2700 /* fixed clock - xtal */ #define CGU_MAX_CLOCKS 26 #define CGU_SYS_CLOCKS 16 @@ -237,6 +242,7 @@ 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); @@ -248,16 +254,19 @@ static int hsdk_pll_comm_update_rate(struct hsdk_cgu_clk *, unsigned long, const struct hsdk_pll_cfg *); static const struct hsdk_pll_devdata core_pll_dat = { + .parent_rate = PARENT_RATE_33, .pll_cfg = asdt_pll_cfg, .update_rate = hsdk_pll_core_update_rate, }; static const struct hsdk_pll_devdata sdt_pll_dat = { + .parent_rate = PARENT_RATE_33, .pll_cfg = asdt_pll_cfg, .update_rate = hsdk_pll_comm_update_rate, }; static const struct hsdk_pll_devdata hdmi_pll_dat = { + .parent_rate = PARENT_RATE_27, .pll_cfg = hdmi_pll_cfg, .update_rate = hsdk_pll_comm_update_rate, }; @@ -372,6 +381,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; val = hsdk_pll_read(clk, CGU_PLL_CTRL); @@ -379,7 +389,7 @@ static ulong pll_get(struct clk *sclk) /* Check if PLL is bypassed */ if (val & CGU_PLL_CTRL_BYPASS) - return PARENT_RATE; + return parent_rate; /* Check if PLL is disabled */ if (val & CGU_PLL_CTRL_PD) @@ -392,7 +402,7 @@ static ulong pll_get(struct clk *sclk) /* output divider = 2^(reg.odiv) */ odiv = 1 << ((val & CGU_PLL_CTRL_ODIV_MASK) >> CGU_PLL_CTRL_ODIV_SHIFT); - rate = (u64)PARENT_RATE * fbdiv; + rate = (u64)parent_rate * fbdiv; do_div(rate, idiv * odiv); return rate; @@ -490,7 +500,8 @@ static ulong pll_set(struct clk *sclk, ulong rate) } } - pr_err("invalid rate=%ld Hz, parent_rate=%d Hz\n", best_rate, PARENT_RATE); + pr_err("invalid rate=%ld Hz, parent_rate=%d Hz\n", best_rate, + clk->pll_devdata->parent_rate); return -EINVAL; } -- 2.21.0
[PATCH] ARC: rework setting of ARC CPU specific compiler options
It's a very rare if at all existing occasion when ARC CPU template is used as is w/o any changes - in the end it's a beauty and competitive advantage of ARC cores to be tailored for a particular use-case - and so it doesn't make a lot of sense to offer template-based "-mcpu" selection. Given for each and every platform we end-up adding quite a few more flags it's logical to move "-mcpu" selection to platform's definition as well which we exactly do here. Signed-off-by: Eugeniy Paltsev --- arch/arc/config.mk | 20 board/abilis/tb100/config.mk| 5 + board/synopsys/axs10x/config.mk | 6 ++ board/synopsys/emsdp/config.mk | 2 +- board/synopsys/hsdk/config.mk | 4 board/synopsys/iot_devkit/config.mk | 3 ++- board/synopsys/nsim/Kconfig | 9 + board/synopsys/nsim/config.mk | 8 configs/nsim_700_defconfig | 1 + configs/nsim_700be_defconfig| 1 + configs/nsim_hs38_defconfig | 1 + configs/nsim_hs38be_defconfig | 1 + 12 files changed, 39 insertions(+), 22 deletions(-) create mode 100644 board/abilis/tb100/config.mk create mode 100644 board/synopsys/nsim/config.mk diff --git a/arch/arc/config.mk b/arch/arc/config.mk index 18005d99930..6fa29adae81 100644 --- a/arch/arc/config.mk +++ b/arch/arc/config.mk @@ -22,26 +22,6 @@ ifdef CONFIG_ARC_MMU_VER CONFIG_MMU = 1 endif -ifdef CONFIG_CPU_ARC750D -PLATFORM_CPPFLAGS += -mcpu=arc700 -endif - -ifdef CONFIG_CPU_ARC770D -PLATFORM_CPPFLAGS += -mcpu=arc700 -mlock -mswape -endif - -ifdef CONFIG_CPU_ARCEM6 -PLATFORM_CPPFLAGS += -mcpu=arcem -endif - -ifdef CONFIG_CPU_ARCHS34 -PLATFORM_CPPFLAGS += -mcpu=archs -endif - -ifdef CONFIG_CPU_ARCHS38 -PLATFORM_CPPFLAGS += -mcpu=archs -endif - PLATFORM_CPPFLAGS += -ffixed-r25 -D__ARC__ -gdwarf-2 -mno-sdata PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections -fno-common diff --git a/board/abilis/tb100/config.mk b/board/abilis/tb100/config.mk new file mode 100644 index 000..9e8dee49bd3 --- /dev/null +++ b/board/abilis/tb100/config.mk @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2020 Synopsys, Inc. All rights reserved. + +PLATFORM_CPPFLAGS += -mcpu=arc700 -mlock -mswape diff --git a/board/synopsys/axs10x/config.mk b/board/synopsys/axs10x/config.mk index 81ff498f818..ccac5442908 100644 --- a/board/synopsys/axs10x/config.mk +++ b/board/synopsys/axs10x/config.mk @@ -2,6 +2,12 @@ # # Copyright (C) 2018 Synopsys, Inc. All rights reserved. +ifdef CONFIG_TARGET_AXS103 + PLATFORM_CPPFLAGS += -mcpu=archs +else + PLATFORM_CPPFLAGS += -mcpu=arc700 -mlock -mswape +endif + bsp-generate: u-boot u-boot.bin ifdef CONFIG_ISA_ARCV2 $(Q)python3 $(srctree)/board/$(BOARDDIR)/headerize-axs.py \ diff --git a/board/synopsys/emsdp/config.mk b/board/synopsys/emsdp/config.mk index 67fd7bf82a3..5bd10442aff 100644 --- a/board/synopsys/emsdp/config.mk +++ b/board/synopsys/emsdp/config.mk @@ -1,2 +1,2 @@ -PLATFORM_CPPFLAGS += -mlittle-endian -mnorm -mswap -mmpy-option=3 \ +PLATFORM_CPPFLAGS += -mcpu=arcem -mlittle-endian -mnorm -mswap -mmpy-option=3 \ -mbarrel-shifter -mfpu=fpuda_all -mcode-density diff --git a/board/synopsys/hsdk/config.mk b/board/synopsys/hsdk/config.mk index 9e280f921a1..5ae22fa2b75 100644 --- a/board/synopsys/hsdk/config.mk +++ b/board/synopsys/hsdk/config.mk @@ -2,6 +2,10 @@ # # Copyright (C) 2018 Synopsys, Inc. All rights reserved. +PLATFORM_CPPFLAGS += -mcpu=hs38_linux -mlittle-endian -matomic -mll64 \ + -mdiv-rem -mswap -mnorm -mmpy-option=9 -mbarrel-shifter \ + -mfpu=fpud_all + bsp-generate: u-boot u-boot.bin $(Q)python3 $(srctree)/board/$(BOARDDIR)/headerize-hsdk.py \ --arc-id 0x52 --image $(srctree)/u-boot.bin \ diff --git a/board/synopsys/iot_devkit/config.mk b/board/synopsys/iot_devkit/config.mk index 120733538a4..e1e546a3d04 100644 --- a/board/synopsys/iot_devkit/config.mk +++ b/board/synopsys/iot_devkit/config.mk @@ -1,2 +1,3 @@ -PLATFORM_CPPFLAGS += -mlittle-endian -mcode-density -mdiv-rem -mswap -mnorm -mmpy-option=6 -mbarrel-shifter +PLATFORM_CPPFLAGS += -mcpu=em4_fpuda -mlittle-endian -mcode-density -mdiv-rem \ + -mswap -mnorm -mmpy-option=6 -mbarrel-shifter LDSCRIPT = $(srctree)/board/synopsys/iot_devkit/u-boot.lds diff --git a/board/synopsys/nsim/Kconfig b/board/synopsys/nsim/Kconfig index 22287032bf5..b6966b2991e 100644 --- a/board/synopsys/nsim/Kconfig +++ b/board/synopsys/nsim/Kconfig @@ -9,4 +9,13 @@ config SYS_VENDOR config SYS_CONFIG_NAME default "nsim" +config NSIM_BOARD_CPPFLAGS + string "board arc-specific compiler options" + help + For nSIM we allow to set custom arc-specific compiler options + (like -mcpu=) instead of hardcoding them in its makefile as nSIM + target is used for represe
Re: [PATCH v3 08/10] spi: dw: Add mem_ops
> From: Sean Anderson > Sent: Monday, September 14, 2020 18:35 > To: u-boot@lists.denx.de; uboot-snps-...@synopsys.com > Cc: Marek Vasut; Horatiu Vultur; Eugeniy Paltsev; Jagan Teki; Heinrich > Schuchardt; Sean Anderson > Subject: [PATCH v3 08/10] spi: dw: Add mem_ops > > Changes in v3: > - Use constant 0x1 instead of SZ_64K. The latter is not included on > some platforms and I'm too lazy to figure out what the correct header is. ??? #include
[U-Boot] [PATCH] ARC: HSDK: Fix timer frequency value
CPU (and hence cpu timers) on HSDK board runs at 500MHz after preloader so fix wrong CPU frequency value in hsdk.dts Signed-off-by: Eugeniy Paltsev --- arch/arc/dts/hsdk.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arc/dts/hsdk.dts b/arch/arc/dts/hsdk.dts index e41e4ce84b..673bc5b26a 100644 --- a/arch/arc/dts/hsdk.dts +++ b/arch/arc/dts/hsdk.dts @@ -20,7 +20,7 @@ core_clk: core_clk { #clock-cells = <0>; compatible = "fixed-clock"; - clock-frequency = <10>; + clock-frequency = <5>; u-boot,dm-pre-reloc; }; }; -- 2.14.4 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH] ARC: HSDK: add tool and make target to generate bsp
HSDK board has preloader that reads SPI flash pages and searches special image header to fetch and load binary. Add tool, make target (bsp-generate) to generate update script and u-boot binary image with header for preloader. Also add script to default environment to apply updates. Signed-off-by: Eugeniy Paltsev --- board/synopsys/hsdk/config.mk | 11 +++ board/synopsys/hsdk/headerize-hsdk.py | 147 ++ include/configs/hsdk.h| 6 ++ 3 files changed, 164 insertions(+) create mode 100644 board/synopsys/hsdk/config.mk create mode 100644 board/synopsys/hsdk/headerize-hsdk.py diff --git a/board/synopsys/hsdk/config.mk b/board/synopsys/hsdk/config.mk new file mode 100644 index 00..7a0ed3ca36 --- /dev/null +++ b/board/synopsys/hsdk/config.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2018 Synopsys, Inc. All rights reserved. + +bsp-generate: u-boot u-boot.bin + $(Q)python3 $(srctree)/board/$(BOARDDIR)/headerize-hsdk.py \ + --arc-id 0x52 --image $(srctree)/u-boot.bin \ + --elf $(srctree)/u-boot + $(Q)mkimage -T script -C none -n 'uboot update script' \ + -d $(srctree)/u-boot-update.txt \ + $(srctree)/u-boot-update.img &> /dev/null diff --git a/board/synopsys/hsdk/headerize-hsdk.py b/board/synopsys/hsdk/headerize-hsdk.py new file mode 100644 index 00..97510474c4 --- /dev/null +++ b/board/synopsys/hsdk/headerize-hsdk.py @@ -0,0 +1,147 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2018 Synopsys, Inc. All rights reserved. +# Author: Eugeniy Paltsev + +import os, getopt, sys, zlib +from elftools.elf.elffile import ELFFile + + +def usage(exit_code): +print("usage:") +print(sys.argv[0] + " --arc-id 0x52 --image u-boot.bin --elf u-boot") +sys.exit(exit_code) + + +def elf_get_entry(filename): +with open(filename, 'rb') as f: +elffile = ELFFile(f) +return elffile.header['e_entry'] + + +def calc_check_sum(filename): +# u-boot.head check_sum for preloader - it is sum of all u-boot binary bytes +with open(filename, "rb") as file: +ba = bytearray(file.read()) +return sum(ba) & 0xFF + + +def arg_verify(uboot_bin_filename, uboot_elf_filename, arc_id): +if arc_id not in [0x52, 0x53]: +print("unknown ARC ID: " + hex(arc_id)) +sys.exit(2) + +if not os.path.isfile(uboot_bin_filename): +print("uboot bin file not exists: " + uboot_bin_filename) +sys.exit(2) + +if not os.path.isfile(uboot_elf_filename): +print("uboot elf file not exists: " + uboot_elf_filename) +sys.exit(2) + + +def main(): +try: +opts, args = getopt.getopt(sys.argv[1:], +"ha:i:l:e:", ["help", "arc-id=", "image=", "elf="]) +except getopt.GetoptError as err: +print(err) +usage(2) + +# default filenames +uboot_elf_filename = "u-boot" +uboot_bin_filename = "u-boot.bin" +headerised_filename = "u-boot.head" +uboot_scrypt_file = "u-boot-update.txt" + +# initial header values +arc_id = 0x52 # 0x52 for first HSDK release +image_copy_adr = 0x8100 # place where preloader will store u-boot binary +# initial constant header values, do not change these values +magic1 = 0xdeadbeafaf # big endian byte order +flash_address = 0x0 +flash_type = 0x0 # 0 - SPI flash, 1 - NOR flash +magic2 = [# big endian byte order +0x20202a2020202020202020202a20202020207c5c2e20202020202e2f7c20202020207c2d, +0x2e5c2020202f2e2d7c20202020205c2020602d2d2d6020202f20202020202f205f202020, +0x205f20205c20202020207c205f60712070205f207c2020202020272e5f3d2f205c3d5f2e, +0x272020202020202020605c202f60202020202020202020202020206f2020202020202020] + +for opt, arg in opts: +if opt in ('-h', "--help"): usage(0) +if opt in ('-a', "--arc-id"): arc_id = int(arg, 16) +if opt in ('-i', "--image"): uboot_bin_filename = arg +if opt in ('-e', "--elf"):uboot_elf_filename = arg + +arg_verify(uboot_bin_filename, uboot_elf_filename, arc_id) + +uboot_img_size = os.path.getsize(uboot_bin_filename) +jump_address = elf_get_entry(uboot_elf_filename) +check_sum = calc_check_sum(uboot_bin_filename) + +# write header to file +with open(headerised_filename, "wb") as file: +file.write(arc_id.to_bytes(2, byteorder='little')) +file.write(uboot_img_size.to_bytes(4, byteorder='little')) +file.write(check_sum.to_bytes(1, byteorder='little')) +fi
[U-Boot] [PATCH v2] ARC: HSDK: add tool and make target to generate bsp
HSDK board has preloader that reads SPI flash pages and searches special image header to fetch and load binary. Add tool, make target (bsp-generate) to generate update script and u-boot binary image with header for preloader. Also add script to default environment to apply updates. Signed-off-by: Eugeniy Paltsev --- Changes v1->v2: * Comments change board/synopsys/hsdk/config.mk | 11 +++ board/synopsys/hsdk/headerize-hsdk.py | 149 ++ include/configs/hsdk.h| 6 ++ 3 files changed, 166 insertions(+) create mode 100644 board/synopsys/hsdk/config.mk create mode 100644 board/synopsys/hsdk/headerize-hsdk.py diff --git a/board/synopsys/hsdk/config.mk b/board/synopsys/hsdk/config.mk` new file mode 100644 index 00..7a0ed3ca36 --- /dev/null +++ b/board/synopsys/hsdk/config.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2018 Synopsys, Inc. All rights reserved. + +bsp-generate: u-boot u-boot.bin + $(Q)python3 $(srctree)/board/$(BOARDDIR)/headerize-hsdk.py \ + --arc-id 0x52 --image $(srctree)/u-boot.bin \ + --elf $(srctree)/u-boot + $(Q)mkimage -T script -C none -n 'uboot update script' \ + -d $(srctree)/u-boot-update.txt \ + $(srctree)/u-boot-update.img &> /dev/null diff --git a/board/synopsys/hsdk/headerize-hsdk.py b/board/synopsys/hsdk/headerize-hsdk.py new file mode 100644 index 00..fce749723e --- /dev/null +++ b/board/synopsys/hsdk/headerize-hsdk.py @@ -0,0 +1,149 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2018 Synopsys, Inc. All rights reserved. +# Author: Eugeniy Paltsev + +import os, getopt, sys, zlib +from elftools.elf.elffile import ELFFile + + +def usage(exit_code): +print("usage:") +print(sys.argv[0] + " --arc-id 0x52 --image u-boot.bin --elf u-boot") +sys.exit(exit_code) + + +def elf_get_entry(filename): +with open(filename, 'rb') as f: +elffile = ELFFile(f) +return elffile.header['e_entry'] + + +def calc_check_sum(filename): +# u-boot.head check_sum for preloader - it is sum of all u-boot binary bytes +with open(filename, "rb") as file: +ba = bytearray(file.read()) +return sum(ba) & 0xFF + + +def arg_verify(uboot_bin_filename, uboot_elf_filename, arc_id): +if arc_id not in [0x52, 0x53]: +print("unknown ARC ID: " + hex(arc_id)) +sys.exit(2) + +if not os.path.isfile(uboot_bin_filename): +print("uboot bin file not exists: " + uboot_bin_filename) +sys.exit(2) + +if not os.path.isfile(uboot_elf_filename): +print("uboot elf file not exists: " + uboot_elf_filename) +sys.exit(2) + + +def main(): +try: +opts, args = getopt.getopt(sys.argv[1:], +"ha:i:l:e:", ["help", "arc-id=", "image=", "elf="]) +except getopt.GetoptError as err: +print(err) +usage(2) + +# default filenames +uboot_elf_filename = "u-boot" +uboot_bin_filename = "u-boot.bin" +headerised_filename = "u-boot.head" +uboot_scrypt_file = "u-boot-update.txt" + +# initial header values: place where preloader will store u-boot binary, +# should be equal to CONFIG_SYS_TEXT_BASE +image_copy_adr = 0x8100 + +# initial constant header values, do not change these values +arc_id = 0x52 # 0x52 for 1st HSDK release (hardcoded in RTL) +magic1 = 0xdeadbeafaf # big endian byte order +flash_address = 0x0 +flash_type = 0x0 # 0 - SPI flash, 1 - NOR flash +magic2 = [# big endian byte order +0x20202a2020202020202020202a20202020207c5c2e20202020202e2f7c20202020207c2d, +0x2e5c2020202f2e2d7c20202020205c2020602d2d2d6020202f20202020202f205f202020, +0x205f20205c20202020207c205f60712070205f207c2020202020272e5f3d2f205c3d5f2e, +0x272020202020202020605c202f60202020202020202020202020206f2020202020202020] + +for opt, arg in opts: +if opt in ('-h', "--help"): usage(0) +if opt in ('-a', "--arc-id"): arc_id = int(arg, 16) +if opt in ('-i', "--image"): uboot_bin_filename = arg +if opt in ('-e', "--elf"):uboot_elf_filename = arg + +arg_verify(uboot_bin_filename, uboot_elf_filename, arc_id) + +uboot_img_size = os.path.getsize(uboot_bin_filename) +jump_address = elf_get_entry(uboot_elf_filename) +check_sum = calc_check_sum(uboot_bin_filename) + +# write header to file +with open(headerised_filename, "wb") as file: +file.write(arc_id.to_bytes(2, byteorder='little')) +file.write(uboot_img_size.to_bytes(4, byteord
[U-Boot] [PATCH 0/2] GPIO: CREG: improve flexibility of hsdk-creg-gpio driver
CREG GPIO is a driver for weird soc-specific output ports, which are controlled by some fields in memory mapped register. Example: 31 975 0 < bit number | ||| | [ not used | gpio-1 | gpio-0 | <-shift-> ] < 32 bit register ^^ || write 0x2 == set output to "1" (activate) write 0x3 == set output to "0" (deactivate) As of tooday we only support fixed (hardcoded) bit per gpio line, activate / deactivatei and shift values. Fix that by read them from device tree to be able to use this driver for other boards. Eugeniy Paltsev (2): GPIO: CREG: improve flexibility of hsdk-creg-gpio driver CREG GPIO: add device tree bindings MAINTAINERS | 1 + arch/arc/dts/hsdk.dts| 7 +- doc/device-tree-bindings/gpio/snps,creg-gpio.txt | 43 ++ drivers/gpio/hsdk-creg-gpio.c| 103 ++- 4 files changed, 131 insertions(+), 23 deletions(-) create mode 100644 doc/device-tree-bindings/gpio/snps,creg-gpio.txt -- 2.14.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 1/2] GPIO: CREG: improve flexibility of hsdk-creg-gpio driver
CREG GPIO is a driver for weird soc-specific output ports, which are controlled by some fields in memory mapped register. Example: 31 975 0 < bit number | ||| | [ not used | gpio-1 | gpio-0 | <-shift-> ] < 32 bit register ^^ || write 0x2 == set output to "1" (activate) write 0x3 == set output to "0" (deactivate) As of tooday we only support fixed (hardcoded) bit per gpio line, activate / deactivatei and shift values. Fix that by read them from device tree to be able to use this driver for other boards. Remove "hsdk" prefix from compatible string as this driver can be used with different boards like HSDK, AXS101, AXS103, etc. Signed-off-by: Eugeniy Paltsev --- arch/arc/dts/hsdk.dts | 7 ++- drivers/gpio/hsdk-creg-gpio.c | 103 +- 2 files changed, 87 insertions(+), 23 deletions(-) diff --git a/arch/arc/dts/hsdk.dts b/arch/arc/dts/hsdk.dts index 264512877e..e41e4ce84b 100644 --- a/arch/arc/dts/hsdk.dts +++ b/arch/arc/dts/hsdk.dts @@ -101,11 +101,16 @@ }; cs_gpio: gpio@f00014b0 { - compatible = "snps,hsdk-creg-gpio"; + compatible = "snps,creg-gpio"; reg = <0xf00014b0 0x4>; gpio-controller; #gpio-cells = <1>; gpio-bank-name = "hsdk-spi-cs"; gpio-count = <1>; + gpio-first-shift = <0>; + gpio-bit-per-line = <2>; + gpio-activate-val = <2>; + gpio-deactivate-val = <3>; + gpio-default-val = <1>; }; }; diff --git a/drivers/gpio/hsdk-creg-gpio.c b/drivers/gpio/hsdk-creg-gpio.c index 084a2da652..800027f18e 100644 --- a/drivers/gpio/hsdk-creg-gpio.c +++ b/drivers/gpio/hsdk-creg-gpio.c @@ -16,25 +16,24 @@ #include #include -#define HSDK_CREG_MAX_GPIO 8 - -#define GPIO_ACTIVATE 0x2 -#define GPIO_DEACTIVATE0x3 -#define GPIO_PIN_MASK 0x3 -#define BIT_PER_GPIO 2 +#define DRV_NAME "gpio_creg" struct hsdk_creg_gpio { - uint32_t *regs; + u32 *regs; + u8 shift; + u8 activate; + u8 deactivate; + u8 bit_per_gpio; }; static int hsdk_creg_gpio_set_value(struct udevice *dev, unsigned oft, int val) { struct hsdk_creg_gpio *hcg = dev_get_priv(dev); - uint32_t reg = readl(hcg->regs); - uint32_t cmd = val ? GPIO_DEACTIVATE : GPIO_ACTIVATE; + u8 reg_shift = oft * hcg->bit_per_gpio + hcg->shift; + u32 reg = readl(hcg->regs); - reg &= ~(GPIO_PIN_MASK << (oft * BIT_PER_GPIO)); - reg |= (cmd << (oft * BIT_PER_GPIO)); + reg &= ~(GENMASK(hcg->bit_per_gpio - 1, 0) << reg_shift); + reg |= ((val ? hcg->deactivate : hcg->activate) << reg_shift); writel(reg, hcg->regs); @@ -51,7 +50,9 @@ static int hsdk_creg_gpio_direction_output(struct udevice *dev, unsigned oft, static int hsdk_creg_gpio_direction_input(struct udevice *dev, unsigned oft) { - pr_err("hsdk-creg-gpio can't be used as input!\n"); + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + + pr_err("%s can't be used as input!\n", uc_priv->bank_name); return -ENOTSUPP; } @@ -59,10 +60,11 @@ static int hsdk_creg_gpio_direction_input(struct udevice *dev, unsigned oft) static int hsdk_creg_gpio_get_value(struct udevice *dev, unsigned int oft) { struct hsdk_creg_gpio *hcg = dev_get_priv(dev); - uint32_t val = readl(hcg->regs); + u32 val = readl(hcg->regs); - val = (val >> (oft * BIT_PER_GPIO)) & GPIO_PIN_MASK; - return (val == GPIO_DEACTIVATE) ? 1 : 0; + val >>= oft * hcg->bit_per_gpio + hcg->shift; + val &= GENMASK(hcg->bit_per_gpio - 1, 0); + return (val == hcg->deactivate) ? 1 : 0; } static const struct dm_gpio_ops hsdk_creg_gpio_ops = { @@ -76,17 +78,74 @@ static int hsdk_creg_gpio_probe(struct udevice *dev) { struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); struct hsdk_creg_gpio *hcg = dev_get_priv(dev); + u32 shift, bit_per_gpio, activate, deactivate, gpio_count; + const u8 *defaults; - hcg->regs = (uint32_t *)devfdt_get_addr_ptr(dev); - - uc_priv->gpio_count = dev_read_u32_default(dev, "gpio-count", 1); - if (uc_priv->gpio_count > HSDK_CREG_MAX_GPIO) - uc_priv->gpio_count = HSDK_CREG_MAX_GPIO; + hcg->regs = (u32 *)devfdt_get_addr_ptr(dev); + gpio_count = dev_read_u32_default(dev, "
[U-Boot] [PATCH 2/2] CREG GPIO: add device tree bindings
Signed-off-by: Eugeniy Paltsev --- MAINTAINERS | 1 + doc/device-tree-bindings/gpio/snps,creg-gpio.txt | 43 2 files changed, 44 insertions(+) create mode 100644 doc/device-tree-bindings/gpio/snps,creg-gpio.txt diff --git a/MAINTAINERS b/MAINTAINERS index 642c448093..0ea730e33c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -74,6 +74,7 @@ ARC HSDK CREG GPIO M: Eugeniy Paltsev S: Maintained L: uboot-snps-...@synopsys.com +F: doc/device-tree-bindings/gpio/snps,creg-gpio.txt F: drivers/gpio/hsdk-creg-gpio.c ARM diff --git a/doc/device-tree-bindings/gpio/snps,creg-gpio.txt b/doc/device-tree-bindings/gpio/snps,creg-gpio.txt new file mode 100644 index 00..46ceb65c53 --- /dev/null +++ b/doc/device-tree-bindings/gpio/snps,creg-gpio.txt @@ -0,0 +1,43 @@ +GPIO via CREG (control registers) driver + +31 975 0 < bit number +| ||| | +[ not used | gpio-1 | gpio-0 | <-shift-> ] < 32 bit register + ^^ + || +write 0x2 == set output to "1" (activate) +write 0x3 == set output to "0" (deactivate) + +Required properties: +- compatible : "snps,creg-gpio" +- reg : Exactly one register range with length 0x4. +- #gpio-cells : Should be one - the pin number. +- gpio-controller : Marks the device node as a GPIO controller. +- gpio-count: Number of GPIO pins. +- gpio-bit-per-line: Number of bits per gpio line (see picture). +- gpio-first-shift: Shift (in bits) of the first GPIO field in register + (see picture). +- gpio-activate-val: Value should be set in corresponding field to set + output to "1" (see picture). Applied to all GPIO ports. +- gpio-deactivate-val: Value should be set in corresponding field to set + output to "0" (see picture). Applied to all GPIO ports. + +Optional properties: +- gpio-bank-name: name of bank (as default driver name is used is used) +- gpio-default-val: array of default output values (must me 0 or 1) + +Example (see picture): + +gpio: gpio@f00014b0 { + compatible = "snps,creg-gpio"; + reg = <0xf00014b0 0x4>; + gpio-controller; + #gpio-cells = <1>; + gpio-bank-name = "hsdk-spi-cs"; + gpio-count = <2>; + gpio-first-shift = <5>; + gpio-bit-per-line = <2>; + gpio-activate-val = <2>; + gpio-deactivate-val = <3>; + gpio-default-val = <1 1>; +}; -- 2.14.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH] AXS10x: add spi flash support
AXS10x boards have n25q512 spi flash IC, so add corresponding nodes to device tree and enaple corresponding options in defconfig. Signed-off-by: Eugeniy Paltsev --- NOTE: this patch has prerequisite: http://patchwork.ozlabs.org/patch/926871/ arch/arc/dts/axs10x_mb.dtsi | 34 ++ configs/axs101_defconfig| 12 configs/axs103_defconfig| 12 3 files changed, 58 insertions(+) diff --git a/arch/arc/dts/axs10x_mb.dtsi b/arch/arc/dts/axs10x_mb.dtsi index 3855a34dc2..56b993fdfc 100644 --- a/arch/arc/dts/axs10x_mb.dtsi +++ b/arch/arc/dts/axs10x_mb.dtsi @@ -4,6 +4,10 @@ */ / { + aliases { + spi0 = &spi0; + }; + axs10x_mb@e000 { compatible = "simple-bus"; #address-cells = <1>; @@ -56,5 +60,35 @@ reg-shift = <2>; reg-io-width = <4>; }; + + spi0: spi@0 { + compatible = "snps,dw-apb-ssi"; + reg = <0x0 0x100>; + #address-cells = <1>; + #size-cells = <0>; + spi-max-frequency = <400>; + clocks = <&apbclk>; + clock-names = "spi_clk"; + cs-gpio = <&cs_gpio 0>; + spi_flash@0 { + compatible = "spi-flash"; + reg = <0>; + spi-max-frequency = <400>; + }; + }; + + cs_gpio: gpio@11218 { + compatible = "snps,hsdk-creg-gpio"; + reg = <0x11218 0x4>; + gpio-controller; + #gpio-cells = <1>; + gpio-bank-name = "axs-spi-cs"; + gpio-count = <1>; + gpio-first-shift = <0>; + gpio-bit-per-line = <2>; + gpio-activate-val = <1>; + gpio-deactivate-val = <3>; + gpio-default-val = <1>; + }; }; }; diff --git a/configs/axs101_defconfig b/configs/axs101_defconfig index 25b10888ce..ae2f92faab 100644 --- a/configs/axs101_defconfig +++ b/configs/axs101_defconfig @@ -12,6 +12,8 @@ CONFIG_SYS_PROMPT="AXS# " # CONFIG_CMD_FLASH is not set CONFIG_CMD_MMC=y CONFIG_CMD_NAND=y +CONFIG_CMD_SF=y +CONFIG_CMD_SPI=y CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y @@ -27,13 +29,23 @@ CONFIG_ENV_FAT_INTERFACE="mmc" CONFIG_ENV_FAT_DEVICE_AND_PART="0:1" CONFIG_NET_RANDOM_ETHADDR=y CONFIG_DM=y +CONFIG_DM_GPIO=y +CONFIG_HSDK_CREG_GPIO=y CONFIG_MMC=y CONFIG_MMC_DW=y +CONFIG_DM_SPI_FLASH=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_BAR=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_SPI_FLASH_MTD=y CONFIG_DM_ETH=y CONFIG_PHY_GIGE=y CONFIG_ETH_DESIGNWARE=y CONFIG_DM_SERIAL=y CONFIG_SYS_NS16550=y +CONFIG_SPI=y +CONFIG_DM_SPI=y +CONFIG_DESIGNWARE_SPI=y CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USB_EHCI_HCD=y diff --git a/configs/axs103_defconfig b/configs/axs103_defconfig index b9d387b88a..6b0edd4127 100644 --- a/configs/axs103_defconfig +++ b/configs/axs103_defconfig @@ -12,6 +12,8 @@ CONFIG_SYS_PROMPT="AXS# " # CONFIG_CMD_FLASH is not set CONFIG_CMD_MMC=y CONFIG_CMD_NAND=y +CONFIG_CMD_SF=y +CONFIG_CMD_SPI=y CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y @@ -27,13 +29,23 @@ CONFIG_ENV_FAT_INTERFACE="mmc" CONFIG_ENV_FAT_DEVICE_AND_PART="0:1" CONFIG_NET_RANDOM_ETHADDR=y CONFIG_DM=y +CONFIG_DM_GPIO=y +CONFIG_HSDK_CREG_GPIO=y CONFIG_MMC=y CONFIG_MMC_DW=y +CONFIG_DM_SPI_FLASH=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_BAR=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_SPI_FLASH_MTD=y CONFIG_DM_ETH=y CONFIG_PHY_GIGE=y CONFIG_ETH_DESIGNWARE=y CONFIG_DM_SERIAL=y CONFIG_SYS_NS16550=y +CONFIG_SPI=y +CONFIG_DM_SPI=y +CONFIG_DESIGNWARE_SPI=y CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USB_OHCI_HCD=y -- 2.14.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v2] AXS10x: add spi flash support
AXS10x boards have n25q512 spi flash IC, so add corresponding nodes to device tree and enaple corresponding options in defconfig. Signed-off-by: Eugeniy Paltsev --- NOTE: this patch has prerequisite: http://patchwork.ozlabs.org/patch/926871/ Changes v1->v2: * change SPI CS gpio compatible name. arch/arc/dts/axs10x_mb.dtsi | 34 ++ configs/axs101_defconfig| 12 configs/axs103_defconfig| 12 3 files changed, 58 insertions(+) diff --git a/arch/arc/dts/axs10x_mb.dtsi b/arch/arc/dts/axs10x_mb.dtsi index 3855a34dc2..dfc03810ca 100644 --- a/arch/arc/dts/axs10x_mb.dtsi +++ b/arch/arc/dts/axs10x_mb.dtsi @@ -4,6 +4,10 @@ */ / { + aliases { + spi0 = &spi0; + }; + axs10x_mb@e000 { compatible = "simple-bus"; #address-cells = <1>; @@ -56,5 +60,35 @@ reg-shift = <2>; reg-io-width = <4>; }; + + spi0: spi@0 { + compatible = "snps,dw-apb-ssi"; + reg = <0x0 0x100>; + #address-cells = <1>; + #size-cells = <0>; + spi-max-frequency = <400>; + clocks = <&apbclk>; + clock-names = "spi_clk"; + cs-gpio = <&cs_gpio 0>; + spi_flash@0 { + compatible = "spi-flash"; + reg = <0>; + spi-max-frequency = <400>; + }; + }; + + cs_gpio: gpio@11218 { + compatible = "snps,creg-gpio"; + reg = <0x11218 0x4>; + gpio-controller; + #gpio-cells = <1>; + gpio-bank-name = "axs-spi-cs"; + gpio-count = <1>; + gpio-first-shift = <0>; + gpio-bit-per-line = <2>; + gpio-activate-val = <1>; + gpio-deactivate-val = <3>; + gpio-default-val = <1>; + }; }; }; diff --git a/configs/axs101_defconfig b/configs/axs101_defconfig index d056719e14..a981398cb5 100644 --- a/configs/axs101_defconfig +++ b/configs/axs101_defconfig @@ -15,6 +15,8 @@ CONFIG_SYS_PROMPT="AXS# " # CONFIG_CMD_FLASH is not set CONFIG_CMD_MMC=y CONFIG_CMD_NAND=y +CONFIG_CMD_SF=y +CONFIG_CMD_SPI=y CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y @@ -30,8 +32,15 @@ CONFIG_ENV_FAT_INTERFACE="mmc" CONFIG_ENV_FAT_DEVICE_AND_PART="0:1" CONFIG_NET_RANDOM_ETHADDR=y CONFIG_DM=y +CONFIG_DM_GPIO=y +CONFIG_HSDK_CREG_GPIO=y CONFIG_MMC=y CONFIG_MMC_DW=y +CONFIG_DM_SPI_FLASH=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_BAR=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_SPI_FLASH_MTD=y CONFIG_DM_ETH=y CONFIG_PHY_GIGE=y CONFIG_ETH_DESIGNWARE=y @@ -39,6 +48,9 @@ CONFIG_DM_SERIAL=y CONFIG_DEBUG_UART_SHIFT=2 CONFIG_DEBUG_UART_ANNOUNCE=y CONFIG_SYS_NS16550=y +CONFIG_SPI=y +CONFIG_DM_SPI=y +CONFIG_DESIGNWARE_SPI=y CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USB_EHCI_HCD=y diff --git a/configs/axs103_defconfig b/configs/axs103_defconfig index f0fccf4d9f..e524e6a9c6 100644 --- a/configs/axs103_defconfig +++ b/configs/axs103_defconfig @@ -15,6 +15,8 @@ CONFIG_SYS_PROMPT="AXS# " # CONFIG_CMD_FLASH is not set CONFIG_CMD_MMC=y CONFIG_CMD_NAND=y +CONFIG_CMD_SF=y +CONFIG_CMD_SPI=y CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y @@ -30,8 +32,15 @@ CONFIG_ENV_FAT_INTERFACE="mmc" CONFIG_ENV_FAT_DEVICE_AND_PART="0:1" CONFIG_NET_RANDOM_ETHADDR=y CONFIG_DM=y +CONFIG_DM_GPIO=y +CONFIG_HSDK_CREG_GPIO=y CONFIG_MMC=y CONFIG_MMC_DW=y +CONFIG_DM_SPI_FLASH=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_BAR=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_SPI_FLASH_MTD=y CONFIG_DM_ETH=y CONFIG_PHY_GIGE=y CONFIG_ETH_DESIGNWARE=y @@ -39,6 +48,9 @@ CONFIG_DM_SERIAL=y CONFIG_DEBUG_UART_SHIFT=2 CONFIG_DEBUG_UART_ANNOUNCE=y CONFIG_SYS_NS16550=y +CONFIG_SPI=y +CONFIG_DM_SPI=y +CONFIG_DESIGNWARE_SPI=y CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USB_OHCI_HCD=y -- 2.14.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH] ARC: AXS10x: add tool and make target to generate bsp
AXS10x boards have preloader that reads SPI flash pages and searches special image header to fetch and load binary. Add tool, make target (bsp-generate) to generate update script and u-boot binary image with header for preloader. Also add script to default environment to apply updates. Signed-off-by: Eugeniy Paltsev --- board/synopsys/axs10x/config.mk| 23 + board/synopsys/axs10x/headerize-axs.py | 176 + include/configs/axs10x.h | 7 ++ 3 files changed, 206 insertions(+) create mode 100644 board/synopsys/axs10x/config.mk create mode 100644 board/synopsys/axs10x/headerize-axs.py diff --git a/board/synopsys/axs10x/config.mk b/board/synopsys/axs10x/config.mk new file mode 100644 index 00..db04b986d1 --- /dev/null +++ b/board/synopsys/axs10x/config.mk @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2018 Synopsys, Inc. All rights reserved. + +bsp-generate: u-boot u-boot.bin +ifdef CONFIG_ISA_ARCV2 + $(Q)python3 $(srctree)/board/$(BOARDDIR)/headerize-axs.py \ + --header-type v2 \ + --arc-id 0x53 \ + --spi-flash-offset 0x20 \ + --image $(srctree)/u-boot.bin \ + --elf $(srctree)/u-boot +else + $(Q)python3 $(srctree)/board/$(BOARDDIR)/headerize-axs.py \ + --header-type v1 \ + --arc-id 0x434 \ + --spi-flash-offset 0x0 \ + --image $(srctree)/u-boot.bin \ + --elf $(srctree)/u-boot +endif + $(Q)mkimage -T script -C none -n 'uboot update script' \ + -d $(srctree)/u-boot-update.txt \ + $(srctree)/u-boot-update.img &> /dev/null diff --git a/board/synopsys/axs10x/headerize-axs.py b/board/synopsys/axs10x/headerize-axs.py new file mode 100644 index 00..fa6aaf350c --- /dev/null +++ b/board/synopsys/axs10x/headerize-axs.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python3 + +#we can use binascii instead of zlib +import os, getopt, sys, zlib +from elftools.elf.elffile import ELFFile + + +def usage(exit_code): +print("typical usage:") +print("AXS101:") +print(sys.argv[0] + \ +" --header-type v1 --arc-id 0x434 --spi-flash-offset 0x0 --image u-boot.bin --elf u-boot") +print("AXS103:") +print(sys.argv[0] + \ +" --header-type v2 --arc-id 0x53 --spi-flash-offset 0x20 --image u-boot.bin --elf u-boot") +sys.exit(exit_code) + + +def elf_get_entry(filename): +with open(filename, 'rb') as f: +elffile = ELFFile(f) +return elffile.header['e_entry'] + + +def calc_check_sum(filename): +# Calculate u-boot image check_sum: it is sum of all u-boot binary bytes +with open(filename, "rb") as file: +ba = bytearray(file.read()) +return sum(ba) & 0xFF + + +def arg_verify(uboot_bin_filename, uboot_elf_filename, header_type): +if not os.path.isfile(uboot_bin_filename): +print("uboot bin file not exists: " + uboot_bin_filename) +sys.exit(2) + +if not os.path.isfile(uboot_elf_filename): +print("uboot elf file not exists: " + uboot_elf_filename) +sys.exit(2) + +if header_type not in ("v1", "v2"): +print("unknown header type: " + header_type) +print("choose between 'v1' (most likely AXS101) and 'v2' (most likely AXS103)") +sys.exit(2) + + +def main(): +try: +opts, args = getopt.getopt(sys.argv[1:], +"ht:a:s:i:l:e:", +["help", "header-type=", "arc-id=", "spi-flash-offset=", "image=", "elf="]) +except getopt.GetoptError as err: +print(err) +usage(2) + +# default filenames +uboot_elf_filename = "u-boot" +uboot_bin_filename = "u-boot.bin" +headerised_filename = "u-boot.head" +uboot_scrypt_file = "u-boot-update.txt" + +# default values +spi_flash_offset= 0x20 +header_type = "v2" +arc_id = 0x53 + +# initial header values: place where preloader will store u-boot binary, +# should be equal to CONFIG_SYS_TEXT_BASE +image_copy_adr = 0x8100 + +# initial constant header values, do not change these values +magic1 = 0xdeadbeafaf # big endian byte order +magic2 = [# big endian byte order +0x20202a2020202020202020202a20202020207c5c2e20202020202e2f7c20202020207c2d, +0x2e5c2020202f2e2d7c20202020205c2020602d2d2d6020202f20202020202f205f202020, +0x205f20205c20202020207c205f60712070205f207c2020202020272e5f3d2f205c3d5f2e, +0x272020202020202020605c202f60202020202020202020202020206f2020202020202020] + +for opt, arg in opts: +
Re: [U-Boot] [uboot-snps-arc] [PATCH v3 2/5] dts: switch spi-flash to jedec, spi-nor compatible
Hi Neil, On Tue, 2019-01-15 at 13:59 +0100, Neil Armstrong wrote: > There is no reason not to use the Linux "jedec,spi-nor" binding in U-Boot > dts files. This compatible has been added in sf_probe, let use it. > > This patch switches to jedec,spi-nor when spi-flash is used in the DTS > and DTSI files, and removed spi-flash when jedec,spi-nor is already > present. > > The x86 dts are switched in a separate commit since it depends on a change > in fdtdec. > > Signed-off-by: Neil Armstrong > Acked-by: Stefan Roese > Reviewed-by: Simon Goldschmidt > --- For the ARC part: > arch/arc/dts/axs10x_mb.dtsi | 2 +- > arch/arc/dts/hsdk.dts | 2 +- Reviewed-by: Evgeniy Paltsev > diff --git a/arch/arc/dts/axs10x_mb.dtsi b/arch/arc/dts/axs10x_mb.dtsi > index dfc03810ca..b5aacd5170 100644 > --- a/arch/arc/dts/axs10x_mb.dtsi > +++ b/arch/arc/dts/axs10x_mb.dtsi > @@ -71,7 +71,7 @@ > clock-names = "spi_clk"; > cs-gpio = <&cs_gpio 0>; > spi_flash@0 { > - compatible = "spi-flash"; > + compatible = "jedec,spi-nor"; > reg = <0>; > spi-max-frequency = <400>; > }; > diff --git a/arch/arc/dts/hsdk.dts b/arch/arc/dts/hsdk.dts > index f024b96925..5e9ba054a4 100644 > --- a/arch/arc/dts/hsdk.dts > +++ b/arch/arc/dts/hsdk.dts > @@ -96,7 +96,7 @@ > clock-names = "spi_clk"; > cs-gpio = <&cs_gpio 0>; > spi_flash@0 { > - compatible = "spi-flash"; > + compatible = "jedec,spi-nor"; > reg = <0>; > spi-max-frequency = <400>; > }; > -- Eugeniy Paltsev ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 00/18] ARC: cache subsystem improvement/refactoring
Eugeniy Paltsev (18): ARC: cache: move i$ entire operation to separate function ARC: cache: remove per-line I$ operations as unused ARC: cache: Add support of FLUSH_N_INV d$ operations ARC: introduce is_isa_X functions ARC: flush & invalidate D$ with a single command ARC: cache: move IOC initialization to separate function ARC: move BCR encodings to separate header file ARC: cache: allways check dcache status before entire/line operations ARC: cache: Use is_isa_arcv2() instead of CONFIG_ISA_ARCV2 ifdef ARC: cache: move slc status check into slc_entire_op and slc_rgn_op ARC: cache: get rid of [slc,pae,icache,dcache]_exists global variables ARC: mode cache global variables to global data struct ARC: move IOC enabling to compile time options ARC: implement function to sync I/D caches before relocation ARC: implement function to cleanup caches before linux ARC: cache: move pae exists check into slc_upper_region_init ARC: cache: don't invalidate SLC in invalidate_icache_all ARC: cache: add missing cache cleanup before cache disable arch/arc/Kconfig | 18 ++ arch/arc/include/asm/arc-bcr.h | 77 ++ arch/arc/include/asm/arcregs.h | 11 + arch/arc/include/asm/cache.h | 8 + arch/arc/include/asm/global_data.h | 6 + arch/arc/lib/bootm.c | 4 +- arch/arc/lib/cache.c | 469 +++-- arch/arc/lib/init_helpers.c| 6 +- 8 files changed, 365 insertions(+), 234 deletions(-) create mode 100644 arch/arc/include/asm/arc-bcr.h -- 2.9.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 01/18] ARC: cache: move i$ entire operation to separate function
Move icache entire operation to separate function as we are planing to use it in another places (like sync_icache_dcache_all) Signed-off-by: Eugeniy Paltsev --- arch/arc/lib/cache.c | 31 +++ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index 04f1d9d..26f0a1f 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -315,20 +315,27 @@ void icache_disable(void) IC_CTRL_CACHE_DISABLE); } -void invalidate_icache_all(void) +/* IC supports only invalidation */ +static inline void __ic_entire_invalidate(void) { + if (!icache_status()) + return; + /* Any write to IC_IVIC register triggers invalidation of entire I$ */ - if (icache_status()) { - write_aux_reg(ARC_AUX_IC_IVIC, 1); - /* -* As per ARC HS databook (see chapter 5.3.3.2) -* it is required to add 3 NOPs after each write to IC_IVIC. -*/ - __builtin_arc_nop(); - __builtin_arc_nop(); - __builtin_arc_nop(); - read_aux_reg(ARC_AUX_IC_CTRL); /* blocks */ - } + write_aux_reg(ARC_AUX_IC_IVIC, 1); + /* +* As per ARC HS databook (see chapter 5.3.3.2) +* it is required to add 3 NOPs after each write to IC_IVIC. +*/ + __builtin_arc_nop(); + __builtin_arc_nop(); + __builtin_arc_nop(); + read_aux_reg(ARC_AUX_IC_CTRL); /* blocks */ +} + +void invalidate_icache_all(void) +{ + __ic_entire_invalidate(); #ifdef CONFIG_ISA_ARCV2 if (slc_exists) -- 2.9.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 10/18] ARC: cache: move slc status check into slc_entire_op and slc_rgn_op
As of today we check slc status before each call of __slc_rgn_op or __slc_entire_op. So move status check into __slc_rgn_op and __slc_entire_op. As we need to check status before *each* function call and we slc_entire_op and slc_rgn_op functions from different places we add this check directly into slc entire/line functions instead of their callers to avoid code duplication. Signed-off-by: Eugeniy Paltsev --- arch/arc/lib/cache.c | 22 +- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index eac3d66..8633ba5 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -63,10 +63,19 @@ void read_decode_mmu_bcr(void) #endif /* (CONFIG_ARC_MMU_VER >= 4) */ } +static inline bool slc_status(void) +{ + /* TODO: HS 3.0 supports SLC disable so we need to check it here */ + return slc_exists; +} + static void __slc_entire_op(const int op) { unsigned int ctrl; + if (!slc_status()) + return; + ctrl = read_aux_reg(ARC_AUX_SLC_CTRL); if (!(op & OP_FLUSH)) /* i.e. OP_INV */ @@ -103,6 +112,9 @@ static void __slc_rgn_op(unsigned long paddr, unsigned long sz, const int op) unsigned int ctrl; unsigned long end; + if (!slc_status()) + return; + /* * The Region Flush operation is specified by CTRL.RGN_OP[11..9] * - b'000 (default) is Flush, @@ -284,7 +296,7 @@ void invalidate_icache_all(void) { __ic_entire_invalidate(); - if (is_isa_arcv2() && slc_exists) + if (is_isa_arcv2()) __slc_entire_op(OP_INV); } @@ -405,7 +417,7 @@ void invalidate_dcache_range(unsigned long start, unsigned long end) if (!is_isa_arcv2() || !ioc_exists) __dc_line_op(start, end - start, OP_INV); - if (is_isa_arcv2() && slc_exists && !ioc_exists) + if (is_isa_arcv2() && !ioc_exists) __slc_rgn_op(start, end - start, OP_INV); } @@ -422,7 +434,7 @@ void flush_dcache_range(unsigned long start, unsigned long end) if (!is_isa_arcv2() || !ioc_exists) __dc_line_op(start, end - start, OP_FLUSH); - if (is_isa_arcv2() && slc_exists && !ioc_exists) + if (is_isa_arcv2() && !ioc_exists) __slc_rgn_op(start, end - start, OP_FLUSH); } @@ -441,7 +453,7 @@ void flush_n_invalidate_dcache_all(void) { __dc_entire_op(OP_FLUSH_N_INV); - if (is_isa_arcv2() && slc_exists) + if (is_isa_arcv2()) __slc_entire_op(OP_FLUSH_N_INV); } @@ -449,6 +461,6 @@ void flush_dcache_all(void) { __dc_entire_op(OP_FLUSH); - if (is_isa_arcv2() && slc_exists) + if (is_isa_arcv2()) __slc_entire_op(OP_FLUSH); } -- 2.9.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 05/18] ARC: flush & invalidate D$ with a single command
We don't implement separate flush_dcache_all intentionally as entire data cache invalidation is dangerous operation even if we flush data cache right before invalidation. There is the real example: We may hang in the next code if we store any context (like BLINK register) on stack in invalidate_dcache_all() function. BLINK register is the register where return address is automatically saved when we do function call with instructions like 'bl'. void flush_dcache_all() { __dc_entire_op(OP_FLUSH); // Other code // } void invalidate_dcache_all() { __dc_entire_op(OP_INV); // Other code // } void foo(void) { flush_dcache_all(); invalidate_dcache_all(); } Now let's see what really happens during that code execution: foo() |->> call flush_dcache_all [return address is saved to BLINK register] [push BLINK] (save to stack) ![point 1] |->> call __dc_entire_op(OP_FLUSH) [return address is saved to BLINK register] [flush L1 D$] return [jump to BLINK] <<-- [other flush_dcache_all code] [pop BLINK] (get from stack) return [jump to BLINK] <<-- |->> call invalidate_dcache_all [return address is saved to BLINK register] [push BLINK] (save to stack) ![point 2] |->> call __dc_entire_op(OP_FLUSH) [return address is saved to BLINK register] [invalidate L1 D$] ![point 3] // Oops!!! // We lose return address from invalidate_dcache_all function: // we save it to stack and invalidate L1 D$ after that! return [jump to BLINK] <<-- [other invalidate_dcache_all code] [pop BLINK] (get from stack) // we don't have this data in L1 dcache as we invalidated it in [point 3] // so we get it from next memory level (for example DDR memory) // but in the memory we have value which we save in [point 1], which // is return address from flush_dcache_all function (instead of // address from current invalidate_dcache_all function which we // saved in [point 2] !) return [jump to BLINK] <<-- // As BLINK points to invalidate_dcache_all, we call it again and // loop forever. Fortunately we may do flush and invalidation of D$ with a single one instruction which automatically mitigates a situation described above. And because invalidate_dcache_all isn't used in common u-boot code we implement "flush and invalidate dcache all" instead. Signed-off-by: Eugeniy Paltsev --- arch/arc/include/asm/cache.h | 1 + arch/arc/lib/cache.c | 15 ++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h index d26d9fb..382c412 100644 --- a/arch/arc/include/asm/cache.h +++ b/arch/arc/include/asm/cache.h @@ -30,6 +30,7 @@ #ifndef __ASSEMBLY__ void cache_init(void); +void flush_n_invalidate_dcache_all(void); #endif /* __ASSEMBLY__ */ diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index 83b77b9..a22ffe5 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -256,8 +256,7 @@ void cache_init(void) /* IOC Aperture size is equal to DDR size */ long ap_size = CONFIG_SYS_SDRAM_SIZE; - flush_dcache_all(); - invalidate_dcache_all(); + flush_n_invalidate_dcache_all(); if (!is_power_of_2(ap_size) || ap_size < 4096) panic("IOC Aperture size must be power of 2 and bigger 4Kib"); @@ -483,13 +482,19 @@ void flush_cache(unsigned long start, unsigned long size) flush_dcache_range(start, start + size); } -void invalidate_dcache_all(void) +/* + * As invalidate_dcache_all() is not used in generic U-Boot code and as we + * don't need it in arch/arc code alone (invalidate without flush) we implement + * flush_n_invalidate_dcache_all (flush and invalidate in 1 operation) because + * it's much safer. + */ +void flush_n_invalidate_dcache_all(void) { - __dc_entire_op(OP_INV); + __dc_entire_op(OP_FLUSH_N_INV); #ifdef CONFIG_ISA_ARCV2 if (slc_exists) - __slc_entire_op(OP_INV); + __slc_entire_op(OP_FLUSH_N_INV); #endif } -- 2.9.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 13/18] ARC: move IOC enabling to compile time options
Use CONFIG_ARC_DBG_IOC_ENABLE Kconfig option instead of ioc_enable global variable. Signed-off-by: Eugeniy Paltsev --- arch/arc/Kconfig | 18 arch/arc/include/asm/cache.h | 5 + arch/arc/lib/cache.c | 49 ++-- 3 files changed, 52 insertions(+), 20 deletions(-) diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index e3f9db7..cc96fa8 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -116,6 +116,24 @@ config SYS_DCACHE_OFF bool "Do not use Data Cache" default n +menuconfig ARC_DBG + bool "ARC debugging" + default y + +if ARC_DBG + +config ARC_DBG_IOC_ENABLE + bool "Enable IO coherency unit" + depends on CPU_ARCHS38 + default n + help + Enable IO coherency unit to debug problems with caches and + DMA peripherals. + NOTE: as of today linux will not work properly if this option + is enabled in u-boot! + +endif + choice prompt "Target select" default TARGET_AXS103 diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h index 382c412..fe75409 100644 --- a/arch/arc/include/asm/cache.h +++ b/arch/arc/include/asm/cache.h @@ -32,6 +32,11 @@ void cache_init(void); void flush_n_invalidate_dcache_all(void); +static const inline int is_ioc_enabled(void) +{ + return IS_ENABLED(CONFIG_ARC_DBG_IOC_ENABLE); +} + #endif /* __ASSEMBLY__ */ #endif /* __ASM_ARC_CACHE_H */ diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index d31606c..df269cf 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -33,18 +33,8 @@ DECLARE_GLOBAL_DATA_PTR; #define SLC_CTRL_BUSY 0x100 #define SLC_CTRL_RGN_OP_INV0x200 -/* - * By default that variable will fall into .bss section. - * But .bss section is not relocated and so it will be initilized before - * relocation but will be used after being zeroed. - */ #define CACHE_LINE_MASK(~(gd->arch.l1_line_sz - 1)) -bool ioc_exists __section(".data") = false; - -/* To force enable IOC set ioc_enable to 'true' */ -bool ioc_enable __section(".data") = false; - static inline bool pae_exists(void) { /* TODO: should we compare mmu version from BCR and from CONFIG? */ @@ -88,6 +78,30 @@ static inline bool slc_exists(void) return false; } +static inline bool ioc_exists(void) +{ + if (is_isa_arcv2()) { + union bcr_clust_cfg cbcr; + + cbcr.word = read_aux_reg(ARC_BCR_CLUSTER); + return cbcr.fields.c; + } + + return false; +} + +static inline bool ioc_status(void) +{ + /* +* We check only CONFIG option instead of IOC HW state check as IOC +* must be disabled by default. +*/ + if (is_ioc_enabled()) + return ioc_exists(); + + return false; +} + static inline bool slc_status(void) { /* TODO: HS 3.0 supports SLC disable so we need to check it here */ @@ -213,16 +227,11 @@ static void arc_ioc_setup(void) static void read_decode_cache_bcr_arcv2(void) { union bcr_slc_cfg slc_cfg; - union bcr_clust_cfg cbcr; if (slc_exists()) { slc_cfg.word = read_aux_reg(ARC_AUX_SLC_CONFIG); gd->arch.slc_line_sz = (slc_cfg.fields.lsz == 0) ? 128 : 64; } - - cbcr.word = read_aux_reg(ARC_BCR_CLUSTER); - if (cbcr.fields.c && ioc_enable) - ioc_exists = true; } void read_decode_cache_bcr(void) @@ -255,7 +264,7 @@ void cache_init(void) if (is_isa_arcv2()) read_decode_cache_bcr_arcv2(); - if (is_isa_arcv2() && ioc_exists) + if (is_isa_arcv2() && ioc_status()) arc_ioc_setup(); /* @@ -432,10 +441,10 @@ void invalidate_dcache_range(unsigned long start, unsigned long end) * ARCv2 && no IOC-> call __dc_line_op; call __slc_rgn_op * ARCv2 && IOC enabled -> nothing */ - if (!is_isa_arcv2() || !ioc_exists) + if (!is_isa_arcv2() || !ioc_status()) __dc_line_op(start, end - start, OP_INV); - if (is_isa_arcv2() && !ioc_exists) + if (is_isa_arcv2() && !ioc_status()) __slc_rgn_op(start, end - start, OP_INV); } @@ -449,10 +458,10 @@ void flush_dcache_range(unsigned long start, unsigned long end) * ARCv2 && no IOC-> call __dc_line_op; call __slc_rgn_op * ARCv2 && IOC enabled -> nothing */ - if (!is_isa_arcv2() || !ioc_exists) + if (!is_isa_arcv2() || !ioc_status()) __dc_line_op(start, end - start, OP_FLUSH); - if (is_isa_arcv2() && !ioc_exists) + if (is_isa_arcv2() && !ioc_status()) __slc_rgn_op(start, end - start, OP_FLUSH); } -- 2.9.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 02/18] ARC: cache: remove per-line I$ operations as unused
__cache_line_loop function was copied from linux kernel code where per line instruction cache operations are used. In uboot we use only entire instruction cache operations, so we can drop support of per line instruction cache operations from __cache_line_loop function as __cache_line_loop is never called with OP_INV_IC parameter. Signed-off-by: Eugeniy Paltsev --- arch/arc/lib/cache.c | 30 +++--- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index 26f0a1f..2252542 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -23,7 +23,6 @@ #define OP_INV 0x1 #define OP_FLUSH 0x2 -#define OP_INV_IC 0x3 /* Bit val in SLC_CONTROL */ #define SLC_CTRL_DIS 0x001 @@ -373,30 +372,15 @@ void dcache_disable(void) } #ifndef CONFIG_SYS_DCACHE_OFF -/* - * Common Helper for Line Operations on {I,D}-Cache - */ -static inline void __cache_line_loop(unsigned long paddr, unsigned long sz, -const int cacheop) +/* Common Helper for Line Operations on D-cache */ +static inline void __dcache_line_loop(unsigned long paddr, unsigned long sz, + const int cacheop) { unsigned int aux_cmd; -#if (CONFIG_ARC_MMU_VER == 3) - unsigned int aux_tag; -#endif int num_lines; - if (cacheop == OP_INV_IC) { - aux_cmd = ARC_AUX_IC_IVIL; -#if (CONFIG_ARC_MMU_VER == 3) - aux_tag = ARC_AUX_IC_PTAG; -#endif - } else { - /* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */ - aux_cmd = cacheop & OP_INV ? ARC_AUX_DC_IVDL : ARC_AUX_DC_FLDL; -#if (CONFIG_ARC_MMU_VER == 3) - aux_tag = ARC_AUX_DC_PTAG; -#endif - } + /* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */ + aux_cmd = cacheop & OP_INV ? ARC_AUX_DC_IVDL : ARC_AUX_DC_FLDL; sz += paddr & ~CACHE_LINE_MASK; paddr &= CACHE_LINE_MASK; @@ -405,7 +389,7 @@ static inline void __cache_line_loop(unsigned long paddr, unsigned long sz, while (num_lines-- > 0) { #if (CONFIG_ARC_MMU_VER == 3) - write_aux_reg(aux_tag, paddr); + write_aux_reg(ARC_AUX_DC_PTAG, paddr); #endif write_aux_reg(aux_cmd, paddr); paddr += l1_line_sz; @@ -458,7 +442,7 @@ static inline void __dc_line_op(unsigned long paddr, unsigned long sz, { unsigned int ctrl_reg = __before_dc_op(cacheop); - __cache_line_loop(paddr, sz, cacheop); + __dcache_line_loop(paddr, sz, cacheop); __after_dc_op(cacheop, ctrl_reg); } #else -- 2.9.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 17/18] ARC: cache: don't invalidate SLC in invalidate_icache_all
We don't want to invalidate SLC in invalidate_icache_all as we can lose some data from SLC (especially if L1 D$ is disabled) because SLC is shared for data and instructions. Signed-off-by: Eugeniy Paltsev --- arch/arc/lib/cache.c | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index 4e93ab9..907e9e3 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -326,8 +326,11 @@ void invalidate_icache_all(void) { __ic_entire_invalidate(); - if (is_isa_arcv2()) - __slc_entire_op(OP_INV); + /* +* We don't to invalidate SLC here as we can lose some data from +* SLC (especially if L1 D$ is disabled) because SLC is shared for +* data and instructions. +*/ } int dcache_status(void) -- 2.9.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 12/18] ARC: mode cache global variables to global data struct
There is the problem with current implementation if we start u-boot from ROM, as we use global variables before ther initialization, so these variables are overwritten when we copy .data section from ROM. So move these cache global variables into our arch "global data" structure so that we may really start from ROM. Signed-off-by: Eugeniy Paltsev --- arch/arc/include/asm/global_data.h | 6 ++ arch/arc/lib/cache.c | 19 +-- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/arch/arc/include/asm/global_data.h b/arch/arc/include/asm/global_data.h index f0242f1..43e1343 100644 --- a/arch/arc/include/asm/global_data.h +++ b/arch/arc/include/asm/global_data.h @@ -7,9 +7,15 @@ #ifndef__ASM_ARC_GLOBAL_DATA_H #define __ASM_ARC_GLOBAL_DATA_H +#include + #ifndef __ASSEMBLY__ /* Architecture-specific global data */ struct arch_global_data { + int l1_line_sz; +#if defined(CONFIG_ISA_ARCV2) + int slc_line_sz; +#endif }; #endif /* __ASSEMBLY__ */ diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index cb90c60..d31606c 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -13,6 +13,8 @@ #include #include +DECLARE_GLOBAL_DATA_PTR; + /* Bit values in IC_CTRL */ #define IC_CTRL_CACHE_DISABLE BIT(0) @@ -36,11 +38,8 @@ * But .bss section is not relocated and so it will be initilized before * relocation but will be used after being zeroed. */ -int l1_line_sz __section(".data"); - -#define CACHE_LINE_MASK(~(l1_line_sz - 1)) +#define CACHE_LINE_MASK(~(gd->arch.l1_line_sz - 1)) -int slc_line_sz __section(".data"); bool ioc_exists __section(".data") = false; /* To force enable IOC set ioc_enable to 'true' */ @@ -167,7 +166,7 @@ static void __slc_rgn_op(unsigned long paddr, unsigned long sz, const int op) * END needs to be setup before START (latter triggers the operation) * END can't be same as START, so add (l2_line_sz - 1) to sz */ - end = paddr + sz + slc_line_sz - 1; + end = paddr + sz + gd->arch.slc_line_sz - 1; /* * Upper addresses (ARC_AUX_SLC_RGN_END1 and ARC_AUX_SLC_RGN_START1) @@ -218,7 +217,7 @@ static void read_decode_cache_bcr_arcv2(void) if (slc_exists()) { slc_cfg.word = read_aux_reg(ARC_AUX_SLC_CONFIG); - slc_line_sz = (slc_cfg.fields.lsz == 0) ? 128 : 64; + gd->arch.slc_line_sz = (slc_cfg.fields.lsz == 0) ? 128 : 64; } cbcr.word = read_aux_reg(ARC_BCR_CLUSTER); @@ -233,14 +232,14 @@ void read_decode_cache_bcr(void) ibcr.word = read_aux_reg(ARC_BCR_IC_BUILD); if (ibcr.fields.ver) { - l1_line_sz = ic_line_sz = 8 << ibcr.fields.line_len; + gd->arch.l1_line_sz = ic_line_sz = 8 << ibcr.fields.line_len; if (!ic_line_sz) panic("Instruction exists but line length is 0\n"); } dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD); if (dbcr.fields.ver) { - l1_line_sz = dc_line_sz = 16 << dbcr.fields.line_len; + gd->arch.l1_line_sz = dc_line_sz = 16 << dbcr.fields.line_len; if (!dc_line_sz) panic("Data cache exists but line length is 0\n"); } @@ -361,14 +360,14 @@ static inline void __dcache_line_loop(unsigned long paddr, unsigned long sz, sz += paddr & ~CACHE_LINE_MASK; paddr &= CACHE_LINE_MASK; - num_lines = DIV_ROUND_UP(sz, l1_line_sz); + num_lines = DIV_ROUND_UP(sz, gd->arch.l1_line_sz); while (num_lines-- > 0) { #if (CONFIG_ARC_MMU_VER == 3) write_aux_reg(ARC_AUX_DC_PTAG, paddr); #endif write_aux_reg(aux_cmd, paddr); - paddr += l1_line_sz; + paddr += gd->arch.l1_line_sz; } } -- 2.9.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 07/18] ARC: move BCR encodings to separate header file
Signed-off-by: Eugeniy Paltsev --- arch/arc/include/asm/arc-bcr.h | 77 ++ arch/arc/lib/cache.c | 67 +--- 2 files changed, 85 insertions(+), 59 deletions(-) create mode 100644 arch/arc/include/asm/arc-bcr.h diff --git a/arch/arc/include/asm/arc-bcr.h b/arch/arc/include/asm/arc-bcr.h new file mode 100644 index 000..823906d --- /dev/null +++ b/arch/arc/include/asm/arc-bcr.h @@ -0,0 +1,77 @@ +/* + * ARC Build Configuration Registers, with encoded hardware config + * + * Copyright (C) 2018 Synopsys + * Author: Eugeniy Paltsev + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __ARC_BCR_H +#define __ARC_BCR_H +#ifndef __ASSEMBLY__ + +#include + +union bcr_di_cache { + struct { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int pad:12, line_len:4, sz:4, config:4, ver:8; +#else + unsigned int ver:8, config:4, sz:4, line_len:4, pad:12; +#endif + } fields; + unsigned int word; +}; + +union bcr_slc_cfg { + struct { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int pad:24, way:2, lsz:2, sz:4; +#else + unsigned int sz:4, lsz:2, way:2, pad:24; +#endif + } fields; + unsigned int word; +}; + +union bcr_generic { + struct { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int pad:24, ver:8; +#else + unsigned int ver:8, pad:24; +#endif + } fields; + unsigned int word; +}; + +union bcr_clust_cfg { + struct { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int pad:7, c:1, num_entries:8, num_cores:8, ver:8; +#else + unsigned int ver:8, num_cores:8, num_entries:8, c:1, pad:7; +#endif + } fields; + unsigned int word; +}; + +union bcr_mmu_4 { + struct { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int ver:8, sasid:1, sz1:4, sz0:4, res:2, pae:1, +n_ways:2, n_entry:2, n_super:2, u_itlb:3, u_dtlb:3; +#else + /* DTLB ITLB JESJE JA */ + unsigned int u_dtlb:3, u_itlb:3, n_super:2, n_entry:2, n_ways:2, +pae:1, res:2, sz0:4, sz1:4, sasid:1, ver:8; +#endif + } fields; + unsigned int word; +}; + +#endif /* __ASSEMBLY__ */ +#endif /* __ARC_BCR_H */ diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index 5070e9f..a743063 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -10,6 +10,7 @@ #include #include #include +#include #include /* Bit values in IC_CTRL */ @@ -55,24 +56,11 @@ void read_decode_mmu_bcr(void) { /* TODO: should we compare mmu version from BCR and from CONFIG? */ #if (CONFIG_ARC_MMU_VER >= 4) - u32 tmp; + union bcr_mmu_4 mmu4; - tmp = read_aux_reg(ARC_AUX_MMU_BCR); + mmu4.word = read_aux_reg(ARC_AUX_MMU_BCR); - struct bcr_mmu_4 { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int ver:8, sasid:1, sz1:4, sz0:4, res:2, pae:1, -n_ways:2, n_entry:2, n_super:2, u_itlb:3, u_dtlb:3; -#else - /* DTLB ITLB JESJE JA */ - unsigned int u_dtlb:3, u_itlb:3, n_super:2, n_entry:2, n_ways:2, -pae:1, res:2, sz0:4, sz1:4, sasid:1, ver:8; -#endif /* CONFIG_CPU_BIG_ENDIAN */ - } *mmu4; - - mmu4 = (struct bcr_mmu_4 *)&tmp; - - pae_exists = !!mmu4->pae; + pae_exists = !!mmu4.fields.pae; #endif /* (CONFIG_ARC_MMU_VER >= 4) */ } @@ -190,27 +178,9 @@ static void arc_ioc_setup(void) #ifdef CONFIG_ISA_ARCV2 static void read_decode_cache_bcr_arcv2(void) { - union { - struct { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int pad:24, way:2, lsz:2, sz:4; -#else - unsigned int sz:4, lsz:2, way:2, pad:24; -#endif - } fields; - unsigned int word; - } slc_cfg; - - union { - struct { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int pad:24, ver:8; -#else - unsigned int ver:8, pad:24; -#endif - } fields; - unsigned int word; - } sbcr; + union bcr_slc_cfg slc_cfg; + union bcr_clust_cfg cbcr; + union bcr_generic sbcr; sbcr.word = read_aux_reg(ARC_BCR_SLC); if (sbcr.fields.ver) { @@ -219,17 +189,6 @@ static void read_decode_cache_bcr_arcv2(void) slc_line_sz = (slc_cfg.fields.lsz == 0) ? 128 : 64; } - union { - struct bcr_clust_cfg { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int pad:7, c:1, num_entries:8, num_cores:8, ver:8; -#else - unsigned int ver:8, num_cores:8, num_entries:8, c:1, pad:7; -#endif - } fields; -
[U-Boot] [PATCH 14/18] ARC: implement function to sync I/D caches before relocation
As of today we call flush_dcache_all before relocation, to sync I/D caches so there are two problems: * We also flush SLC (on ARCv2) - this is overhead as SLC is shared for data and instructions. * We don't invalidate I$ - this can be dangerous if have some valid lines in I$ in relocation area for some reason. Fix this by implementing specialized sync_icache_dcache_all function. Signed-off-by: Eugeniy Paltsev --- arch/arc/include/asm/cache.h | 1 + arch/arc/lib/cache.c | 10 ++ arch/arc/lib/init_helpers.c | 6 +++--- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h index fe75409..6300676 100644 --- a/arch/arc/include/asm/cache.h +++ b/arch/arc/include/asm/cache.h @@ -31,6 +31,7 @@ void cache_init(void); void flush_n_invalidate_dcache_all(void); +void sync_icache_dcache_all(void); static const inline int is_ioc_enabled(void) { diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index df269cf..76602ae 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -491,3 +491,13 @@ void flush_dcache_all(void) if (is_isa_arcv2()) __slc_entire_op(OP_FLUSH); } + +/* + * This is function for making I/D Caches consistent when modifying u-boot code + * (relocation, etc...) + */ +void sync_icache_dcache_all(void) +{ + __dc_entire_op(OP_FLUSH); + __ic_entire_invalidate(); +} diff --git a/arch/arc/lib/init_helpers.c b/arch/arc/lib/init_helpers.c index dbc8d68..f7022ab 100644 --- a/arch/arc/lib/init_helpers.c +++ b/arch/arc/lib/init_helpers.c @@ -4,14 +4,14 @@ * SPDX-License-Identifier:GPL-2.0+ */ +#include #include DECLARE_GLOBAL_DATA_PTR; int init_cache_f_r(void) { -#ifndef CONFIG_SYS_DCACHE_OFF - flush_dcache_all(); -#endif + sync_icache_dcache_all(); + return 0; } -- 2.9.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 06/18] ARC: cache: move IOC initialization to separate function
Move IOC initialization to separate function from cache_init function. This is the preparation for the next patch when we will switch to is_isa_arcv2() function using instead of "CONFIG_ISA_ARCV2" ifdef using. Also it makes cache_init function clear. Signed-off-by: Eugeniy Paltsev --- arch/arc/lib/cache.c | 56 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index a22ffe5..5070e9f 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -157,6 +157,34 @@ static void __slc_rgn_op(unsigned long paddr, unsigned long sz, const int op) while (read_aux_reg(ARC_AUX_SLC_CTRL) & SLC_CTRL_BUSY); } + +static void arc_ioc_setup(void) +{ + /* IOC Aperture start is equal to DDR start */ + unsigned int ap_base = CONFIG_SYS_SDRAM_BASE; + /* IOC Aperture size is equal to DDR size */ + long ap_size = CONFIG_SYS_SDRAM_SIZE; + + flush_n_invalidate_dcache_all(); + + if (!is_power_of_2(ap_size) || ap_size < 4096) + panic("IOC Aperture size must be power of 2 and bigger 4Kib"); + + /* +* IOC Aperture size decoded as 2 ^ (SIZE + 2) KB, +* so setting 0x11 implies 512M, 0x12 implies 1G... +*/ + write_aux_reg(ARC_AUX_IO_COH_AP0_SIZE, + order_base_2(ap_size / 1024) - 2); + + /* IOC Aperture start must be aligned to the size of the aperture */ + if (ap_base % ap_size != 0) + panic("IOC Aperture start must be aligned to the size of the aperture"); + + write_aux_reg(ARC_AUX_IO_COH_AP0_BASE, ap_base >> 12); + write_aux_reg(ARC_AUX_IO_COH_PARTIAL, 1); + write_aux_reg(ARC_AUX_IO_COH_ENABLE, 1); +} #endif /* CONFIG_ISA_ARCV2 */ #ifdef CONFIG_ISA_ARCV2 @@ -250,32 +278,8 @@ void cache_init(void) #ifdef CONFIG_ISA_ARCV2 read_decode_cache_bcr_arcv2(); - if (ioc_exists) { - /* IOC Aperture start is equal to DDR start */ - unsigned int ap_base = CONFIG_SYS_SDRAM_BASE; - /* IOC Aperture size is equal to DDR size */ - long ap_size = CONFIG_SYS_SDRAM_SIZE; - - flush_n_invalidate_dcache_all(); - - if (!is_power_of_2(ap_size) || ap_size < 4096) - panic("IOC Aperture size must be power of 2 and bigger 4Kib"); - - /* -* IOC Aperture size decoded as 2 ^ (SIZE + 2) KB, -* so setting 0x11 implies 512M, 0x12 implies 1G... -*/ - write_aux_reg(ARC_AUX_IO_COH_AP0_SIZE, - order_base_2(ap_size / 1024) - 2); - - /* IOC Aperture start must be aligned to the size of the aperture */ - if (ap_base % ap_size != 0) - panic("IOC Aperture start must be aligned to the size of the aperture"); - - write_aux_reg(ARC_AUX_IO_COH_AP0_BASE, ap_base >> 12); - write_aux_reg(ARC_AUX_IO_COH_PARTIAL, 1); - write_aux_reg(ARC_AUX_IO_COH_ENABLE, 1); - } + if (ioc_exists) + arc_ioc_setup(); read_decode_mmu_bcr(); -- 2.9.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 15/18] ARC: implement function to cleanup caches before linux
Implement specialized function to clenup caches (and therefore sync I/D caches) which can be used for cleanup before linux launch instead of flush_dcache_all/invalidate_icache_all pair. It also allow us to safely invalidate L1 D$ and SLC before linux launch. Signed-off-by: Eugeniy Paltsev --- arch/arc/include/asm/cache.h | 1 + arch/arc/lib/bootm.c | 4 ++-- arch/arc/lib/cache.c | 10 ++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h index 6300676..7f1c247 100644 --- a/arch/arc/include/asm/cache.h +++ b/arch/arc/include/asm/cache.h @@ -32,6 +32,7 @@ void cache_init(void); void flush_n_invalidate_dcache_all(void); void sync_icache_dcache_all(void); +void sync_n_cleanup_cache_all(void); static const inline int is_ioc_enabled(void) { diff --git a/arch/arc/lib/bootm.c b/arch/arc/lib/bootm.c index 9eef707..c6800cb 100644 --- a/arch/arc/lib/bootm.c +++ b/arch/arc/lib/bootm.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier:GPL-2.0+ */ +#include #include DECLARE_GLOBAL_DATA_PTR; @@ -45,8 +46,7 @@ int arch_fixup_fdt(void *blob) static int cleanup_before_linux(void) { disable_interrupts(); - flush_dcache_all(); - invalidate_icache_all(); + sync_n_cleanup_cache_all(); return 0; } diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index 76602ae..c706fbd 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -501,3 +501,13 @@ void sync_icache_dcache_all(void) __dc_entire_op(OP_FLUSH); __ic_entire_invalidate(); } + +void sync_n_cleanup_cache_all(void) +{ + __dc_entire_op(OP_FLUSH_N_INV); + + if (is_isa_arcv2()) + __slc_entire_op(OP_FLUSH_N_INV); + + __ic_entire_invalidate(); +} -- 2.9.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 18/18] ARC: cache: add missing cache cleanup before cache disable
Add missing cache cleanup before cache disable: * Flush and invalidate L1 D$ before disabling. Otherwise we can lose some data when we disable L1 D$ if this data isn't flushed to next level cache. Or we can get wrong data if L1 D$ has some entries after enable which we modified when the L1 D$ was disabled. * Invalidate L1 I$ before disabling. Otherwise we can execute wrong instructions after L1 I$ enable if we modified any code when L1 I$ was disabled. Signed-off-by: Eugeniy Paltsev --- arch/arc/lib/cache.c | 15 --- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index 907e9e3..ba442fb 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -15,6 +15,9 @@ DECLARE_GLOBAL_DATA_PTR; +static inline void __ic_entire_invalidate(void); +static inline void __dc_entire_op(const int cacheop); + /* Bit values in IC_CTRL */ #define IC_CTRL_CACHE_DISABLE BIT(0) @@ -299,9 +302,13 @@ void icache_enable(void) void icache_disable(void) { - if (icache_exists()) - write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) | - IC_CTRL_CACHE_DISABLE); + if (!icache_exists()) + return; + + __ic_entire_invalidate(); + + write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) | + IC_CTRL_CACHE_DISABLE); } /* IC supports only invalidation */ @@ -358,6 +365,8 @@ void dcache_disable(void) if (!dcache_exists()) return; + __dc_entire_op(OP_FLUSH_N_INV); + write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) | DC_CTRL_CACHE_DISABLE); } -- 2.9.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 16/18] ARC: cache: move pae exists check into slc_upper_region_init
Move pae exists check into slc_upper_region_init function itself instead of its caller as more appropriate place. Signed-off-by: Eugeniy Paltsev --- arch/arc/lib/cache.c | 15 +-- 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index c706fbd..4e93ab9 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -139,6 +139,14 @@ static void __slc_entire_op(const int op) static void slc_upper_region_init(void) { /* +* ARC_AUX_SLC_RGN_START1 and ARC_AUX_SLC_RGN_END1 register exist +* only if PAE exists in current HW. So we had to check pae_exist +* before using them. +*/ + if (!pae_exists()) + return; + + /* * ARC_AUX_SLC_RGN_END1 and ARC_AUX_SLC_RGN_START1 are always == 0 * as we don't use PAE40. */ @@ -267,12 +275,7 @@ void cache_init(void) if (is_isa_arcv2() && ioc_status()) arc_ioc_setup(); - /* -* ARC_AUX_SLC_RGN_START1 and ARC_AUX_SLC_RGN_END1 register exist -* only if PAE exists in current HW. So we had to check pae_exist -* before using them. -*/ - if (is_isa_arcv2() && slc_exists() && pae_exists()) + if (is_isa_arcv2() && slc_exists()) slc_upper_region_init(); } -- 2.9.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 11/18] ARC: cache: get rid of [slc, pae, icache, dcache]_exists global variables
There is the problem with current implementation if we start u-boot from ROM, as we use cache global variables before ther initialization, so these variables are overwritten when we copy .data section from ROM. So use icache_exists(), dcache_exists(), slc_exists(), pae_exists() functions which check BCRs every time instead of corresponding global variables. Signed-off-by: Eugeniy Paltsev --- arch/arc/lib/cache.c | 65 +--- 1 file changed, 42 insertions(+), 23 deletions(-) diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index 8633ba5..cb90c60 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -20,7 +20,6 @@ #define DC_CTRL_CACHE_DISABLE BIT(0) #define DC_CTRL_INV_MODE_FLUSH BIT(6) #define DC_CTRL_FLUSH_STATUS BIT(8) -#define CACHE_VER_NUM_MASK 0xF #define OP_INV BIT(0) #define OP_FLUSH BIT(1) @@ -38,20 +37,16 @@ * relocation but will be used after being zeroed. */ int l1_line_sz __section(".data"); -bool dcache_exists __section(".data") = false; -bool icache_exists __section(".data") = false; #define CACHE_LINE_MASK(~(l1_line_sz - 1)) int slc_line_sz __section(".data"); -bool slc_exists __section(".data") = false; bool ioc_exists __section(".data") = false; -bool pae_exists __section(".data") = false; /* To force enable IOC set ioc_enable to 'true' */ bool ioc_enable __section(".data") = false; -void read_decode_mmu_bcr(void) +static inline bool pae_exists(void) { /* TODO: should we compare mmu version from BCR and from CONFIG? */ #if (CONFIG_ARC_MMU_VER >= 4) @@ -59,14 +54,45 @@ void read_decode_mmu_bcr(void) mmu4.word = read_aux_reg(ARC_AUX_MMU_BCR); - pae_exists = !!mmu4.fields.pae; + if (mmu4.fields.pae) + return true; #endif /* (CONFIG_ARC_MMU_VER >= 4) */ + + return false; +} + +static inline bool icache_exists(void) +{ + union bcr_di_cache ibcr; + + ibcr.word = read_aux_reg(ARC_BCR_IC_BUILD); + return !!ibcr.fields.ver; +} + +static inline bool dcache_exists(void) +{ + union bcr_di_cache dbcr; + + dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD); + return !!dbcr.fields.ver; +} + +static inline bool slc_exists(void) +{ + if (is_isa_arcv2()) { + union bcr_generic sbcr; + + sbcr.word = read_aux_reg(ARC_BCR_SLC); + return !!sbcr.fields.ver; + } + + return false; } static inline bool slc_status(void) { /* TODO: HS 3.0 supports SLC disable so we need to check it here */ - return slc_exists; + return slc_exists(); } static void __slc_entire_op(const int op) @@ -189,12 +215,9 @@ static void read_decode_cache_bcr_arcv2(void) { union bcr_slc_cfg slc_cfg; union bcr_clust_cfg cbcr; - union bcr_generic sbcr; - sbcr.word = read_aux_reg(ARC_BCR_SLC); - if (sbcr.fields.ver) { + if (slc_exists()) { slc_cfg.word = read_aux_reg(ARC_AUX_SLC_CONFIG); - slc_exists = true; slc_line_sz = (slc_cfg.fields.lsz == 0) ? 128 : 64; } @@ -210,7 +233,6 @@ void read_decode_cache_bcr(void) ibcr.word = read_aux_reg(ARC_BCR_IC_BUILD); if (ibcr.fields.ver) { - icache_exists = true; l1_line_sz = ic_line_sz = 8 << ibcr.fields.line_len; if (!ic_line_sz) panic("Instruction exists but line length is 0\n"); @@ -218,7 +240,6 @@ void read_decode_cache_bcr(void) dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD); if (dbcr.fields.ver) { - dcache_exists = true; l1_line_sz = dc_line_sz = 16 << dbcr.fields.line_len; if (!dc_line_sz) panic("Data cache exists but line length is 0\n"); @@ -238,20 +259,18 @@ void cache_init(void) if (is_isa_arcv2() && ioc_exists) arc_ioc_setup(); - read_decode_mmu_bcr(); - /* * ARC_AUX_SLC_RGN_START1 and ARC_AUX_SLC_RGN_END1 register exist * only if PAE exists in current HW. So we had to check pae_exist * before using them. */ - if (is_isa_arcv2() && slc_exists && pae_exists) + if (is_isa_arcv2() && slc_exists() && pae_exists()) slc_upper_region_init(); } int icache_status(void) { - if (!icache_exists) + if (!icache_exists()) return 0; if (read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE) @@ -262,14 +281,14 @@ int icache_status(void) void icache_enable(void) { - if (icache_exists) + if (icache_exists()) write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) &
[U-Boot] [PATCH 04/18] ARC: introduce is_isa_X functions
Introduce is_isa_arcv2 and is_isa_arcompact functions. As this functions only check configuration options and return compile-time constant they can be used instead of #ifdef's to to write clear code. So we can write -->8--- if (is_isa_arcv2()) ioc_configure(); -->8--- instead of -->8--- ifdef CONFIG_ISA_ARCV2 ioc_configure(); endif -->8--- Signed-off-by: Eugeniy Paltsev --- arch/arc/include/asm/arcregs.h | 11 +++ 1 file changed, 11 insertions(+) diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h index 67f4163..3a51314 100644 --- a/arch/arc/include/asm/arcregs.h +++ b/arch/arc/include/asm/arcregs.h @@ -8,6 +8,7 @@ #define _ASM_ARC_ARCREGS_H #include +#include /* * ARC architecture has additional address space - auxiliary registers. @@ -88,6 +89,16 @@ /* ARCNUM [15:8] - field to identify each core in a multi-core system */ #define CPU_ID_GET() ((read_aux_reg(ARC_AUX_IDENTITY) & 0xFF00) >> 8) + +static const inline int is_isa_arcv2(void) +{ + return IS_ENABLED(CONFIG_ISA_ARCV2); +} + +static const inline int is_isa_arcompact(void) +{ + return IS_ENABLED(CONFIG_ISA_ARCOMPACT); +} #endif /* __ASSEMBLY__ */ #endif /* _ASM_ARC_ARCREGS_H */ -- 2.9.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 08/18] ARC: cache: allways check dcache status before entire/line operations
As we are planning to get rid of dozens of ifdef's in cache.c we would better check dcache status before each entire/line operation then check CONFIG_SYS_DCACHE_OFF config option. This makes the code clear. Another advantage is that the dcache entire/line functions remain functional even if we enable dcache in runtime. As we need to check status before *each* function call and we dcache entire/line functions from different places we add this check directly into dcache entire/line functions instead of their callers to avoid code duplication. Signed-off-by: Eugeniy Paltsev --- arch/arc/lib/cache.c | 11 ++- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index a743063..f566528 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -324,7 +324,6 @@ void dcache_disable(void) DC_CTRL_CACHE_DISABLE); } -#ifndef CONFIG_SYS_DCACHE_OFF /* Common Helper for Line Operations on D-cache */ static inline void __dcache_line_loop(unsigned long paddr, unsigned long sz, const int cacheop) @@ -374,6 +373,9 @@ static inline void __dc_entire_op(const int cacheop) { int aux; + if (!dcache_status()) + return; + __before_dc_op(cacheop); if (cacheop & OP_INV) /* Inv or flush-n-inv use same cmd reg */ @@ -389,14 +391,13 @@ static inline void __dc_entire_op(const int cacheop) static inline void __dc_line_op(unsigned long paddr, unsigned long sz, const int cacheop) { + if (!dcache_status()) + return; + __before_dc_op(cacheop); __dcache_line_loop(paddr, sz, cacheop); __after_dc_op(cacheop); } -#else -#define __dc_entire_op(cacheop) -#define __dc_line_op(paddr, sz, cacheop) -#endif /* !CONFIG_SYS_DCACHE_OFF */ void invalidate_dcache_range(unsigned long start, unsigned long end) { -- 2.9.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 09/18] ARC: cache: Use is_isa_arcv2() instead of CONFIG_ISA_ARCV2 ifdef
Use is_isa_arcv2() function instead of CONFIG_ISA_ARCV2 define check to make code clear at the same time keeping pretty much the same functionality - code in branches under "if (is_isa_arcv2())" won't be compiled if CONFIG_ISA_ARCV2 is not defined. Signed-off-by: Eugeniy Paltsev --- arch/arc/lib/cache.c | 51 +-- 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index f566528..eac3d66 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -43,7 +43,6 @@ bool icache_exists __section(".data") = false; #define CACHE_LINE_MASK(~(l1_line_sz - 1)) -#ifdef CONFIG_ISA_ARCV2 int slc_line_sz __section(".data"); bool slc_exists __section(".data") = false; bool ioc_exists __section(".data") = false; @@ -173,9 +172,7 @@ static void arc_ioc_setup(void) write_aux_reg(ARC_AUX_IO_COH_PARTIAL, 1); write_aux_reg(ARC_AUX_IO_COH_ENABLE, 1); } -#endif /* CONFIG_ISA_ARCV2 */ -#ifdef CONFIG_ISA_ARCV2 static void read_decode_cache_bcr_arcv2(void) { union bcr_slc_cfg slc_cfg; @@ -193,7 +190,6 @@ static void read_decode_cache_bcr_arcv2(void) if (cbcr.fields.c && ioc_enable) ioc_exists = true; } -#endif void read_decode_cache_bcr(void) { @@ -224,10 +220,10 @@ void cache_init(void) { read_decode_cache_bcr(); -#ifdef CONFIG_ISA_ARCV2 - read_decode_cache_bcr_arcv2(); + if (is_isa_arcv2()) + read_decode_cache_bcr_arcv2(); - if (ioc_exists) + if (is_isa_arcv2() && ioc_exists) arc_ioc_setup(); read_decode_mmu_bcr(); @@ -237,9 +233,8 @@ void cache_init(void) * only if PAE exists in current HW. So we had to check pae_exist * before using them. */ - if (slc_exists && pae_exists) + if (is_isa_arcv2() && slc_exists && pae_exists) slc_upper_region_init(); -#endif /* CONFIG_ISA_ARCV2 */ } int icache_status(void) @@ -289,10 +284,8 @@ void invalidate_icache_all(void) { __ic_entire_invalidate(); -#ifdef CONFIG_ISA_ARCV2 - if (slc_exists) + if (is_isa_arcv2() && slc_exists) __slc_entire_op(OP_INV); -#endif } int dcache_status(void) @@ -404,15 +397,16 @@ void invalidate_dcache_range(unsigned long start, unsigned long end) if (start >= end) return; -#ifdef CONFIG_ISA_ARCV2 - if (!ioc_exists) -#endif + /* +* ARCv1 -> call __dc_line_op +* ARCv2 && no IOC-> call __dc_line_op; call __slc_rgn_op +* ARCv2 && IOC enabled -> nothing +*/ + if (!is_isa_arcv2() || !ioc_exists) __dc_line_op(start, end - start, OP_INV); -#ifdef CONFIG_ISA_ARCV2 - if (slc_exists && !ioc_exists) + if (is_isa_arcv2() && slc_exists && !ioc_exists) __slc_rgn_op(start, end - start, OP_INV); -#endif } void flush_dcache_range(unsigned long start, unsigned long end) @@ -420,15 +414,16 @@ void flush_dcache_range(unsigned long start, unsigned long end) if (start >= end) return; -#ifdef CONFIG_ISA_ARCV2 - if (!ioc_exists) -#endif + /* +* ARCv1 -> call __dc_line_op +* ARCv2 && no IOC-> call __dc_line_op; call __slc_rgn_op +* ARCv2 && IOC enabled -> nothing +*/ + if (!is_isa_arcv2() || !ioc_exists) __dc_line_op(start, end - start, OP_FLUSH); -#ifdef CONFIG_ISA_ARCV2 - if (slc_exists && !ioc_exists) + if (is_isa_arcv2() && slc_exists && !ioc_exists) __slc_rgn_op(start, end - start, OP_FLUSH); -#endif } void flush_cache(unsigned long start, unsigned long size) @@ -446,18 +441,14 @@ void flush_n_invalidate_dcache_all(void) { __dc_entire_op(OP_FLUSH_N_INV); -#ifdef CONFIG_ISA_ARCV2 - if (slc_exists) + if (is_isa_arcv2() && slc_exists) __slc_entire_op(OP_FLUSH_N_INV); -#endif } void flush_dcache_all(void) { __dc_entire_op(OP_FLUSH); -#ifdef CONFIG_ISA_ARCV2 - if (slc_exists) + if (is_isa_arcv2() && slc_exists) __slc_entire_op(OP_FLUSH); -#endif } -- 2.9.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 03/18] ARC: cache: Add support of FLUSH_N_INV d$ operations
As of today __dc_line_op and __dc_entire_op support only flush (OP_FLUSH) and invalidate (OP_INV) operations. Add support of flush and invalidate (OP_FLUSH_N_INV) operation which we planing to use in next patches. Signed-off-by: Eugeniy Paltsev --- arch/arc/lib/cache.c | 42 +++--- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index 2252542..83b77b9 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -21,8 +21,9 @@ #define DC_CTRL_FLUSH_STATUS BIT(8) #define CACHE_VER_NUM_MASK 0xF -#define OP_INV 0x1 -#define OP_FLUSH 0x2 +#define OP_INV BIT(0) +#define OP_FLUSH BIT(1) +#define OP_FLUSH_N_INV (OP_FLUSH | OP_INV) /* Bit val in SLC_CONTROL */ #define SLC_CTRL_DIS 0x001 @@ -396,36 +397,32 @@ static inline void __dcache_line_loop(unsigned long paddr, unsigned long sz, } } -static unsigned int __before_dc_op(const int op) +static void __before_dc_op(const int op) { - unsigned int reg; + unsigned int ctrl; - if (op == OP_INV) { - /* -* IM is set by default and implies Flush-n-inv -* Clear it here for vanilla inv -*/ - reg = read_aux_reg(ARC_AUX_DC_CTRL); - write_aux_reg(ARC_AUX_DC_CTRL, reg & ~DC_CTRL_INV_MODE_FLUSH); - } + ctrl = read_aux_reg(ARC_AUX_DC_CTRL); - return reg; + /* IM bit implies flush-n-inv, instead of vanilla inv */ + if (op == OP_INV) + ctrl &= ~DC_CTRL_INV_MODE_FLUSH; + else + ctrl |= DC_CTRL_INV_MODE_FLUSH; + + write_aux_reg(ARC_AUX_DC_CTRL, ctrl); } -static void __after_dc_op(const int op, unsigned int reg) +static void __after_dc_op(const int op) { if (op & OP_FLUSH) /* flush / flush-n-inv both wait */ while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS); - - /* Switch back to default Invalidate mode */ - if (op == OP_INV) - write_aux_reg(ARC_AUX_DC_CTRL, reg | DC_CTRL_INV_MODE_FLUSH); } static inline void __dc_entire_op(const int cacheop) { int aux; - unsigned int ctrl_reg = __before_dc_op(cacheop); + + __before_dc_op(cacheop); if (cacheop & OP_INV) /* Inv or flush-n-inv use same cmd reg */ aux = ARC_AUX_DC_IVDC; @@ -434,16 +431,15 @@ static inline void __dc_entire_op(const int cacheop) write_aux_reg(aux, 0x1); - __after_dc_op(cacheop, ctrl_reg); + __after_dc_op(cacheop); } static inline void __dc_line_op(unsigned long paddr, unsigned long sz, const int cacheop) { - unsigned int ctrl_reg = __before_dc_op(cacheop); - + __before_dc_op(cacheop); __dcache_line_loop(paddr, sz, cacheop); - __after_dc_op(cacheop, ctrl_reg); + __after_dc_op(cacheop); } #else #define __dc_entire_op(cacheop) -- 2.9.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
Re: [U-Boot] [uboot-snps-arc] [PATCH 1/2] SPI Flash: add support of sst26wf* flash series
Hi Jagan, Maybe you have any comments or remarks about this patch? And if you don't could you please apply it. Thanks! On Tue, 2018-02-06 at 18:15 +0300, Eugeniy Paltsev wrote: > sst26wf flash series block protection implementation differs > from other SST series, so add implementation for sst26wf > lock/unlock/is_locked functions. > > Signed-off-by: Eugeniy Paltsev > --- >  drivers/mtd/spi/spi_flash.c | 188 > >  1 file changed, 188 insertions(+) > > diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c > index 294d9f9..ec3f5bc 100644 > --- a/drivers/mtd/spi/spi_flash.c > +++ b/drivers/mtd/spi/spi_flash.c > @@ -842,6 +842,184 @@ int stm_unlock(struct spi_flash *flash, u32 ofs, size_t > len) >  } >  #endif >  > +#if defined(CONFIG_SPI_FLASH_SST) > +#define SST26_CMD_READ_BPR 0x72 > +#define SST26_CMD_WRITE_BPR 0x42 > + > +#define BLOCK_64K_SZ 0x1 > +#define MAX_BPR_REG_LEN (18 + 1) > +#define SST26WF_BOUND_REG_SIZE ((32 + 4 * 8) * 1024) > + > +bool sst26_check_bpr(u32 bpr_size, u8 *cmd, u32 bit) > +{ > + return !!(cmd[bpr_size - (bit / 8) - 1] & BIT(bit % 8)); > +} > + > +bool sst26_clear_bpr(u32 bpr_size, u8 *cmd, u32 bit) > +{ > + cmd[bpr_size - (bit / 8) - 1] &= ~BIT(bit % 8); > + return false; > +} > + > +bool sst26_set_bpr(u32 bpr_size, u8 *cmd, u32 bit) > +{ > + cmd[bpr_size - (bit / 8) - 1] |= BIT(bit % 8); > + return false; > +} > + > +enum lock_ctl { > + CTL_LOCK, > + CTL_UNLOCK, > + CTL_CHECK > +}; > + > +/* > + * sst26wf016/sst26wf032/sst26wf064 have next block protection: > + * 4x   - 8  KByte blocks - read & write protection bits - upper addresses > + * 1x   - 32 KByte blocks - write protection bits > + * rest - 64 KByte blocks - write protection bits > + * 1x   - 32 KByte blocks - write protection bits > + * 4x   - 8  KByte blocks - read & write protection bits - lower addresses > + * > + * We'll support only per 64k lock/unlock so lower and upper 64 KByte region > + * will be treated as single block. > + */ > + > +/* > + * Lock, unlock or check lock status of the flash region of the flash > (depending > + * on the lock_ctl value) > + */ > +int sst26_lock_ctl(struct spi_flash *flash, u32 ofs, size_t len, enum > lock_ctl ctl) > +{ > + u32 i, bpr_ptr, rptr_64k, lptr_64k, bpr_size; > + bool lower_64k = false, upper_64k = false; > + u8 cmd, bpr_buff[MAX_BPR_REG_LEN] = {}; > + int ret; > + > + bool (* bpr_bit_process) (u32 bpr_size, u8 *, u32); > + > + /* Check length and offset for 64k alignment */ > + if ((ofs & 0x) || (len & 0x)) > + return -EINVAL; > + > + if (ofs + len > flash->size) > + return -EINVAL; > + > + /* SST26 family has only 16 Mbit, 32 Mbit and 64 Mbit IC */ > + if (flash->size != 0x20 && > + flash->size != 0x40 && > + flash->size != 0x80) > + return -EINVAL; > + > + bpr_size = 2 + (flash->size / BLOCK_64K_SZ / 8); > + > + cmd = SST26_CMD_READ_BPR; > + ret = spi_flash_read_common(flash, &cmd, 1, bpr_buff, bpr_size); > + if (ret < 0) { > + printf("SF: fail to read block-protection register\n"); > + return ret; > + } > + > + if (ctl == CTL_LOCK) > + bpr_bit_process = sst26_set_bpr; > + else if (ctl == CTL_UNLOCK) > + bpr_bit_process = sst26_clear_bpr; > + else > + bpr_bit_process = sst26_check_bpr; > + > + rptr_64k = min_t(u32, ofs + len , flash->size - SST26WF_BOUND_REG_SIZE); > + lptr_64k = max_t(u32, ofs, SST26WF_BOUND_REG_SIZE); > + > + upper_64k = ((ofs + len) > (flash->size - SST26WF_BOUND_REG_SIZE)); > + lower_64k = (ofs < SST26WF_BOUND_REG_SIZE); > + > + /* Lower bits in block-protection register are about 64k region */ > + bpr_ptr = lptr_64k / BLOCK_64K_SZ - 1; > + > + /* Process 64K blocks region */ > + while (lptr_64k < rptr_64k) { > + if (bpr_bit_process(bpr_size, bpr_buff, bpr_ptr)) > + return 1; > + > + bpr_ptr++; > + lptr_64k += BLOCK_64K_SZ; > + } > + > + /* 32K and 8K region bits in BPR are after 64k region bits */ > + bpr_ptr = (flash->size - 2 * SST26WF_BOUND_REG_SIZE) / BLOCK_64K_SZ; > + > + /* Process lower 32K block region */ > + if (lower_64k) > + if (bpr_bit_process(bpr_size, bpr_
[U-Boot] [PATCH 0/5] DW SPI: fixes and improvements
Various fixes and improvements of designware spi driver. Eugeniy Paltsev (5): DW SPI: fix tx data loss on FIFO flush DW SPI: fix transmit only mode DW SPI: refactor poll_transfer functions DW SPI: add option to use external gpio for chip select DW SPI: use 32 bit access instead of 16 and 32 bit mix drivers/spi/designware_spi.c | 132 --- 1 file changed, 87 insertions(+), 45 deletions(-) -- 2.14.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 2/5] DW SPI: fix transmit only mode
In current implementation we get -ETIMEDOUT error when we try to use transmit only mode (SPI_TMOD_TO) This happens because in transmit only mode input FIFO never gets any data which breaks our logic in dw_reader(): we are waiting until RX data will be ready in dw_reader, but this newer happens, so we return with error. Fix that by using SPI_TMOD_TR instead of SPI_TMOD_TO which allows to use RX FIFO. Signed-off-by: Eugeniy Paltsev --- drivers/spi/designware_spi.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c index 71d8839d55..37ce16dc11 100644 --- a/drivers/spi/designware_spi.c +++ b/drivers/spi/designware_spi.c @@ -360,7 +360,11 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen, else if (rx) priv->tmode = SPI_TMOD_RO; else - priv->tmode = SPI_TMOD_TO; + /* +* In transmit only mode (SPI_TMOD_TO) input FIFO never gets +* any data which breaks our logic in poll_transfer() above. +*/ + priv->tmode = SPI_TMOD_TR; cr0 &= ~SPI_TMOD_MASK; cr0 |= (priv->tmode << SPI_TMOD_OFFSET); -- 2.14.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 3/5] DW SPI: refactor poll_transfer functions
There is no sense in waiting for RX data in dw_reader function: there is no chance that RX data will appear in RX FIFO if RX FIFO is empty after previous TX write in dw_writer function. So get rid of this waiting. After that we can get rid of dw_reader return value and make it returning void. After that we can get rid of dw_reader return value check in poll_transfer function. With these changes we're getting closer to Linux DW SPI driver. Signed-off-by: Eugeniy Paltsev --- drivers/spi/designware_spi.c | 26 -- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c index 37ce16dc11..630dc17f16 100644 --- a/drivers/spi/designware_spi.c +++ b/drivers/spi/designware_spi.c @@ -285,28 +285,16 @@ static void dw_writer(struct dw_spi_priv *priv) } } -static int dw_reader(struct dw_spi_priv *priv) +static void dw_reader(struct dw_spi_priv *priv) { - unsigned start = get_timer(0); - u32 max; + u32 max = rx_max(priv); u16 rxw; - /* Wait for rx data to be ready */ - while (rx_max(priv) == 0) { - if (get_timer(start) > RX_TIMEOUT) - return -ETIMEDOUT; - } - - max = rx_max(priv); - while (max--) { rxw = dw_readw(priv, DW_SPI_DR); debug("%s: rx=0x%02x\n", __func__, rxw); - /* -* Care about rx only if the transfer's original "rx" is -* not null -*/ + /* Care about rx if the transfer's original "rx" is not null */ if (priv->rx_end - priv->len) { if (priv->bits_per_word == 8) *(u8 *)(priv->rx) = rxw; @@ -315,19 +303,13 @@ static int dw_reader(struct dw_spi_priv *priv) } priv->rx += priv->bits_per_word >> 3; } - - return 0; } static int poll_transfer(struct dw_spi_priv *priv) { - int ret; - do { dw_writer(priv); - ret = dw_reader(priv); - if (ret < 0) - return ret; + dw_reader(priv); } while (priv->rx_end > priv->rx); return 0; -- 2.14.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 1/5] DW SPI: fix tx data loss on FIFO flush
In current implementation if some data still exists in Tx FIFO it can be silently flushed, i.e. dropped on disabling of the controller, which happens when writing 0 to DW_SPI_SSIENR (it happens in the beginning of new transfer) So add wait for current transmit operation to complete to be sure that current transmit operation is finished before new one. Signed-off-by: Eugeniy Paltsev --- drivers/spi/designware_spi.c | 17 + 1 file changed, 17 insertions(+) diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c index c501aeea16..71d8839d55 100644 --- a/drivers/spi/designware_spi.c +++ b/drivers/spi/designware_spi.c @@ -338,6 +338,7 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen, { struct udevice *bus = dev->parent; struct dw_spi_priv *priv = dev_get_priv(bus); + unsigned long start; const u8 *tx = dout; u8 *rx = din; int ret = 0; @@ -394,6 +395,22 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen, /* Start transfer in a polling loop */ ret = poll_transfer(priv); + /* +* Wait for current transmit operation to complete. +* Otherwise if some data still exists in Tx FIFO it can be +* silently flushed, i.e. dropped on disabling of the controller, +* which happens when writing 0 to DW_SPI_SSIENR which happens +* in the beginning of new transfer. +*/ + start = get_timer(0); + while (!(dw_readl(priv, DW_SPI_SR) & SR_TF_EMPT) || + (dw_readl(priv, DW_SPI_SR) & SR_BUSY)) { + if (get_timer(start) > RX_TIMEOUT) { + ret = -ETIMEDOUT; + break; + } + } + return ret; } -- 2.14.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 4/5] DW SPI: add option to use external gpio for chip select
DW SPI internal chip select management has limitation: it hold CS line in active state only when the FIFO is not empty. If the FIFO freed before we add new data the SPI transaction will be broken. So add option to use external gpio for chip select. Gpio can be added via device tree using standard gpio bindings. Signed-off-by: Eugeniy Paltsev --- drivers/spi/designware_spi.c | 51 +++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c index 630dc17f16..099c9c4d03 100644 --- a/drivers/spi/designware_spi.c +++ b/drivers/spi/designware_spi.c @@ -10,6 +10,7 @@ * SPDX-License-Identifier:GPL-2.0 */ +#include #include #include #include @@ -97,6 +98,8 @@ struct dw_spi_priv { struct clk clk; unsigned long bus_clk_rate; + struct gpio_desc cs_gpio; /* External chip-select gpio */ + int bits_per_word; u8 cs; /* chip select pin */ u8 tmode; /* TR/TO/RO/EEPROM */ @@ -130,6 +133,32 @@ static inline void dw_writew(struct dw_spi_priv *priv, u32 offset, u16 val) __raw_writew(val, priv->regs + offset); } +static int request_gpio_cs(struct udevice *bus) +{ +#if defined(CONFIG_DM_GPIO) && !defined(CONFIG_SPL_BUILD) + struct dw_spi_priv *priv = dev_get_priv(bus); + int ret; + + /* External chip select gpio line is optional */ + ret = gpio_request_by_name(bus, "cs-gpio", 0, &priv->cs_gpio, 0); + if (ret == -ENOENT) + return 0; + + if (ret < 0) { + printf("Error: %d: Can't get %s gpio!\n", ret, bus->name); + return ret; + } + + if (dm_gpio_is_valid(&priv->cs_gpio)) { + dm_gpio_set_dir_flags(&priv->cs_gpio, + GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); + } + + debug("%s: used external gpio for CS management\n", __func__); +#endif + return 0; +} + static int dw_spi_ofdata_to_platdata(struct udevice *bus) { struct dw_spi_platdata *plat = bus->platdata; @@ -144,7 +173,7 @@ static int dw_spi_ofdata_to_platdata(struct udevice *bus) debug("%s: regs=%p max-frequency=%d\n", __func__, plat->regs, plat->frequency); - return 0; + return request_gpio_cs(bus); } static inline void spi_enable_chip(struct dw_spi_priv *priv, int enable) @@ -315,6 +344,18 @@ static int poll_transfer(struct dw_spi_priv *priv) return 0; } +static void external_cs_manage(struct udevice *dev, bool on) +{ +#if defined(CONFIG_DM_GPIO) && !defined(CONFIG_SPL_BUILD) + struct dw_spi_priv *priv = dev_get_priv(dev->parent); + + if (!dm_gpio_is_valid(&priv->cs_gpio)) + return; + + dm_gpio_set_value(&priv->cs_gpio, on ? 1 : 0); +#endif +} + static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen, const void *dout, void *din, unsigned long flags) { @@ -333,6 +374,10 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen, return -1; } + /* Start the transaction if necessary. */ + if (flags & SPI_XFER_BEGIN) + external_cs_manage(dev, false); + cr0 = (priv->bits_per_word - 1) | (priv->type << SPI_FRF_OFFSET) | (priv->mode << SPI_MODE_OFFSET) | (priv->tmode << SPI_TMOD_OFFSET); @@ -397,6 +442,10 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen, } } + /* Stop the transaction if necessary */ + if (flags & SPI_XFER_END) + external_cs_manage(dev, true); + return ret; } -- 2.14.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 5/5] DW SPI: use 32 bit access instead of 16 and 32 bit mix
Current DW SPI driver uses 32 bit access for some registers and 16 bit access for others. So if DW SPI IP is connected via bus which doesn't support 16 bit access we will get bus error. Fix that by switching to 32 bit access only instead of 16 and 32 bit mix Additional Documentation to Support this Change: The DW_apb_ssi databook states: "All registers in the DW_apb_ssi are addressed at 32-bit boundaries to remain consistent with the AHB bus. Where the physical size of any register is less than 32-bits wide, the upper unused bits of the 32-bit boundary are reserved. Writing to these bits has no effect; reading from these bits returns 0." [1] [1] Section 6.1 of dw_apb_ssi.pdf (version 3.22a) Signed-off-by: Eugeniy Paltsev --- drivers/spi/designware_spi.c | 44 +--- 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c index 099c9c4d03..24034c79b3 100644 --- a/drivers/spi/designware_spi.c +++ b/drivers/spi/designware_spi.c @@ -113,26 +113,16 @@ struct dw_spi_priv { void *rx_end; }; -static inline u32 dw_readl(struct dw_spi_priv *priv, u32 offset) +static inline u32 dw_read(struct dw_spi_priv *priv, u32 offset) { return __raw_readl(priv->regs + offset); } -static inline void dw_writel(struct dw_spi_priv *priv, u32 offset, u32 val) +static inline void dw_write(struct dw_spi_priv *priv, u32 offset, u32 val) { __raw_writel(val, priv->regs + offset); } -static inline u16 dw_readw(struct dw_spi_priv *priv, u32 offset) -{ - return __raw_readw(priv->regs + offset); -} - -static inline void dw_writew(struct dw_spi_priv *priv, u32 offset, u16 val) -{ - __raw_writew(val, priv->regs + offset); -} - static int request_gpio_cs(struct udevice *bus) { #if defined(CONFIG_DM_GPIO) && !defined(CONFIG_SPL_BUILD) @@ -178,14 +168,14 @@ static int dw_spi_ofdata_to_platdata(struct udevice *bus) static inline void spi_enable_chip(struct dw_spi_priv *priv, int enable) { - dw_writel(priv, DW_SPI_SSIENR, (enable ? 1 : 0)); + dw_write(priv, DW_SPI_SSIENR, (enable ? 1 : 0)); } /* Restart the controller, disable all interrupts, clean rx fifo */ static void spi_hw_init(struct dw_spi_priv *priv) { spi_enable_chip(priv, 0); - dw_writel(priv, DW_SPI_IMR, 0xff); + dw_write(priv, DW_SPI_IMR, 0xff); spi_enable_chip(priv, 1); /* @@ -196,13 +186,13 @@ static void spi_hw_init(struct dw_spi_priv *priv) u32 fifo; for (fifo = 1; fifo < 256; fifo++) { - dw_writew(priv, DW_SPI_TXFLTR, fifo); - if (fifo != dw_readw(priv, DW_SPI_TXFLTR)) + dw_write(priv, DW_SPI_TXFLTR, fifo); + if (fifo != dw_read(priv, DW_SPI_TXFLTR)) break; } priv->fifo_len = (fifo == 1) ? 0 : fifo; - dw_writew(priv, DW_SPI_TXFLTR, 0); + dw_write(priv, DW_SPI_TXFLTR, 0); } debug("%s: fifo_len=%d\n", __func__, priv->fifo_len); } @@ -271,7 +261,7 @@ static inline u32 tx_max(struct dw_spi_priv *priv) u32 tx_left, tx_room, rxtx_gap; tx_left = (priv->tx_end - priv->tx) / (priv->bits_per_word >> 3); - tx_room = priv->fifo_len - dw_readw(priv, DW_SPI_TXFLR); + tx_room = priv->fifo_len - dw_read(priv, DW_SPI_TXFLR); /* * Another concern is about the tx/rx mismatch, we @@ -292,7 +282,7 @@ static inline u32 rx_max(struct dw_spi_priv *priv) { u32 rx_left = (priv->rx_end - priv->rx) / (priv->bits_per_word >> 3); - return min_t(u32, rx_left, dw_readw(priv, DW_SPI_RXFLR)); + return min_t(u32, rx_left, dw_read(priv, DW_SPI_RXFLR)); } static void dw_writer(struct dw_spi_priv *priv) @@ -308,7 +298,7 @@ static void dw_writer(struct dw_spi_priv *priv) else txw = *(u16 *)(priv->tx); } - dw_writew(priv, DW_SPI_DR, txw); + dw_write(priv, DW_SPI_DR, txw); debug("%s: tx=0x%02x\n", __func__, txw); priv->tx += priv->bits_per_word >> 3; } @@ -320,7 +310,7 @@ static void dw_reader(struct dw_spi_priv *priv) u16 rxw; while (max--) { - rxw = dw_readw(priv, DW_SPI_DR); + rxw = dw_read(priv, DW_SPI_DR); debug("%s: rx=0x%02x\n", __func__, rxw); /* Care about rx if the transfer's original "rx" is not null */ @@ -409,8 +399,8 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen, debug("%s: cr0=%08x\n", __func__, cr0); /* Reprogram cr0 only if changed */ - if (dw_readw(priv, DW_SPI_CTRL0) != cr0
Re: [U-Boot] [uboot-snps-arc] Re: [PATCH 1/2] SPI Flash: add support of sst26wf* flash series
Hi Jagan, On Tue, 2018-03-13 at 22:11 +0530, Jagan Teki wrote: > On Tue, Feb 6, 2018 at 8:45 PM, Eugeniy Paltsev > wrote: > > sst26wf flash series block protection implementation differs > > from other SST series, so add implementation for sst26wf > > lock/unlock/is_locked functions. > > How it is different from existing SST implementation, Linux has > support this similar part and use normal SST? Looks like the person, who add sst26wf* flash series support to Linux only use/test reading from these flash ICs and reading works fine as only write protection implementation was changed. Also it ids possible that these write protection bits were cleared by prebootloader on platform there that patch was test - so flash IC was already unlocked. BTW: I have plans to port this patch to linux too. -- Eugeniy Paltsev ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v2 00/20] ARC: cache subsystem improvement/refactoring
This iv v2 version of "ARC: cache subsystem improvement/refactoring" patch series. You can find v1 patch series here: http://patchwork.ozlabs.org/cover/873039/ Eugeniy Paltsev (20): ARC: cache: move i$ entire operation to separate function ARC: cache: remove per-line I$ operations as unused ARC: cache: Add support of FLUSH_N_INV d$ operations ARC: introduce is_isa_X functions ARC: flush & invalidate D$ with a single command ARC: cache: move IOC initialization to separate function ARC: move BCR encodings to separate header file ARC: cache: allways check dcache status before entire/line operations ARC: cache: Use is_isa_arcv2() instead of CONFIG_ISA_ARCV2 ifdef ARC: cache: move slc status check into slc_entire_op and slc_rgn_op ARC: cache: get rid of [slc,pae,icache,dcache]_exists global variables ARC: move cache global variables to global data struct ARC: cache: move pae exists check into slc_upper_region_init ARC: move IOC enabling to compile time options ARC: cache: implement [i,d]cache_enabled as separate functions ARC: cache: fix SLC operations when SLC is bypassed for data ARC: implement function to sync and cleanup caches ARC: cache: add additional configuration checks ARC: cache: add missing cache cleanup before cache disable ARC: cache: refactor arc_ioc_setup function arch/arc/Kconfig | 18 + arch/arc/include/asm/arc-bcr.h | 77 + arch/arc/include/asm/arcregs.h | 11 + arch/arc/include/asm/cache.h | 7 + arch/arc/include/asm/global_data.h | 6 + arch/arc/lib/bootm.c | 4 +- arch/arc/lib/cache.c | 677 - arch/arc/lib/init_helpers.c| 6 +- 8 files changed, 562 insertions(+), 244 deletions(-) create mode 100644 arch/arc/include/asm/arc-bcr.h -- 2.14.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v2 02/20] ARC: cache: remove per-line I$ operations as unused
__cache_line_loop function was copied from linux kernel code where per line instruction cache operations are used. In uboot we use only entire instruction cache operations, so we can drop support of per line instruction cache operations from __cache_line_loop function as __cache_line_loop is never called with OP_INV_IC parameter. Signed-off-by: Eugeniy Paltsev --- arch/arc/lib/cache.c | 30 +++--- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index 26f0a1ff9b..2252542f16 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -23,7 +23,6 @@ #define OP_INV 0x1 #define OP_FLUSH 0x2 -#define OP_INV_IC 0x3 /* Bit val in SLC_CONTROL */ #define SLC_CTRL_DIS 0x001 @@ -373,30 +372,15 @@ void dcache_disable(void) } #ifndef CONFIG_SYS_DCACHE_OFF -/* - * Common Helper for Line Operations on {I,D}-Cache - */ -static inline void __cache_line_loop(unsigned long paddr, unsigned long sz, -const int cacheop) +/* Common Helper for Line Operations on D-cache */ +static inline void __dcache_line_loop(unsigned long paddr, unsigned long sz, + const int cacheop) { unsigned int aux_cmd; -#if (CONFIG_ARC_MMU_VER == 3) - unsigned int aux_tag; -#endif int num_lines; - if (cacheop == OP_INV_IC) { - aux_cmd = ARC_AUX_IC_IVIL; -#if (CONFIG_ARC_MMU_VER == 3) - aux_tag = ARC_AUX_IC_PTAG; -#endif - } else { - /* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */ - aux_cmd = cacheop & OP_INV ? ARC_AUX_DC_IVDL : ARC_AUX_DC_FLDL; -#if (CONFIG_ARC_MMU_VER == 3) - aux_tag = ARC_AUX_DC_PTAG; -#endif - } + /* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */ + aux_cmd = cacheop & OP_INV ? ARC_AUX_DC_IVDL : ARC_AUX_DC_FLDL; sz += paddr & ~CACHE_LINE_MASK; paddr &= CACHE_LINE_MASK; @@ -405,7 +389,7 @@ static inline void __cache_line_loop(unsigned long paddr, unsigned long sz, while (num_lines-- > 0) { #if (CONFIG_ARC_MMU_VER == 3) - write_aux_reg(aux_tag, paddr); + write_aux_reg(ARC_AUX_DC_PTAG, paddr); #endif write_aux_reg(aux_cmd, paddr); paddr += l1_line_sz; @@ -458,7 +442,7 @@ static inline void __dc_line_op(unsigned long paddr, unsigned long sz, { unsigned int ctrl_reg = __before_dc_op(cacheop); - __cache_line_loop(paddr, sz, cacheop); + __dcache_line_loop(paddr, sz, cacheop); __after_dc_op(cacheop, ctrl_reg); } #else -- 2.14.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v2 01/20] ARC: cache: move i$ entire operation to separate function
Move icache entire operation to separate function as we are planing to use it in another places (like sync_icache_dcache_all) Signed-off-by: Eugeniy Paltsev --- arch/arc/lib/cache.c | 31 +++ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index 04f1d9d59b..26f0a1ff9b 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -315,20 +315,27 @@ void icache_disable(void) IC_CTRL_CACHE_DISABLE); } -void invalidate_icache_all(void) +/* IC supports only invalidation */ +static inline void __ic_entire_invalidate(void) { + if (!icache_status()) + return; + /* Any write to IC_IVIC register triggers invalidation of entire I$ */ - if (icache_status()) { - write_aux_reg(ARC_AUX_IC_IVIC, 1); - /* -* As per ARC HS databook (see chapter 5.3.3.2) -* it is required to add 3 NOPs after each write to IC_IVIC. -*/ - __builtin_arc_nop(); - __builtin_arc_nop(); - __builtin_arc_nop(); - read_aux_reg(ARC_AUX_IC_CTRL); /* blocks */ - } + write_aux_reg(ARC_AUX_IC_IVIC, 1); + /* +* As per ARC HS databook (see chapter 5.3.3.2) +* it is required to add 3 NOPs after each write to IC_IVIC. +*/ + __builtin_arc_nop(); + __builtin_arc_nop(); + __builtin_arc_nop(); + read_aux_reg(ARC_AUX_IC_CTRL); /* blocks */ +} + +void invalidate_icache_all(void) +{ + __ic_entire_invalidate(); #ifdef CONFIG_ISA_ARCV2 if (slc_exists) -- 2.14.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v2 05/20] ARC: flush & invalidate D$ with a single command
We don't implement separate flush_dcache_all intentionally as entire data cache invalidation is dangerous operation even if we flush data cache right before invalidation. There is the real example: We may hang in the next code if we store any context (like BLINK register) on stack in invalidate_dcache_all() function. BLINK register is the register where return address is automatically saved when we do function call with instructions like 'bl'. void flush_dcache_all() { __dc_entire_op(OP_FLUSH); // Other code // } void invalidate_dcache_all() { __dc_entire_op(OP_INV); // Other code // } void foo(void) { flush_dcache_all(); invalidate_dcache_all(); } Now let's see what really happens during that code execution: foo() |->> call flush_dcache_all [return address is saved to BLINK register] [push BLINK] (save to stack) ![point 1] |->> call __dc_entire_op(OP_FLUSH) [return address is saved to BLINK register] [flush L1 D$] return [jump to BLINK] <<-- [other flush_dcache_all code] [pop BLINK] (get from stack) return [jump to BLINK] <<-- |->> call invalidate_dcache_all [return address is saved to BLINK register] [push BLINK] (save to stack) ![point 2] |->> call __dc_entire_op(OP_FLUSH) [return address is saved to BLINK register] [invalidate L1 D$] ![point 3] // Oops!!! // We lose return address from invalidate_dcache_all function: // we save it to stack and invalidate L1 D$ after that! return [jump to BLINK] <<-- [other invalidate_dcache_all code] [pop BLINK] (get from stack) // we don't have this data in L1 dcache as we invalidated it in [point 3] // so we get it from next memory level (for example DDR memory) // but in the memory we have value which we save in [point 1], which // is return address from flush_dcache_all function (instead of // address from current invalidate_dcache_all function which we // saved in [point 2] !) return [jump to BLINK] <<-- // As BLINK points to invalidate_dcache_all, we call it again and // loop forever. Fortunately we may do flush and invalidation of D$ with a single one instruction which automatically mitigates a situation described above. And because invalidate_dcache_all isn't used in common u-boot code we implement "flush and invalidate dcache all" instead. Signed-off-by: Eugeniy Paltsev --- arch/arc/include/asm/cache.h | 1 + arch/arc/lib/cache.c | 89 +--- 2 files changed, 85 insertions(+), 5 deletions(-) diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h index d26d9fb18d..382c4126c3 100644 --- a/arch/arc/include/asm/cache.h +++ b/arch/arc/include/asm/cache.h @@ -30,6 +30,7 @@ #ifndef __ASSEMBLY__ void cache_init(void); +void flush_n_invalidate_dcache_all(void); #endif /* __ASSEMBLY__ */ diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index 83b77b9716..42207b201c 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -12,6 +12,80 @@ #include #include +/* + * [ NOTE 1 ]: + * Data cache (L1 D$ or SL$) entire invalidate operation or data cache disable + * operation may result in unexpected behavior and data loss even if we flush + * data cache right before invalidation. That may happens if we store any context + * on stack (like we store BLINK register on stack before function call). + * BLINK register is the register where return address is automatically saved + * when we do function call with instructions like 'bl'. + * + * There is the real example: + * We may hang in the next code as we store any BLINK register on stack in + * invalidate_dcache_all() function. + * + * void flush_dcache_all() { + * __dc_entire_op(OP_FLUSH); + * // Other code // + * } + * + * void invalidate_dcache_all() { + * __dc_entire_op(OP_INV); + * // Other code // + * } + * + * void foo(void) { + * flush_dcache_all(); + * invalidate_dcache_all(); + * } + * + * Now let's see what really happens during that code execution: + * + * foo() + * |->> call flush_dcache_all + * [return address is saved to BLINK register] + * [push BLINK] (save to stack) ![point 1] + * |->> call __dc_entire_op(OP_FLUSH) + * [return address is saved to BLINK register] + * [flush L1 D$] + * return [jump to BLINK] + * <<-- + * [other flush_dcache_all code] + * [pop BLINK] (get from stack) + * return [jump to BLINK] + * <<-- + * |->> call invalidate_dcache_al
[U-Boot] [PATCH v2 03/20] ARC: cache: Add support of FLUSH_N_INV d$ operations
As of today __dc_line_op and __dc_entire_op support only flush (OP_FLUSH) and invalidate (OP_INV) operations. Add support of flush and invalidate (OP_FLUSH_N_INV) operation which we planing to use in next patches. Signed-off-by: Eugeniy Paltsev --- arch/arc/lib/cache.c | 42 +++--- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index 2252542f16..83b77b9716 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -21,8 +21,9 @@ #define DC_CTRL_FLUSH_STATUS BIT(8) #define CACHE_VER_NUM_MASK 0xF -#define OP_INV 0x1 -#define OP_FLUSH 0x2 +#define OP_INV BIT(0) +#define OP_FLUSH BIT(1) +#define OP_FLUSH_N_INV (OP_FLUSH | OP_INV) /* Bit val in SLC_CONTROL */ #define SLC_CTRL_DIS 0x001 @@ -396,36 +397,32 @@ static inline void __dcache_line_loop(unsigned long paddr, unsigned long sz, } } -static unsigned int __before_dc_op(const int op) +static void __before_dc_op(const int op) { - unsigned int reg; + unsigned int ctrl; - if (op == OP_INV) { - /* -* IM is set by default and implies Flush-n-inv -* Clear it here for vanilla inv -*/ - reg = read_aux_reg(ARC_AUX_DC_CTRL); - write_aux_reg(ARC_AUX_DC_CTRL, reg & ~DC_CTRL_INV_MODE_FLUSH); - } + ctrl = read_aux_reg(ARC_AUX_DC_CTRL); - return reg; + /* IM bit implies flush-n-inv, instead of vanilla inv */ + if (op == OP_INV) + ctrl &= ~DC_CTRL_INV_MODE_FLUSH; + else + ctrl |= DC_CTRL_INV_MODE_FLUSH; + + write_aux_reg(ARC_AUX_DC_CTRL, ctrl); } -static void __after_dc_op(const int op, unsigned int reg) +static void __after_dc_op(const int op) { if (op & OP_FLUSH) /* flush / flush-n-inv both wait */ while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS); - - /* Switch back to default Invalidate mode */ - if (op == OP_INV) - write_aux_reg(ARC_AUX_DC_CTRL, reg | DC_CTRL_INV_MODE_FLUSH); } static inline void __dc_entire_op(const int cacheop) { int aux; - unsigned int ctrl_reg = __before_dc_op(cacheop); + + __before_dc_op(cacheop); if (cacheop & OP_INV) /* Inv or flush-n-inv use same cmd reg */ aux = ARC_AUX_DC_IVDC; @@ -434,16 +431,15 @@ static inline void __dc_entire_op(const int cacheop) write_aux_reg(aux, 0x1); - __after_dc_op(cacheop, ctrl_reg); + __after_dc_op(cacheop); } static inline void __dc_line_op(unsigned long paddr, unsigned long sz, const int cacheop) { - unsigned int ctrl_reg = __before_dc_op(cacheop); - + __before_dc_op(cacheop); __dcache_line_loop(paddr, sz, cacheop); - __after_dc_op(cacheop, ctrl_reg); + __after_dc_op(cacheop); } #else #define __dc_entire_op(cacheop) -- 2.14.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v2 17/20] ARC: implement function to sync and cleanup caches
Implement specialized function to clenup caches (and therefore sync I/D caches) which can be used for cleanup before linux launch or to sync caches during uboot relocation. Signed-off-by: Eugeniy Paltsev --- arch/arc/include/asm/cache.h | 1 + arch/arc/lib/bootm.c | 4 ++-- arch/arc/lib/cache.c | 23 +++ arch/arc/lib/init_helpers.c | 6 +++--- 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h index fe75409b5c..2269183615 100644 --- a/arch/arc/include/asm/cache.h +++ b/arch/arc/include/asm/cache.h @@ -31,6 +31,7 @@ void cache_init(void); void flush_n_invalidate_dcache_all(void); +void sync_n_cleanup_cache_all(void); static const inline int is_ioc_enabled(void) { diff --git a/arch/arc/lib/bootm.c b/arch/arc/lib/bootm.c index 9eef7070cf..c6800cb0ec 100644 --- a/arch/arc/lib/bootm.c +++ b/arch/arc/lib/bootm.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier:GPL-2.0+ */ +#include #include DECLARE_GLOBAL_DATA_PTR; @@ -45,8 +46,7 @@ int arch_fixup_fdt(void *blob) static int cleanup_before_linux(void) { disable_interrupts(); - flush_dcache_all(); - invalidate_icache_all(); + sync_n_cleanup_cache_all(); return 0; } diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index a5aae3d232..5d7583d868 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -591,3 +591,26 @@ void flush_dcache_all(void) if (is_isa_arcv2() && !slc_data_bypass()) __slc_entire_op(OP_FLUSH); } + +/* + * This is function to cleanup all caches (and therefore sync I/D caches) which + * can be used for cleanup before linux launch or to sync caches during + * relocation. + */ +void sync_n_cleanup_cache_all(void) +{ + __dc_entire_op(OP_FLUSH_N_INV); + + /* +* If SL$ is bypassed for data it is used only for instructions, +* and we shouldn't flush it. So invalidate it instead of flush_n_inv. +*/ + if (is_isa_arcv2()) { + if (slc_data_bypass()) + __slc_entire_op(OP_INV); + else + __slc_entire_op(OP_FLUSH_N_INV); + } + + __ic_entire_invalidate(); +} diff --git a/arch/arc/lib/init_helpers.c b/arch/arc/lib/init_helpers.c index dbc8d68ffb..435fe96ef4 100644 --- a/arch/arc/lib/init_helpers.c +++ b/arch/arc/lib/init_helpers.c @@ -4,14 +4,14 @@ * SPDX-License-Identifier:GPL-2.0+ */ +#include #include DECLARE_GLOBAL_DATA_PTR; int init_cache_f_r(void) { -#ifndef CONFIG_SYS_DCACHE_OFF - flush_dcache_all(); -#endif + sync_n_cleanup_cache_all(); + return 0; } -- 2.14.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v2 11/20] ARC: cache: get rid of [slc, pae, icache, dcache]_exists global variables
There is the problem with current implementation if we start u-boot from ROM, as we use cache global variables before ther initialization, so these variables are overwritten when we copy .data section from ROM. So use icache_exists(), dcache_exists(), slc_exists(), pae_exists() functions which check BCRs every time instead of corresponding global variables. Signed-off-by: Eugeniy Paltsev --- arch/arc/lib/cache.c | 67 +--- 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index f147674ae8..1b74f55ab7 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -94,7 +94,6 @@ #define DC_CTRL_CACHE_DISABLE BIT(0) #define DC_CTRL_INV_MODE_FLUSH BIT(6) #define DC_CTRL_FLUSH_STATUS BIT(8) -#define CACHE_VER_NUM_MASK 0xF #define OP_INV BIT(0) #define OP_FLUSH BIT(1) @@ -112,20 +111,16 @@ * relocation but will be used after being zeroed. */ int l1_line_sz __section(".data"); -bool dcache_exists __section(".data") = false; -bool icache_exists __section(".data") = false; #define CACHE_LINE_MASK(~(l1_line_sz - 1)) int slc_line_sz __section(".data"); -bool slc_exists __section(".data") = false; bool ioc_exists __section(".data") = false; -bool pae_exists __section(".data") = false; /* To force enable IOC set ioc_enable to 'true' */ bool ioc_enable __section(".data") = false; -void read_decode_mmu_bcr(void) +static inline bool pae_exists(void) { /* TODO: should we compare mmu version from BCR and from CONFIG? */ #if (CONFIG_ARC_MMU_VER >= 4) @@ -133,15 +128,46 @@ void read_decode_mmu_bcr(void) mmu4.word = read_aux_reg(ARC_AUX_MMU_BCR); - pae_exists = !!mmu4.fields.pae; + if (mmu4.fields.pae) + return true; #endif /* (CONFIG_ARC_MMU_VER >= 4) */ + + return false; +} + +static inline bool icache_exists(void) +{ + union bcr_di_cache ibcr; + + ibcr.word = read_aux_reg(ARC_BCR_IC_BUILD); + return !!ibcr.fields.ver; +} + +static inline bool dcache_exists(void) +{ + union bcr_di_cache dbcr; + + dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD); + return !!dbcr.fields.ver; +} + +static inline bool slc_exists(void) +{ + if (is_isa_arcv2()) { + union bcr_generic sbcr; + + sbcr.word = read_aux_reg(ARC_BCR_SLC); + return !!sbcr.fields.ver; + } + + return false; } static void __slc_entire_op(const int op) { unsigned int ctrl; - if (!slc_exists) + if (!slc_exists()) return; ctrl = read_aux_reg(ARC_AUX_SLC_CTRL); @@ -182,7 +208,7 @@ static void __slc_rgn_op(unsigned long paddr, unsigned long sz, const int op) unsigned int ctrl; unsigned long end; - if (!slc_exists) + if (!slc_exists()) return; /* @@ -263,12 +289,9 @@ static void read_decode_cache_bcr_arcv2(void) union bcr_slc_cfg slc_cfg; union bcr_clust_cfg cbcr; - union bcr_generic sbcr; - sbcr.word = read_aux_reg(ARC_BCR_SLC); - if (sbcr.fields.ver) { + if (slc_exists()) { slc_cfg.word = read_aux_reg(ARC_AUX_SLC_CONFIG); - slc_exists = true; slc_line_sz = (slc_cfg.fields.lsz == 0) ? 128 : 64; } @@ -286,7 +309,6 @@ void read_decode_cache_bcr(void) ibcr.word = read_aux_reg(ARC_BCR_IC_BUILD); if (ibcr.fields.ver) { - icache_exists = true; l1_line_sz = ic_line_sz = 8 << ibcr.fields.line_len; if (!ic_line_sz) panic("Instruction exists but line length is 0\n"); @@ -294,7 +316,6 @@ void read_decode_cache_bcr(void) dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD); if (dbcr.fields.ver) { - dcache_exists = true; l1_line_sz = dc_line_sz = 16 << dbcr.fields.line_len; if (!dc_line_sz) panic("Data cache exists but line length is 0\n"); @@ -314,20 +335,18 @@ void cache_init(void) if (is_isa_arcv2() && ioc_exists) arc_ioc_setup(); - read_decode_mmu_bcr(); - /* * ARC_AUX_SLC_RGN_START1 and ARC_AUX_SLC_RGN_END1 register exist * only if PAE exists in current HW. So we had to check pae_exist * before using them. */ - if (is_isa_arcv2() && slc_exists && pae_exists) + if (is_isa_arcv2() && slc_exists() && pae_exists()) slc_upper_region_init(); } int icache_status(void) { - if (!icache_exists) + if (!icache_exists()) return 0; if (read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE
[U-Boot] [PATCH v2 07/20] ARC: move BCR encodings to separate header file
Signed-off-by: Eugeniy Paltsev --- arch/arc/include/asm/arc-bcr.h | 77 ++ arch/arc/lib/cache.c | 67 +--- 2 files changed, 85 insertions(+), 59 deletions(-) create mode 100644 arch/arc/include/asm/arc-bcr.h diff --git a/arch/arc/include/asm/arc-bcr.h b/arch/arc/include/asm/arc-bcr.h new file mode 100644 index 00..823906d946 --- /dev/null +++ b/arch/arc/include/asm/arc-bcr.h @@ -0,0 +1,77 @@ +/* + * ARC Build Configuration Registers, with encoded hardware config + * + * Copyright (C) 2018 Synopsys + * Author: Eugeniy Paltsev + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __ARC_BCR_H +#define __ARC_BCR_H +#ifndef __ASSEMBLY__ + +#include + +union bcr_di_cache { + struct { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int pad:12, line_len:4, sz:4, config:4, ver:8; +#else + unsigned int ver:8, config:4, sz:4, line_len:4, pad:12; +#endif + } fields; + unsigned int word; +}; + +union bcr_slc_cfg { + struct { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int pad:24, way:2, lsz:2, sz:4; +#else + unsigned int sz:4, lsz:2, way:2, pad:24; +#endif + } fields; + unsigned int word; +}; + +union bcr_generic { + struct { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int pad:24, ver:8; +#else + unsigned int ver:8, pad:24; +#endif + } fields; + unsigned int word; +}; + +union bcr_clust_cfg { + struct { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int pad:7, c:1, num_entries:8, num_cores:8, ver:8; +#else + unsigned int ver:8, num_cores:8, num_entries:8, c:1, pad:7; +#endif + } fields; + unsigned int word; +}; + +union bcr_mmu_4 { + struct { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int ver:8, sasid:1, sz1:4, sz0:4, res:2, pae:1, +n_ways:2, n_entry:2, n_super:2, u_itlb:3, u_dtlb:3; +#else + /* DTLB ITLB JESJE JA */ + unsigned int u_dtlb:3, u_itlb:3, n_super:2, n_entry:2, n_ways:2, +pae:1, res:2, sz0:4, sz1:4, sasid:1, ver:8; +#endif + } fields; + unsigned int word; +}; + +#endif /* __ASSEMBLY__ */ +#endif /* __ARC_BCR_H */ diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index af07a11724..e6e439aab8 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -10,6 +10,7 @@ #include #include #include +#include #include /* @@ -129,24 +130,11 @@ void read_decode_mmu_bcr(void) { /* TODO: should we compare mmu version from BCR and from CONFIG? */ #if (CONFIG_ARC_MMU_VER >= 4) - u32 tmp; + union bcr_mmu_4 mmu4; - tmp = read_aux_reg(ARC_AUX_MMU_BCR); + mmu4.word = read_aux_reg(ARC_AUX_MMU_BCR); - struct bcr_mmu_4 { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int ver:8, sasid:1, sz1:4, sz0:4, res:2, pae:1, -n_ways:2, n_entry:2, n_super:2, u_itlb:3, u_dtlb:3; -#else - /* DTLB ITLB JESJE JA */ - unsigned int u_dtlb:3, u_itlb:3, n_super:2, n_entry:2, n_ways:2, -pae:1, res:2, sz0:4, sz1:4, sasid:1, ver:8; -#endif /* CONFIG_CPU_BIG_ENDIAN */ - } *mmu4; - - mmu4 = (struct bcr_mmu_4 *)&tmp; - - pae_exists = !!mmu4->pae; + pae_exists = !!mmu4.fields.pae; #endif /* (CONFIG_ARC_MMU_VER >= 4) */ } @@ -264,27 +252,9 @@ static void arc_ioc_setup(void) #ifdef CONFIG_ISA_ARCV2 static void read_decode_cache_bcr_arcv2(void) { - union { - struct { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int pad:24, way:2, lsz:2, sz:4; -#else - unsigned int sz:4, lsz:2, way:2, pad:24; -#endif - } fields; - unsigned int word; - } slc_cfg; - - union { - struct { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int pad:24, ver:8; -#else - unsigned int ver:8, pad:24; -#endif - } fields; - unsigned int word; - } sbcr; + union bcr_slc_cfg slc_cfg; + union bcr_clust_cfg cbcr; + union bcr_generic sbcr; sbcr.word = read_aux_reg(ARC_BCR_SLC); if (sbcr.fields.ver) { @@ -293,17 +263,6 @@ static void read_decode_cache_bcr_arcv2(void) slc_line_sz = (slc_cfg.fields.lsz == 0) ? 128 : 64; } - union { - struct bcr_clust_cfg { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int pad:7, c:1, num_entries:8, num_cores:8, ver:8; -#else - unsigned int ver:8, num_cores:8, num_entries:8, c:1, pad:7; -#endif - } fields; -
[U-Boot] [PATCH v2 18/20] ARC: cache: add additional configuration checks
Add additional cache configuration checks and note about supported configurations. Signed-off-by: Eugeniy Paltsev --- arch/arc/lib/cache.c | 75 1 file changed, 75 insertions(+) diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index 5d7583d868..fd70ce8efe 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -85,6 +85,66 @@ * enabling force function inline with '__attribute__((always_inline))' gcc * attribute to avoid any function call (and BLINK store) between cache flush * and disable. + * + * + * [ NOTE 2 ]: + * As of today we only support the following cache configurations on ARC. + * Other configurations may exist in HW (for example, since version 3.0 HS + * supports SL$ (L2 system level cache) disable) but we don't support it in SW. + * Configuration 1: + *__ + * | | + * | ARC CPU| + * |__| + *___|______|___ + * | | | | + * | L1 I$ | | L1 D$ | + * |___| |___| + *on/off on/off + *___|__| + * | | + * | main memory| + * |__| + * + * Configuration 2: + *__ + * | | + * | ARC CPU| + * |__| + *___|______|___ + * | | | | + * | L1 I$ | | L1 D$ | + * |___| |___| + *on/off on/off + *___|__| + * | | + * | L2 (SL$) | + * |__| + * always must be on + *___|__| + * | | + * | main memory| + * |__| + * + * Configuration 3: + *__ + * | | + * | ARC CPU| + * |__| + *___|______|___ + * | | | | + * | L1 I$ | | L1 D$ | + * |___| |___| + *on/offmust be on + *___|__| ___ + * | | | | + * | L2 (SL$) |-| IOC | + * |__| |___| + * always must be on on/off + *___|__| + * | | + * | main memory| + * |__| */ DECLARE_GLOBAL_DATA_PTR; @@ -308,6 +368,14 @@ static void arc_ioc_setup(void) /* IOC Aperture size is equal to DDR size */ long ap_size = CONFIG_SYS_SDRAM_SIZE; + /* Unsupported configuration. See [ NOTE 2 ] for more details. */ + if (!slc_exists()) + panic("Try to enable IOC but SLC is not present"); + + /* Unsupported configuration. See [ NOTE 2 ] for more details. */ + if (!dcache_enabled()) + panic("Try to enable IOC but L1 D$ is disabled"); + flush_n_invalidate_dcache_all(); if (!is_power_of_2(ap_size) || ap_size < 4096) @@ -338,6 +406,13 @@ static void read_decode_cache_bcr_arcv2(void) if (slc_exists()) { slc_cfg.word = read_aux_reg(ARC_AUX_SLC_CONFIG); gd->arch.slc_line_sz = (slc_cfg.fields.lsz == 0) ? 128 : 64; + + /* +* We don't support configuration where L1 I$ or L1 D$ is +* absent but SL$ exists. See [ NOTE 2 ] for more details. +*/ + if (!icache_exists() || !dcache_exists()) + panic("Unsupported cache configuration: SLC exists but one of L1 caches is absent"); } #endif /* CONFIG_ISA_ARCV2 */ -- 2.14.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v2 14/20] ARC: move IOC enabling to compile time options
Use CONFIG_ARC_DBG_IOC_ENABLE Kconfig option instead of ioc_enable global variable. Signed-off-by: Eugeniy Paltsev --- arch/arc/Kconfig | 18 arch/arc/include/asm/cache.h | 5 + arch/arc/lib/cache.c | 49 ++-- 3 files changed, 52 insertions(+), 20 deletions(-) diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index e3f9db7b29..aee15d5353 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -116,6 +116,24 @@ config SYS_DCACHE_OFF bool "Do not use Data Cache" default n +menuconfig ARC_DBG + bool "ARC debugging" + default n + +if ARC_DBG + +config ARC_DBG_IOC_ENABLE + bool "Enable IO coherency unit" + depends on CPU_ARCHS38 + default n + help + Enable IO coherency unit to debug problems with caches and + DMA peripherals. + NOTE: as of today linux will not work properly if this option + is enabled in u-boot! + +endif + choice prompt "Target select" default TARGET_AXS103 diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h index 382c4126c3..fe75409b5c 100644 --- a/arch/arc/include/asm/cache.h +++ b/arch/arc/include/asm/cache.h @@ -32,6 +32,11 @@ void cache_init(void); void flush_n_invalidate_dcache_all(void); +static const inline int is_ioc_enabled(void) +{ + return IS_ENABLED(CONFIG_ARC_DBG_IOC_ENABLE); +} + #endif /* __ASSEMBLY__ */ #endif /* __ASM_ARC_CACHE_H */ diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index 031ebd7765..ad14900135 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -107,18 +107,8 @@ DECLARE_GLOBAL_DATA_PTR; #define SLC_CTRL_BUSY 0x100 #define SLC_CTRL_RGN_OP_INV0x200 -/* - * By default that variable will fall into .bss section. - * But .bss section is not relocated and so it will be initilized before - * relocation but will be used after being zeroed. - */ #define CACHE_LINE_MASK(~(gd->arch.l1_line_sz - 1)) -bool ioc_exists __section(".data") = false; - -/* To force enable IOC set ioc_enable to 'true' */ -bool ioc_enable __section(".data") = false; - static inline bool pae_exists(void) { /* TODO: should we compare mmu version from BCR and from CONFIG? */ @@ -162,6 +152,30 @@ static inline bool slc_exists(void) return false; } +static inline bool ioc_exists(void) +{ + if (is_isa_arcv2()) { + union bcr_clust_cfg cbcr; + + cbcr.word = read_aux_reg(ARC_BCR_CLUSTER); + return cbcr.fields.c; + } + + return false; +} + +static inline bool ioc_enabled(void) +{ + /* +* We check only CONFIG option instead of IOC HW state check as IOC +* must be disabled by default. +*/ + if (is_ioc_enabled()) + return ioc_exists(); + + return false; +} + static void __slc_entire_op(const int op) { unsigned int ctrl; @@ -295,17 +309,12 @@ static void read_decode_cache_bcr_arcv2(void) #ifdef CONFIG_ISA_ARCV2 union bcr_slc_cfg slc_cfg; - union bcr_clust_cfg cbcr; if (slc_exists()) { slc_cfg.word = read_aux_reg(ARC_AUX_SLC_CONFIG); gd->arch.slc_line_sz = (slc_cfg.fields.lsz == 0) ? 128 : 64; } - cbcr.word = read_aux_reg(ARC_BCR_CLUSTER); - if (cbcr.fields.c && ioc_enable) - ioc_exists = true; - #endif /* CONFIG_ISA_ARCV2 */ } @@ -339,7 +348,7 @@ void cache_init(void) if (is_isa_arcv2()) read_decode_cache_bcr_arcv2(); - if (is_isa_arcv2() && ioc_exists) + if (is_isa_arcv2() && ioc_enabled()) arc_ioc_setup(); if (is_isa_arcv2() && slc_exists()) @@ -511,10 +520,10 @@ void invalidate_dcache_range(unsigned long start, unsigned long end) * ARCv2 && no IOC-> call __dc_line_op; call __slc_rgn_op * ARCv2 && IOC enabled -> nothing */ - if (!is_isa_arcv2() || !ioc_exists) + if (!is_isa_arcv2() || !ioc_enabled()) __dc_line_op(start, end - start, OP_INV); - if (is_isa_arcv2() && !ioc_exists) + if (is_isa_arcv2() && !ioc_enabled()) __slc_rgn_op(start, end - start, OP_INV); } @@ -528,10 +537,10 @@ void flush_dcache_range(unsigned long start, unsigned long end) * ARCv2 && no IOC-> call __dc_line_op; call __slc_rgn_op * ARCv2 && IOC enabled -> nothing */ - if (!is_isa_arcv2() || !ioc_exists) + if (!is_isa_arcv2() || !ioc_enabled()) __dc_line_op(start, end - start, OP_FLUSH); - if (is_isa_arcv2() && !ioc_exists) + if (is_isa_arcv2() && !ioc_enabled()) __slc_rgn_op(start, end - start, OP_FLUSH); } -- 2.14.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v2 10/20] ARC: cache: move slc status check into slc_entire_op and slc_rgn_op
As of today we check slc status before each call of __slc_rgn_op or __slc_entire_op. So move status check into __slc_rgn_op and __slc_entire_op. As we need to check status before *each* function call and we slc_entire_op and slc_rgn_op functions from different places we add this check directly into slc entire/line functions instead of their callers to avoid code duplication. Signed-off-by: Eugeniy Paltsev --- arch/arc/lib/cache.c | 16 +++- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index 354dbc600e..f147674ae8 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -141,6 +141,9 @@ static void __slc_entire_op(const int op) { unsigned int ctrl; + if (!slc_exists) + return; + ctrl = read_aux_reg(ARC_AUX_SLC_CTRL); if (!(op & OP_FLUSH)) /* i.e. OP_INV */ @@ -179,6 +182,9 @@ static void __slc_rgn_op(unsigned long paddr, unsigned long sz, const int op) unsigned int ctrl; unsigned long end; + if (!slc_exists) + return; + /* * The Region Flush operation is specified by CTRL.RGN_OP[11..9] * - b'000 (default) is Flush, @@ -366,7 +372,7 @@ void invalidate_icache_all(void) { __ic_entire_invalidate(); - if (is_isa_arcv2() && slc_exists) + if (is_isa_arcv2()) __slc_entire_op(OP_INV); } @@ -487,7 +493,7 @@ void invalidate_dcache_range(unsigned long start, unsigned long end) if (!is_isa_arcv2() || !ioc_exists) __dc_line_op(start, end - start, OP_INV); - if (is_isa_arcv2() && slc_exists && !ioc_exists) + if (is_isa_arcv2() && !ioc_exists) __slc_rgn_op(start, end - start, OP_INV); } @@ -504,7 +510,7 @@ void flush_dcache_range(unsigned long start, unsigned long end) if (!is_isa_arcv2() || !ioc_exists) __dc_line_op(start, end - start, OP_FLUSH); - if (is_isa_arcv2() && slc_exists && !ioc_exists) + if (is_isa_arcv2() && !ioc_exists) __slc_rgn_op(start, end - start, OP_FLUSH); } @@ -523,7 +529,7 @@ void flush_n_invalidate_dcache_all(void) { __dc_entire_op(OP_FLUSH_N_INV); - if (is_isa_arcv2() && slc_exists) + if (is_isa_arcv2()) __slc_entire_op(OP_FLUSH_N_INV); } @@ -531,6 +537,6 @@ void flush_dcache_all(void) { __dc_entire_op(OP_FLUSH); - if (is_isa_arcv2() && slc_exists) + if (is_isa_arcv2()) __slc_entire_op(OP_FLUSH); } -- 2.14.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v2 06/20] ARC: cache: move IOC initialization to separate function
Move IOC initialization to separate function from cache_init function. This is the preparation for the next patch when we will switch to is_isa_arcv2() function using instead of "CONFIG_ISA_ARCV2" ifdef using. Also it makes cache_init function clear. Signed-off-by: Eugeniy Paltsev --- arch/arc/lib/cache.c | 56 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index 42207b201c..af07a11724 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -231,6 +231,34 @@ static void __slc_rgn_op(unsigned long paddr, unsigned long sz, const int op) while (read_aux_reg(ARC_AUX_SLC_CTRL) & SLC_CTRL_BUSY); } + +static void arc_ioc_setup(void) +{ + /* IOC Aperture start is equal to DDR start */ + unsigned int ap_base = CONFIG_SYS_SDRAM_BASE; + /* IOC Aperture size is equal to DDR size */ + long ap_size = CONFIG_SYS_SDRAM_SIZE; + + flush_n_invalidate_dcache_all(); + + if (!is_power_of_2(ap_size) || ap_size < 4096) + panic("IOC Aperture size must be power of 2 and bigger 4Kib"); + + /* +* IOC Aperture size decoded as 2 ^ (SIZE + 2) KB, +* so setting 0x11 implies 512M, 0x12 implies 1G... +*/ + write_aux_reg(ARC_AUX_IO_COH_AP0_SIZE, + order_base_2(ap_size / 1024) - 2); + + /* IOC Aperture start must be aligned to the size of the aperture */ + if (ap_base % ap_size != 0) + panic("IOC Aperture start must be aligned to the size of the aperture"); + + write_aux_reg(ARC_AUX_IO_COH_AP0_BASE, ap_base >> 12); + write_aux_reg(ARC_AUX_IO_COH_PARTIAL, 1); + write_aux_reg(ARC_AUX_IO_COH_ENABLE, 1); +} #endif /* CONFIG_ISA_ARCV2 */ #ifdef CONFIG_ISA_ARCV2 @@ -324,32 +352,8 @@ void cache_init(void) #ifdef CONFIG_ISA_ARCV2 read_decode_cache_bcr_arcv2(); - if (ioc_exists) { - /* IOC Aperture start is equal to DDR start */ - unsigned int ap_base = CONFIG_SYS_SDRAM_BASE; - /* IOC Aperture size is equal to DDR size */ - long ap_size = CONFIG_SYS_SDRAM_SIZE; - - flush_n_invalidate_dcache_all(); - - if (!is_power_of_2(ap_size) || ap_size < 4096) - panic("IOC Aperture size must be power of 2 and bigger 4Kib"); - - /* -* IOC Aperture size decoded as 2 ^ (SIZE + 2) KB, -* so setting 0x11 implies 512M, 0x12 implies 1G... -*/ - write_aux_reg(ARC_AUX_IO_COH_AP0_SIZE, - order_base_2(ap_size / 1024) - 2); - - /* IOC Aperture start must be aligned to the size of the aperture */ - if (ap_base % ap_size != 0) - panic("IOC Aperture start must be aligned to the size of the aperture"); - - write_aux_reg(ARC_AUX_IO_COH_AP0_BASE, ap_base >> 12); - write_aux_reg(ARC_AUX_IO_COH_PARTIAL, 1); - write_aux_reg(ARC_AUX_IO_COH_ENABLE, 1); - } + if (ioc_exists) + arc_ioc_setup(); read_decode_mmu_bcr(); -- 2.14.3 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot