uboot/arch/mips/mach-mtmips/mt7620/init.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
   4 *
   5 * Author:  Weijie Gao <weijie.gao@mediatek.com>
   6 */
   7
   8#include <config.h>
   9#include <asm/global_data.h>
  10#include <linux/io.h>
  11#include "mt7620.h"
  12
  13DECLARE_GLOBAL_DATA_PTR;
  14
  15static const char * const dram_type[] = {
  16        "SDRAM", "DDR", "DDR2", "SDRAM"
  17};
  18
  19static const char * const boot_mode[(CHIP_MODE_M >> CHIP_MODE_S) + 1] = {
  20        [1] = "NAND 4-cycles 2KB-page",
  21        [2] = "SPI-NOR 3-Byte Addr",
  22        [3] = "SPI-NOR 4-Byte Addr",
  23        [10] = "NAND 4-cycles 512B-page",
  24        [11] = "NAND 5-cycles 2KB-page",
  25        [12] = "NAND 3-cycles 512B-page",
  26};
  27
  28static void cpu_pll_init(void)
  29{
  30        void __iomem *sysc = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE);
  31        u32 pllmul = CONFIG_CPU_FREQ_MULTI;
  32
  33        /* Make sure the pll multiplier is valid */
  34        if (pllmul > 7)
  35                pllmul = 7;
  36
  37        /* Set init CPU clock to 480MHz */
  38        clrsetbits_32(sysc + SYSCTL_CPLL_CFG1_REG, CPU_CLK_AUX1, CPU_CLK_AUX0);
  39
  40        /* Enable software control of CPU PLL */
  41        setbits_32(sysc + SYSCTL_CPLL_CFG0_REG, CPLL_SW_CFG);
  42
  43        /* CPU PLL power down */
  44        setbits_32(sysc + SYSCTL_CPLL_CFG1_REG, CPLL_PD);
  45
  46        /* PLL configuration */
  47        clrsetbits_32(sysc + SYSCTL_CPLL_CFG0_REG, PLL_MULT_RATIO_M |
  48                      PLL_DIV_RATIO_M | SSC_UP_BOUND_M | SSC_EN,
  49                      (pllmul << PLL_MULT_RATIO_S) | SSC_SWING_M);
  50
  51        /* CPU PLL power up */
  52        clrbits_32(sysc + SYSCTL_CPLL_CFG1_REG, CPLL_PD);
  53
  54        /* Wait for CPU PLL locked */
  55        while (!(readl(sysc + SYSCTL_CPLL_CFG1_REG) & CPLL_LD))
  56                ;
  57
  58        /* Set final CPU clock source */
  59        clrbits_32(sysc + SYSCTL_CPLL_CFG1_REG, CPU_CLK_AUX1 | CPU_CLK_AUX0);
  60
  61        /* Adjust CPU clock */
  62        clrsetbits_32(sysc + SYSCTL_CPU_SYS_CLKCFG_REG,
  63                      CPU_FDIV_M | CPU_FFRAC_M,
  64                      (1 << CPU_FDIV_S) | (1 << CPU_FFRAC_S));
  65}
  66
  67void mt7620_init(void)
  68{
  69        u32 cpu_clk;
  70
  71        cpu_pll_init();
  72
  73        /*
  74         * Set timer freq, which will be used during DRAM initialization
  75         * Note that this function is using a temporary gd which will be
  76         * destroyed after leaving this function.
  77         */
  78        mt7620_get_clks(&cpu_clk, NULL, NULL);
  79        gd->arch.timer_freq = cpu_clk / 2;
  80
  81        mt7620_dram_init();
  82}
  83
  84void mt7620_get_clks(u32 *cpu_clk, u32 *sys_clk, u32 *xtal_clk)
  85{
  86        void __iomem *sysc = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE);
  87        u32 val, multi, div, fdiv, ffrac, dram_type, sys_div;
  88        u32 cpu_freq, xtal_freq;
  89
  90        static const u32 div_ratio_table[] = {2, 3, 4, 8};
  91
  92        val = readl(sysc + SYSCTL_SYSCFG0_REG);
  93
  94        dram_type = (val & DRAM_TYPE_M) >> DRAM_TYPE_S;
  95
  96        if (val & XTAL_FREQ_SEL)
  97                xtal_freq = 40000000;
  98        else
  99                xtal_freq = 20000000;
 100
 101        val = readl(sysc + SYSCTL_CPLL_CFG1_REG);
 102        if (val & CPU_CLK_AUX1) {
 103                cpu_freq = xtal_freq;
 104        } else if (val & CPU_CLK_AUX0) {
 105                cpu_freq = 480000000;
 106        } else {
 107                val = readl(sysc + SYSCTL_CPLL_CFG0_REG);
 108                if (val & CPLL_SW_CFG) {
 109                        multi = (val & PLL_MULT_RATIO_M) >> PLL_MULT_RATIO_S;
 110                        div = (val & PLL_DIV_RATIO_M) >> PLL_DIV_RATIO_S;
 111                        cpu_freq = (multi + 24) * 40000000 /
 112                                        div_ratio_table[div];
 113                } else {
 114                        cpu_freq = 600000000;
 115                }
 116        }
 117
 118        val = readl(sysc + SYSCTL_CUR_CLK_STS_REG);
 119        ffrac = (val & CUR_CPU_FFRAC_M) >> CUR_CPU_FFRAC_S;
 120        fdiv = (val & CUR_CPU_FDIV_M) >> CUR_CPU_FDIV_S;
 121        cpu_freq = (cpu_freq * ffrac) / fdiv;
 122
 123        switch (dram_type) {
 124        case DRAM_SDRAM_E1:
 125                sys_div = 4;
 126                break;
 127        case DRAM_DDR1:
 128        case DRAM_DDR2:
 129                sys_div = 3;
 130                break;
 131        case DRAM_SDRAM:
 132                sys_div = 5;
 133                break;
 134        }
 135
 136        if (cpu_clk)
 137                *cpu_clk = cpu_freq;
 138
 139        if (sys_clk)
 140                *sys_clk = cpu_freq / sys_div;
 141
 142        if (xtal_clk)
 143                *xtal_clk = xtal_freq;
 144}
 145
 146int print_cpuinfo(void)
 147{
 148        void __iomem *sysc = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE);
 149        u32 cpu_clk, bus_clk, xtal_clk;
 150        u32 val, ver, eco, pkg, dram, chipmode;
 151        const char *bootdev;
 152
 153        val = readl(sysc + SYSCTL_CHIP_REV_ID_REG);
 154        ver = (val & VER_M) >> VER_S;
 155        eco = (val & ECO_M) >> ECO_S;
 156        pkg = !!(val & PKG_ID);
 157
 158        val = readl(sysc + SYSCTL_SYSCFG0_REG);
 159        dram = (val & DRAM_TYPE_M) >> DRAM_TYPE_S;
 160        chipmode = (val & CHIP_MODE_M) >> CHIP_MODE_S;
 161
 162        bootdev = boot_mode[chipmode];
 163        if (!bootdev)
 164                bootdev = "Unsupported boot mode";
 165
 166        printf("CPU:   MediaTek MT7620%c ver:%u eco:%u\n",
 167               pkg ? 'A' : 'N', ver, eco);
 168
 169        printf("Boot:  %s, %s\n", dram_type[dram], bootdev);
 170
 171        mt7620_get_clks(&cpu_clk, &bus_clk, &xtal_clk);
 172
 173        /* Set final timer frequency */
 174        gd->arch.timer_freq = cpu_clk / 2;
 175
 176        printf("Clock: CPU: %uMHz, Bus: %uMHz, XTAL: %uMHz\n",
 177               cpu_clk / 1000000, bus_clk / 1000000, xtal_clk / 1000000);
 178
 179        return 0;
 180}
 181
 182ulong notrace get_tbclk(void)
 183{
 184        return gd->arch.timer_freq;
 185}
 186
 187void _machine_restart(void)
 188{
 189        void __iomem *sysc = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE);
 190
 191        while (1)
 192                writel(SYS_RST, sysc + SYSCTL_RSTCTL_REG);
 193}
 194