uboot/arch/arm/cpu/armv7/vf610/generic.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2013 Freescale Semiconductor, Inc.
   4 */
   5
   6#include <common.h>
   7#include <clock_legacy.h>
   8#include <command.h>
   9#include <cpu_func.h>
  10#include <init.h>
  11#include <net.h>
  12#include <asm/cache.h>
  13#include <asm/global_data.h>
  14#include <asm/io.h>
  15#include <asm/arch/imx-regs.h>
  16#include <asm/arch/clock.h>
  17#include <asm/arch/crm_regs.h>
  18#include <asm/mach-imx/sys_proto.h>
  19#include <env.h>
  20#include <netdev.h>
  21#ifdef CONFIG_FSL_ESDHC_IMX
  22#include <fsl_esdhc_imx.h>
  23#endif
  24
  25#ifdef CONFIG_FSL_ESDHC_IMX
  26DECLARE_GLOBAL_DATA_PTR;
  27#endif
  28
  29static char soc_type[] = "xx0";
  30
  31#ifdef CONFIG_MXC_OCOTP
  32void enable_ocotp_clk(unsigned char enable)
  33{
  34        struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR;
  35        u32 reg;
  36
  37        reg = readl(&ccm->ccgr6);
  38        if (enable)
  39                reg |= CCM_CCGR6_OCOTP_CTRL_MASK;
  40        else
  41                reg &= ~CCM_CCGR6_OCOTP_CTRL_MASK;
  42        writel(reg, &ccm->ccgr6);
  43}
  44#endif
  45
  46static u32 get_mcu_main_clk(void)
  47{
  48        struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR;
  49        u32 ccm_ccsr, ccm_cacrr, armclk_div;
  50        u32 sysclk_sel, pll_pfd_sel = 0;
  51        u32 freq = 0;
  52
  53        ccm_ccsr = readl(&ccm->ccsr);
  54        sysclk_sel = ccm_ccsr & CCM_CCSR_SYS_CLK_SEL_MASK;
  55        sysclk_sel >>= CCM_CCSR_SYS_CLK_SEL_OFFSET;
  56
  57        ccm_cacrr = readl(&ccm->cacrr);
  58        armclk_div = ccm_cacrr & CCM_CACRR_ARM_CLK_DIV_MASK;
  59        armclk_div >>= CCM_CACRR_ARM_CLK_DIV_OFFSET;
  60        armclk_div += 1;
  61
  62        switch (sysclk_sel) {
  63        case 0:
  64                freq = FASE_CLK_FREQ;
  65                break;
  66        case 1:
  67                freq = SLOW_CLK_FREQ;
  68                break;
  69        case 2:
  70                pll_pfd_sel = ccm_ccsr & CCM_CCSR_PLL2_PFD_CLK_SEL_MASK;
  71                pll_pfd_sel >>= CCM_CCSR_PLL2_PFD_CLK_SEL_OFFSET;
  72                if (pll_pfd_sel == 0)
  73                        freq = PLL2_MAIN_FREQ;
  74                else if (pll_pfd_sel == 1)
  75                        freq = PLL2_PFD1_FREQ;
  76                else if (pll_pfd_sel == 2)
  77                        freq = PLL2_PFD2_FREQ;
  78                else if (pll_pfd_sel == 3)
  79                        freq = PLL2_PFD3_FREQ;
  80                else if (pll_pfd_sel == 4)
  81                        freq = PLL2_PFD4_FREQ;
  82                break;
  83        case 3:
  84                freq = PLL2_MAIN_FREQ;
  85                break;
  86        case 4:
  87                pll_pfd_sel = ccm_ccsr & CCM_CCSR_PLL1_PFD_CLK_SEL_MASK;
  88                pll_pfd_sel >>= CCM_CCSR_PLL1_PFD_CLK_SEL_OFFSET;
  89                if (pll_pfd_sel == 0)
  90                        freq = PLL1_MAIN_FREQ;
  91                else if (pll_pfd_sel == 1)
  92                        freq = PLL1_PFD1_FREQ;
  93                else if (pll_pfd_sel == 2)
  94                        freq = PLL1_PFD2_FREQ;
  95                else if (pll_pfd_sel == 3)
  96                        freq = PLL1_PFD3_FREQ;
  97                else if (pll_pfd_sel == 4)
  98                        freq = PLL1_PFD4_FREQ;
  99                break;
 100        case 5:
 101                freq = PLL3_MAIN_FREQ;
 102                break;
 103        default:
 104                printf("unsupported system clock select\n");
 105        }
 106
 107        return freq / armclk_div;
 108}
 109
 110static u32 get_bus_clk(void)
 111{
 112        struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR;
 113        u32 ccm_cacrr, busclk_div;
 114
 115        ccm_cacrr = readl(&ccm->cacrr);
 116
 117        busclk_div = ccm_cacrr & CCM_CACRR_BUS_CLK_DIV_MASK;
 118        busclk_div >>= CCM_CACRR_BUS_CLK_DIV_OFFSET;
 119        busclk_div += 1;
 120
 121        return get_mcu_main_clk() / busclk_div;
 122}
 123
 124static u32 get_ipg_clk(void)
 125{
 126        struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR;
 127        u32 ccm_cacrr, ipgclk_div;
 128
 129        ccm_cacrr = readl(&ccm->cacrr);
 130
 131        ipgclk_div = ccm_cacrr & CCM_CACRR_IPG_CLK_DIV_MASK;
 132        ipgclk_div >>= CCM_CACRR_IPG_CLK_DIV_OFFSET;
 133        ipgclk_div += 1;
 134
 135        return get_bus_clk() / ipgclk_div;
 136}
 137
 138static u32 get_uart_clk(void)
 139{
 140        return get_ipg_clk();
 141}
 142
 143static u32 get_sdhc_clk(void)
 144{
 145        struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR;
 146        u32 ccm_cscmr1, ccm_cscdr2, sdhc_clk_sel, sdhc_clk_div;
 147        u32 freq = 0;
 148
 149        ccm_cscmr1 = readl(&ccm->cscmr1);
 150        sdhc_clk_sel = ccm_cscmr1 & CCM_CSCMR1_ESDHC1_CLK_SEL_MASK;
 151        sdhc_clk_sel >>= CCM_CSCMR1_ESDHC1_CLK_SEL_OFFSET;
 152
 153        ccm_cscdr2 = readl(&ccm->cscdr2);
 154        sdhc_clk_div = ccm_cscdr2 & CCM_CSCDR2_ESDHC1_CLK_DIV_MASK;
 155        sdhc_clk_div >>= CCM_CSCDR2_ESDHC1_CLK_DIV_OFFSET;
 156        sdhc_clk_div += 1;
 157
 158        switch (sdhc_clk_sel) {
 159        case 0:
 160                freq = PLL3_MAIN_FREQ;
 161                break;
 162        case 1:
 163                freq = PLL3_PFD3_FREQ;
 164                break;
 165        case 2:
 166                freq = PLL1_PFD3_FREQ;
 167                break;
 168        case 3:
 169                freq = get_bus_clk();
 170                break;
 171        }
 172
 173        return freq / sdhc_clk_div;
 174}
 175
 176u32 get_fec_clk(void)
 177{
 178        struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR;
 179        u32 ccm_cscmr2, rmii_clk_sel;
 180        u32 freq = 0;
 181
 182        ccm_cscmr2 = readl(&ccm->cscmr2);
 183        rmii_clk_sel = ccm_cscmr2 & CCM_CSCMR2_RMII_CLK_SEL_MASK;
 184        rmii_clk_sel >>= CCM_CSCMR2_RMII_CLK_SEL_OFFSET;
 185
 186        switch (rmii_clk_sel) {
 187        case 0:
 188                freq = ENET_EXTERNAL_CLK;
 189                break;
 190        case 1:
 191                freq = AUDIO_EXTERNAL_CLK;
 192                break;
 193        case 2:
 194                freq = PLL5_MAIN_FREQ;
 195                break;
 196        case 3:
 197                freq = PLL5_MAIN_FREQ / 2;
 198                break;
 199        }
 200
 201        return freq;
 202}
 203
 204static u32 get_i2c_clk(void)
 205{
 206        return get_ipg_clk();
 207}
 208
 209static u32 get_dspi_clk(void)
 210{
 211        return get_ipg_clk();
 212}
 213
 214u32 get_lpuart_clk(void)
 215{
 216        return get_uart_clk();
 217}
 218
 219unsigned int mxc_get_clock(enum mxc_clock clk)
 220{
 221        switch (clk) {
 222        case MXC_ARM_CLK:
 223                return get_mcu_main_clk();
 224        case MXC_BUS_CLK:
 225                return get_bus_clk();
 226        case MXC_IPG_CLK:
 227                return get_ipg_clk();
 228        case MXC_UART_CLK:
 229                return get_uart_clk();
 230        case MXC_ESDHC_CLK:
 231                return get_sdhc_clk();
 232        case MXC_FEC_CLK:
 233                return get_fec_clk();
 234        case MXC_I2C_CLK:
 235                return get_i2c_clk();
 236        case MXC_DSPI_CLK:
 237                return get_dspi_clk();
 238        default:
 239                break;
 240        }
 241        return -1;
 242}
 243
 244/* Dump some core clocks */
 245int do_vf610_showclocks(struct cmd_tbl *cmdtp, int flag, int argc,
 246                        char *const argv[])
 247{
 248        printf("\n");
 249        printf("cpu clock : %8d MHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000);
 250        printf("bus clock : %8d MHz\n", mxc_get_clock(MXC_BUS_CLK) / 1000000);
 251        printf("ipg clock : %8d MHz\n", mxc_get_clock(MXC_IPG_CLK) / 1000000);
 252
 253        return 0;
 254}
 255
 256U_BOOT_CMD(
 257        clocks, CONFIG_SYS_MAXARGS, 1, do_vf610_showclocks,
 258        "display clocks",
 259        ""
 260);
 261
 262#ifdef CONFIG_FEC_MXC
 263__weak void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
 264{
 265        struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
 266        struct fuse_bank *bank = &ocotp->bank[4];
 267        struct fuse_bank4_regs *fuse =
 268                (struct fuse_bank4_regs *)bank->fuse_regs;
 269
 270        u32 value = readl(&fuse->mac_addr0);
 271        mac[0] = (value >> 8);
 272        mac[1] = value;
 273
 274        value = readl(&fuse->mac_addr1);
 275        mac[2] = value >> 24;
 276        mac[3] = value >> 16;
 277        mac[4] = value >> 8;
 278        mac[5] = value;
 279}
 280#endif
 281
 282u32 get_cpu_rev(void)
 283{
 284        return MXC_CPU_VF610 << 12;
 285}
 286
 287#if defined(CONFIG_DISPLAY_CPUINFO)
 288static char *get_reset_cause(void)
 289{
 290        u32 cause;
 291        struct src *src_regs = (struct src *)SRC_BASE_ADDR;
 292
 293        cause = readl(&src_regs->srsr);
 294        writel(cause, &src_regs->srsr);
 295
 296        if (cause & SRC_SRSR_POR_RST)
 297                return "POWER ON RESET";
 298        else if (cause & SRC_SRSR_WDOG_A5)
 299                return "WDOG A5";
 300        else if (cause & SRC_SRSR_WDOG_M4)
 301                return "WDOG M4";
 302        else if (cause & SRC_SRSR_JTAG_RST)
 303                return "JTAG HIGH-Z";
 304        else if (cause & SRC_SRSR_SW_RST)
 305                return "SW RESET";
 306        else if (cause & SRC_SRSR_RESETB)
 307                return "EXTERNAL RESET";
 308        else
 309                return "unknown reset";
 310}
 311
 312int print_cpuinfo(void)
 313{
 314        printf("CPU: Freescale Vybrid VF%s at %d MHz\n",
 315               soc_type, mxc_get_clock(MXC_ARM_CLK) / 1000000);
 316        printf("Reset cause: %s\n", get_reset_cause());
 317
 318        return 0;
 319}
 320#endif
 321
 322int arch_cpu_init(void)
 323{
 324        struct mscm *mscm = (struct mscm *)MSCM_BASE_ADDR;
 325
 326        soc_type[0] = mscm->cpxcount ? '6' : '5'; /*Dual Core => VF6x0 */
 327        soc_type[1] = mscm->cpxcfg1 ? '1' : '0'; /* L2 Cache => VFx10 */
 328
 329        return 0;
 330}
 331
 332#ifdef CONFIG_ARCH_MISC_INIT
 333int arch_misc_init(void)
 334{
 335        char soc[6];
 336
 337        strcpy(soc, "vf");
 338        strcat(soc, soc_type);
 339        env_set("soc", soc);
 340
 341        return 0;
 342}
 343#endif
 344
 345int cpu_eth_init(struct bd_info *bis)
 346{
 347        int rc = -ENODEV;
 348
 349#if defined(CONFIG_FEC_MXC)
 350        rc = fecmxc_initialize(bis);
 351#endif
 352
 353        return rc;
 354}
 355
 356#ifdef CONFIG_FSL_ESDHC_IMX
 357int cpu_mmc_init(struct bd_info *bis)
 358{
 359        return fsl_esdhc_mmc_init(bis);
 360}
 361#endif
 362
 363int get_clocks(void)
 364{
 365#ifdef CONFIG_FSL_ESDHC_IMX
 366        gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
 367#endif
 368        return 0;
 369}
 370
 371#if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
 372void enable_caches(void)
 373{
 374#if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH)
 375        enum dcache_option option = DCACHE_WRITETHROUGH;
 376#else
 377        enum dcache_option option = DCACHE_WRITEBACK;
 378#endif
 379        dcache_enable();
 380        icache_enable();
 381
 382    /* Enable caching on OCRAM */
 383        mmu_set_region_dcache_behaviour(IRAM_BASE_ADDR, IRAM_SIZE, option);
 384}
 385#endif
 386
 387#ifdef CONFIG_SYS_I2C_MXC
 388/* i2c_num can be from 0 - 3 */
 389int enable_i2c_clk(unsigned char enable, unsigned int i2c_num)
 390{
 391        struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR;
 392
 393        switch (i2c_num) {
 394        case 0:
 395                clrsetbits_le32(&ccm->ccgr4, CCM_CCGR4_I2C0_CTRL_MASK,
 396                                CCM_CCGR4_I2C0_CTRL_MASK);
 397        case 2:
 398                clrsetbits_le32(&ccm->ccgr10, CCM_CCGR10_I2C2_CTRL_MASK,
 399                                CCM_CCGR10_I2C2_CTRL_MASK);
 400                break;
 401        default:
 402                return -EINVAL;
 403        }
 404
 405        return 0;
 406}
 407#endif
 408