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
13 DECLARE_GLOBAL_DATA_PTR;
14
15 static const char * const dram_type[] = {
16 "SDRAM", "DDR", "DDR2", "SDRAM"
17 };
18
19 static 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
cpu_pll_init(void)28 static 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
mt7620_init(void)67 void 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
mt7620_get_clks(u32 * cpu_clk,u32 * sys_clk,u32 * xtal_clk)84 void 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
print_cpuinfo(void)146 int 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
get_tbclk(void)182 ulong notrace get_tbclk(void)
183 {
184 return gd->arch.timer_freq;
185 }
186
_machine_restart(void)187 void _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