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