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