diff --git a/arch/arc/dts/hsdk.dts b/arch/arc/dts/hsdk.dts index a7b276c..67dfb93 100644 --- a/arch/arc/dts/hsdk.dts +++ b/arch/arc/dts/hsdk.dts @@ -24,6 +24,12 @@ }; }; + cgu_clk: cgu-clk@f0000000 { + compatible = "snps,hsdk-cgu-clock"; + reg = <0xf0000000 0x10>, <0xf00014B8 0x4>; + #clock-cells = <1>; + }; + uart0: serial0@f0005000 { compatible = "snps,dw-apb-uart"; reg = <0xf0005000 0x1000>; diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h index ba1f7ba..67f4163 100644 --- a/arch/arc/include/asm/arcregs.h +++ b/arch/arc/include/asm/arcregs.h @@ -63,8 +63,15 @@ #define ARC_AUX_SLC_INVALIDATE 0x905 #define ARC_AUX_SLC_IVDL 0x910 #define ARC_AUX_SLC_FLDL 0x912 +#define ARC_AUX_SLC_RGN_START 0x914 +#define ARC_AUX_SLC_RGN_START1 0x915 +#define ARC_AUX_SLC_RGN_END 0x916 +#define ARC_AUX_SLC_RGN_END1 0x917 #define ARC_BCR_CLUSTER 0xcf +/* MMU Management regs */ +#define ARC_AUX_MMU_BCR 0x06f + /* IO coherency related auxiliary registers */ #define ARC_AUX_IO_COH_ENABLE 0x500 #define ARC_AUX_IO_COH_PARTIAL 0x501 diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index 1073e15..04f1d9d 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -13,19 +13,24 @@ #include /* Bit values in IC_CTRL */ -#define IC_CTRL_CACHE_DISABLE (1 << 0) +#define IC_CTRL_CACHE_DISABLE BIT(0) /* Bit values in DC_CTRL */ -#define DC_CTRL_CACHE_DISABLE (1 << 0) -#define DC_CTRL_INV_MODE_FLUSH (1 << 6) -#define DC_CTRL_FLUSH_STATUS (1 << 8) +#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 SLC_CTRL_SB (1 << 2) #define OP_INV 0x1 #define OP_FLUSH 0x2 #define OP_INV_IC 0x3 +/* Bit val in SLC_CONTROL */ +#define SLC_CTRL_DIS 0x001 +#define SLC_CTRL_IM 0x040 +#define SLC_CTRL_BUSY 0x100 +#define SLC_CTRL_RGN_OP_INV 0x200 + /* * By default that variable will fall into .bss section. * But .bss section is not relocated and so it will be initilized before @@ -41,88 +46,118 @@ bool icache_exists __section(".data") = false; 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; -static unsigned int __before_slc_op(const int op) +void read_decode_mmu_bcr(void) { - unsigned int reg = reg; + /* TODO: should we compare mmu version from BCR and from CONFIG? */ +#if (CONFIG_ARC_MMU_VER >= 4) + u32 tmp; - 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_SLC_CTRL); - write_aux_reg(ARC_AUX_SLC_CTRL, reg & ~DC_CTRL_INV_MODE_FLUSH); - } + tmp = read_aux_reg(ARC_AUX_MMU_BCR); - return reg; -} + 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 JES JE 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; -static void __after_slc_op(const int op, unsigned int reg) -{ - if (op & OP_FLUSH) { /* flush / flush-n-inv both wait */ - /* - * Make sure "busy" bit reports correct status, - * see STAR 9001165532 - */ - read_aux_reg(ARC_AUX_SLC_CTRL); - while (read_aux_reg(ARC_AUX_SLC_CTRL) & - DC_CTRL_FLUSH_STATUS) - ; - } + mmu4 = (struct bcr_mmu_4 *)&tmp; - /* Switch back to default Invalidate mode */ - if (op == OP_INV) - write_aux_reg(ARC_AUX_SLC_CTRL, reg | DC_CTRL_INV_MODE_FLUSH); + pae_exists = !!mmu4->pae; +#endif /* (CONFIG_ARC_MMU_VER >= 4) */ } -static inline void __slc_line_loop(unsigned long paddr, unsigned long sz, - const int op) +static void __slc_entire_op(const int op) { - unsigned int aux_cmd; - int num_lines; + unsigned int ctrl; -#define SLC_LINE_MASK (~(slc_line_sz - 1)) + ctrl = read_aux_reg(ARC_AUX_SLC_CTRL); - aux_cmd = op & OP_INV ? ARC_AUX_SLC_IVDL : ARC_AUX_SLC_FLDL; + if (!(op & OP_FLUSH)) /* i.e. OP_INV */ + ctrl &= ~SLC_CTRL_IM; /* clear IM: Disable flush before Inv */ + else + ctrl |= SLC_CTRL_IM; - sz += paddr & ~SLC_LINE_MASK; - paddr &= SLC_LINE_MASK; + write_aux_reg(ARC_AUX_SLC_CTRL, ctrl); - num_lines = DIV_ROUND_UP(sz, slc_line_sz); + if (op & OP_INV) /* Inv or flush-n-inv use same cmd reg */ + write_aux_reg(ARC_AUX_SLC_INVALIDATE, 0x1); + else + write_aux_reg(ARC_AUX_SLC_FLUSH, 0x1); - while (num_lines-- > 0) { - write_aux_reg(aux_cmd, paddr); - paddr += slc_line_sz; - } + /* Make sure "busy" bit reports correct stataus, see STAR 9001165532 */ + read_aux_reg(ARC_AUX_SLC_CTRL); + + /* Important to wait for flush to complete */ + while (read_aux_reg(ARC_AUX_SLC_CTRL) & SLC_CTRL_BUSY); } -static inline void __slc_entire_op(const int cacheop) +static void slc_upper_region_init(void) { - int aux; - unsigned int ctrl_reg = __before_slc_op(cacheop); + /* + * ARC_AUX_SLC_RGN_END1 and ARC_AUX_SLC_RGN_START1 are always == 0 + * as we don't use PAE40. + */ + write_aux_reg(ARC_AUX_SLC_RGN_END1, 0); + write_aux_reg(ARC_AUX_SLC_RGN_START1, 0); +} - if (cacheop & OP_INV) /* Inv or flush-n-inv use same cmd reg */ - aux = ARC_AUX_SLC_INVALIDATE; +static void __slc_rgn_op(unsigned long paddr, unsigned long sz, const int op) +{ + unsigned int ctrl; + unsigned long end; + + /* + * The Region Flush operation is specified by CTRL.RGN_OP[11..9] + * - b'000 (default) is Flush, + * - b'001 is Invalidate if CTRL.IM == 0 + * - b'001 is Flush-n-Invalidate if CTRL.IM == 1 + */ + ctrl = read_aux_reg(ARC_AUX_SLC_CTRL); + + /* Don't rely on default value of IM bit */ + if (!(op & OP_FLUSH)) /* i.e. OP_INV */ + ctrl &= ~SLC_CTRL_IM; /* clear IM: Disable flush before Inv */ else - aux = ARC_AUX_SLC_FLUSH; + ctrl |= SLC_CTRL_IM; - write_aux_reg(aux, 0x1); + if (op & OP_INV) + ctrl |= SLC_CTRL_RGN_OP_INV; /* Inv or flush-n-inv */ + else + ctrl &= ~SLC_CTRL_RGN_OP_INV; - __after_slc_op(cacheop, ctrl_reg); -} + write_aux_reg(ARC_AUX_SLC_CTRL, ctrl); -static inline void __slc_line_op(unsigned long paddr, unsigned long sz, - const int cacheop) -{ - unsigned int ctrl_reg = __before_slc_op(cacheop); - __slc_line_loop(paddr, sz, cacheop); - __after_slc_op(cacheop, ctrl_reg); + /* + * Lower bits are ignored, no need to clip + * 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; + + /* + * Upper addresses (ARC_AUX_SLC_RGN_END1 and ARC_AUX_SLC_RGN_START1) + * are always == 0 as we don't use PAE40, so we only setup lower ones + * (ARC_AUX_SLC_RGN_END and ARC_AUX_SLC_RGN_START) + */ + write_aux_reg(ARC_AUX_SLC_RGN_END, end); + write_aux_reg(ARC_AUX_SLC_RGN_START, paddr); + + /* Make sure "busy" bit reports correct stataus, see STAR 9001165532 */ + read_aux_reg(ARC_AUX_SLC_CTRL); + + while (read_aux_reg(ARC_AUX_SLC_CTRL) & SLC_CTRL_BUSY); } -#else -#define __slc_entire_op(cacheop) -#define __slc_line_op(paddr, sz, cacheop) -#endif +#endif /* CONFIG_ISA_ARCV2 */ #ifdef CONFIG_ISA_ARCV2 static void read_decode_cache_bcr_arcv2(void) @@ -168,7 +203,7 @@ static void read_decode_cache_bcr_arcv2(void) } cbcr; cbcr.word = read_aux_reg(ARC_BCR_CLUSTER); - if (cbcr.fields.c) + if (cbcr.fields.c && ioc_enable) ioc_exists = true; } #endif @@ -197,7 +232,7 @@ void read_decode_cache_bcr(void) } dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD); - if (dbcr.fields.ver){ + if (dbcr.fields.ver) { dcache_exists = true; l1_line_sz = dc_line_sz = 16 << dbcr.fields.line_len; if (!dc_line_sz) @@ -232,8 +267,7 @@ void cache_init(void) * so setting 0x11 implies 512M, 0x12 implies 1G... */ write_aux_reg(ARC_AUX_IO_COH_AP0_SIZE, - order_base_2(ap_size/1024) - 2); - + 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) @@ -242,9 +276,18 @@ void cache_init(void) 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 + + 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 (slc_exists && pae_exists) + slc_upper_region_init(); +#endif /* CONFIG_ISA_ARCV2 */ } int icache_status(void) @@ -272,7 +315,6 @@ void icache_disable(void) IC_CTRL_CACHE_DISABLE); } -#ifndef CONFIG_SYS_DCACHE_OFF void invalidate_icache_all(void) { /* Any write to IC_IVIC register triggers invalidation of entire I$ */ @@ -287,12 +329,12 @@ void invalidate_icache_all(void) __builtin_arc_nop(); read_aux_reg(ARC_AUX_IC_CTRL); /* blocks */ } -} -#else -void invalidate_icache_all(void) -{ -} + +#ifdef CONFIG_ISA_ARCV2 + if (slc_exists) + __slc_entire_op(OP_INV); #endif +} int dcache_status(void) { @@ -382,8 +424,7 @@ static unsigned int __before_dc_op(const int op) static void __after_dc_op(const int op, unsigned int reg) { if (op & OP_FLUSH) /* flush / flush-n-inv both wait */ - while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS) - ; + while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS); /* Switch back to default Invalidate mode */ if (op == OP_INV) @@ -409,6 +450,7 @@ static inline void __dc_line_op(unsigned long paddr, unsigned long sz, const int cacheop) { unsigned int ctrl_reg = __before_dc_op(cacheop); + __cache_line_loop(paddr, sz, cacheop); __after_dc_op(cacheop, ctrl_reg); } @@ -419,6 +461,9 @@ static inline void __dc_line_op(unsigned long paddr, unsigned long sz, void invalidate_dcache_range(unsigned long start, unsigned long end) { + if (start >= end) + return; + #ifdef CONFIG_ISA_ARCV2 if (!ioc_exists) #endif @@ -426,12 +471,15 @@ void invalidate_dcache_range(unsigned long start, unsigned long end) #ifdef CONFIG_ISA_ARCV2 if (slc_exists && !ioc_exists) - __slc_line_op(start, end - start, OP_INV); + __slc_rgn_op(start, end - start, OP_INV); #endif } void flush_dcache_range(unsigned long start, unsigned long end) { + if (start >= end) + return; + #ifdef CONFIG_ISA_ARCV2 if (!ioc_exists) #endif @@ -439,7 +487,7 @@ void flush_dcache_range(unsigned long start, unsigned long end) #ifdef CONFIG_ISA_ARCV2 if (slc_exists && !ioc_exists) - __slc_line_op(start, end - start, OP_FLUSH); + __slc_rgn_op(start, end - start, OP_FLUSH); #endif } diff --git a/arch/arc/lib/start.S b/arch/arc/lib/start.S index 95d64f9..0d72fe7 100644 --- a/arch/arc/lib/start.S +++ b/arch/arc/lib/start.S @@ -44,6 +44,14 @@ ENTRY(_start) #endif sr r5, [ARC_AUX_IC_CTRL] + mov r5, 1 + sr r5, [ARC_AUX_IC_IVIC] + ; As per ARC HS databook (see chapter 5.3.3.2) + ; it is required to add 3 NOPs after each write to IC_IVIC. + nop + nop + nop + 1: ; Disable/enable D-cache according to configuration lr r5, [ARC_BCR_DC_BUILD] @@ -57,6 +65,10 @@ ENTRY(_start) #endif sr r5, [ARC_AUX_DC_CTRL] + mov r5, 1 + sr r5, [ARC_AUX_DC_IVDC] + + 1: #ifdef CONFIG_ISA_ARCV2 ; Disable System-Level Cache (SLC) diff --git a/configs/hsdk_defconfig b/configs/hsdk_defconfig index a04cfee..11cb7e0 100644 --- a/configs/hsdk_defconfig +++ b/configs/hsdk_defconfig @@ -39,3 +39,4 @@ CONFIG_USB_OHCI_HCD=y CONFIG_USB_OHCI_GENERIC=y CONFIG_USB_STORAGE=y CONFIG_USE_PRIVATE_LIBGCC=y +CONFIG_PANIC_HANG=y diff --git a/drivers/clk/clk-hsdk-cgu.c b/drivers/clk/clk-hsdk-cgu.c index c80f90e..4362d58 100644 --- a/drivers/clk/clk-hsdk-cgu.c +++ b/drivers/clk/clk-hsdk-cgu.c @@ -42,7 +42,9 @@ * |-->| TUNNEL PLL | * | -------------- * | | - * | |-->|CGU_TUN_IDIV|-----------> + * | |-->|CGU_TUN_IDIV_TUN|-----------> + * | |-->|CGU_TUN_IDIV_ROM|-----------> + * | |-->|CGU_TUN_IDIV_PWM|-----------> * | * | ------------ * |-->| HDMI PLL | @@ -60,7 +62,9 @@ DECLARE_GLOBAL_DATA_PTR; #define CGU_ARC_IDIV 0x080 -#define CGU_TUN_IDIV 0x380 +#define CGU_TUN_IDIV_TUN 0x380 +#define CGU_TUN_IDIV_ROM 0x390 +#define CGU_TUN_IDIV_PWM 0x3A0 #define CGU_HDMI_IDIV_APB 0x480 #define CGU_SYS_IDIV_APB 0x180 #define CGU_SYS_IDIV_AXI 0x190 @@ -114,8 +118,68 @@ DECLARE_GLOBAL_DATA_PTR; #define CREG_CORE_IF_CLK_DIV_1 0x0 #define CREG_CORE_IF_CLK_DIV_2 0x1 +#define MIN_PLL_RATE 100000000 /* 100 MHz */ #define PARENT_RATE 33333333 /* fixed clock - xtal */ -#define CGU_MAX_CLOCKS 24 +#define CGU_MAX_CLOCKS 26 + +#define CGU_SYS_CLOCKS 16 +#define MAX_AXI_CLOCKS 4 + +#define CGU_TUN_CLOCKS 3 +#define MAX_TUN_CLOCKS 6 + +struct hsdk_tun_idiv_cfg { + u32 oft; + u8 val[MAX_TUN_CLOCKS]; +}; + +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]; +}; + +static const struct hsdk_tun_clk_cfg tun_clk_cfg = { + { 25000000, 50000000, 75000000, 100000000, 125000000, 150000000 }, + { 600000000, 600000000, 600000000, 600000000, 700000000, 600000000 }, { + { CGU_TUN_IDIV_TUN, { 24, 12, 8, 6, 6, 4 } }, + { CGU_TUN_IDIV_ROM, { 4, 4, 4, 4, 5, 4 } }, + { CGU_TUN_IDIV_PWM, { 8, 8, 8, 8, 10, 8 } } + } +}; + +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 = { + { 200000000, 400000000, 600000000, 800000000 }, + { 800000000, 800000000, 600000000, 800000000 }, { + { CGU_SYS_IDIV_APB, { 4, 4, 3, 4 } }, /* APB */ + { CGU_SYS_IDIV_AXI, { 4, 2, 1, 1 } }, /* AXI */ + { CGU_SYS_IDIV_ETH, { 2, 2, 2, 2 } }, /* ETH */ + { CGU_SYS_IDIV_USB, { 2, 2, 2, 2 } }, /* USB */ + { CGU_SYS_IDIV_SDIO, { 2, 2, 2, 2 } }, /* SDIO */ + { CGU_SYS_IDIV_HDMI, { 2, 2, 2, 2 } }, /* HDMI */ + { CGU_SYS_IDIV_GFX_CORE, { 1, 1, 1, 1 } }, /* GPU-CORE */ + { CGU_SYS_IDIV_GFX_DMA, { 2, 2, 2, 2 } }, /* GPU-DMA */ + { CGU_SYS_IDIV_GFX_CFG, { 4, 4, 3, 4 } }, /* GPU-CFG */ + { CGU_SYS_IDIV_DMAC_CORE,{ 2, 2, 2, 2 } }, /* DMAC-CORE */ + { CGU_SYS_IDIV_DMAC_CFG, { 4, 4, 3, 4 } }, /* DMAC-CFG */ + { CGU_SYS_IDIV_SDIO_REF, { 8, 8, 6, 8 } }, /* SDIO-REF */ + { 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 */ + } +}; struct hsdk_pll_cfg { u32 rate; @@ -201,6 +265,9 @@ 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 idiv_get(struct clk *); static int idiv_off(struct clk *); static ulong pll_set(struct clk *, ulong); @@ -218,11 +285,11 @@ 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, idiv_set, idiv_off }, + { 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, 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 }, @@ -238,7 +305,9 @@ static const struct hsdk_cgu_clock_map clock_map[] = { { 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, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + { 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_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 } }; @@ -423,7 +492,7 @@ static ulong pll_set(struct clk *sclk, ulong rate) } } - pr_err("invalid rate=%ld, parent_rate=%d\n", best_rate, PARENT_RATE); + pr_err("invalid rate=%ld Hz, parent_rate=%d Hz\n", best_rate, PARENT_RATE); return -EINVAL; } @@ -453,6 +522,94 @@ static ulong idiv_get(struct clk *sclk) return parent_rate / div_factor; } +/* Special behavior: wen we set this clock we set both idiv and pll */ +static ulong cpu_clk_set(struct clk *sclk, ulong rate) +{ + ulong ret; + + ret = pll_set(sclk, rate); + idiv_set(sclk, 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) +{ + struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); + ulong pll_rate; + int i, freq_idx = -1; + ulong ret = 0; + + pll_rate = pll_get(sclk); + + for (i = 0; i < MAX_AXI_CLOCKS; i++) { + if (axi_clk_cfg.clk_rate[i] == rate) { + freq_idx = i; + break; + } + } + + if (freq_idx < 0) { + pr_err("axi 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]); + + /* configure SYS dividers */ + for (i = 0; i < CGU_SYS_CLOCKS; i++) { + clk->idiv_regs = clk->cgu_regs + axi_clk_cfg.idiv[i].oft; + hsdk_idiv_write(clk, axi_clk_cfg.idiv[i].val[freq_idx]); + } + + /* configure PLL after dividers */ + if (axi_clk_cfg.pll_rate[freq_idx] >= pll_rate) + ret = pll_set(sclk, axi_clk_cfg.pll_rate[freq_idx]); + + return ret; +} + +static ulong tun_clk_set(struct clk *sclk, ulong rate) +{ + struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); + ulong pll_rate; + int i, freq_idx = -1; + ulong ret = 0; + + pll_rate = pll_get(sclk); + + for (i = 0; i < MAX_TUN_CLOCKS; i++) { + if (tun_clk_cfg.clk_rate[i] == rate) { + freq_idx = i; + break; + } + } + + if (freq_idx < 0) { + pr_err("tun clk: invalid rate=%ld Hz\n", rate); + return -EINVAL; + } + + /* configure PLL before dividers */ + if (tun_clk_cfg.pll_rate[freq_idx] < pll_rate) + ret = pll_set(sclk, tun_clk_cfg.pll_rate[freq_idx]); + + /* configure SYS dividers */ + for (i = 0; i < CGU_TUN_CLOCKS; i++) { + clk->idiv_regs = clk->cgu_regs + tun_clk_cfg.idiv[i].oft; + hsdk_idiv_write(clk, tun_clk_cfg.idiv[i].val[freq_idx]); + } + + /* configure PLL after dividers */ + if (tun_clk_cfg.pll_rate[freq_idx] >= pll_rate) + ret = pll_set(sclk, tun_clk_cfg.pll_rate[freq_idx]); + + return ret; +} + static ulong idiv_set(struct clk *sclk, ulong rate) { struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); @@ -466,14 +623,14 @@ static ulong idiv_set(struct clk *sclk, ulong rate) } if (div_factor & ~CGU_IDIV_MASK) { - pr_err("invalid rate=%ld, parent_rate=%ld, div=%d: max divider valie is%d\n", + pr_err("invalid rate=%ld Hz, parent_rate=%ld Hz, div=%d: max divider valie is%d\n", rate, parent_rate, div_factor, CGU_IDIV_MASK); div_factor = CGU_IDIV_MASK; } if (div_factor == 0) { - pr_err("invalid rate=%ld, parent_rate=%ld, div=%d: min divider valie is 1\n", + pr_err("invalid rate=%ld Hz, parent_rate=%ld Hz, div=%d: min divider valie is 1\n", rate, parent_rate, div_factor); div_factor = 1; @@ -559,6 +716,6 @@ U_BOOT_DRIVER(hsdk_cgu_clk) = { .id = UCLASS_CLK, .of_match = hsdk_cgu_clk_id, .probe = hsdk_cgu_clk_probe, - .platdata_auto_alloc_size = sizeof(struct hsdk_cgu_clk), + .priv_auto_alloc_size = sizeof(struct hsdk_cgu_clk), .ops = &hsdk_cgu_ops, }; diff --git a/include/configs/axs10x.h b/include/configs/axs10x.h index 29c5959..a9c4d1a 100644 --- a/include/configs/axs10x.h +++ b/include/configs/axs10x.h @@ -29,7 +29,7 @@ (CONFIG_SYS_SDRAM_BASE + 0x1000 - GENERATED_GBL_DATA_SIZE) #define CONFIG_SYS_MALLOC_LEN SZ_2M -#define CONFIG_SYS_BOOTM_LEN SZ_32M +#define CONFIG_SYS_BOOTM_LEN SZ_128M #define CONFIG_SYS_LOAD_ADDR 0x82000000 /* diff --git a/include/configs/hsdk.h b/include/configs/hsdk.h index 0ac8022..e17b56e 100644 --- a/include/configs/hsdk.h +++ b/include/configs/hsdk.h @@ -29,7 +29,7 @@ (CONFIG_SYS_SDRAM_BASE + 0x1000 - GENERATED_GBL_DATA_SIZE) #define CONFIG_SYS_MALLOC_LEN SZ_2M -#define CONFIG_SYS_BOOTM_LEN SZ_32M +#define CONFIG_SYS_BOOTM_LEN SZ_128M #define CONFIG_SYS_LOAD_ADDR 0x82000000 /* diff --git a/include/dt-bindings/clock/snps,hsdk-cgu.h b/include/dt-bindings/clock/snps,hsdk-cgu.h index 813ab71..2cfe34e 100644 --- a/include/dt-bindings/clock/snps,hsdk-cgu.h +++ b/include/dt-bindings/clock/snps,hsdk-cgu.h @@ -33,8 +33,10 @@ #define CLK_SYS_UART_REF 18 #define CLK_SYS_EBI_REF 19 #define CLK_TUN_PLL 20 -#define CLK_TUN 21 -#define CLK_HDMI_PLL 22 -#define CLK_HDMI 23 +#define CLK_TUN_TUN 21 +#define CLK_TUN_ROM 22 +#define CLK_TUN_PWM 23 +#define CLK_HDMI_PLL 24 +#define CLK_HDMI 25 #endif /* __DT_BINDINGS_CLK_HSDK_CGU_H_ */