Commit | Line | Data |
---|---|---|
d4a67d9d GJ |
1 | /* |
2 | * Atheros AR71XX/AR724X/AR913X specific setup | |
3 | * | |
d8411466 | 4 | * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com> |
d4a67d9d GJ |
5 | * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> |
6 | * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> | |
7 | * | |
d8411466 | 8 | * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP |
d4a67d9d GJ |
9 | * |
10 | * This program is free software; you can redistribute it and/or modify it | |
11 | * under the terms of the GNU General Public License version 2 as published | |
12 | * by the Free Software Foundation. | |
13 | */ | |
14 | ||
15 | #include <linux/kernel.h> | |
16 | #include <linux/init.h> | |
17 | #include <linux/bootmem.h> | |
18 | #include <linux/err.h> | |
19 | #include <linux/clk.h> | |
03c8c407 AB |
20 | #include <linux/of_platform.h> |
21 | #include <linux/of_fdt.h> | |
d4a67d9d GJ |
22 | |
23 | #include <asm/bootinfo.h> | |
bdc92d74 | 24 | #include <asm/idle.h> |
d4a67d9d GJ |
25 | #include <asm/time.h> /* for mips_hpt_frequency */ |
26 | #include <asm/reboot.h> /* for _machine_{restart,halt} */ | |
0aabf1a4 | 27 | #include <asm/mips_machine.h> |
03c8c407 AB |
28 | #include <asm/prom.h> |
29 | #include <asm/fw/fw.h> | |
d4a67d9d GJ |
30 | |
31 | #include <asm/mach-ath79/ath79.h> | |
32 | #include <asm/mach-ath79/ar71xx_regs.h> | |
33 | #include "common.h" | |
34 | #include "dev-common.h" | |
0aabf1a4 | 35 | #include "machtypes.h" |
d4a67d9d GJ |
36 | |
37 | #define ATH79_SYS_TYPE_LEN 64 | |
38 | ||
39 | #define AR71XX_BASE_FREQ 40000000 | |
40 | #define AR724X_BASE_FREQ 5000000 | |
41 | #define AR913X_BASE_FREQ 5000000 | |
42 | ||
43 | static char ath79_sys_type[ATH79_SYS_TYPE_LEN]; | |
44 | ||
45 | static void ath79_restart(char *command) | |
46 | { | |
47 | ath79_device_reset_set(AR71XX_RESET_FULL_CHIP); | |
48 | for (;;) | |
49 | if (cpu_wait) | |
50 | cpu_wait(); | |
51 | } | |
52 | ||
53 | static void ath79_halt(void) | |
54 | { | |
55 | while (1) | |
56 | cpu_wait(); | |
57 | } | |
58 | ||
d4a67d9d GJ |
59 | static void __init ath79_detect_sys_type(void) |
60 | { | |
61 | char *chip = "????"; | |
62 | u32 id; | |
63 | u32 major; | |
64 | u32 minor; | |
65 | u32 rev = 0; | |
66 | ||
67 | id = ath79_reset_rr(AR71XX_RESET_REG_REV_ID); | |
68 | major = id & REV_ID_MAJOR_MASK; | |
69 | ||
70 | switch (major) { | |
71 | case REV_ID_MAJOR_AR71XX: | |
72 | minor = id & AR71XX_REV_ID_MINOR_MASK; | |
73 | rev = id >> AR71XX_REV_ID_REVISION_SHIFT; | |
74 | rev &= AR71XX_REV_ID_REVISION_MASK; | |
75 | switch (minor) { | |
76 | case AR71XX_REV_ID_MINOR_AR7130: | |
77 | ath79_soc = ATH79_SOC_AR7130; | |
78 | chip = "7130"; | |
79 | break; | |
80 | ||
81 | case AR71XX_REV_ID_MINOR_AR7141: | |
82 | ath79_soc = ATH79_SOC_AR7141; | |
83 | chip = "7141"; | |
84 | break; | |
85 | ||
86 | case AR71XX_REV_ID_MINOR_AR7161: | |
87 | ath79_soc = ATH79_SOC_AR7161; | |
88 | chip = "7161"; | |
89 | break; | |
90 | } | |
91 | break; | |
92 | ||
93 | case REV_ID_MAJOR_AR7240: | |
94 | ath79_soc = ATH79_SOC_AR7240; | |
95 | chip = "7240"; | |
8bed1288 | 96 | rev = id & AR724X_REV_ID_REVISION_MASK; |
d4a67d9d GJ |
97 | break; |
98 | ||
99 | case REV_ID_MAJOR_AR7241: | |
100 | ath79_soc = ATH79_SOC_AR7241; | |
101 | chip = "7241"; | |
8bed1288 | 102 | rev = id & AR724X_REV_ID_REVISION_MASK; |
d4a67d9d GJ |
103 | break; |
104 | ||
105 | case REV_ID_MAJOR_AR7242: | |
106 | ath79_soc = ATH79_SOC_AR7242; | |
107 | chip = "7242"; | |
8bed1288 | 108 | rev = id & AR724X_REV_ID_REVISION_MASK; |
d4a67d9d GJ |
109 | break; |
110 | ||
111 | case REV_ID_MAJOR_AR913X: | |
112 | minor = id & AR913X_REV_ID_MINOR_MASK; | |
113 | rev = id >> AR913X_REV_ID_REVISION_SHIFT; | |
114 | rev &= AR913X_REV_ID_REVISION_MASK; | |
115 | switch (minor) { | |
116 | case AR913X_REV_ID_MINOR_AR9130: | |
117 | ath79_soc = ATH79_SOC_AR9130; | |
118 | chip = "9130"; | |
119 | break; | |
120 | ||
121 | case AR913X_REV_ID_MINOR_AR9132: | |
122 | ath79_soc = ATH79_SOC_AR9132; | |
123 | chip = "9132"; | |
124 | break; | |
125 | } | |
126 | break; | |
127 | ||
80a7ed81 GJ |
128 | case REV_ID_MAJOR_AR9330: |
129 | ath79_soc = ATH79_SOC_AR9330; | |
130 | chip = "9330"; | |
131 | rev = id & AR933X_REV_ID_REVISION_MASK; | |
132 | break; | |
133 | ||
134 | case REV_ID_MAJOR_AR9331: | |
135 | ath79_soc = ATH79_SOC_AR9331; | |
136 | chip = "9331"; | |
137 | rev = id & AR933X_REV_ID_REVISION_MASK; | |
138 | break; | |
139 | ||
d8411466 GJ |
140 | case REV_ID_MAJOR_AR9341: |
141 | ath79_soc = ATH79_SOC_AR9341; | |
142 | chip = "9341"; | |
143 | rev = id & AR934X_REV_ID_REVISION_MASK; | |
144 | break; | |
145 | ||
146 | case REV_ID_MAJOR_AR9342: | |
147 | ath79_soc = ATH79_SOC_AR9342; | |
148 | chip = "9342"; | |
149 | rev = id & AR934X_REV_ID_REVISION_MASK; | |
150 | break; | |
151 | ||
152 | case REV_ID_MAJOR_AR9344: | |
153 | ath79_soc = ATH79_SOC_AR9344; | |
154 | chip = "9344"; | |
155 | rev = id & AR934X_REV_ID_REVISION_MASK; | |
156 | break; | |
157 | ||
2e6c91e3 GJ |
158 | case REV_ID_MAJOR_QCA9556: |
159 | ath79_soc = ATH79_SOC_QCA9556; | |
160 | chip = "9556"; | |
161 | rev = id & QCA955X_REV_ID_REVISION_MASK; | |
162 | break; | |
163 | ||
164 | case REV_ID_MAJOR_QCA9558: | |
165 | ath79_soc = ATH79_SOC_QCA9558; | |
166 | chip = "9558"; | |
167 | rev = id & QCA955X_REV_ID_REVISION_MASK; | |
168 | break; | |
169 | ||
d4a67d9d | 170 | default: |
ab75dc02 | 171 | panic("ath79: unknown SoC, id:0x%08x", id); |
d4a67d9d GJ |
172 | } |
173 | ||
be5f3623 GJ |
174 | ath79_soc_rev = rev; |
175 | ||
2e6c91e3 GJ |
176 | if (soc_is_qca955x()) |
177 | sprintf(ath79_sys_type, "Qualcomm Atheros QCA%s rev %u", | |
178 | chip, rev); | |
179 | else | |
180 | sprintf(ath79_sys_type, "Atheros AR%s rev %u", chip, rev); | |
d4a67d9d GJ |
181 | pr_info("SoC: %s\n", ath79_sys_type); |
182 | } | |
183 | ||
184 | const char *get_system_type(void) | |
185 | { | |
186 | return ath79_sys_type; | |
187 | } | |
188 | ||
a669efc4 AB |
189 | int get_c0_perfcount_int(void) |
190 | { | |
191 | return ATH79_MISC_IRQ(5); | |
192 | } | |
0cb0985f | 193 | EXPORT_SYMBOL_GPL(get_c0_perfcount_int); |
a669efc4 | 194 | |
078a55fc | 195 | unsigned int get_c0_compare_int(void) |
d4a67d9d GJ |
196 | { |
197 | return CP0_LEGACY_COMPARE_IRQ; | |
198 | } | |
199 | ||
200 | void __init plat_mem_setup(void) | |
201 | { | |
03c8c407 AB |
202 | unsigned long fdt_start; |
203 | ||
d4a67d9d GJ |
204 | set_io_port_base(KSEG1); |
205 | ||
03c8c407 AB |
206 | /* Get the position of the FDT passed by the bootloader */ |
207 | fdt_start = fw_getenvl("fdt_start"); | |
208 | if (fdt_start) | |
209 | __dt_setup_arch((void *)KSEG0ADDR(fdt_start)); | |
210 | #ifdef CONFIG_BUILTIN_DTB | |
211 | else | |
212 | __dt_setup_arch(__dtb_start); | |
213 | #endif | |
214 | ||
d4a67d9d GJ |
215 | ath79_reset_base = ioremap_nocache(AR71XX_RESET_BASE, |
216 | AR71XX_RESET_SIZE); | |
217 | ath79_pll_base = ioremap_nocache(AR71XX_PLL_BASE, | |
218 | AR71XX_PLL_SIZE); | |
24b0e3e8 | 219 | ath79_ddr_ctrl_init(); |
d4a67d9d GJ |
220 | |
221 | ath79_detect_sys_type(); | |
03c8c407 AB |
222 | if (mips_machtype != ATH79_MACH_GENERIC_OF) |
223 | detect_memory_region(0, ATH79_MEM_SIZE_MIN, ATH79_MEM_SIZE_MAX); | |
d4a67d9d GJ |
224 | |
225 | _machine_restart = ath79_restart; | |
226 | _machine_halt = ath79_halt; | |
227 | pm_power_off = ath79_halt; | |
228 | } | |
229 | ||
230 | void __init plat_time_init(void) | |
231 | { | |
23107802 | 232 | unsigned long cpu_clk_rate; |
59a8c10b GJ |
233 | unsigned long ahb_clk_rate; |
234 | unsigned long ddr_clk_rate; | |
235 | unsigned long ref_clk_rate; | |
d4a67d9d | 236 | |
2c4f1ac5 GJ |
237 | ath79_clocks_init(); |
238 | ||
23107802 | 239 | cpu_clk_rate = ath79_get_sys_clk_rate("cpu"); |
59a8c10b GJ |
240 | ahb_clk_rate = ath79_get_sys_clk_rate("ahb"); |
241 | ddr_clk_rate = ath79_get_sys_clk_rate("ddr"); | |
242 | ref_clk_rate = ath79_get_sys_clk_rate("ref"); | |
243 | ||
a26484bb | 244 | pr_info("Clocks: CPU:%lu.%03luMHz, DDR:%lu.%03luMHz, AHB:%lu.%03luMHz, Ref:%lu.%03luMHz\n", |
59a8c10b GJ |
245 | cpu_clk_rate / 1000000, (cpu_clk_rate / 1000) % 1000, |
246 | ddr_clk_rate / 1000000, (ddr_clk_rate / 1000) % 1000, | |
247 | ahb_clk_rate / 1000000, (ahb_clk_rate / 1000) % 1000, | |
248 | ref_clk_rate / 1000000, (ref_clk_rate / 1000) % 1000); | |
d4a67d9d | 249 | |
23107802 | 250 | mips_hpt_frequency = cpu_clk_rate / 2; |
d4a67d9d GJ |
251 | } |
252 | ||
253 | static int __init ath79_setup(void) | |
254 | { | |
03c8c407 AB |
255 | of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); |
256 | if (mips_machtype == ATH79_MACH_GENERIC_OF) | |
257 | return 0; | |
258 | ||
6eae43c5 | 259 | ath79_gpio_init(); |
d4a67d9d | 260 | ath79_register_uart(); |
858f763c | 261 | ath79_register_wdt(); |
0aabf1a4 GJ |
262 | |
263 | mips_machine_setup(); | |
264 | ||
d4a67d9d GJ |
265 | return 0; |
266 | } | |
267 | ||
268 | arch_initcall(ath79_setup); | |
0aabf1a4 | 269 | |
03c8c407 AB |
270 | void __init device_tree_init(void) |
271 | { | |
272 | unflatten_and_copy_device_tree(); | |
273 | } | |
274 | ||
0aabf1a4 GJ |
275 | static void __init ath79_generic_init(void) |
276 | { | |
277 | /* Nothing to do */ | |
278 | } | |
279 | ||
280 | MIPS_MACHINE(ATH79_MACH_GENERIC, | |
281 | "Generic", | |
282 | "Generic AR71XX/AR724X/AR913X based board", | |
283 | ath79_generic_init); |