uboot/cpu/arm926ejs/mx27/generic.c
<<
>>
Prefs
   1/*
   2 *  Copyright (c) 2008 Eric Jarrige <eric.jarrige@armadeus.org>
   3 *  Copyright (c) 2009 Ilya Yanok <yanok@emcraft.com>
   4 *
   5 * This program is free software; you can redistribute it and/or
   6 * modify it under the terms of the GNU General Public License as
   7 * published by the Free Software Foundation; either version 2 of
   8 * the License, or (at your option) any later version.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License
  16 * along with this program; if not, write to the Free Software
  17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  18 * MA 02111-1307 USA
  19 */
  20
  21#include <common.h>
  22#include <div64.h>
  23#include <netdev.h>
  24#include <asm/io.h>
  25#include <asm/arch/imx-regs.h>
  26#ifdef CONFIG_MXC_MMC
  27#include <asm/arch/mxcmmc.h>
  28#endif
  29
  30/*
  31 *  get the system pll clock in Hz
  32 *
  33 *                  mfi + mfn / (mfd +1)
  34 *  f = 2 * f_ref * --------------------
  35 *                        pd + 1
  36 */
  37unsigned int imx_decode_pll(unsigned int pll, unsigned int f_ref)
  38{
  39        unsigned int mfi = (pll >> 10) & 0xf;
  40        unsigned int mfn = pll & 0x3ff;
  41        unsigned int mfd = (pll >> 16) & 0x3ff;
  42        unsigned int pd =  (pll >> 26) & 0xf;
  43
  44        mfi = mfi <= 5 ? 5 : mfi;
  45
  46        return lldiv(2 * (u64)f_ref * (mfi * (mfd + 1) + mfn),
  47                        (mfd + 1) * (pd + 1));
  48}
  49
  50static ulong clk_in_32k(void)
  51{
  52        return 1024 * CONFIG_MX27_CLK32;
  53}
  54
  55static ulong clk_in_26m(void)
  56{
  57        struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
  58
  59        if (readl(&pll->cscr) & CSCR_OSC26M_DIV1P5) {
  60                /* divide by 1.5 */
  61                return 26000000 * 2 / 3;
  62        } else {
  63                return 26000000;
  64        }
  65}
  66
  67ulong imx_get_mpllclk(void)
  68{
  69        struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
  70        ulong cscr = readl(&pll->cscr);
  71        ulong fref;
  72
  73        if (cscr & CSCR_MCU_SEL)
  74                fref = clk_in_26m();
  75        else
  76                fref = clk_in_32k();
  77
  78        return imx_decode_pll(readl(&pll->mpctl0), fref);
  79}
  80
  81ulong imx_get_armclk(void)
  82{
  83        struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
  84        ulong cscr = readl(&pll->cscr);
  85        ulong fref = imx_get_mpllclk();
  86        ulong div;
  87
  88        if (!(cscr & CSCR_ARM_SRC_MPLL))
  89                fref = lldiv((fref * 2), 3);
  90
  91        div = ((cscr >> 12) & 0x3) + 1;
  92
  93        return lldiv(fref, div);
  94}
  95
  96ulong imx_get_ahbclk(void)
  97{
  98        struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
  99        ulong cscr = readl(&pll->cscr);
 100        ulong fref = imx_get_mpllclk();
 101        ulong div;
 102
 103        div = ((cscr >> 8) & 0x3) + 1;
 104
 105        return lldiv(fref * 2, 3 * div);
 106}
 107
 108ulong imx_get_spllclk(void)
 109{
 110        struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
 111        ulong cscr = readl(&pll->cscr);
 112        ulong fref;
 113
 114        if (cscr & CSCR_SP_SEL)
 115                fref = clk_in_26m();
 116        else
 117                fref = clk_in_32k();
 118
 119        return imx_decode_pll(readl(&pll->spctl0), fref);
 120}
 121
 122static ulong imx_decode_perclk(ulong div)
 123{
 124        return lldiv((imx_get_mpllclk() * 2), (div * 3));
 125}
 126
 127ulong imx_get_perclk1(void)
 128{
 129        struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
 130
 131        return imx_decode_perclk((readl(&pll->pcdr1) & 0x3f) + 1);
 132}
 133
 134ulong imx_get_perclk2(void)
 135{
 136        struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
 137
 138        return imx_decode_perclk(((readl(&pll->pcdr1) >> 8) & 0x3f) + 1);
 139}
 140
 141ulong imx_get_perclk3(void)
 142{
 143        struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
 144
 145        return imx_decode_perclk(((readl(&pll->pcdr1) >> 16) & 0x3f) + 1);
 146}
 147
 148ulong imx_get_perclk4(void)
 149{
 150        struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
 151
 152        return imx_decode_perclk(((readl(&pll->pcdr1) >> 24) & 0x3f) + 1);
 153}
 154
 155#if defined(CONFIG_DISPLAY_CPUINFO)
 156int print_cpuinfo (void)
 157{
 158        char buf[32];
 159
 160        printf("CPU:   Freescale i.MX27 at %s MHz\n\n",
 161                        strmhz(buf, imx_get_mpllclk()));
 162        return 0;
 163}
 164#endif
 165
 166int cpu_eth_init(bd_t *bis)
 167{
 168#if defined(CONFIG_FEC_MXC)
 169        return fecmxc_initialize(bis);
 170#else
 171        return 0;
 172#endif
 173}
 174
 175/*
 176 * Initializes on-chip MMC controllers.
 177 * to override, implement board_mmc_init()
 178 */
 179int cpu_mmc_init(bd_t *bis)
 180{
 181#ifdef CONFIG_MXC_MMC
 182        return mxc_mmc_init(bis);
 183#else
 184        return 0;
 185#endif
 186}
 187
 188void imx_gpio_mode(int gpio_mode)
 189{
 190        struct gpio_regs *regs = (struct gpio_regs *)IMX_GPIO_BASE;
 191        unsigned int pin = gpio_mode & GPIO_PIN_MASK;
 192        unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
 193        unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> GPIO_OCR_SHIFT;
 194        unsigned int aout = (gpio_mode & GPIO_AOUT_MASK) >> GPIO_AOUT_SHIFT;
 195        unsigned int bout = (gpio_mode & GPIO_BOUT_MASK) >> GPIO_BOUT_SHIFT;
 196        unsigned int tmp;
 197
 198        /* Pullup enable */
 199        if (gpio_mode & GPIO_PUEN) {
 200                writel(readl(&regs->port[port].puen) | (1 << pin),
 201                                &regs->port[port].puen);
 202        } else {
 203                writel(readl(&regs->port[port].puen) & ~(1 << pin),
 204                                &regs->port[port].puen);
 205        }
 206
 207        /* Data direction */
 208        if (gpio_mode & GPIO_OUT) {
 209                writel(readl(&regs->port[port].ddir) | 1 << pin,
 210                                &regs->port[port].ddir);
 211        } else {
 212                writel(readl(&regs->port[port].ddir) & ~(1 << pin),
 213                                &regs->port[port].ddir);
 214        }
 215
 216        /* Primary / alternate function */
 217        if (gpio_mode & GPIO_AF) {
 218                writel(readl(&regs->port[port].gpr) | (1 << pin),
 219                                &regs->port[port].gpr);
 220        } else {
 221                writel(readl(&regs->port[port].gpr) & ~(1 << pin),
 222                                &regs->port[port].gpr);
 223        }
 224
 225        /* use as gpio? */
 226        if (!(gpio_mode & (GPIO_PF | GPIO_AF))) {
 227                writel(readl(&regs->port[port].gius) | (1 << pin),
 228                                &regs->port[port].gius);
 229        } else {
 230                writel(readl(&regs->port[port].gius) & ~(1 << pin),
 231                                &regs->port[port].gius);
 232        }
 233
 234        /* Output / input configuration */
 235        if (pin < 16) {
 236                tmp = readl(&regs->port[port].ocr1);
 237                tmp &= ~(3 << (pin * 2));
 238                tmp |= (ocr << (pin * 2));
 239                writel(tmp, &regs->port[port].ocr1);
 240
 241                writel(readl(&regs->port[port].iconfa1) & ~(3 << (pin * 2)),
 242                                &regs->port[port].iconfa1);
 243                writel(readl(&regs->port[port].iconfa1) | aout << (pin * 2),
 244                                &regs->port[port].iconfa1);
 245                writel(readl(&regs->port[port].iconfb1) & ~(3 << (pin * 2)),
 246                                &regs->port[port].iconfb1);
 247                writel(readl(&regs->port[port].iconfb1) | bout << (pin * 2),
 248                                &regs->port[port].iconfb1);
 249        } else {
 250                pin -= 16;
 251
 252                tmp = readl(&regs->port[port].ocr2);
 253                tmp &= ~(3 << (pin * 2));
 254                tmp |= (ocr << (pin * 2));
 255                writel(tmp, &regs->port[port].ocr2);
 256
 257                writel(readl(&regs->port[port].iconfa2) & ~(3 << (pin * 2)),
 258                                &regs->port[port].iconfa2);
 259                writel(readl(&regs->port[port].iconfa2) | aout << (pin * 2),
 260                                &regs->port[port].iconfa2);
 261                writel(readl(&regs->port[port].iconfb2) & ~(3 << (pin * 2)),
 262                                &regs->port[port].iconfb2);
 263                writel(readl(&regs->port[port].iconfb2) | bout << (pin * 2),
 264                                &regs->port[port].iconfb2);
 265        }
 266}
 267