uboot/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_speed.c
<<
>>
Prefs
   1/*
   2 * Copyright 2014-2015, Freescale Semiconductor, Inc.
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 *
   6 * Derived from arch/power/cpu/mpc85xx/speed.c
   7 */
   8
   9#include <common.h>
  10#include <linux/compiler.h>
  11#include <fsl_ifc.h>
  12#include <asm/processor.h>
  13#include <asm/io.h>
  14#include <asm/arch-fsl-layerscape/immap_lsch3.h>
  15#include <asm/arch/clock.h>
  16#include <asm/arch/soc.h>
  17#include "cpu.h"
  18
  19DECLARE_GLOBAL_DATA_PTR;
  20
  21#ifndef CONFIG_SYS_FSL_NUM_CC_PLLS
  22#define CONFIG_SYS_FSL_NUM_CC_PLLS      6
  23#endif
  24
  25
  26void get_sys_info(struct sys_info *sys_info)
  27{
  28        struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
  29        struct ccsr_clk_cluster_group __iomem *clk_grp[2] = {
  30                (void *)(CONFIG_SYS_FSL_CH3_CLK_GRPA_ADDR),
  31                (void *)(CONFIG_SYS_FSL_CH3_CLK_GRPB_ADDR)
  32        };
  33        struct ccsr_clk_ctrl __iomem *clk_ctrl =
  34                (void *)(CONFIG_SYS_FSL_CH3_CLK_CTRL_ADDR);
  35        unsigned int cpu;
  36        const u8 core_cplx_pll[16] = {
  37                [0] = 0,        /* CC1 PPL / 1 */
  38                [1] = 0,        /* CC1 PPL / 2 */
  39                [2] = 0,        /* CC1 PPL / 4 */
  40                [4] = 1,        /* CC2 PPL / 1 */
  41                [5] = 1,        /* CC2 PPL / 2 */
  42                [6] = 1,        /* CC2 PPL / 4 */
  43                [8] = 2,        /* CC3 PPL / 1 */
  44                [9] = 2,        /* CC3 PPL / 2 */
  45                [10] = 2,       /* CC3 PPL / 4 */
  46                [12] = 3,       /* CC4 PPL / 1 */
  47                [13] = 3,       /* CC4 PPL / 2 */
  48                [14] = 3,       /* CC4 PPL / 4 */
  49        };
  50
  51        const u8 core_cplx_pll_div[16] = {
  52                [0] = 1,        /* CC1 PPL / 1 */
  53                [1] = 2,        /* CC1 PPL / 2 */
  54                [2] = 4,        /* CC1 PPL / 4 */
  55                [4] = 1,        /* CC2 PPL / 1 */
  56                [5] = 2,        /* CC2 PPL / 2 */
  57                [6] = 4,        /* CC2 PPL / 4 */
  58                [8] = 1,        /* CC3 PPL / 1 */
  59                [9] = 2,        /* CC3 PPL / 2 */
  60                [10] = 4,       /* CC3 PPL / 4 */
  61                [12] = 1,       /* CC4 PPL / 1 */
  62                [13] = 2,       /* CC4 PPL / 2 */
  63                [14] = 4,       /* CC4 PPL / 4 */
  64        };
  65
  66        uint i, cluster;
  67        uint freq_c_pll[CONFIG_SYS_FSL_NUM_CC_PLLS];
  68        uint ratio[CONFIG_SYS_FSL_NUM_CC_PLLS];
  69        unsigned long sysclk = CONFIG_SYS_CLK_FREQ;
  70        int cc_group[12] = CONFIG_SYS_FSL_CLUSTER_CLOCKS;
  71        u32 c_pll_sel, cplx_pll;
  72        void *offset;
  73
  74        sys_info->freq_systembus = sysclk;
  75#ifdef CONFIG_DDR_CLK_FREQ
  76        sys_info->freq_ddrbus = CONFIG_DDR_CLK_FREQ;
  77#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
  78        sys_info->freq_ddrbus2 = CONFIG_DDR_CLK_FREQ;
  79#endif
  80#else
  81        sys_info->freq_ddrbus = sysclk;
  82#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
  83        sys_info->freq_ddrbus2 = sysclk;
  84#endif
  85#endif
  86
  87        /* The freq_systembus is used to record frequency of platform PLL */
  88        sys_info->freq_systembus *= (gur_in32(&gur->rcwsr[0]) >>
  89                        FSL_CHASSIS3_RCWSR0_SYS_PLL_RAT_SHIFT) &
  90                        FSL_CHASSIS3_RCWSR0_SYS_PLL_RAT_MASK;
  91        sys_info->freq_ddrbus *= (gur_in32(&gur->rcwsr[0]) >>
  92                        FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_SHIFT) &
  93                        FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_MASK;
  94#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
  95        if (soc_has_dp_ddr()) {
  96                sys_info->freq_ddrbus2 *= (gur_in32(&gur->rcwsr[0]) >>
  97                        FSL_CHASSIS3_RCWSR0_MEM2_PLL_RAT_SHIFT) &
  98                        FSL_CHASSIS3_RCWSR0_MEM2_PLL_RAT_MASK;
  99        } else {
 100                sys_info->freq_ddrbus2 = 0;
 101        }
 102#endif
 103
 104        for (i = 0; i < CONFIG_SYS_FSL_NUM_CC_PLLS; i++) {
 105                /*
 106                 * fixme: prefer to combine the following into one line, but
 107                 * cannot pass compiling without warning about in_le32.
 108                 */
 109                offset = (void *)((size_t)clk_grp[i/3] +
 110                         offsetof(struct ccsr_clk_cluster_group,
 111                                  pllngsr[i%3].gsr));
 112                ratio[i] = (in_le32(offset) >> 1) & 0x3f;
 113                freq_c_pll[i] = sysclk * ratio[i];
 114        }
 115
 116        for_each_cpu(i, cpu, cpu_numcores(), cpu_mask()) {
 117                cluster = fsl_qoriq_core_to_cluster(cpu);
 118                c_pll_sel = (in_le32(&clk_ctrl->clkcncsr[cluster].csr) >> 27)
 119                            & 0xf;
 120                cplx_pll = core_cplx_pll[c_pll_sel];
 121                cplx_pll += cc_group[cluster] - 1;
 122                sys_info->freq_processor[cpu] =
 123                        freq_c_pll[cplx_pll] / core_cplx_pll_div[c_pll_sel];
 124        }
 125
 126#if defined(CONFIG_FSL_IFC)
 127        sys_info->freq_localbus = sys_info->freq_systembus /
 128                                                CONFIG_SYS_FSL_IFC_CLK_DIV;
 129#endif
 130}
 131
 132
 133int get_clocks(void)
 134{
 135        struct sys_info sys_info;
 136        get_sys_info(&sys_info);
 137        gd->cpu_clk = sys_info.freq_processor[0];
 138        gd->bus_clk = sys_info.freq_systembus / CONFIG_SYS_FSL_PCLK_DIV;
 139        gd->mem_clk = sys_info.freq_ddrbus;
 140#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
 141        gd->arch.mem2_clk = sys_info.freq_ddrbus2;
 142#endif
 143#if defined(CONFIG_FSL_ESDHC)
 144        gd->arch.sdhc_clk = gd->bus_clk / CONFIG_SYS_FSL_SDHC_CLK_DIV;
 145#endif /* defined(CONFIG_FSL_ESDHC) */
 146
 147        if (gd->cpu_clk != 0)
 148                return 0;
 149        else
 150                return 1;
 151}
 152
 153/********************************************
 154 * get_bus_freq
 155 * return platform clock in Hz
 156 *********************************************/
 157ulong get_bus_freq(ulong dummy)
 158{
 159        if (!gd->bus_clk)
 160                get_clocks();
 161
 162        return gd->bus_clk;
 163}
 164
 165/********************************************
 166 * get_ddr_freq
 167 * return ddr bus freq in Hz
 168 *********************************************/
 169ulong get_ddr_freq(ulong ctrl_num)
 170{
 171        if (!gd->mem_clk)
 172                get_clocks();
 173
 174        /*
 175         * DDR controller 0 & 1 are on memory complex 0
 176         * DDR controller 2 is on memory complext 1
 177         */
 178#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
 179        if (ctrl_num >= 2)
 180                return gd->arch.mem2_clk;
 181#endif
 182
 183        return gd->mem_clk;
 184}
 185
 186int get_i2c_freq(ulong dummy)
 187{
 188        return get_bus_freq(0) / CONFIG_SYS_FSL_I2C_CLK_DIV;
 189}
 190
 191int get_dspi_freq(ulong dummy)
 192{
 193        return get_bus_freq(0) / CONFIG_SYS_FSL_DSPI_CLK_DIV;
 194}
 195
 196int get_serial_clock(void)
 197{
 198        return get_bus_freq(0) / CONFIG_SYS_FSL_DUART_CLK_DIV;
 199}
 200
 201unsigned int mxc_get_clock(enum mxc_clock clk)
 202{
 203        switch (clk) {
 204        case MXC_I2C_CLK:
 205                return get_i2c_freq(0);
 206        case MXC_DSPI_CLK:
 207                return get_dspi_freq(0);
 208        default:
 209                printf("Unsupported clock\n");
 210        }
 211        return 0;
 212}
 213