blob: 18eda1736c5c8fe54ec45055cd367b70789af00b [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2 * Copyright (C) 2018 MediaTek Inc.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13#include <linux/delay.h>
14#include <linux/module.h> /* symbol_get */
15
16#include "ondiemet_sspm.h"
17#define MET_USER_EVENT_SUPPORT
18#include "met_drv.h"
19#include "interface.h"
20
21#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
22#if defined(CONFIG_MTK_GMO_RAM_OPTIMIZE) || defined(CONFIG_MTK_MET_MEM_ALLOC)
23#ifdef CONFIG_MET_ARM_32BIT
24#include <asm/dma-mapping.h> /* arm_coherent_dma_ops */
25#else /* CONFIG_MET_ARM_32BIT */
26#include <linux/dma-mapping.h>
27#endif /* CONFIG_MET_ARM_32BIT */
28#else /* CONFIG_MTK_GMO_RAM_OPTIMIZE */
29#include "sspm_reservedmem.h"
30#include "sspm_reservedmem_define.h"
31#endif /* CONFIG_MTK_GMO_RAM_OPTIMIZE */
32
33dma_addr_t ondiemet_sspm_log_phy_addr;
34void *ondiemet_sspm_log_virt_addr;
35uint32_t ondiemet_sspm_log_size = 0x400000;
36
37/* SSPM_LOG_FILE 0 */
38/* SSPM_LOG_SRAM 1 */
39/* SSPM_LOG_DRAM 2 */
40int sspm_log_mode;
41/* SSPM_RUN_NORMAL mode 0 */
42/* SSPM_RUN_CONTINUOUS mode 1 */
43int sspm_run_mode;
44int met_sspm_log_discard = -1;
45int sspm_log_size = 100;
46
47int sspm_buffer_size;
48int sspm_buf_available;
49EXPORT_SYMBOL(sspm_buf_available);
50int sspm_buf_mapped = -1; /* get buffer by MET itself */
51
52static ssize_t sspm_buffer_size_show(struct device *dev, struct device_attribute *attr, char *buf);
53static DEVICE_ATTR(sspm_buffer_size, 0444, sspm_buffer_size_show, NULL);
54
55static ssize_t sspm_available_show(struct device *dev, struct device_attribute *attr, char *buf);
56static DEVICE_ATTR(sspm_available, 0444, sspm_available_show, NULL);
57
58static ssize_t sspm_log_discard_show(struct device *dev, struct device_attribute *attr, char *buf);
59static DEVICE_ATTR(sspm_log_discard, 0444, sspm_log_discard_show, NULL);
60
61static ssize_t sspm_log_mode_show(struct device *dev, struct device_attribute *attr, char *buf);
62static ssize_t sspm_log_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
63static DEVICE_ATTR(sspm_log_mode, 0664, sspm_log_mode_show, sspm_log_mode_store);
64
65static ssize_t sspm_log_size_show(struct device *dev, struct device_attribute *attr, char *buf);
66static ssize_t sspm_log_size_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
67static DEVICE_ATTR(sspm_log_size, 0664, sspm_log_size_show, sspm_log_size_store);
68
69
70static ssize_t sspm_run_mode_show(struct device *dev, struct device_attribute *attr, char *buf);
71static ssize_t sspm_run_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
72static DEVICE_ATTR(sspm_run_mode, 0664, sspm_run_mode_show, sspm_run_mode_store);
73
74static ssize_t sspm_modules_show(struct device *dev, struct device_attribute *attr, char *buf);
75static ssize_t sspm_modules_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
76static DEVICE_ATTR(sspm_modules, 0664, sspm_modules_show, sspm_modules_store);
77
78static ssize_t sspm_op_ctrl_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
79static DEVICE_ATTR(sspm_op_ctrl, 0220, NULL, sspm_op_ctrl_store);
80
81static ssize_t sspm_buffer_size_show(struct device *dev, struct device_attribute *attr, char *buf)
82{
83 int i;
84
85 mutex_lock(&dev->mutex);
86 i = snprintf(buf, PAGE_SIZE, "%d\n", sspm_buffer_size);
87 mutex_unlock(&dev->mutex);
88 return i;
89}
90
91static ssize_t sspm_available_show(struct device *dev, struct device_attribute *attr, char *buf)
92{
93 int i;
94
95 mutex_lock(&dev->mutex);
96 i = snprintf(buf, PAGE_SIZE, "%d\n", 1);
97 mutex_unlock(&dev->mutex);
98 return i;
99}
100
101static ssize_t sspm_log_discard_show(struct device *dev, struct device_attribute *attr, char *buf)
102{
103 int i;
104
105 mutex_lock(&dev->mutex);
106 i = snprintf(buf, PAGE_SIZE, "%d\n", met_sspm_log_discard);
107 mutex_unlock(&dev->mutex);
108 return i;
109}
110
111static ssize_t sspm_log_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
112{
113 int i;
114
115 mutex_lock(&dev->mutex);
116 i = snprintf(buf, PAGE_SIZE, "%d\n", sspm_log_mode);
117 mutex_unlock(&dev->mutex);
118 return i;
119}
120
121static ssize_t sspm_log_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
122{
123 int value;
124
125 if (kstrtoint(buf, 0, &value) != 0)
126 return -EINVAL;
127 mutex_lock(&dev->mutex);
128 sspm_log_mode = value;
129 mutex_unlock(&dev->mutex);
130 return count;
131}
132
133
134static ssize_t sspm_log_size_show(struct device *dev, struct device_attribute *attr, char *buf)
135{
136 int i;
137
138 mutex_lock(&dev->mutex);
139 i = snprintf(buf, PAGE_SIZE, "%d\n", sspm_log_size);
140 mutex_unlock(&dev->mutex);
141 return i;
142}
143
144static ssize_t sspm_log_size_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
145{
146 int value;
147
148 if (kstrtoint(buf, 0, &value) != 0)
149 return -EINVAL;
150 mutex_lock(&dev->mutex);
151 sspm_log_size = value;
152 mutex_unlock(&dev->mutex);
153 return count;
154}
155
156
157static ssize_t sspm_run_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
158{
159 int i;
160
161 mutex_lock(&dev->mutex);
162 i = snprintf(buf, PAGE_SIZE, "%d\n", sspm_run_mode);
163 mutex_unlock(&dev->mutex);
164 return i;
165}
166
167static ssize_t sspm_run_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
168{
169 int value;
170
171 if (kstrtoint(buf, 0, &value) != 0)
172 return -EINVAL;
173 mutex_lock(&dev->mutex);
174 sspm_run_mode = value;
175 mutex_unlock(&dev->mutex);
176 return count;
177}
178
179static ssize_t sspm_op_ctrl_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
180{
181 int value;
182
183 if (kstrtoint(buf, 0, &value) != 0)
184 return -EINVAL;
185 mutex_lock(&dev->mutex);
186 if (value == 1)
187 sspm_start();
188 else if (value == 2)
189 sspm_stop();
190 else if (value == 3)
191 sspm_extract();
192 else if (value == 4)
193 sspm_flush();
194 mutex_unlock(&dev->mutex);
195 return count;
196}
197
198static ssize_t sspm_modules_show(struct device *dev, struct device_attribute *attr, char *buf)
199{
200 int i;
201
202 mutex_lock(&dev->mutex);
203 i = snprintf(buf, PAGE_SIZE, "%x\n", ondiemet_module[ONDIEMET_SSPM]);
204 mutex_unlock(&dev->mutex);
205 return i;
206}
207
208static ssize_t sspm_modules_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
209{
210 uint32_t value;
211
212 if (kstrtouint(buf, 0, &value) != 0)
213 return -EINVAL;
214 mutex_lock(&dev->mutex);
215 ondiemet_module[ONDIEMET_SSPM] = value;
216 mutex_unlock(&dev->mutex);
217 return count;
218}
219
220int sspm_attr_init(struct device *dev)
221{
222 int ret;
223
224#if defined(CONFIG_MTK_GMO_RAM_OPTIMIZE) || defined(CONFIG_MTK_MET_MEM_ALLOC)
225#ifdef CONFIG_MET_ARM_32BIT
226 struct dma_map_ops *ops = (struct dma_map_ops *)symbol_get(arm_coherent_dma_ops);
227
228 if (ops && ops->alloc) {
229 dev->coherent_dma_mask = DMA_BIT_MASK(32);
230 ondiemet_sspm_log_virt_addr = ops->alloc(dev,
231 ondiemet_sspm_log_size,
232 &ondiemet_sspm_log_phy_addr,
233 GFP_KERNEL,
234 0);
235 }
236#else /* CONFIG_MET_ARM_32BIT */
237 /* dma_alloc */
238 ondiemet_sspm_log_virt_addr = dma_alloc_coherent(dev,
239 ondiemet_sspm_log_size,
240 &ondiemet_sspm_log_phy_addr,
241 GFP_KERNEL);
242#endif /* CONFIG_MET_ARM_32BIT */
243#else /* CONFIG_MTK_GMO_RAM_OPTIMIZE */
244
245 phys_addr_t (*sspm_reserve_mem_get_phys_sym)(unsigned int id) = NULL;
246 phys_addr_t (*sspm_reserve_mem_get_virt_sym)(unsigned int id) = NULL;
247 phys_addr_t (*sspm_reserve_mem_get_size_sym)(unsigned int id) = NULL;
248
249 sspm_reserve_mem_get_phys_sym = (phys_addr_t (*)(unsigned int id))symbol_get(sspm_reserve_mem_get_virt);
250 sspm_reserve_mem_get_virt_sym = (phys_addr_t (*)(unsigned int id))symbol_get(sspm_reserve_mem_get_phys);
251 sspm_reserve_mem_get_size_sym = (phys_addr_t (*)(unsigned int id))symbol_get(sspm_reserve_mem_get_size);
252 if (sspm_reserve_mem_get_phys_sym)
253 ondiemet_sspm_log_virt_addr = (void*)sspm_reserve_mem_get_virt(MET_MEM_ID);
254 if (sspm_reserve_mem_get_virt_sym)
255 ondiemet_sspm_log_phy_addr = sspm_reserve_mem_get_phys(MET_MEM_ID);
256 if (sspm_reserve_mem_get_size_sym)
257 ondiemet_sspm_log_size = sspm_reserve_mem_get_size(MET_MEM_ID);
258#endif /* CONFIG_MTK_GMO_RAM_OPTIMIZE */
259
260 ret = device_create_file(dev, &dev_attr_sspm_buffer_size);
261 if (ret != 0) {
262 pr_debug("can not create device file: sspm_buffer_size\n");
263 return ret;
264 }
265
266 ret = device_create_file(dev, &dev_attr_sspm_available);
267 if (ret != 0) {
268 pr_debug("can not create device file: sspm_available\n");
269 return ret;
270 }
271
272 ret = device_create_file(dev, &dev_attr_sspm_log_discard);
273 if (ret != 0) {
274 pr_debug("can not create device file: sspm_log_discard\n");
275 return ret;
276 }
277 ret = device_create_file(dev, &dev_attr_sspm_log_mode);
278 if (ret != 0) {
279 pr_debug("can not create device file: sspm_log_mode\n");
280 return ret;
281 }
282 ret = device_create_file(dev, &dev_attr_sspm_log_size);
283 if (ret != 0) {
284 pr_debug("can not create device file: sspm_log_size\n");
285 return ret;
286 }
287 ret = device_create_file(dev, &dev_attr_sspm_run_mode);
288 if (ret != 0) {
289 pr_debug("can not create device file: sspm_run_mode\n");
290 return ret;
291 }
292 ret = device_create_file(dev, &dev_attr_sspm_op_ctrl);
293 if (ret != 0) {
294 pr_debug("can not create device file: sspm_op_ctrl\n");
295 return ret;
296 }
297 ret = device_create_file(dev, &dev_attr_sspm_modules);
298 if (ret != 0) {
299 pr_debug("can not create device file: sspm_modules\n");
300 return ret;
301 }
302
303 if (ondiemet_sspm_log_virt_addr != NULL) {
304 start_sspm_ipi_recv_thread();
305 sspm_buf_available = 1;
306 sspm_buffer_size = ondiemet_sspm_log_size;
307 } else {
308 sspm_buf_available = 0;
309 sspm_buffer_size = -1;
310 }
311
312 return 0;
313}
314
315int sspm_attr_uninit(struct device *dev)
316{
317 /* dma_free */
318 if (ondiemet_sspm_log_virt_addr != NULL) {
319#if defined(CONFIG_MTK_GMO_RAM_OPTIMIZE) || defined(CONFIG_MTK_MET_MEM_ALLOC)
320#ifdef CONFIG_MET_ARM_32BIT
321 struct dma_map_ops *ops = (struct dma_map_ops *)symbol_get(arm_coherent_dma_ops);
322
323 if (ops && ops->free) {
324 ops->free(dev,
325 ondiemet_sspm_log_size,
326 ondiemet_sspm_log_virt_addr,
327 ondiemet_sspm_log_phy_addr,
328 0);
329 }
330#else /* CONFIG_MET_ARM_32BIT */
331 dma_free_coherent(dev,
332 ondiemet_sspm_log_size,
333 ondiemet_sspm_log_virt_addr,
334 ondiemet_sspm_log_phy_addr);
335#endif /* CONFIG_MET_ARM_32BIT */
336#endif /* CONFIG_MTK_GMO_RAM_OPTIMIZE */
337 ondiemet_sspm_log_virt_addr = NULL;
338 stop_sspm_ipi_recv_thread();
339 }
340
341 device_remove_file(dev, &dev_attr_sspm_buffer_size);
342 device_remove_file(dev, &dev_attr_sspm_available);
343 device_remove_file(dev, &dev_attr_sspm_log_discard);
344 device_remove_file(dev, &dev_attr_sspm_log_mode);
345 device_remove_file(dev, &dev_attr_sspm_log_size);
346 device_remove_file(dev, &dev_attr_sspm_run_mode);
347 device_remove_file(dev, &dev_attr_sspm_op_ctrl);
348 device_remove_file(dev, &dev_attr_sspm_modules);
349
350 return 0;
351}
352
353#if 0 /* move to sspm_attr_init() */
354void sspm_get_buffer_info(void)
355{
356 if (ondiemet_sspm_log_virt_addr != NULL) {
357 sspm_buf_available = 1;
358 sspm_buffer_size = ondiemet_sspm_log_size;
359 } else {
360 sspm_buf_available = 0;
361 sspm_buffer_size = -1;
362 }
363}
364#endif
365
366extern const char *met_get_platform_name(void);
367void sspm_start(void)
368{
369 int32_t ret = 0;
370 uint32_t rdata;
371 uint32_t ipi_buf[4];
372 const char* platform_name = NULL;
373 unsigned int platform_id = 0;
374 met_sspm_log_discard = -1;
375
376 /* clear DRAM buffer */
377 if (ondiemet_sspm_log_virt_addr != NULL)
378 memset_io((void *)ondiemet_sspm_log_virt_addr, 0, ondiemet_sspm_log_size);
379 else
380 return;
381
382 platform_name = met_get_platform_name();
383 if (platform_name) {
384 char buf[5];
385
386 memset(buf, 0x0, 5);
387 memcpy(buf, &platform_name[2], 4);
388 ret = kstrtouint(buf, 10, &platform_id);
389 }
390
391 /* send DRAM physical address */
392 ipi_buf[0] = MET_MAIN_ID | MET_BUFFER_INFO;
393 ipi_buf[1] = (unsigned int)ondiemet_sspm_log_phy_addr; /* address */
394 if (ret == 0)
395 ipi_buf[2] = platform_id;
396 else
397 ipi_buf[2] = 0;
398 ipi_buf[3] = 0;
399 ret = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1);
400
401 /* start ondiemet now */
402 ipi_buf[0] = MET_MAIN_ID | MET_OP | MET_OP_START;
403 ipi_buf[1] = ondiemet_module[ONDIEMET_SSPM];
404 ipi_buf[2] = sspm_log_mode;
405 ipi_buf[3] = sspm_run_mode;
406 ret = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1);
407}
408
409void sspm_stop(void)
410{
411 int32_t ret;
412 uint32_t rdata;
413 uint32_t ipi_buf[4];
414
415 if (sspm_buf_available == 1) {
416 ipi_buf[0] = MET_MAIN_ID|MET_OP|MET_OP_STOP;
417 ipi_buf[1] = 0;
418 ipi_buf[2] = 0;
419 ipi_buf[3] = 0;
420 ret = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1);
421 }
422}
423
424void sspm_extract(void)
425{
426 int32_t ret;
427 uint32_t rdata;
428 uint32_t ipi_buf[4];
429 int32_t count;
430
431 count = 20;
432 if (sspm_buf_available == 1) {
433 while ((sspm_buffer_dumping == 1) && (count != 0)) {
434 msleep(50);
435 count--;
436 }
437 ipi_buf[0] = MET_MAIN_ID|MET_OP|MET_OP_EXTRACT;
438 ipi_buf[1] = 0;
439 ipi_buf[2] = 0;
440 ipi_buf[3] = 0;
441 ret = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1);
442 }
443
444 if (sspm_run_mode == SSPM_RUN_NORMAL)
445 ondiemet_module[ONDIEMET_SSPM] = 0;
446}
447
448void sspm_flush(void)
449{
450 int32_t ret;
451 uint32_t rdata;
452 uint32_t ipi_buf[4];
453
454 if (sspm_buf_available == 1) {
455 ipi_buf[0] = MET_MAIN_ID|MET_OP|MET_OP_FLUSH;
456 ipi_buf[1] = 0;
457 ipi_buf[2] = 0;
458 ipi_buf[3] = 0;
459 ret = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1);
460 }
461
462 if (sspm_run_mode == SSPM_RUN_NORMAL)
463 ondiemet_module[ONDIEMET_SSPM] = 0;
464}
465#else /* CONFIG_MTK_TINYSYS_SSPM_SUPPORT */
466int sspm_buffer_size = -1;
467
468int sspm_attr_init(struct device *dev)
469{
470 return 0;
471}
472
473int sspm_attr_uninit(struct device *dev)
474{
475 return 0;
476}
477
478void sspm_start(void)
479{
480}
481
482void sspm_stop(void)
483{
484}
485
486void sspm_extract(void)
487{
488}
489
490void sspm_flush(void)
491{
492}
493
494#endif /* CONFIG_MTK_TINYSYS_SSPM_SUPPORT */