uboot/arch/arm/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#include <asm/arch/clock.h>
  27#include <asm/arch/gpio.h>
  28#ifdef CONFIG_MXC_MMC
  29#include <asm/arch/mxcmmc.h>
  30#endif
  31
  32/*
  33 *  get the system pll clock in Hz
  34 *
  35 *                  mfi + mfn / (mfd +1)
  36 *  f = 2 * f_ref * --------------------
  37 *                        pd + 1
  38 */
  39static unsigned int imx_decode_pll(unsigned int pll, unsigned int f_ref)
  40{
  41        unsigned int mfi = (pll >> 10) & 0xf;
  42        unsigned int mfn = pll & 0x3ff;
  43        unsigned int mfd = (pll >> 16) & 0x3ff;
  44        unsigned int pd =  (pll >> 26) & 0xf;
  45
  46        mfi = mfi <= 5 ? 5 : mfi;
  47
  48        return lldiv(2 * (u64)f_ref * (mfi * (mfd + 1) + mfn),
  49                        (mfd + 1) * (pd + 1));
  50}
  51
  52static ulong clk_in_32k(void)
  53{
  54        return 1024 * CONFIG_MX27_CLK32;
  55}
  56
  57static ulong clk_in_26m(void)
  58{
  59        struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
  60
  61        if (readl(&pll->cscr) & CSCR_OSC26M_DIV1P5) {
  62                /* divide by 1.5 */
  63                return 26000000 * 2 / 3;
  64        } else {
  65                return 26000000;
  66        }
  67}
  68
  69static ulong imx_get_mpllclk(void)
  70{
  71        struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
  72        ulong cscr = readl(&pll->cscr);
  73        ulong fref;
  74
  75        if (cscr & CSCR_MCU_SEL)
  76                fref = clk_in_26m();
  77        else
  78                fref = clk_in_32k();
  79
  80        return imx_decode_pll(readl(&pll->mpctl0), fref);
  81}
  82
  83static ulong imx_get_armclk(void)
  84{
  85        struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
  86        ulong cscr = readl(&pll->cscr);
  87        ulong fref = imx_get_mpllclk();
  88        ulong div;
  89
  90        if (!(cscr & CSCR_ARM_SRC_MPLL))
  91                fref = lldiv((fref * 2), 3);
  92
  93        div = ((cscr >> 12) & 0x3) + 1;
  94
  95        return lldiv(fref, div);
  96}
  97
  98static ulong imx_get_ahbclk(void)
  99{
 100        struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
 101        ulong cscr = readl(&pll->cscr);
 102        ulong fref = imx_get_mpllclk();
 103        ulong div;
 104
 105        div = ((cscr >> 8) & 0x3) + 1;
 106
 107        return lldiv(fref * 2, 3 * div);
 108}
 109
 110static __attribute__((unused)) ulong imx_get_spllclk(void)
 111{
 112        struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
 113        ulong cscr = readl(&pll->cscr);
 114        ulong fref;
 115
 116        if (cscr & CSCR_SP_SEL)
 117                fref = clk_in_26m();
 118        else
 119                fref = clk_in_32k();
 120
 121        return imx_decode_pll(readl(&pll->spctl0), fref);
 122}
 123
 124static ulong imx_decode_perclk(ulong div)
 125{
 126        return lldiv((imx_get_mpllclk() * 2), (div * 3));
 127}
 128
 129static ulong imx_get_perclk1(void)
 130{
 131        struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
 132
 133        return imx_decode_perclk((readl(&pll->pcdr1) & 0x3f) + 1);
 134}
 135
 136static ulong imx_get_perclk2(void)
 137{
 138        struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
 139
 140        return imx_decode_perclk(((readl(&pll->pcdr1) >> 8) & 0x3f) + 1);
 141}
 142
 143static __attribute__((unused)) ulong imx_get_perclk3(void)
 144{
 145        struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
 146
 147        return imx_decode_perclk(((readl(&pll->pcdr1) >> 16) & 0x3f) + 1);
 148}
 149
 150static __attribute__((unused)) ulong imx_get_perclk4(void)
 151{
 152        struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
 153
 154        return imx_decode_perclk(((readl(&pll->pcdr1) >> 24) & 0x3f) + 1);
 155}
 156
 157unsigned int mxc_get_clock(enum mxc_clock clk)
 158{
 159        switch (clk) {
 160        case MXC_ARM_CLK:
 161                return imx_get_armclk();
 162        case MXC_UART_CLK:
 163                return imx_get_perclk1();
 164        case MXC_FEC_CLK:
 165                return imx_get_ahbclk();
 166        case MXC_ESDHC_CLK:
 167                return imx_get_perclk2();
 168        }
 169        return -1;
 170}
 171
 172
 173#if defined(CONFIG_DISPLAY_CPUINFO)
 174int print_cpuinfo (void)
 175{
 176        char buf[32];
 177
 178        printf("CPU:   Freescale i.MX27 at %s MHz\n\n",
 179                        strmhz(buf, imx_get_mpllclk()));
 180        return 0;
 181}
 182#endif
 183
 184int cpu_eth_init(bd_t *bis)
 185{
 186#if defined(CONFIG_FEC_MXC)
 187        struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
 188
 189        /* enable FEC clock */
 190        writel(readl(&pll->pccr1) | PCCR1_HCLK_FEC, &pll->pccr1);
 191        writel(readl(&pll->pccr0) | PCCR0_FEC_EN, &pll->pccr0);
 192        return fecmxc_initialize(bis);
 193#else
 194        return 0;
 195#endif
 196}
 197
 198/*
 199 * Initializes on-chip MMC controllers.
 200 * to override, implement board_mmc_init()
 201 */
 202int cpu_mmc_init(bd_t *bis)
 203{
 204#ifdef CONFIG_MXC_MMC
 205        return mxc_mmc_init(bis);
 206#else
 207        return 0;
 208#endif
 209}
 210
 211void imx_gpio_mode(int gpio_mode)
 212{
 213        struct gpio_port_regs *regs = (struct gpio_port_regs *)IMX_GPIO_BASE;
 214        unsigned int pin = gpio_mode & GPIO_PIN_MASK;
 215        unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
 216        unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> GPIO_OCR_SHIFT;
 217        unsigned int aout = (gpio_mode & GPIO_AOUT_MASK) >> GPIO_AOUT_SHIFT;
 218        unsigned int bout = (gpio_mode & GPIO_BOUT_MASK) >> GPIO_BOUT_SHIFT;
 219        unsigned int tmp;
 220
 221        /* Pullup enable */
 222        if (gpio_mode & GPIO_PUEN) {
 223                writel(readl(&regs->port[port].puen) | (1 << pin),
 224                                &regs->port[port].puen);
 225        } else {
 226                writel(readl(&regs->port[port].puen) & ~(1 << pin),
 227                                &regs->port[port].puen);
 228        }
 229
 230        /* Data direction */
 231        if (gpio_mode & GPIO_OUT) {
 232                writel(readl(&regs->port[port].gpio_dir) | 1 << pin,
 233                                &regs->port[port].gpio_dir);
 234        } else {
 235                writel(readl(&regs->port[port].gpio_dir) & ~(1 << pin),
 236                                &regs->port[port].gpio_dir);
 237        }
 238
 239        /* Primary / alternate function */
 240        if (gpio_mode & GPIO_AF) {
 241                writel(readl(&regs->port[port].gpr) | (1 << pin),
 242                                &regs->port[port].gpr);
 243        } else {
 244                writel(readl(&regs->port[port].gpr) & ~(1 << pin),
 245                                &regs->port[port].gpr);
 246        }
 247
 248        /* use as gpio? */
 249        if (!(gpio_mode & (GPIO_PF | GPIO_AF))) {
 250                writel(readl(&regs->port[port].gius) | (1 << pin),
 251                                &regs->port[port].gius);
 252        } else {
 253                writel(readl(&regs->port[port].gius) & ~(1 << pin),
 254                                &regs->port[port].gius);
 255        }
 256
 257        /* Output / input configuration */
 258        if (pin < 16) {
 259                tmp = readl(&regs->port[port].ocr1);
 260                tmp &= ~(3 << (pin * 2));
 261                tmp |= (ocr << (pin * 2));
 262                writel(tmp, &regs->port[port].ocr1);
 263
 264                writel(readl(&regs->port[port].iconfa1) & ~(3 << (pin * 2)),
 265                                &regs->port[port].iconfa1);
 266                writel(readl(&regs->port[port].iconfa1) | aout << (pin * 2),
 267                                &regs->port[port].iconfa1);
 268                writel(readl(&regs->port[port].iconfb1) & ~(3 << (pin * 2)),
 269                                &regs->port[port].iconfb1);
 270                writel(readl(&regs->port[port].iconfb1) | bout << (pin * 2),
 271                                &regs->port[port].iconfb1);
 272        } else {
 273                pin -= 16;
 274
 275                tmp = readl(&regs->port[port].ocr2);
 276                tmp &= ~(3 << (pin * 2));
 277                tmp |= (ocr << (pin * 2));
 278                writel(tmp, &regs->port[port].ocr2);
 279
 280                writel(readl(&regs->port[port].iconfa2) & ~(3 << (pin * 2)),
 281                                &regs->port[port].iconfa2);
 282                writel(readl(&regs->port[port].iconfa2) | aout << (pin * 2),
 283                                &regs->port[port].iconfa2);
 284                writel(readl(&regs->port[port].iconfb2) & ~(3 << (pin * 2)),
 285                                &regs->port[port].iconfb2);
 286                writel(readl(&regs->port[port].iconfb2) | bout << (pin * 2),
 287                                &regs->port[port].iconfb2);
 288        }
 289}
 290
 291#ifdef CONFIG_MXC_UART
 292void mx27_uart1_init_pins(void)
 293{
 294        int i;
 295        unsigned int mode[] = {
 296                PE12_PF_UART1_TXD,
 297                PE13_PF_UART1_RXD,
 298        };
 299
 300        for (i = 0; i < ARRAY_SIZE(mode); i++)
 301                imx_gpio_mode(mode[i]);
 302
 303}
 304#endif /* CONFIG_MXC_UART */
 305
 306#ifdef CONFIG_FEC_MXC
 307void mx27_fec_init_pins(void)
 308{
 309        int i;
 310        unsigned int mode[] = {
 311                PD0_AIN_FEC_TXD0,
 312                PD1_AIN_FEC_TXD1,
 313                PD2_AIN_FEC_TXD2,
 314                PD3_AIN_FEC_TXD3,
 315                PD4_AOUT_FEC_RX_ER,
 316                PD5_AOUT_FEC_RXD1,
 317                PD6_AOUT_FEC_RXD2,
 318                PD7_AOUT_FEC_RXD3,
 319                PD8_AF_FEC_MDIO,
 320                PD9_AIN_FEC_MDC | GPIO_PUEN,
 321                PD10_AOUT_FEC_CRS,
 322                PD11_AOUT_FEC_TX_CLK,
 323                PD12_AOUT_FEC_RXD0,
 324                PD13_AOUT_FEC_RX_DV,
 325                PD14_AOUT_FEC_CLR,
 326                PD15_AOUT_FEC_COL,
 327                PD16_AIN_FEC_TX_ER,
 328                PF23_AIN_FEC_TX_EN,
 329        };
 330
 331        for (i = 0; i < ARRAY_SIZE(mode); i++)
 332                imx_gpio_mode(mode[i]);
 333}
 334
 335void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
 336{
 337        int i;
 338        struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE;
 339        struct fuse_bank *bank = &iim->bank[0];
 340        struct fuse_bank0_regs *fuse =
 341                        (struct fuse_bank0_regs *)bank->fuse_regs;
 342
 343        for (i = 0; i < 6; i++)
 344                mac[6 - 1 - i] = readl(&fuse->mac_addr[i]) & 0xff;
 345}
 346#endif /* CONFIG_FEC_MXC */
 347
 348#ifdef CONFIG_MXC_MMC
 349void mx27_sd1_init_pins(void)
 350{
 351        int i;
 352        unsigned int mode[] = {
 353                PE18_PF_SD1_D0,
 354                PE19_PF_SD1_D1,
 355                PE20_PF_SD1_D2,
 356                PE21_PF_SD1_D3,
 357                PE22_PF_SD1_CMD,
 358                PE23_PF_SD1_CLK,
 359        };
 360
 361        for (i = 0; i < ARRAY_SIZE(mode); i++)
 362                imx_gpio_mode(mode[i]);
 363
 364}
 365
 366void mx27_sd2_init_pins(void)
 367{
 368        int i;
 369        unsigned int mode[] = {
 370                PB4_PF_SD2_D0,
 371                PB5_PF_SD2_D1,
 372                PB6_PF_SD2_D2,
 373                PB7_PF_SD2_D3,
 374                PB8_PF_SD2_CMD,
 375                PB9_PF_SD2_CLK,
 376        };
 377
 378        for (i = 0; i < ARRAY_SIZE(mode); i++)
 379                imx_gpio_mode(mode[i]);
 380
 381}
 382#endif /* CONFIG_MXC_MMC */
 383