1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * |
4 | * Parts of this file are based on Ralink's 2.6.21 BSP |
5 | * |
6 | * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> |
7 | * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> |
8 | * Copyright (C) 2013 John Crispin <john@phrozen.org> |
9 | */ |
10 | |
11 | #include <linux/kernel.h> |
12 | #include <linux/init.h> |
13 | #include <linux/bug.h> |
14 | #include <linux/slab.h> |
15 | #include <linux/sys_soc.h> |
16 | |
17 | #include <asm/io.h> |
18 | #include <asm/mipsregs.h> |
19 | #include <asm/mach-ralink/ralink_regs.h> |
20 | #include <asm/mach-ralink/rt305x.h> |
21 | |
22 | #include "common.h" |
23 | |
24 | static struct ralink_soc_info *soc_info_ptr; |
25 | |
26 | static unsigned long rt5350_get_mem_size(void) |
27 | { |
28 | unsigned long ret; |
29 | u32 t; |
30 | |
31 | t = __raw_readl(addr: RT305X_SYSC_BASE + SYSC_REG_SYSTEM_CONFIG); |
32 | t = (t >> RT5350_SYSCFG0_DRAM_SIZE_SHIFT) & |
33 | RT5350_SYSCFG0_DRAM_SIZE_MASK; |
34 | |
35 | switch (t) { |
36 | case RT5350_SYSCFG0_DRAM_SIZE_2M: |
37 | ret = 2; |
38 | break; |
39 | case RT5350_SYSCFG0_DRAM_SIZE_8M: |
40 | ret = 8; |
41 | break; |
42 | case RT5350_SYSCFG0_DRAM_SIZE_16M: |
43 | ret = 16; |
44 | break; |
45 | case RT5350_SYSCFG0_DRAM_SIZE_32M: |
46 | ret = 32; |
47 | break; |
48 | case RT5350_SYSCFG0_DRAM_SIZE_64M: |
49 | ret = 64; |
50 | break; |
51 | default: |
52 | panic(fmt: "rt5350: invalid DRAM size: %u" , t); |
53 | break; |
54 | } |
55 | |
56 | return ret; |
57 | } |
58 | |
59 | static unsigned int __init rt305x_get_soc_name0(void) |
60 | { |
61 | return __raw_readl(addr: RT305X_SYSC_BASE + SYSC_REG_CHIP_NAME0); |
62 | } |
63 | |
64 | static unsigned int __init rt305x_get_soc_name1(void) |
65 | { |
66 | return __raw_readl(addr: RT305X_SYSC_BASE + SYSC_REG_CHIP_NAME1); |
67 | } |
68 | |
69 | static bool __init rt3052_soc_valid(void) |
70 | { |
71 | if (rt305x_get_soc_name0() == RT3052_CHIP_NAME0 && |
72 | rt305x_get_soc_name1() == RT3052_CHIP_NAME1) |
73 | return true; |
74 | else |
75 | return false; |
76 | } |
77 | |
78 | static bool __init rt3350_soc_valid(void) |
79 | { |
80 | if (rt305x_get_soc_name0() == RT3350_CHIP_NAME0 && |
81 | rt305x_get_soc_name1() == RT3350_CHIP_NAME1) |
82 | return true; |
83 | else |
84 | return false; |
85 | } |
86 | |
87 | static bool __init rt3352_soc_valid(void) |
88 | { |
89 | if (rt305x_get_soc_name0() == RT3352_CHIP_NAME0 && |
90 | rt305x_get_soc_name1() == RT3352_CHIP_NAME1) |
91 | return true; |
92 | else |
93 | return false; |
94 | } |
95 | |
96 | static bool __init rt5350_soc_valid(void) |
97 | { |
98 | if (rt305x_get_soc_name0() == RT5350_CHIP_NAME0 && |
99 | rt305x_get_soc_name1() == RT5350_CHIP_NAME1) |
100 | return true; |
101 | else |
102 | return false; |
103 | } |
104 | |
105 | static const char __init *rt305x_get_soc_name(struct ralink_soc_info *soc_info) |
106 | { |
107 | if (rt3052_soc_valid()) { |
108 | unsigned long icache_sets; |
109 | |
110 | icache_sets = (read_c0_config1() >> 22) & 7; |
111 | if (icache_sets == 1) { |
112 | ralink_soc = RT305X_SOC_RT3050; |
113 | soc_info->compatible = "ralink,rt3050-soc" ; |
114 | return "RT3050" ; |
115 | } else { |
116 | ralink_soc = RT305X_SOC_RT3052; |
117 | soc_info->compatible = "ralink,rt3052-soc" ; |
118 | return "RT3052" ; |
119 | } |
120 | } else if (rt3350_soc_valid()) { |
121 | ralink_soc = RT305X_SOC_RT3350; |
122 | soc_info->compatible = "ralink,rt3350-soc" ; |
123 | return "RT3350" ; |
124 | } else if (rt3352_soc_valid()) { |
125 | ralink_soc = RT305X_SOC_RT3352; |
126 | soc_info->compatible = "ralink,rt3352-soc" ; |
127 | return "RT3352" ; |
128 | } else if (rt5350_soc_valid()) { |
129 | ralink_soc = RT305X_SOC_RT5350; |
130 | soc_info->compatible = "ralink,rt5350-soc" ; |
131 | return "RT5350" ; |
132 | } else { |
133 | panic(fmt: "rt305x: unknown SoC, n0:%08x n1:%08x" , |
134 | rt305x_get_soc_name0(), rt305x_get_soc_name1()); |
135 | } |
136 | } |
137 | |
138 | static unsigned int __init rt305x_get_soc_id(void) |
139 | { |
140 | return __raw_readl(RT305X_SYSC_BASE + SYSC_REG_CHIP_ID); |
141 | } |
142 | |
143 | static unsigned int __init rt305x_get_soc_ver(void) |
144 | { |
145 | return (rt305x_get_soc_id() >> CHIP_ID_ID_SHIFT) & CHIP_ID_ID_MASK; |
146 | } |
147 | |
148 | static unsigned int __init rt305x_get_soc_rev(void) |
149 | { |
150 | return (rt305x_get_soc_id() & CHIP_ID_REV_MASK); |
151 | } |
152 | |
153 | static const char __init *rt305x_get_soc_id_name(void) |
154 | { |
155 | if (soc_is_rt3050()) |
156 | return "rt3050" ; |
157 | else if (soc_is_rt3052()) |
158 | return "rt3052" ; |
159 | else if (soc_is_rt3350()) |
160 | return "rt3350" ; |
161 | else if (soc_is_rt3352()) |
162 | return "rt3352" ; |
163 | else if (soc_is_rt5350()) |
164 | return "rt5350" ; |
165 | else |
166 | return "invalid" ; |
167 | } |
168 | |
169 | static int __init rt305x_soc_dev_init(void) |
170 | { |
171 | struct soc_device *soc_dev; |
172 | struct soc_device_attribute *soc_dev_attr; |
173 | |
174 | soc_dev_attr = kzalloc(size: sizeof(*soc_dev_attr), GFP_KERNEL); |
175 | if (!soc_dev_attr) |
176 | return -ENOMEM; |
177 | |
178 | soc_dev_attr->family = "Ralink" ; |
179 | soc_dev_attr->soc_id = rt305x_get_soc_id_name(); |
180 | |
181 | soc_dev_attr->data = soc_info_ptr; |
182 | |
183 | soc_dev = soc_device_register(soc_plat_dev_attr: soc_dev_attr); |
184 | if (IS_ERR(ptr: soc_dev)) { |
185 | kfree(objp: soc_dev_attr); |
186 | return PTR_ERR(ptr: soc_dev); |
187 | } |
188 | |
189 | return 0; |
190 | } |
191 | device_initcall(rt305x_soc_dev_init); |
192 | |
193 | void __init prom_soc_init(struct ralink_soc_info *soc_info) |
194 | { |
195 | const char *name = rt305x_get_soc_name(soc_info); |
196 | |
197 | snprintf(buf: soc_info->sys_type, RAMIPS_SYS_TYPE_LEN, |
198 | fmt: "Ralink %s id:%u rev:%u" , |
199 | name, |
200 | rt305x_get_soc_ver(), |
201 | rt305x_get_soc_rev()); |
202 | |
203 | soc_info->mem_base = RT305X_SDRAM_BASE; |
204 | if (soc_is_rt5350()) { |
205 | soc_info->mem_size = rt5350_get_mem_size(); |
206 | } else if (soc_is_rt305x() || soc_is_rt3350()) { |
207 | soc_info->mem_size_min = RT305X_MEM_SIZE_MIN; |
208 | soc_info->mem_size_max = RT305X_MEM_SIZE_MAX; |
209 | } else if (soc_is_rt3352()) { |
210 | soc_info->mem_size_min = RT3352_MEM_SIZE_MIN; |
211 | soc_info->mem_size_max = RT3352_MEM_SIZE_MAX; |
212 | } |
213 | |
214 | soc_info_ptr = soc_info; |
215 | } |
216 | |