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