uboot/arch/arm/cpu/armv8/s32v234/generic.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2013-2016, Freescale Semiconductor, Inc.
   4 */
   5
   6#include <common.h>
   7#include <asm/io.h>
   8#include <asm/arch/imx-regs.h>
   9#include <asm/arch/clock.h>
  10#include <asm/arch/mc_cgm_regs.h>
  11#include <asm/arch/mc_me_regs.h>
  12#include <asm/arch/mc_rgm_regs.h>
  13#include <netdev.h>
  14#include <div64.h>
  15#include <errno.h>
  16
  17u32 get_cpu_rev(void)
  18{
  19        struct mscm_ir *mscmir = (struct mscm_ir *)MSCM_BASE_ADDR;
  20        u32 cpu = readl(&mscmir->cpxtype);
  21
  22        return cpu;
  23}
  24
  25DECLARE_GLOBAL_DATA_PTR;
  26
  27static uintptr_t get_pllfreq(u32 pll, u32 refclk_freq, u32 plldv,
  28                             u32 pllfd, u32 selected_output)
  29{
  30        u32 vco = 0, plldv_prediv = 0, plldv_mfd = 0, pllfd_mfn = 0;
  31        u32 plldv_rfdphi_div = 0, fout = 0;
  32        u32 dfs_portn = 0, dfs_mfn = 0, dfs_mfi = 0;
  33
  34        if (selected_output > DFS_MAXNUMBER) {
  35                return -1;
  36        }
  37
  38        plldv_prediv =
  39            (plldv & PLLDIG_PLLDV_PREDIV_MASK) >> PLLDIG_PLLDV_PREDIV_OFFSET;
  40        plldv_mfd = (plldv & PLLDIG_PLLDV_MFD_MASK);
  41
  42        pllfd_mfn = (pllfd & PLLDIG_PLLFD_MFN_MASK);
  43
  44        plldv_prediv = plldv_prediv == 0 ? 1 : plldv_prediv;
  45
  46        /* The formula for VCO is from TR manual, rev. D */
  47        vco = refclk_freq / plldv_prediv * (plldv_mfd + pllfd_mfn / 20481);
  48
  49        if (selected_output != 0) {
  50                /* Determine the RFDPHI for PHI1 */
  51                plldv_rfdphi_div =
  52                    (plldv & PLLDIG_PLLDV_RFDPHI1_MASK) >>
  53                    PLLDIG_PLLDV_RFDPHI1_OFFSET;
  54                plldv_rfdphi_div = plldv_rfdphi_div == 0 ? 1 : plldv_rfdphi_div;
  55                if (pll == ARM_PLL || pll == ENET_PLL || pll == DDR_PLL) {
  56                        dfs_portn =
  57                            readl(DFS_DVPORTn(pll, selected_output - 1));
  58                        dfs_mfi =
  59                            (dfs_portn & DFS_DVPORTn_MFI_MASK) >>
  60                            DFS_DVPORTn_MFI_OFFSET;
  61                        dfs_mfn =
  62                            (dfs_portn & DFS_DVPORTn_MFI_MASK) >>
  63                            DFS_DVPORTn_MFI_OFFSET;
  64                        fout = vco / (dfs_mfi + (dfs_mfn / 256));
  65                } else {
  66                        fout = vco / plldv_rfdphi_div;
  67                }
  68
  69        } else {
  70                /* Determine the RFDPHI for PHI0 */
  71                plldv_rfdphi_div =
  72                    (plldv & PLLDIG_PLLDV_RFDPHI_MASK) >>
  73                    PLLDIG_PLLDV_RFDPHI_OFFSET;
  74                fout = vco / plldv_rfdphi_div;
  75        }
  76
  77        return fout;
  78
  79}
  80
  81/* Implemented for ARMPLL, PERIPH_PLL, ENET_PLL, DDR_PLL, VIDEO_LL */
  82static uintptr_t decode_pll(enum pll_type pll, u32 refclk_freq,
  83                            u32 selected_output)
  84{
  85        u32 plldv, pllfd;
  86
  87        plldv = readl(PLLDIG_PLLDV(pll));
  88        pllfd = readl(PLLDIG_PLLFD(pll));
  89
  90        return get_pllfreq(pll, refclk_freq, plldv, pllfd, selected_output);
  91}
  92
  93static u32 get_mcu_main_clk(void)
  94{
  95        u32 coreclk_div;
  96        u32 sysclk_sel;
  97        u32 freq = 0;
  98
  99        sysclk_sel = readl(CGM_SC_SS(MC_CGM1_BASE_ADDR)) & MC_CGM_SC_SEL_MASK;
 100        sysclk_sel >>= MC_CGM_SC_SEL_OFFSET;
 101
 102        coreclk_div =
 103            readl(CGM_SC_DCn(MC_CGM1_BASE_ADDR, 0)) & MC_CGM_SC_DCn_PREDIV_MASK;
 104        coreclk_div >>= MC_CGM_SC_DCn_PREDIV_OFFSET;
 105        coreclk_div += 1;
 106
 107        switch (sysclk_sel) {
 108        case MC_CGM_SC_SEL_FIRC:
 109                freq = FIRC_CLK_FREQ;
 110                break;
 111        case MC_CGM_SC_SEL_XOSC:
 112                freq = XOSC_CLK_FREQ;
 113                break;
 114        case MC_CGM_SC_SEL_ARMPLL:
 115                /* ARMPLL has as source XOSC and CORE_CLK has as input PHI0 */
 116                freq = decode_pll(ARM_PLL, XOSC_CLK_FREQ, 0);
 117                break;
 118        case MC_CGM_SC_SEL_CLKDISABLE:
 119                printf("Sysclk is disabled\n");
 120                break;
 121        default:
 122                printf("unsupported system clock select\n");
 123        }
 124
 125        return freq / coreclk_div;
 126}
 127
 128static u32 get_sys_clk(u32 number)
 129{
 130        u32 sysclk_div, sysclk_div_number;
 131        u32 sysclk_sel;
 132        u32 freq = 0;
 133
 134        switch (number) {
 135        case 3:
 136                sysclk_div_number = 0;
 137                break;
 138        case 6:
 139                sysclk_div_number = 1;
 140                break;
 141        default:
 142                printf("unsupported system clock \n");
 143                return -1;
 144        }
 145        sysclk_sel = readl(CGM_SC_SS(MC_CGM0_BASE_ADDR)) & MC_CGM_SC_SEL_MASK;
 146        sysclk_sel >>= MC_CGM_SC_SEL_OFFSET;
 147
 148        sysclk_div =
 149            readl(CGM_SC_DCn(MC_CGM1_BASE_ADDR, sysclk_div_number)) &
 150            MC_CGM_SC_DCn_PREDIV_MASK;
 151        sysclk_div >>= MC_CGM_SC_DCn_PREDIV_OFFSET;
 152        sysclk_div += 1;
 153
 154        switch (sysclk_sel) {
 155        case MC_CGM_SC_SEL_FIRC:
 156                freq = FIRC_CLK_FREQ;
 157                break;
 158        case MC_CGM_SC_SEL_XOSC:
 159                freq = XOSC_CLK_FREQ;
 160                break;
 161        case MC_CGM_SC_SEL_ARMPLL:
 162                /* ARMPLL has as source XOSC and SYSn_CLK has as input DFS1 */
 163                freq = decode_pll(ARM_PLL, XOSC_CLK_FREQ, 1);
 164                break;
 165        case MC_CGM_SC_SEL_CLKDISABLE:
 166                printf("Sysclk is disabled\n");
 167                break;
 168        default:
 169                printf("unsupported system clock select\n");
 170        }
 171
 172        return freq / sysclk_div;
 173}
 174
 175static u32 get_peripherals_clk(void)
 176{
 177        u32 aux5clk_div;
 178        u32 freq = 0;
 179
 180        aux5clk_div =
 181            readl(CGM_ACn_DCm(MC_CGM0_BASE_ADDR, 5, 0)) &
 182            MC_CGM_ACn_DCm_PREDIV_MASK;
 183        aux5clk_div >>= MC_CGM_ACn_DCm_PREDIV_OFFSET;
 184        aux5clk_div += 1;
 185
 186        freq = decode_pll(PERIPH_PLL, XOSC_CLK_FREQ, 0);
 187
 188        return freq / aux5clk_div;
 189
 190}
 191
 192static u32 get_uart_clk(void)
 193{
 194        u32 auxclk3_div, auxclk3_sel, freq = 0;
 195
 196        auxclk3_sel =
 197            readl(CGM_ACn_SS(MC_CGM0_BASE_ADDR, 3)) & MC_CGM_ACn_SEL_MASK;
 198        auxclk3_sel >>= MC_CGM_ACn_SEL_OFFSET;
 199
 200        auxclk3_div =
 201            readl(CGM_ACn_DCm(MC_CGM0_BASE_ADDR, 3, 0)) &
 202            MC_CGM_ACn_DCm_PREDIV_MASK;
 203        auxclk3_div >>= MC_CGM_ACn_DCm_PREDIV_OFFSET;
 204        auxclk3_div += 1;
 205
 206        switch (auxclk3_sel) {
 207        case MC_CGM_ACn_SEL_FIRC:
 208                freq = FIRC_CLK_FREQ;
 209                break;
 210        case MC_CGM_ACn_SEL_XOSC:
 211                freq = XOSC_CLK_FREQ;
 212                break;
 213        case MC_CGM_ACn_SEL_PERPLLDIVX:
 214                freq = get_peripherals_clk() / 3;
 215                break;
 216        case MC_CGM_ACn_SEL_SYSCLK:
 217                freq = get_sys_clk(6);
 218                break;
 219        default:
 220                printf("unsupported system clock select\n");
 221        }
 222
 223        return freq / auxclk3_div;
 224}
 225
 226static u32 get_fec_clk(void)
 227{
 228        u32 aux2clk_div;
 229        u32 freq = 0;
 230
 231        aux2clk_div =
 232            readl(CGM_ACn_DCm(MC_CGM0_BASE_ADDR, 2, 0)) &
 233            MC_CGM_ACn_DCm_PREDIV_MASK;
 234        aux2clk_div >>= MC_CGM_ACn_DCm_PREDIV_OFFSET;
 235        aux2clk_div += 1;
 236
 237        freq = decode_pll(ENET_PLL, XOSC_CLK_FREQ, 0);
 238
 239        return freq / aux2clk_div;
 240}
 241
 242static u32 get_usdhc_clk(void)
 243{
 244        u32 aux15clk_div;
 245        u32 freq = 0;
 246
 247        aux15clk_div =
 248            readl(CGM_ACn_DCm(MC_CGM0_BASE_ADDR, 15, 0)) &
 249            MC_CGM_ACn_DCm_PREDIV_MASK;
 250        aux15clk_div >>= MC_CGM_ACn_DCm_PREDIV_OFFSET;
 251        aux15clk_div += 1;
 252
 253        freq = decode_pll(ENET_PLL, XOSC_CLK_FREQ, 4);
 254
 255        return freq / aux15clk_div;
 256}
 257
 258static u32 get_i2c_clk(void)
 259{
 260        return get_peripherals_clk();
 261}
 262
 263/* return clocks in Hz */
 264unsigned int mxc_get_clock(enum mxc_clock clk)
 265{
 266        switch (clk) {
 267        case MXC_ARM_CLK:
 268                return get_mcu_main_clk();
 269        case MXC_PERIPHERALS_CLK:
 270                return get_peripherals_clk();
 271        case MXC_UART_CLK:
 272                return get_uart_clk();
 273        case MXC_FEC_CLK:
 274                return get_fec_clk();
 275        case MXC_I2C_CLK:
 276                return get_i2c_clk();
 277        case MXC_USDHC_CLK:
 278                return get_usdhc_clk();
 279        default:
 280                break;
 281        }
 282        printf("Error: Unsupported function to read the frequency! \
 283                        Please define it correctly!");
 284        return -1;
 285}
 286
 287/* Not yet implemented - int soc_clk_dump(); */
 288
 289#if defined(CONFIG_DISPLAY_CPUINFO)
 290static char *get_reset_cause(void)
 291{
 292        u32 cause = readl(MC_RGM_BASE_ADDR + 0x300);
 293
 294        switch (cause) {
 295        case F_SWT4:
 296                return "WDOG";
 297        case F_JTAG:
 298                return "JTAG";
 299        case F_FCCU_SOFT:
 300                return "FCCU soft reaction";
 301        case F_FCCU_HARD:
 302                return "FCCU hard reaction";
 303        case F_SOFT_FUNC:
 304                return "Software Functional reset";
 305        case F_ST_DONE:
 306                return "Self Test done reset";
 307        case F_EXT_RST:
 308                return "External reset";
 309        default:
 310                return "unknown reset";
 311        }
 312
 313}
 314
 315#define SRC_SCR_SW_RST                                  (1<<12)
 316
 317void reset_cpu(ulong addr)
 318{
 319        printf("Feature not supported.\n");
 320};
 321
 322int print_cpuinfo(void)
 323{
 324        printf("CPU:   Freescale Treerunner S32V234 at %d MHz\n",
 325               mxc_get_clock(MXC_ARM_CLK) / 1000000);
 326        printf("Reset cause: %s\n", get_reset_cause());
 327
 328        return 0;
 329}
 330#endif
 331
 332int cpu_eth_init(bd_t * bis)
 333{
 334        int rc = -ENODEV;
 335
 336#if defined(CONFIG_FEC_MXC)
 337        rc = fecmxc_initialize(bis);
 338#endif
 339
 340        return rc;
 341}
 342
 343int get_clocks(void)
 344{
 345#ifdef CONFIG_FSL_ESDHC_IMX
 346        gd->arch.sdhc_clk = mxc_get_clock(MXC_USDHC_CLK);
 347#endif
 348        return 0;
 349}
 350