uboot/arch/arm/cpu/arm1136/mx35/generic.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2007
   4 * Sascha Hauer, Pengutronix
   5 *
   6 * (C) Copyright 2008-2010 Freescale Semiconductor, Inc.
   7 */
   8
   9#include <common.h>
  10#include <div64.h>
  11#include <asm/io.h>
  12#include <linux/errno.h>
  13#include <asm/arch/imx-regs.h>
  14#include <asm/arch/crm_regs.h>
  15#include <asm/arch/clock.h>
  16#include <asm/arch/sys_proto.h>
  17#ifdef CONFIG_FSL_ESDHC_IMX
  18#include <fsl_esdhc_imx.h>
  19#endif
  20#include <netdev.h>
  21#include <spl.h>
  22
  23#define CLK_CODE(arm, ahb, sel) (((arm) << 16) + ((ahb) << 8) + (sel))
  24#define CLK_CODE_ARM(c)         (((c) >> 16) & 0xFF)
  25#define CLK_CODE_AHB(c)         (((c) >>  8) & 0xFF)
  26#define CLK_CODE_PATH(c)        ((c) & 0xFF)
  27
  28#define CCM_GET_DIVIDER(x, m, o) (((x) & (m)) >> (o))
  29
  30#ifdef CONFIG_FSL_ESDHC_IMX
  31DECLARE_GLOBAL_DATA_PTR;
  32#endif
  33
  34static int g_clk_mux_auto[8] = {
  35        CLK_CODE(1, 3, 0), CLK_CODE(1, 2, 1), CLK_CODE(2, 1, 1), -1,
  36        CLK_CODE(1, 6, 0), CLK_CODE(1, 4, 1), CLK_CODE(2, 2, 1), -1,
  37};
  38
  39static int g_clk_mux_consumer[16] = {
  40        CLK_CODE(1, 4, 0), CLK_CODE(1, 3, 1), CLK_CODE(1, 3, 1), -1,
  41        -1, -1, CLK_CODE(4, 1, 0), CLK_CODE(1, 5, 0),
  42        CLK_CODE(1, 8, 1), CLK_CODE(1, 6, 1), CLK_CODE(2, 4, 0), -1,
  43        -1, -1, CLK_CODE(4, 2, 0), -1,
  44};
  45
  46static int hsp_div_table[3][16] = {
  47        {4, 3, 2, -1, -1, -1, 1, 5, 4, 3, 2, -1, -1, -1, 1, -1},
  48        {-1, -1, -1, -1, -1, -1, -1, -1, 8, 6, 4, -1, -1, -1, 2, -1},
  49        {3, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1},
  50};
  51
  52u32 get_cpu_rev(void)
  53{
  54        int reg;
  55        struct iim_regs *iim =
  56                (struct iim_regs *)IIM_BASE_ADDR;
  57        reg = readl(&iim->iim_srev);
  58        if (!reg) {
  59                reg = readw(ROMPATCH_REV);
  60                reg <<= 4;
  61        } else {
  62                reg += CHIP_REV_1_0;
  63        }
  64
  65        return 0x35000 + (reg & 0xFF);
  66}
  67
  68static u32 get_arm_div(u32 pdr0, u32 *fi, u32 *fd)
  69{
  70        int *pclk_mux;
  71        if (pdr0 & MXC_CCM_PDR0_AUTO_CON) {
  72                pclk_mux = g_clk_mux_consumer +
  73                        ((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >>
  74                        MXC_CCM_PDR0_CON_MUX_DIV_OFFSET);
  75        } else {
  76                pclk_mux = g_clk_mux_auto +
  77                        ((pdr0 & MXC_CCM_PDR0_AUTO_MUX_DIV_MASK) >>
  78                        MXC_CCM_PDR0_AUTO_MUX_DIV_OFFSET);
  79        }
  80
  81        if ((*pclk_mux) == -1)
  82                return -1;
  83
  84        if (fi && fd) {
  85                if (!CLK_CODE_PATH(*pclk_mux)) {
  86                        *fi = *fd = 1;
  87                        return CLK_CODE_ARM(*pclk_mux);
  88                }
  89                if (pdr0 & MXC_CCM_PDR0_AUTO_CON) {
  90                        *fi = 3;
  91                        *fd = 4;
  92                } else {
  93                        *fi = 2;
  94                        *fd = 3;
  95                }
  96        }
  97        return CLK_CODE_ARM(*pclk_mux);
  98}
  99
 100static int get_ahb_div(u32 pdr0)
 101{
 102        int *pclk_mux;
 103
 104        pclk_mux = g_clk_mux_consumer +
 105                ((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >>
 106                MXC_CCM_PDR0_CON_MUX_DIV_OFFSET);
 107
 108        if ((*pclk_mux) == -1)
 109                return -1;
 110
 111        return CLK_CODE_AHB(*pclk_mux);
 112}
 113
 114static u32 decode_pll(u32 reg, u32 infreq)
 115{
 116        u32 mfi = (reg >> 10) & 0xf;
 117        s32 mfn = reg & 0x3ff;
 118        u32 mfd = (reg >> 16) & 0x3ff;
 119        u32 pd = (reg >> 26) & 0xf;
 120
 121        mfi = mfi <= 5 ? 5 : mfi;
 122        mfn = mfn >= 512 ? mfn - 1024 : mfn;
 123        mfd += 1;
 124        pd += 1;
 125
 126        return lldiv(2 * (u64)infreq * (mfi * mfd + mfn),
 127                mfd * pd);
 128}
 129
 130static u32 get_mcu_main_clk(void)
 131{
 132        u32 arm_div = 0, fi = 0, fd = 0;
 133        struct ccm_regs *ccm =
 134                (struct ccm_regs *)IMX_CCM_BASE;
 135        arm_div = get_arm_div(readl(&ccm->pdr0), &fi, &fd);
 136        fi *= decode_pll(readl(&ccm->mpctl), MXC_HCLK);
 137        return fi / (arm_div * fd);
 138}
 139
 140static u32 get_ipg_clk(void)
 141{
 142        u32 freq = get_mcu_main_clk();
 143        struct ccm_regs *ccm =
 144                (struct ccm_regs *)IMX_CCM_BASE;
 145        u32 pdr0 = readl(&ccm->pdr0);
 146
 147        return freq / (get_ahb_div(pdr0) * 2);
 148}
 149
 150static u32 get_ipg_per_clk(void)
 151{
 152        u32 freq = get_mcu_main_clk();
 153        struct ccm_regs *ccm =
 154                (struct ccm_regs *)IMX_CCM_BASE;
 155        u32 pdr0 = readl(&ccm->pdr0);
 156        u32 pdr4 = readl(&ccm->pdr4);
 157        u32 div;
 158        if (pdr0 & MXC_CCM_PDR0_PER_SEL) {
 159                div = CCM_GET_DIVIDER(pdr4,
 160                        MXC_CCM_PDR4_PER0_PODF_MASK,
 161                        MXC_CCM_PDR4_PER0_PODF_OFFSET) + 1;
 162        } else {
 163                div = CCM_GET_DIVIDER(pdr0,
 164                        MXC_CCM_PDR0_PER_PODF_MASK,
 165                        MXC_CCM_PDR0_PER_PODF_OFFSET) + 1;
 166                div *= get_ahb_div(pdr0);
 167        }
 168        return freq / div;
 169}
 170
 171u32 imx_get_uartclk(void)
 172{
 173        u32 freq;
 174        struct ccm_regs *ccm =
 175                (struct ccm_regs *)IMX_CCM_BASE;
 176        u32 pdr4 = readl(&ccm->pdr4);
 177
 178        if (readl(&ccm->pdr3) & MXC_CCM_PDR3_UART_M_U)
 179                freq = get_mcu_main_clk();
 180        else
 181                freq = decode_pll(readl(&ccm->ppctl), MXC_HCLK);
 182        freq /= CCM_GET_DIVIDER(pdr4,
 183                        MXC_CCM_PDR4_UART_PODF_MASK,
 184                        MXC_CCM_PDR4_UART_PODF_OFFSET) + 1;
 185        return freq;
 186}
 187
 188unsigned int mxc_get_main_clock(enum mxc_main_clock clk)
 189{
 190        u32 nfc_pdf, hsp_podf;
 191        u32 pll, ret_val = 0, usb_podf;
 192        struct ccm_regs *ccm =
 193                (struct ccm_regs *)IMX_CCM_BASE;
 194
 195        u32 reg = readl(&ccm->pdr0);
 196        u32 reg4 = readl(&ccm->pdr4);
 197
 198        reg |= 0x1;
 199
 200        switch (clk) {
 201        case CPU_CLK:
 202                ret_val = get_mcu_main_clk();
 203                break;
 204        case AHB_CLK:
 205                ret_val = get_mcu_main_clk();
 206                break;
 207        case HSP_CLK:
 208                if (reg & CLKMODE_CONSUMER) {
 209                        hsp_podf = (reg >> 20) & 0x3;
 210                        pll = get_mcu_main_clk();
 211                        hsp_podf = hsp_div_table[hsp_podf][(reg>>16)&0xF];
 212                        if (hsp_podf > 0) {
 213                                ret_val = pll / hsp_podf;
 214                        } else {
 215                                puts("mismatch HSP with ARM clock setting\n");
 216                                ret_val = 0;
 217                        }
 218                } else {
 219                        ret_val = get_mcu_main_clk();
 220                }
 221                break;
 222        case IPG_CLK:
 223                ret_val = get_ipg_clk();
 224                break;
 225        case IPG_PER_CLK:
 226                ret_val = get_ipg_per_clk();
 227                break;
 228        case NFC_CLK:
 229                nfc_pdf = (reg4 >> 28) & 0xF;
 230                pll = get_mcu_main_clk();
 231                /* AHB/nfc_pdf */
 232                ret_val = pll / (nfc_pdf + 1);
 233                break;
 234        case USB_CLK:
 235                usb_podf = (reg4 >> 22) & 0x3F;
 236                if (reg4 & 0x200)
 237                        pll = get_mcu_main_clk();
 238                else
 239                        pll = decode_pll(readl(&ccm->ppctl), MXC_HCLK);
 240
 241                ret_val = pll / (usb_podf + 1);
 242                break;
 243        default:
 244                printf("Unknown clock: %d\n", clk);
 245                break;
 246        }
 247
 248        return ret_val;
 249}
 250unsigned int mxc_get_peri_clock(enum mxc_peri_clock clk)
 251{
 252        u32 ret_val = 0, pdf, pre_pdf, clk_sel;
 253        struct ccm_regs *ccm =
 254                (struct ccm_regs *)IMX_CCM_BASE;
 255        u32 mpdr2 = readl(&ccm->pdr2);
 256        u32 mpdr3 = readl(&ccm->pdr3);
 257        u32 mpdr4 = readl(&ccm->pdr4);
 258
 259        switch (clk) {
 260        case UART1_BAUD:
 261        case UART2_BAUD:
 262        case UART3_BAUD:
 263                clk_sel = mpdr3 & (1 << 14);
 264                pdf = (mpdr4 >> 10) & 0x3F;
 265                ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
 266                        decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1);
 267                break;
 268        case SSI1_BAUD:
 269                pre_pdf = (mpdr2 >> 24) & 0x7;
 270                pdf = mpdr2 & 0x3F;
 271                clk_sel = mpdr2 & (1 << 6);
 272                ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
 273                        decode_pll(readl(&ccm->ppctl), MXC_HCLK)) /
 274                                ((pre_pdf + 1) * (pdf + 1));
 275                break;
 276        case SSI2_BAUD:
 277                pre_pdf = (mpdr2 >> 27) & 0x7;
 278                pdf = (mpdr2 >> 8) & 0x3F;
 279                clk_sel = mpdr2 & (1 << 6);
 280                ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
 281                        decode_pll(readl(&ccm->ppctl), MXC_HCLK)) /
 282                                ((pre_pdf + 1) * (pdf + 1));
 283                break;
 284        case CSI_BAUD:
 285                clk_sel = mpdr2 & (1 << 7);
 286                pdf = (mpdr2 >> 16) & 0x3F;
 287                ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
 288                        decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1);
 289                break;
 290        case MSHC_CLK:
 291                pre_pdf = readl(&ccm->pdr1);
 292                clk_sel = (pre_pdf & 0x80);
 293                pdf = (pre_pdf >> 22) & 0x3F;
 294                pre_pdf = (pre_pdf >> 28) & 0x7;
 295                ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
 296                        decode_pll(readl(&ccm->ppctl), MXC_HCLK)) /
 297                                ((pre_pdf + 1) * (pdf + 1));
 298                break;
 299        case ESDHC1_CLK:
 300                clk_sel = mpdr3 & 0x40;
 301                pdf = mpdr3 & 0x3F;
 302                ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
 303                        decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1);
 304                break;
 305        case ESDHC2_CLK:
 306                clk_sel = mpdr3 & 0x40;
 307                pdf = (mpdr3 >> 8) & 0x3F;
 308                ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
 309                        decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1);
 310                break;
 311        case ESDHC3_CLK:
 312                clk_sel = mpdr3 & 0x40;
 313                pdf = (mpdr3 >> 16) & 0x3F;
 314                ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
 315                        decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1);
 316                break;
 317        case SPDIF_CLK:
 318                clk_sel = mpdr3 & 0x400000;
 319                pre_pdf = (mpdr3 >> 29) & 0x7;
 320                pdf = (mpdr3 >> 23) & 0x3F;
 321                ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
 322                        decode_pll(readl(&ccm->ppctl), MXC_HCLK)) /
 323                                ((pre_pdf + 1) * (pdf + 1));
 324                break;
 325        default:
 326                printf("%s(): This clock: %d not supported yet\n",
 327                                __func__, clk);
 328                break;
 329        }
 330
 331        return ret_val;
 332}
 333
 334unsigned int mxc_get_clock(enum mxc_clock clk)
 335{
 336        switch (clk) {
 337        case MXC_ARM_CLK:
 338                return get_mcu_main_clk();
 339        case MXC_AHB_CLK:
 340                break;
 341        case MXC_IPG_CLK:
 342                return get_ipg_clk();
 343        case MXC_IPG_PERCLK:
 344        case MXC_I2C_CLK:
 345                return get_ipg_per_clk();
 346        case MXC_UART_CLK:
 347                return imx_get_uartclk();
 348        case MXC_ESDHC1_CLK:
 349                return mxc_get_peri_clock(ESDHC1_CLK);
 350        case MXC_ESDHC2_CLK:
 351                return mxc_get_peri_clock(ESDHC2_CLK);
 352        case MXC_ESDHC3_CLK:
 353                return mxc_get_peri_clock(ESDHC3_CLK);
 354        case MXC_USB_CLK:
 355                return mxc_get_main_clock(USB_CLK);
 356        case MXC_FEC_CLK:
 357                return get_ipg_clk();
 358        case MXC_CSPI_CLK:
 359                return get_ipg_clk();
 360        }
 361        return -1;
 362}
 363
 364#ifdef CONFIG_FEC_MXC
 365/*
 366 * The MX35 has no fuse for MAC, return a NULL MAC
 367 */
 368void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
 369{
 370        memset(mac, 0, 6);
 371}
 372
 373u32 imx_get_fecclk(void)
 374{
 375        return mxc_get_clock(MXC_IPG_CLK);
 376}
 377#endif
 378
 379int do_mx35_showclocks(cmd_tbl_t *cmdtp,
 380        int flag, int argc, char * const argv[])
 381{
 382        u32 cpufreq = get_mcu_main_clk();
 383        printf("mx35 cpu clock: %dMHz\n", cpufreq / 1000000);
 384        printf("ipg clock     : %dHz\n", get_ipg_clk());
 385        printf("ipg per clock : %dHz\n", get_ipg_per_clk());
 386        printf("uart clock    : %dHz\n", mxc_get_clock(MXC_UART_CLK));
 387
 388        return 0;
 389}
 390
 391U_BOOT_CMD(
 392        clocks, CONFIG_SYS_MAXARGS, 1, do_mx35_showclocks,
 393        "display clocks",
 394        ""
 395);
 396
 397#if defined(CONFIG_DISPLAY_CPUINFO)
 398static char *get_reset_cause(void)
 399{
 400        /* read RCSR register from CCM module */
 401        struct ccm_regs *ccm =
 402                (struct ccm_regs *)IMX_CCM_BASE;
 403
 404        u32 cause = readl(&ccm->rcsr) & 0x0F;
 405
 406        switch (cause) {
 407        case 0x0000:
 408                return "POR";
 409        case 0x0002:
 410                return "JTAG";
 411        case 0x0004:
 412                return "RST";
 413        case 0x0008:
 414                return "WDOG";
 415        default:
 416                return "unknown reset";
 417        }
 418}
 419
 420int print_cpuinfo(void)
 421{
 422        u32 srev = get_cpu_rev();
 423
 424        printf("CPU:   Freescale i.MX35 rev %d.%d at %d MHz.\n",
 425                (srev & 0xF0) >> 4, (srev & 0x0F),
 426                get_mcu_main_clk() / 1000000);
 427
 428        printf("Reset cause: %s\n", get_reset_cause());
 429
 430        return 0;
 431}
 432#endif
 433
 434/*
 435 * Initializes on-chip ethernet controllers.
 436 * to override, implement board_eth_init()
 437 */
 438int cpu_eth_init(bd_t *bis)
 439{
 440        int rc = -ENODEV;
 441
 442#if defined(CONFIG_FEC_MXC)
 443        rc = fecmxc_initialize(bis);
 444#endif
 445
 446        return rc;
 447}
 448
 449#ifdef CONFIG_FSL_ESDHC_IMX
 450/*
 451 * Initializes on-chip MMC controllers.
 452 * to override, implement board_mmc_init()
 453 */
 454int cpu_mmc_init(bd_t *bis)
 455{
 456        return fsl_esdhc_mmc_init(bis);
 457}
 458#endif
 459
 460int get_clocks(void)
 461{
 462#ifdef CONFIG_FSL_ESDHC_IMX
 463#if CONFIG_SYS_FSL_ESDHC_ADDR == MMC_SDHC2_BASE_ADDR
 464        gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
 465#elif CONFIG_SYS_FSL_ESDHC_ADDR == MMC_SDHC3_BASE_ADDR
 466        gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
 467#else
 468        gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC1_CLK);
 469#endif
 470#endif
 471        return 0;
 472}
 473
 474#define RCSR_MEM_CTL_WEIM       0
 475#define RCSR_MEM_CTL_NAND       1
 476#define RCSR_MEM_CTL_ATA        2
 477#define RCSR_MEM_CTL_EXPANSION  3
 478#define RCSR_MEM_TYPE_NOR       0
 479#define RCSR_MEM_TYPE_ONENAND   2
 480#define RCSR_MEM_TYPE_SD        0
 481#define RCSR_MEM_TYPE_I2C       2
 482#define RCSR_MEM_TYPE_SPI       3
 483
 484u32 spl_boot_device(void)
 485{
 486        struct ccm_regs *ccm =
 487                (struct ccm_regs *)IMX_CCM_BASE;
 488
 489        u32 rcsr = readl(&ccm->rcsr);
 490        u32 mem_type, mem_ctl;
 491
 492        /* In external mode, no boot device is returned */
 493        if ((rcsr >> 10) & 0x03)
 494                return BOOT_DEVICE_NONE;
 495
 496        mem_ctl = (rcsr >> 25) & 0x03;
 497        mem_type = (rcsr >> 23) & 0x03;
 498
 499        switch (mem_ctl) {
 500        case RCSR_MEM_CTL_WEIM:
 501                switch (mem_type) {
 502                case RCSR_MEM_TYPE_NOR:
 503                        return BOOT_DEVICE_NOR;
 504                case RCSR_MEM_TYPE_ONENAND:
 505                        return BOOT_DEVICE_ONENAND;
 506                default:
 507                        return BOOT_DEVICE_NONE;
 508                }
 509        case RCSR_MEM_CTL_NAND:
 510                return BOOT_DEVICE_NAND;
 511        case RCSR_MEM_CTL_EXPANSION:
 512                switch (mem_type) {
 513                case RCSR_MEM_TYPE_SD:
 514                        return BOOT_DEVICE_MMC1;
 515                case RCSR_MEM_TYPE_I2C:
 516                        return BOOT_DEVICE_I2C;
 517                case RCSR_MEM_TYPE_SPI:
 518                        return BOOT_DEVICE_SPI;
 519                default:
 520                        return BOOT_DEVICE_NONE;
 521                }
 522        }
 523
 524        return BOOT_DEVICE_NONE;
 525}
 526