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