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