From: David Brownell <dbrown...@users.sourceforge.net> Make the DaVinci clock display code work on the dm355 too ... there are pre- and post- dividers on its PLLs, which most other DaVinci processors don't use; and it uses different PLL dividers. Stubbed in support for the DM6467 too. Verified on dm355 and dm6446.
Signed-off-by: David Brownell <dbrown...@users.sourceforge.net> --- This should move to cpu/arm926ejs/davinci (cpuinfo.c?) someday, like the other SoC-specific code. For another patch. board/davinci/common/misc.c | 88 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 83 insertions(+), 5 deletions(-) --- a/board/davinci/common/misc.c +++ b/board/davinci/common/misc.c @@ -28,6 +28,40 @@ #include <net.h> #include <asm/arch/hardware.h> + +/* offsets from PLL controller base */ +#define PLLC_PLLCTL 0x100 +#define PLLC_PLLM 0x110 +#define PLLC_PREDIV 0x114 +#define PLLC_PLLDIV1 0x118 +#define PLLC_PLLDIV2 0x11c +#define PLLC_PLLDIV3 0x120 +#define PLLC_POSTDIV 0x128 +#define PLLC_BPDIV 0x12c +#define PLLC_PLLDIV4 0x160 +#define PLLC_PLLDIV5 0x164 +#define PLLC_PLLDIV6 0x168 +#define PLLC_PLLDIV8 0x170 +#define PLLC_PLLDIV9 0x174 + +#define BIT(x) (1 << (x)) + +/* SOC-specific pll info */ +#ifdef CONFIG_SOC_DM355 +#define ARM_PLLDIV PLLC_PLLDIV1 +#define DDR_PLLDIV PLLC_PLLDIV1 +#endif + +#ifdef CONFIG_SOC_DM644X +#define ARM_PLLDIV PLLC_PLLDIV2 +#define DDR_PLLDIV PLLC_PLLDIV2 +#endif + +#ifdef CONFIG_SOC_DM6447 +#define ARM_PLLDIV PLLC_PLLDIV2 +#define DDR_PLLDIV PLLC_PLLDIV1 +#endif + DECLARE_GLOBAL_DATA_PTR; int dram_init(void) @@ -38,16 +72,60 @@ int dram_init(void) return(0); } -static int dv_get_pllm_output(uint32_t pllm) +static unsigned pll_div(volatile void *pllbase, unsigned offset) { - return (pllm + 1) * (CONFIG_SYS_HZ_CLOCK / 1000000); + u32 div; + + div = REG(pllbase + offset); + return (div & BIT(15)) ? (1 + (div & 0x1f)) : 1; +} + +static inline unsigned pll_prediv(volatile void *pllbase) +{ +#ifdef CONFIG_SOC_DM355 + /* this register read seems to fail on pll0 */ + if (pllbase == (volatile void *)DAVINCI_PLL_CNTRL0_BASE) + return 8; + else + return pll_div(pllbase, PLLC_PREDIV); +#endif + return 1; +} + +static inline unsigned pll_postdiv(volatile void *pllbase) +{ +#ifdef CONFIG_SOC_DM355 + return pll_div(pllbase, PLLC_POSTDIV); +#elif defined(CONFIG_SOC_DM6446) + if (pllbase == (volatile void *)DAVINCI_PLL_CNTRL0_BASE) + return pll_div(pllbase, PLLC_POSTDIV); +#endif + return 1; +} + +static unsigned pll_sysclk_mhz(unsigned pll_addr, unsigned div) +{ + volatile void *pllbase = (volatile void *) pll_addr; + unsigned base = CONFIG_SYS_HZ_CLOCK / 1000; + + /* the PLL might be bypassed */ + if (REG(pllbase + PLLC_PLLCTL) & BIT(0)) { + base /= pll_prediv(pllbase); + base *= 1 + (REG(pllbase + PLLC_PLLM) & 0x0ff); + base /= pll_postdiv(pllbase); + } + return DIV_ROUND_UP(base, 1000 * pll_div(pllbase, div)); } void dv_display_clk_infos(void) { - printf("ARM Clock: %dMHz\n", dv_get_pllm_output(REG(PLL1_PLLM)) / 2); - printf("DDR Clock: %dMHz\n", dv_get_pllm_output(REG(PLL2_PLLM)) / - ((REG(PLL2_DIV2) & 0x1f) + 1) / 2); + printf("ARM Clock: %dMHz\n", + pll_sysclk_mhz(DAVINCI_PLL_CNTRL0_BASE, ARM_PLLDIV)); + printf("DDR Clock: %dMHz\n", + /* DDR PHY uses an x2 input clock */ + pll_sysclk_mhz(DAVINCI_PLL_CNTRL1_BASE, DDR_PLLDIV) + / 2); + printf("\n"); } #ifdef CONFIG_DRIVER_TI_EMAC _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot