uboot/arch/arm/cpu/arm926ejs/davinci/cpu.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2004 Texas Instruments.
   3 * Copyright (C) 2009 David Brownell
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; either version 2 of the License, or
  11 * (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21 */
  22
  23#include <common.h>
  24#include <netdev.h>
  25#include <asm/arch/hardware.h>
  26#include <asm/io.h>
  27
  28DECLARE_GLOBAL_DATA_PTR;
  29
  30/* offsets from PLL controller base */
  31#define PLLC_PLLCTL     0x100
  32#define PLLC_PLLM       0x110
  33#define PLLC_PREDIV     0x114
  34#define PLLC_PLLDIV1    0x118
  35#define PLLC_PLLDIV2    0x11c
  36#define PLLC_PLLDIV3    0x120
  37#define PLLC_POSTDIV    0x128
  38#define PLLC_BPDIV      0x12c
  39#define PLLC_PLLDIV4    0x160
  40#define PLLC_PLLDIV5    0x164
  41#define PLLC_PLLDIV6    0x168
  42#define PLLC_PLLDIV7    0x16c
  43#define PLLC_PLLDIV8    0x170
  44#define PLLC_PLLDIV9    0x174
  45
  46#define BIT(x)          (1 << (x))
  47
  48/* SOC-specific pll info */
  49#ifdef CONFIG_SOC_DM355
  50#define ARM_PLLDIV      PLLC_PLLDIV1
  51#define DDR_PLLDIV      PLLC_PLLDIV1
  52#endif
  53
  54#ifdef CONFIG_SOC_DM644X
  55#define ARM_PLLDIV      PLLC_PLLDIV2
  56#define DSP_PLLDIV      PLLC_PLLDIV1
  57#define DDR_PLLDIV      PLLC_PLLDIV2
  58#endif
  59
  60#ifdef CONFIG_SOC_DM646X
  61#define DSP_PLLDIV      PLLC_PLLDIV1
  62#define ARM_PLLDIV      PLLC_PLLDIV2
  63#define DDR_PLLDIV      PLLC_PLLDIV1
  64#endif
  65
  66#ifdef CONFIG_SOC_DA8XX
  67unsigned int sysdiv[9] = {
  68        PLLC_PLLDIV1, PLLC_PLLDIV2, PLLC_PLLDIV3, PLLC_PLLDIV4, PLLC_PLLDIV5,
  69        PLLC_PLLDIV6, PLLC_PLLDIV7, PLLC_PLLDIV8, PLLC_PLLDIV9
  70};
  71
  72int clk_get(enum davinci_clk_ids id)
  73{
  74        int pre_div;
  75        int pllm;
  76        int post_div;
  77        int pll_out;
  78        unsigned int pll_base;
  79
  80        pll_out = CONFIG_SYS_OSCIN_FREQ;
  81
  82        if (id == DAVINCI_AUXCLK_CLKID)
  83                goto out;
  84
  85        if ((id >> 16) == 1)
  86                pll_base = (unsigned int)davinci_pllc1_regs;
  87        else
  88                pll_base = (unsigned int)davinci_pllc0_regs;
  89
  90        id &= 0xFFFF;
  91
  92        /*
  93         * Lets keep this simple. Combining operations can result in
  94         * unexpected approximations
  95         */
  96        pre_div = (readl(pll_base + PLLC_PREDIV) &
  97                DAVINCI_PLLC_DIV_MASK) + 1;
  98        pllm = readl(pll_base + PLLC_PLLM) + 1;
  99
 100        pll_out /= pre_div;
 101        pll_out *= pllm;
 102
 103        if (id == DAVINCI_PLLM_CLKID)
 104                goto out;
 105
 106        post_div = (readl(pll_base + PLLC_POSTDIV) &
 107                DAVINCI_PLLC_DIV_MASK) + 1;
 108
 109        pll_out /= post_div;
 110
 111        if (id == DAVINCI_PLLC_CLKID)
 112                goto out;
 113
 114        pll_out /= (readl(pll_base + sysdiv[id - 1]) &
 115                DAVINCI_PLLC_DIV_MASK) + 1;
 116
 117out:
 118        return pll_out;
 119}
 120
 121int set_cpu_clk_info(void)
 122{
 123        gd->bd->bi_arm_freq = clk_get(DAVINCI_ARM_CLKID) / 1000000;
 124        /* DDR PHY uses an x2 input clock */
 125        gd->bd->bi_ddr_freq = cpu_is_da830() ? 0 :
 126                                (clk_get(DAVINCI_DDR_CLKID) / 1000000);
 127        gd->bd->bi_dsp_freq = 0;
 128        return 0;
 129}
 130
 131#else /* CONFIG_SOC_DA8XX */
 132
 133static unsigned pll_div(volatile void *pllbase, unsigned offset)
 134{
 135        u32     div;
 136
 137        div = REG(pllbase + offset);
 138        return (div & BIT(15)) ? (1 + (div & 0x1f)) : 1;
 139}
 140
 141static inline unsigned pll_prediv(volatile void *pllbase)
 142{
 143#ifdef CONFIG_SOC_DM355
 144        /* this register read seems to fail on pll0 */
 145        if (pllbase == (volatile void *)DAVINCI_PLL_CNTRL0_BASE)
 146                return 8;
 147        else
 148                return pll_div(pllbase, PLLC_PREDIV);
 149#elif defined(CONFIG_SOC_DM365)
 150        return pll_div(pllbase, PLLC_PREDIV);
 151#endif
 152        return 1;
 153}
 154
 155static inline unsigned pll_postdiv(volatile void *pllbase)
 156{
 157#if defined(CONFIG_SOC_DM355) || defined(CONFIG_SOC_DM365)
 158        return pll_div(pllbase, PLLC_POSTDIV);
 159#elif defined(CONFIG_SOC_DM6446)
 160        if (pllbase == (volatile void *)DAVINCI_PLL_CNTRL0_BASE)
 161                return pll_div(pllbase, PLLC_POSTDIV);
 162#endif
 163        return 1;
 164}
 165
 166static unsigned pll_sysclk_mhz(unsigned pll_addr, unsigned div)
 167{
 168        volatile void   *pllbase = (volatile void *) pll_addr;
 169#ifdef CONFIG_SOC_DM646X
 170        unsigned        base = CONFIG_REFCLK_FREQ / 1000;
 171#else
 172        unsigned        base = CONFIG_SYS_HZ_CLOCK / 1000;
 173#endif
 174
 175        /* the PLL might be bypassed */
 176        if (readl(pllbase + PLLC_PLLCTL) & BIT(0)) {
 177                base /= pll_prediv(pllbase);
 178#if defined(CONFIG_SOC_DM365)
 179                base *=  2 * (readl(pllbase + PLLC_PLLM) & 0x0ff);
 180#else
 181                base *= 1 + (REG(pllbase + PLLC_PLLM) & 0x0ff);
 182#endif
 183                base /= pll_postdiv(pllbase);
 184        }
 185        return DIV_ROUND_UP(base, 1000 * pll_div(pllbase, div));
 186}
 187
 188#ifdef DAVINCI_DM6467EVM
 189unsigned int davinci_arm_clk_get()
 190{
 191        return pll_sysclk_mhz(DAVINCI_PLL_CNTRL0_BASE, ARM_PLLDIV) * 1000000;
 192}
 193#endif
 194
 195#if defined(CONFIG_SOC_DM365)
 196unsigned int davinci_clk_get(unsigned int div)
 197{
 198        return pll_sysclk_mhz(DAVINCI_PLL_CNTRL0_BASE, div) * 1000000;
 199}
 200#endif
 201
 202int set_cpu_clk_info(void)
 203{
 204        unsigned int pllbase = DAVINCI_PLL_CNTRL0_BASE;
 205#if defined(CONFIG_SOC_DM365)
 206        pllbase = DAVINCI_PLL_CNTRL1_BASE;
 207#endif
 208        gd->bd->bi_arm_freq = pll_sysclk_mhz(pllbase, ARM_PLLDIV);
 209
 210#ifdef DSP_PLLDIV
 211        gd->bd->bi_dsp_freq =
 212                pll_sysclk_mhz(DAVINCI_PLL_CNTRL0_BASE, DSP_PLLDIV);
 213#else
 214        gd->bd->bi_dsp_freq = 0;
 215#endif
 216
 217        pllbase = DAVINCI_PLL_CNTRL1_BASE;
 218#if defined(CONFIG_SOC_DM365)
 219        pllbase = DAVINCI_PLL_CNTRL0_BASE;
 220#endif
 221        gd->bd->bi_ddr_freq = pll_sysclk_mhz(pllbase, DDR_PLLDIV) / 2;
 222
 223        return 0;
 224}
 225
 226#endif /* !CONFIG_SOC_DA8XX */
 227
 228/*
 229 * Initializes on-chip ethernet controllers.
 230 * to override, implement board_eth_init()
 231 */
 232int cpu_eth_init(bd_t *bis)
 233{
 234#if defined(CONFIG_DRIVER_TI_EMAC)
 235        davinci_emac_initialize();
 236#endif
 237        return 0;
 238}
 239