blob: 1a60c272cad07e20f4bfbaa947e4f05850164bde [file] [log] [blame]
xjb04a4022021-11-25 15:01:52 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2019 MediaTek Inc.
4 */
5
6#include <linux/init.h>
7#include <linux/module.h>
8#include <linux/moduleparam.h>
9#include <linux/hrtimer.h>
10#include <linux/cpu.h>
11#include <linux/mm.h>
12#include <linux/slab.h>
13#include <linux/profile.h>
14#include <linux/dcache.h>
15#include <linux/types.h>
16#include <linux/dcookies.h>
17#include <linux/sched.h>
18#include <linux/fs.h>
19/* #include <mt-plat/mtk_chip.h> */
20
21#include <asm/irq_regs.h>
22
23#include "met_struct.h"
24#include "met_drv.h"
25#include "met_kernel_symbol.h"
26#include "interface.h"
27#include <linux/of.h>
28
29#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
30#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
31#if defined(SSPM_VERSION_V2)
32#include "sspm_ipi_id.h" /* for sspm_ipidev */
33#endif
34#endif
35#endif
36
37extern struct device_node *of_root;
38static const char *platform_name;
39
40struct cpu_type_name {
41 char full_name[32];
42 char abbr_name[8];
43};
44
45static struct cpu_type_name met_known_cpu_type[] = {
46 {"arm,cortex-a53", "CA53"},
47 {"arm,cortex-a55", "CA55"},
48 {"arm,cortex-a72", "CA72"},
49 {"arm,cortex-a73", "CA73"},
50 {"arm,cortex-a75", "CA75"},
51 {"arm,cortex-a76", "CA76"},
52};
53#define MET_KNOWN_CPU_TYPE_COUNT \
54 (sizeof(met_known_cpu_type)/sizeof(struct cpu_type_name))
55
56static char met_cpu_topology[64];
57
58struct met_register_tbl *met_register_api_symbol;
59EXPORT_SYMBOL(met_register_api_symbol);
60struct met_export_tbl *met_export_api_symbol;
61EXPORT_SYMBOL(met_export_api_symbol);
62
63#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
64#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
65#if defined(SSPM_VERSION_V2)
66struct mtk_ipi_device *sspm_ipidev_symbol = NULL;
67#endif
68#endif
69#endif
70
71unsigned int (*mt_get_chip_id_symbol)(void);
72
73static int met_minor = -1;
74module_param(met_minor, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
75
76
77#ifdef MTK_PLATFORM
78#define _SHOW_MTK_PLATFORM(X) #X
79#define SHOW_MTK_PLATFORM(X) _SHOW_MTK_PLATFORM(X)
80#endif
81
82static int is_platform_name_valid(const char * buf)
83{
84 int len = strlen(buf);
85 int i;
86
87 for (i=0; i<len; i++) {
88 if ((buf[i] == 'm' && buf[i+1] == 't')
89 || (buf[i] == 'M' && buf[i+1] == 'T')
90 || (buf[i] == 'M' && buf[i+1] == 't')
91 || (buf[i] == 'm' && buf[i+1] == 'T')) {
92 return i;
93 }
94 }
95 return -1;
96}
97
98#if 0
99const char *met_get_platform_name(void)
100{
101 const char default_platform_name[7] = "mtxxxx";
102 int found = -1;
103
104 found = is_platform_name_valid(platform_name);
105
106 if(found < 0){
107#ifdef MTK_PLATFORM
108 const char buf[7] = SHOW_MTK_PLATFORM(MTK_PLATFORM);
109 found = is_platform_name_valid(buf);
110 if ( !(found < 0) )
111 platform_name = buf;
112 else
113#endif
114 platform_name = default_platform_name;
115 }
116
117 strncpy(&buf_tmp[2], &platform_name[found+2], 4);
118 return platform_name;
119}
120EXPORT_SYMBOL(met_get_platform_name);
121#endif
122
123static void get_cpu_type_name(const char *compatible, char *cpu_type)
124{
125 int i;
126
127 for (i = 0; i < MET_KNOWN_CPU_TYPE_COUNT; i++) {
128 if (!strncmp(compatible, met_known_cpu_type[i].full_name,
129 strlen(met_known_cpu_type[i].full_name)))
130 strncpy(cpu_type, met_known_cpu_type[i].abbr_name,
131 strlen(met_known_cpu_type[i].abbr_name) + 1);
132 }
133}
134
135static void met_set_cpu_topology(int core_id, int cluster_core_num)
136{
137 int i, buf_len = strlen(met_cpu_topology);
138 struct device_node *node = NULL;
139 const char *prev_cptb = NULL;
140 const char *cptb;
141 char cpu_type[16];
142
143 for (i = 0; i < cluster_core_num; i++) {
144 node = of_get_cpu_node(core_id + i, NULL);
145 if (node) {
146 cptb = of_get_property(node, "compatible", NULL);
147 if (cptb) {
148 get_cpu_type_name(cptb, cpu_type);
149 if (prev_cptb == NULL)
150 /* first write: write core_type & core_number */
151 buf_len += snprintf(met_cpu_topology + buf_len,
152 sizeof(met_cpu_topology) - buf_len,
153 "%s:%d", cpu_type, core_id + i);
154 else if (!strncmp(prev_cptb, cptb, strlen(prev_cptb)))
155 /* cpu type is the same with before */
156 /* write core_number */
157 buf_len += snprintf(met_cpu_topology + buf_len,
158 sizeof(met_cpu_topology) - buf_len,
159 ",%d", core_id + i);
160 else
161 /* cpu type is different with before */
162 /* write core_type & core_number */
163 buf_len += snprintf(met_cpu_topology + buf_len,
164 sizeof(met_cpu_topology) - buf_len,
165 "|%s:%d", cpu_type, core_id + i);
166
167 prev_cptb = cptb;
168 }
169 }
170 }
171}
172
173static int met_create_cpu_topology(void)
174{
175 int i, j, len;
176 struct device_node *node = NULL, *core_node = NULL;
177 int start_core_id = 0;
178 int cluster_num = 0, cluster_core_num = 0;
179 char cluster_name[16], core_name[16];
180
181 node = of_find_node_by_name(NULL, "cpu-map");
182 if (!node)
183 node = of_find_node_by_name(NULL, "virtual-cpu-map");
184
185 if (node) {
186 cluster_num = of_get_child_count(node);
187 of_node_put(node);
188
189 for (i = 0; i < cluster_num; i++) {
190 snprintf(cluster_name, sizeof(cluster_name), "cluster%d", i);
191 node = of_find_node_by_name(NULL, cluster_name);
192 if (node) {
193
194 j = 0;
195 cluster_core_num = 0;
196 do {
197 snprintf(core_name, sizeof(core_name), "core%d", j);
198 core_node = of_get_child_by_name(node, core_name);
199 if (core_node) {
200 cluster_core_num++;
201 of_node_put(core_node);
202 }
203 j++;
204 } while (core_node);
205 of_node_put(node);
206
207 /* "|" use to separate different cluster */
208 if (i > 0) {
209 len = strlen(met_cpu_topology);
210 snprintf(met_cpu_topology + len, sizeof(met_cpu_topology) - len, "|");
211 }
212
213 met_set_cpu_topology(start_core_id, cluster_core_num);
214 start_core_id = cluster_core_num;
215 }
216 }
217 }
218
219 return strlen(met_cpu_topology);
220}
221
222static int met_kernel_symbol_get(void)
223{
224 int ret = 0;
225
226 ret += _MET_SYMBOL_GET(met_register_api);
227 ret += _MET_SYMBOL_GET(met_export_api);
228
229#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
230#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
231#if defined(SSPM_VERSION_V2)
232 ret += _MET_SYMBOL_GET(sspm_ipidev);
233#endif
234#endif
235#endif
236 return ret;
237}
238
239static void met_kernel_symbol_put(void)
240{
241 _MET_SYMBOL_PUT(met_register_api);
242 _MET_SYMBOL_PUT(met_export_api);
243
244#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
245#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
246#ifdef SSPM_VERSION_V2
247 _MET_SYMBOL_PUT(sspm_ipidev);
248#endif
249#endif
250#endif
251}
252
253DEFINE_PER_CPU(struct met_cpu_struct, met_cpu);
254
255static int __init met_drv_init(void)
256{
257 int cpu;
258 int ret;
259 int cpu_topology_len;
260 struct met_cpu_struct *met_cpu_ptr;
261 unsigned int chip_id;
262
263 for_each_possible_cpu(cpu) {
264 met_cpu_ptr = &per_cpu(met_cpu, cpu);
265 /* snprintf(&(met_cpu_ptr->name[0]), sizeof(met_cpu_ptr->name), "met%02d", cpu); */
266 met_cpu_ptr->cpu = cpu;
267 }
268
269 ret = met_kernel_symbol_get();
270 if (ret) {
271 pr_notice("[MET] met_kernel_symbol_get fail, ret = %d\n", ret);
272 return ret;
273 }
274
275 ret = fs_reg(met_minor);
276 if (ret) {
277 pr_notice("[MET] met fs_reg fail, ret = %d\n", ret);
278 return ret;
279 }
280
281 if (of_root){
282 /*
283 mt6765.dts
284 model = "MT6765";
285 compatible = "mediatek,MT6765";
286 interrupt-parent = <&sysirq>;
287 */
288 if (of_root->properties) {
289 of_property_read_string(of_root, "compatible", &platform_name);
290 PR_BOOTMSG("dts property compatible=%s\n", platform_name);
291 }
292 }
293 if (platform_name) {
294 char buf[7];
295 int found = -1;
296
297 found = is_platform_name_valid(platform_name);
298
299 if ( !(found < 0) ) {
300 memset(buf, 0x0, 7);
301 buf[0] = 'm';
302 buf[1] = 't';
303 strncpy(&buf[2], &platform_name[found+2], 4);
304 met_set_platform(buf, 1);
305 PR_BOOTMSG("Get platform info from dts, platform_name=%s\n", buf);
306 } else {
307#ifdef MTK_PLATFORM
308 memset(buf, 0x0, 7);
309 strcpy(buf, SHOW_MTK_PLATFORM(MTK_PLATFORM));
310 found = is_platform_name_valid((const char *)buf);
311 if( !(found < 0) ){
312 PR_BOOTMSG("Get platform info from met_drv Kbuild, platform_name=%s\n", buf);
313 met_set_platform(buf, 1);
314 }
315 else
316#endif
317 {
318 PR_BOOTMSG("Can not get platform info from dts nor met_drv Kbuild, set platform_name=mtxxxx\n");
319 met_set_platform("mtxxxx", 1);
320 }
321 }
322 }
323
324 /* get the chip id */
325 _MET_SYMBOL_GET(mt_get_chip_id);
326 if (mt_get_chip_id_symbol != NULL)
327 met_set_chip_id(mt_get_chip_id_symbol());
328 else {
329 chip_id = met_get_chipid_from_atag();
330 if (((int) chip_id) < 0) {
331 PR_BOOTMSG("Can not get chip id info, set chip_id=0x0\n");
332 } else
333 met_set_chip_id(chip_id);
334 }
335
336 cpu_topology_len = met_create_cpu_topology();
337 if (cpu_topology_len)
338 met_set_topology(met_cpu_topology, 1);
339
340#ifdef MET_PLF_USE
341 core_plf_init();
342#endif
343 return 0;
344}
345
346static void __exit met_drv_exit(void)
347{
348#ifdef MET_PLF_USE
349 core_plf_exit();
350#endif
351 fs_unreg();
352
353 met_kernel_symbol_put();
354 _MET_SYMBOL_PUT(mt_get_chip_id);
355}
356module_init(met_drv_init);
357module_exit(met_drv_exit);
358
359MODULE_AUTHOR("DT_DM5");
360MODULE_DESCRIPTION("MET_CORE");
361MODULE_LICENSE("GPL");