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