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