import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / arm / mach-mt8127 / mt_mon.c
1 #include <linux/kernel.h>
2 #include <linux/module.h>
3 #include <linux/errno.h>
4 #include <linux/trace_seq.h>
5 #include <linux/ftrace_event.h>
6 #include <linux/device.h>
7 #include <linux/platform_device.h>
8 #include <linux/vmalloc.h>
9
10
11 #include "asm/hardware/cache-l2x0.h"
12 #include "mach/mt_reg_base.h"
13 #include "mach/sync_write.h"
14 #include "mach/mt_emi_bm.h"
15 //#include "mach/mt6573_pll.h"
16 #include "mach/mt_mon.h"
17 // FIX-ME mark for porting
18 #include "mach/mt_dcm.h"
19 //#include <../../kernel/kernel/trace/trace.h>
20 #include <../../../kernel/trace/trace.h>
21 #include <asm/io.h>
22
23 #define MON_LOG_BUFF_LEN (64 * 1024)
24 #define DEF_BM_RW_TYPE (BM_BOTH_READ_WRITE)
25
26 static DECLARE_BITMAP(buf_bitmap, MON_LOG_BUFF_LEN);
27
28
29 static unsigned int bm_master_evt = BM_MASTER_AP_MCU;
30 static unsigned int bm_rw_type_evt = DEF_BM_RW_TYPE;
31
32 static MonitorMode register_mode = MODE_FREE;
33 static unsigned long mon_period_evt;
34 static unsigned int mon_manual_evt;
35
36 struct mt_mon_log *mt_mon_log_buff; //this buffer is allocated for MODE_MANUAL_USER & MODE_MANUAL_KERNEL only
37 unsigned int mt_mon_log_buff_index;
38 unsigned int mt_kernel_ring_buff_index;
39
40 struct arm_pmu *p_pmu;
41 struct mtk_monitor mtk_mon;
42
43 //static DEFINE_SPINLOCK(mtk_monitor_lock);
44
45 /*
46 * mt65xx_mon_init: Initialize the monitor.
47 * Return 0.
48 */
49 static int mt65xx_mon_init(void)
50 {
51 BM_Init();
52
53 #if 0
54 // disable system DCM
55 if (0 == BM_GetEmiDcm()) //0 means EMI dcm is enabled
56 {
57 printk("[MON] Disable system DCM\n");
58 dcm_disable(ALL_DCM);
59 BM_SetEmiDcm(0xff); //disable EMI dcm
60 }
61 #endif
62 return 0;
63 }
64
65 /*
66 * mt65xx_mon_deinit: De-initialize the monitor.
67 * Return 0.
68 */
69 static int mt65xx_mon_deinit(void)
70 {
71
72 BM_DeInit();
73
74 /*
75 if (mt_mon_log_buff) {
76 vfree(mt_mon_log_buff);
77
78 mt_mon_log_buff = 0;
79 }
80 */
81 #if 0
82 // enable system DCM
83 if (1 == BM_GetEmiDcm()) //1 means EMI dcm is disabled
84 {
85 printk("[MON] Enable system DCM\n");
86 dcm_enable(ALL_DCM);
87 BM_SetEmiDcm(0x0); //enable EMI dcm
88 }
89 #endif
90 return 0;
91
92 }
93
94 /*
95 * mt65xx_mon_enable: Enable hardware monitors.
96 * Return 0.
97 */
98 static int mt65xx_mon_enable(void)
99 {
100
101 p_pmu->reset();
102
103 // enable & start ARM performance monitors
104 p_pmu->enable();
105 p_pmu->start();
106
107 // stopping EMI monitors will reset all counters
108 BM_Enable(0);
109
110 // start EMI monitor counting
111 BM_Enable(1);
112
113 return 0;
114 }
115
116 /*
117 * mt65xx_mon_disable: Disable hardware monitors.
118 * Return 0.
119 */
120 static int mt65xx_mon_disable(void)
121 {
122
123 // disable ARM performance monitors
124 p_pmu->stop();
125
126 BM_Pause();
127
128 return 0;
129 }
130
131 static inline void set_cpumask(unsigned int cpu, unsigned int index, volatile unsigned long *p)
132 {
133 unsigned long cpumask = 1UL << cpu;
134 unsigned int offset = (index & 3) << 3; // (index % 4) * 8
135
136 p += (index >> 2);
137
138 *p |= (cpumask << offset);
139 }
140
141 static inline void clear_bitmap(unsigned int bit, volatile unsigned long *p)
142 {
143 /*
144 unsigned long mask = 1UL << (bit & 31);
145
146 p += bit >> 5;
147
148 *p &= ~mask;
149 */
150 }
151
152 static inline int get_cpumask(unsigned int index, volatile unsigned long *p)
153 {
154 unsigned int res;
155 unsigned long offset = (index & 3) << 3; // (index % 4) * 8
156
157 p += (index >> 2);
158 res = *p;
159 res = (res >> offset) & 0x7;
160
161 return res;
162 }
163 /*
164 * mt65xx_mon_log: Get the current log from hardware monitors.
165 * Return a index to the curret log entry in the log buffer.
166 */
167 static unsigned int mt65xx_mon_log(void* log_buff)
168 {
169 struct mt_mon_log* mon_buff;
170 struct pmu_data *pmu_data = & p_pmu->perf_data;
171 unsigned int cpu = raw_smp_processor_id();
172 unsigned int cur = 0;
173
174 p_pmu->read_counter();
175
176
177 /* In MODE_SCHED_SWITCH, we need to record the current CPU number to get the Context Switch CPU number.
178 *
179 * */
180 if( register_mode == MODE_MANUAL_USER || register_mode == MODE_MANUAL_KERNEL){
181 set_cpumask(cpu,cur,buf_bitmap);
182 cur = mt_mon_log_buff_index++;
183 mon_buff = &mt_mon_log_buff[cur];
184 mt_mon_log_buff_index %= MON_LOG_BUFF_LEN;
185 }else {
186 cur = mt_kernel_ring_buff_index++;
187 mon_buff = (struct mt_mon_log*)log_buff;
188 }
189
190 if(mon_buff)
191 {
192 for_each_present_cpu(cpu){
193 mon_buff->cpu_cnt0[cpu] = pmu_data->cnt_val[cpu][0];
194 mon_buff->cpu_cnt1[cpu] = pmu_data->cnt_val[cpu][1];
195 mon_buff->cpu_cnt2[cpu] = pmu_data->cnt_val[cpu][2];
196 mon_buff->cpu_cnt3[cpu] = pmu_data->cnt_val[cpu][3];
197 mon_buff->cpu_cyc[cpu] = pmu_data->cnt_val[cpu][ARMV7_CYCLE_COUNTER];
198 }
199
200 #if 1
201 mon_buff->BM_BCNT = BM_GetBusCycCount();
202 mon_buff->BM_TACT = BM_GetTransAllCount();
203 mon_buff->BM_TSCT = BM_GetTransCount(1);
204 mon_buff->BM_WACT = BM_GetWordAllCount();
205 mon_buff->BM_WSCT = BM_GetWordCount(1);
206 mon_buff->BM_BACT = BM_GetBandwidthWordCount();
207 mon_buff->BM_BSCT = BM_GetOverheadWordCount();
208 mon_buff->BM_TSCT2 = BM_GetTransCount(2);
209 mon_buff->BM_WSCT2 = BM_GetWordCount(2);
210 mon_buff->BM_TSCT3 = BM_GetTransCount(3);
211 mon_buff->BM_WSCT3 = BM_GetWordCount(3);
212 mon_buff->BM_WSCT4 = BM_GetWordCount(4);
213 mon_buff->BM_TTYPE1 = BM_GetLatencyCycle(1);
214 mon_buff->BM_TTYPE2 = BM_GetLatencyCycle(2);
215 mon_buff->BM_TTYPE3 = BM_GetLatencyCycle(3);
216 mon_buff->BM_TTYPE4 = BM_GetLatencyCycle(4);
217 mon_buff->BM_TTYPE5 = BM_GetLatencyCycle(5);
218
219 mon_buff->BM_TTYPE9 = BM_GetLatencyCycle(9);
220 mon_buff->BM_TTYPE10 = BM_GetLatencyCycle(10);
221 mon_buff->BM_TTYPE11 = BM_GetLatencyCycle(11);
222 mon_buff->BM_TTYPE12 = BM_GetLatencyCycle(12);
223 mon_buff->BM_TTYPE13 = BM_GetLatencyCycle(13);
224
225 //mon_buff->BM_TPCT1 = BM_GetTransTypeCount(1); //not used now
226
227
228 mon_buff->DRAMC_PageHit = DRAMC_GetPageHitCount(DRAMC_ALL);
229 mon_buff->DRAMC_PageMiss = DRAMC_GetPageMissCount(DRAMC_ALL);
230 mon_buff->DRAMC_Interbank = DRAMC_GetInterbankCount(DRAMC_ALL);
231 mon_buff->DRAMC_Idle = DRAMC_GetIdleCount();
232 #endif
233 }
234
235 memset(pmu_data->cnt_val[0], 0, sizeof(struct pmu_data));
236 return cur;
237 }
238
239 extern unsigned int mt_get_emi_freq(void);
240
241 enum print_line_t mt65xx_mon_print_entry(struct mt65xx_mon_entry *entry, struct trace_iterator *iter){
242 struct trace_seq *s = &iter->seq;
243 int cpu = entry->cpu;
244 struct mt_mon_log *log_entry;
245 unsigned int log = 0;
246 MonitorMode mon_mode_evt = get_mt65xx_mon_mode();
247
248
249 if(entry == NULL)
250 return TRACE_TYPE_HANDLED;
251 else{
252 log_entry = &entry->field;
253 log = entry->log;
254 }
255
256 if (log == 0) {
257 trace_seq_printf(s, "MON_LOG_BUFF_LEN = %d, ", MON_LOG_BUFF_LEN);
258 trace_seq_printf(s, "EMI_CLOCK = %d, ", mt_get_emi_freq());
259 }
260
261 if(mon_mode_evt != MODE_SCHED_SWITCH){
262 for_each_present_cpu(cpu)
263 {
264 trace_seq_printf(
265 s,
266 " cpu%d_cyc = %d, cpu%d_cnt0 = %d, cpu%d_cnt1 = %d, cpu%d_cnt2 = %d, cpu%d_cnt3 = %d, ",
267 cpu,
268 log_entry->cpu_cyc[cpu],
269 cpu,
270 log_entry->cpu_cnt0[cpu],
271 cpu,
272 log_entry->cpu_cnt1[cpu],
273 cpu,
274 log_entry->cpu_cnt2[cpu],
275 cpu,
276 log_entry->cpu_cnt3[cpu]);
277 }
278 }
279 else /*SCHED_SWITCH - only print self cpu*/
280 {
281 trace_seq_printf(
282 s,
283 " cpu%d_cyc = %d, cpu%d_cnt0 = %d, cpu%d_cnt1 = %d, cpu%d_cnt2 = %d, cpu%d_cnt3 = %d, ",
284 cpu,
285 log_entry->cpu_cyc[cpu],
286 cpu,
287 log_entry->cpu_cnt0[cpu],
288 cpu,
289 log_entry->cpu_cnt1[cpu],
290 cpu,
291 log_entry->cpu_cnt2[cpu],
292 cpu,
293 log_entry->cpu_cnt3[cpu]);
294 }
295
296 trace_seq_printf(
297 s,
298 "BM_BCNT = %d, BM_TACT = %d, BM_TSCT = %d, ",
299 log_entry->BM_BCNT,
300 log_entry->BM_TACT,
301 log_entry->BM_TSCT);
302
303 trace_seq_printf(
304 s,
305 "BM_WACT = %d, BM_WSCT0 = %d, BM_BACT = %d, ",
306 log_entry->BM_WACT,
307 log_entry->BM_WSCT,
308 log_entry->BM_BACT);
309
310 trace_seq_printf(
311 s,
312 "BM_BSCT = %d, ",
313 log_entry->BM_BSCT);
314
315 trace_seq_printf(
316 s,
317 "BM_TSCT2 = %d, BM_WSCT2 = %d, ",
318 log_entry->BM_TSCT2,
319 log_entry->BM_WSCT2);
320
321 trace_seq_printf(
322 s,
323 "BM_TSCT3 = %d, BM_WSCT3 = %d, ",
324 log_entry->BM_TSCT3,
325 log_entry->BM_WSCT3);
326
327 trace_seq_printf(
328 s,
329 "BM_WSCT4 = %d, BM_TPCT1 = %d, ",
330 log_entry->BM_WSCT4,
331 log_entry->BM_TPCT1);
332
333 trace_seq_printf(
334 s,
335 "BM_TTYPE01 = %d, BM_TTYPE09 = %d, ",
336 log_entry->BM_TTYPE1, log_entry->BM_TTYPE9);
337
338 trace_seq_printf(
339 s,
340 "BM_TTYPE02 = %d, BM_TTYPE10 = %d, ",
341 log_entry->BM_TTYPE2, log_entry->BM_TTYPE10);
342
343 trace_seq_printf(
344 s,
345 "BM_TTYPE03 = %d, BM_TTYPE11 = %d, ",
346 log_entry->BM_TTYPE3, log_entry->BM_TTYPE11);
347
348 trace_seq_printf(
349 s,
350 "BM_TTYPE04 = %d, BM_TTYPE12 = %d, ",
351 log_entry->BM_TTYPE4, log_entry->BM_TTYPE12);
352
353 trace_seq_printf(
354 s,
355 "BM_TTYPE05 = %d, BM_TTYPE13 = %d, ",
356 log_entry->BM_TTYPE5, log_entry->BM_TTYPE13);
357
358 trace_seq_printf(
359 s,
360 "DRAMC_PageHit = %d, DRAMC_PageMiss = %d, DRAMC_Interbank = %d, DRAMC_Idle = %d\n",
361 log_entry->DRAMC_PageHit,
362 log_entry->DRAMC_PageMiss,
363 log_entry->DRAMC_Interbank,
364 log_entry->DRAMC_Idle);
365
366 return 0;
367 }
368
369 static void mt65xx_mon_set_pmu(struct pmu_cfg *p_cfg)
370 {
371 memcpy(&p_pmu->perf_cfg, p_cfg, sizeof(struct pmu_cfg));
372 }
373
374 static void mt65xx_mon_get_pmu(struct pmu_cfg *p_cfg)
375 {
376 memcpy(p_cfg, &p_pmu->perf_cfg, sizeof(struct pmu_cfg));
377 }
378
379 static void mt65xx_mon_set_l2c(struct l2c_cfg *l_cfg)
380 {
381 }
382
383 static void mt65xx_mon_get_l2c(struct l2c_cfg *l_cfg)
384 {
385 }
386
387 static void mt65xx_mon_set_bm_rw(int type)
388 {
389
390 if(type > BM_WRITE_ONLY) {
391 printk("invalid event\n");
392 } else {
393 BM_SetReadWriteType(type);
394 }
395
396 }
397
398 static ssize_t bm_master_evt_show(struct device_driver *driver, char *buf)
399 {
400 return snprintf(buf, PAGE_SIZE, "EMI bus monitor master = %d\n", bm_master_evt);
401 }
402
403 static ssize_t bm_master_evt_store(struct device_driver *driver, const char *buf, size_t count)
404 {
405 if (!strncmp(buf, "MM", strlen("MM"))) {
406 bm_master_evt = BM_MASTER_MM;
407 }else if (!strncmp(buf, "APMCU", strlen("APMCU"))) {
408 bm_master_evt = BM_MASTER_AP_MCU;
409 }else if (!strncmp(buf, "MDMCU", strlen("MDMCU"))) {
410 bm_master_evt = BM_MASTER_MD_MCU;
411 }else if (!strncmp(buf, "2G_3G_MDDMA", strlen("2G_3G_MDDMA"))) {
412 bm_master_evt = BM_MASTER_2G_3G_MDDMA;
413 }else if (!strncmp(buf, "MD_ALL", strlen("MD_ALL"))) {
414 bm_master_evt = BM_MASTER_MD_MCU | BM_MASTER_2G_3G_MDDMA;
415 }else if (!strncmp(buf, "PERI", strlen("PERI"))) {
416 bm_master_evt = BM_MASTER_PERI;
417 }else if (!strncmp(buf, "ALL", strlen("ALL"))) {
418 bm_master_evt = BM_MASTER_ALL;
419 }else {
420 printk("invalid event\n");
421
422 return count;
423 }
424
425 BM_SetMaster(1, bm_master_evt);
426
427 return count;
428 }
429
430 static ssize_t bm_rw_type_evt_show(struct device_driver *driver, char *buf)
431 {
432 return snprintf(buf, PAGE_SIZE, "EMI bus read write type = %d\n", bm_rw_type_evt);
433 }
434
435 static ssize_t bm_rw_type_evt_store(struct device_driver *driver, const char *buf, size_t count)
436 {
437 if (!strncmp(buf, "RW", strlen("RW"))) {
438 bm_rw_type_evt = BM_BOTH_READ_WRITE;
439 } else if (!strncmp(buf, "RO", strlen("RO"))) {
440 bm_rw_type_evt = BM_READ_ONLY;
441 } else if (!strncmp(buf, "WO", strlen("WO"))) {
442 bm_rw_type_evt = BM_WRITE_ONLY;
443 } else {
444 printk("invalid event\n");
445 return count;
446 }
447
448 BM_SetReadWriteType(bm_rw_type_evt);
449
450 return count;
451 }
452
453 static ssize_t mon_mode_evt_show(struct device_driver *driver, char *buf)
454 {
455 MonitorMode mon_mode_evt;
456 mon_mode_evt = get_mt65xx_mon_mode();
457 if(mon_mode_evt == MODE_MANUAL_USER)
458 return snprintf(buf, PAGE_SIZE, "Monitor mode = MANUAL_USER\n");
459 else if(mon_mode_evt == MODE_SCHED_SWITCH)
460 return snprintf(buf, PAGE_SIZE, "Monitor mode = SCHED_SWITCH\n");
461 else if(mon_mode_evt == MODE_PERIODIC)
462 return snprintf(buf, PAGE_SIZE, "Monitor mode = PERIODIC\n");
463 else if(mon_mode_evt == MODE_MANUAL_TRACER)
464 return snprintf(buf, PAGE_SIZE, "Monitor mode = MANUAL_TRACER\n");
465 else if(mon_mode_evt == MODE_MANUAL_KERNEL)
466 return snprintf(buf, PAGE_SIZE, "Monitor mode = MANUAL_KERNEL\n");
467 else if(mon_mode_evt == MODE_FREE)
468 return snprintf(buf, PAGE_SIZE, "Monitor mode = FREE\n");
469 else
470 return snprintf(buf, PAGE_SIZE, "Monitor mode = Unknown\n");
471 }
472
473 static ssize_t mon_mode_evt_store(struct device_driver *driver, const char *buf, size_t count)
474 {
475 MonitorMode mon_mode_evt;
476 if (!strncmp(buf, "SCHED_SWITCH", strlen("SCHED_SWITCH"))) {
477 mon_mode_evt = MODE_SCHED_SWITCH;
478 } else if (!strncmp(buf, "PERIODIC", strlen("PERIODIC"))) {
479 mon_mode_evt = MODE_PERIODIC;
480 } else if (!strncmp(buf, "MANUAL_TRACER", strlen("MANUAL_TRACER"))) {
481 mon_mode_evt = MODE_MANUAL_TRACER;
482 } else {
483 printk("invalid event\n");
484 return count;
485 }
486
487 set_mt65xx_mon_mode(mon_mode_evt);
488
489 return count;
490 }
491
492 static ssize_t mon_period_evt_show(struct device_driver *driver, char *buf)
493 {
494 return snprintf(buf, PAGE_SIZE, "Monitor period = %ld (for periodic mode)\n", get_mt65xx_mon_period());
495 }
496
497 static ssize_t mon_period_evt_store(struct device_driver *driver, const char *buf, size_t count)
498 {
499
500 sscanf(buf, "%ld", &mon_period_evt);
501 set_mt65xx_mon_period(mon_period_evt);
502
503 return count;
504 }
505
506 static ssize_t mon_manual_evt_show(struct device_driver *driver, char *buf)
507 {
508 mon_manual_evt = get_mt65xx_mon_manual_start();
509 if(mon_manual_evt == 1)
510 return snprintf(buf, PAGE_SIZE, "Manual Monitor is Started (for manual mode)\n");
511 else if(mon_manual_evt == 0)
512 return snprintf(buf, PAGE_SIZE, "Manual Monitor is Stopped (for manual mode)\n");
513 else
514 return 0;
515 }
516
517 static ssize_t mon_manual_evt_store(struct device_driver *driver, const char *buf, size_t count)
518 {
519
520 if (!strncmp(buf, "START", strlen("START"))) {
521 mon_manual_evt = 1;
522 } else if (!strncmp(buf, "STOP", strlen("STOP"))) {
523 mon_manual_evt = 0;
524 } else {
525 printk("invalid event\n");
526 return count;
527 }
528
529 set_mt65xx_mon_manual_start(mon_manual_evt);
530
531 return count;
532 }
533
534 static ssize_t cpu_pmu_evt_show(struct device_driver *driver, char *buf)
535 {
536
537 u32 j;
538 int size = 0;
539
540 if(p_pmu == NULL) {
541 printk("PMU user interface isn't ready now!\n");
542 return 0;
543 }
544
545 for(j = 0; j < NUMBER_OF_EVENT; j++) {
546 size += sprintf(buf + size, "Evt%d = 0x%x\t", j, p_pmu->perf_cfg.event_cfg[j]);
547 }
548 size += sprintf(buf + size, "\n");
549
550 return (size);
551 }
552
553 static ssize_t cpu_pmu_evt_store(struct device_driver *driver, const char *buf, size_t count)
554 {
555
556 char *p = (char *)buf;
557 char *token[8];
558 char *ptr;
559 int i = 0;
560
561 if((strlen(buf)+1) > 128)
562 {
563 printk("[PMU] command overflow!");
564 return -1;
565 }
566
567 do{
568 ptr = strsep (&p, " ");
569 token[i] = ptr;
570 i++;
571 }while(ptr != NULL);
572
573 //because we use i to count num of evt setting, i is NUMBER_OF_EVENT+1
574 if(i != (NUMBER_OF_EVENT+1)){
575 printk("[PMU]The number of parameter is wrong!!! Please echo ");
576 for(i = 0; i < NUMBER_OF_EVENT; i++)
577 printk("Evt%d ",i);
578 printk("> cpu_pmu_cfg\n");
579 return -1;
580 }
581
582
583 for(i = 0; i < NUMBER_OF_EVENT; i++)
584 p_pmu->perf_cfg.event_cfg[i] = simple_strtoul(token[i], &token[i], 16);
585
586
587 for(i=0; i<NUMBER_OF_EVENT; i++)
588 printk("%x ",p_pmu->perf_cfg.event_cfg[i]);
589 printk("\n");
590 p_pmu->enable();
591
592 return count;
593
594 }
595
596 static ssize_t emi_dcm_ctrl_show(struct device_driver *driver, char *buf)
597 {
598 return snprintf(buf, PAGE_SIZE, "EMI DCM is %s\n", BM_GetEmiDcm() ? "OFF" : "ON");
599 }
600
601 static ssize_t emi_dcm_ctrl_store(struct device_driver *driver, const char *buf, size_t count)
602 {
603 if (!strncmp(buf, "OFF", strlen("OFF"))) {
604 BM_SetEmiDcm(0xff);
605 } else if (!strncmp(buf, "ON", strlen("ON"))) {
606 BM_SetEmiDcm(0x0);
607 } else {
608 printk("invalid event\n");
609 }
610
611 return count;
612 }
613
614 #if 0
615 static ssize_t mci_evt_show(struct device_driver *driver, char *buf)
616 {
617 MCI_Event_Read();
618 return;
619 }
620
621 ssize_t mci_evt_store(struct device_driver *driver, const char *buf, size_t count)
622 {
623 unsigned int evt0, evt1;
624 if (sscanf(buf, "%x %x", &evt0, &evt1) != 2)
625 return -EINVAL;
626 MCI_Event_Set(evt0, evt1);
627
628 return count;
629 }
630 #endif
631
632 DRIVER_ATTR(bm_master_evt, 0644, bm_master_evt_show, bm_master_evt_store);
633 DRIVER_ATTR(bm_rw_type_evt, 0644, bm_rw_type_evt_show, bm_rw_type_evt_store);
634
635 DRIVER_ATTR(mon_mode_evt, 0644, mon_mode_evt_show, mon_mode_evt_store);
636 DRIVER_ATTR(mon_period_evt, 0644, mon_period_evt_show, mon_period_evt_store);
637 DRIVER_ATTR(mon_manual_evt, 0644, mon_manual_evt_show, mon_manual_evt_store);
638
639 DRIVER_ATTR(cpu_pmu_cfg, 0644, cpu_pmu_evt_show, cpu_pmu_evt_store);
640 DRIVER_ATTR(emi_dcm_ctrl, 0644, emi_dcm_ctrl_show, emi_dcm_ctrl_store);
641
642 //DRIVER_ATTR(mci_evt, 0644, mci_evt_show, mci_evt_store);
643
644
645 static struct device_driver mt_mon_drv =
646 {
647 .name = "mt_monitor",
648 .bus = &platform_bus_type,
649 .owner = THIS_MODULE,
650 };
651
652
653 struct mtk_monitor mtk_mon = {
654 .init = mt65xx_mon_init,
655 .deinit = mt65xx_mon_deinit,
656 .enable = mt65xx_mon_enable,
657 .disable = mt65xx_mon_disable,
658 .mon_log = mt65xx_mon_log,
659 .set_pmu = mt65xx_mon_set_pmu,
660 .get_pmu = mt65xx_mon_get_pmu,
661 .set_l2c = mt65xx_mon_set_l2c,
662 .get_l2c = mt65xx_mon_get_l2c,
663 .set_bm_rw = mt65xx_mon_set_bm_rw,
664 };
665
666 /*
667 * mt_mon_mod_init: module init function
668 */
669 static int __init mt_mon_mod_init(void)
670 {
671 int ret;
672
673 /* register driver and create sysfs files */
674 ret = driver_register(&mt_mon_drv);
675
676 if (ret) {
677 printk("fail to register mt_mon_drv\n");
678 return ret;
679 }
680 ret = driver_create_file(&mt_mon_drv, &driver_attr_bm_master_evt);
681 ret |= driver_create_file(&mt_mon_drv, &driver_attr_bm_rw_type_evt);
682 ret |= driver_create_file(&mt_mon_drv, &driver_attr_mon_mode_evt);
683 ret |= driver_create_file(&mt_mon_drv, &driver_attr_mon_period_evt);
684 ret |= driver_create_file(&mt_mon_drv, &driver_attr_mon_manual_evt);
685 ret |= driver_create_file(&mt_mon_drv, &driver_attr_cpu_pmu_cfg);
686 ret |= driver_create_file(&mt_mon_drv, &driver_attr_emi_dcm_ctrl);
687 // ret |= driver_create_file(&mt_mon_drv, &driver_attr_mci_evt);
688
689 if (ret) {
690 printk("fail to create mt_mon sysfs files\n");
691
692 return ret;
693 }
694
695 /* SPNIDEN[12] must be 1 for using ARM11 performance monitor unit */
696 // *(volatile unsigned int *)0xF702A000 |= 0x1000;
697
698
699 ret = register_pmu(&p_pmu);
700 if(ret != 0 || p_pmu == NULL) {
701 printk("Register PMU Fail\n");
702 return ret;
703 }
704
705
706 /* init EMI bus monitor */
707 BM_SetReadWriteType(DEF_BM_RW_TYPE);
708 BM_SetMonitorCounter(1, BM_MASTER_MM, BM_TRANS_TYPE_4BEAT | BM_TRANS_TYPE_8Byte | BM_TRANS_TYPE_BURST_WRAP);
709 BM_SetMonitorCounter(2, BM_MASTER_AP_MCU, BM_TRANS_TYPE_4BEAT | BM_TRANS_TYPE_8Byte | BM_TRANS_TYPE_BURST_WRAP);
710 BM_SetMonitorCounter(3, BM_MASTER_MD_MCU | BM_MASTER_2G_3G_MDDMA, BM_TRANS_TYPE_4BEAT | BM_TRANS_TYPE_8Byte | BM_TRANS_TYPE_BURST_WRAP);
711 BM_SetMonitorCounter(4, BM_MASTER_PERI, BM_TRANS_TYPE_4BEAT | BM_TRANS_TYPE_8Byte | BM_TRANS_TYPE_BURST_WRAP);
712
713 BM_SetLatencyCounter();
714
715 /*select MCI monitor event*/
716 //MCI_Event_Set(0x6, 0x7); /*0x6: Si0 AR input queue full; 0x7: Si0 AW input queue full*/
717
718 return 0;
719 }
720
721 arch_initcall (mt_mon_mod_init);
722
723 static DEFINE_SPINLOCK(reg_mon_lock);
724 int register_monitor(struct mtk_monitor **p_mon, MonitorMode mode)
725 {
726 int ret = 0;
727
728 spin_lock(&reg_mon_lock);
729
730 mt_kernel_ring_buff_index = 0;
731 mt_mon_log_buff_index = 0;
732
733 if(register_mode != MODE_FREE) {
734 goto _err;
735 } else {
736 register_mode = mode;
737 *p_mon = &mtk_mon;
738 }
739
740 if(mode == MODE_MANUAL_USER || mode == MODE_MANUAL_KERNEL) {
741 if (!mt_mon_log_buff) {
742 mt_mon_log_buff = vmalloc(sizeof(struct mt_mon_log) * MON_LOG_BUFF_LEN);
743 if (!mt_mon_log_buff) {
744 printk(KERN_WARNING "fail to allocate the buffer for the monitor log\n");
745 register_mode = MODE_FREE;
746 goto _err;
747 }
748 mtk_mon.log_buff = mt_mon_log_buff;
749 }
750 }
751
752 if(mode == MODE_SCHED_SWITCH)
753 p_pmu->multicore = 0;
754 else
755 p_pmu->multicore = 1;
756
757 spin_unlock(&reg_mon_lock);
758
759 return ret;
760
761 _err:
762 p_mon = NULL;
763 spin_unlock(&reg_mon_lock);
764 return -1;
765 }
766 EXPORT_SYMBOL(register_monitor);
767
768 void unregister_monitor(struct mtk_monitor **p_mon)
769 {
770
771 spin_lock(&reg_mon_lock);
772
773 if(mt_mon_log_buff) {
774 vfree(mt_mon_log_buff);
775 mt_mon_log_buff = NULL;
776 }
777
778 register_mode = MODE_FREE;
779 *p_mon = NULL;
780
781 mt_kernel_ring_buff_index = 0;
782 mt_mon_log_buff_index = 0;
783 spin_unlock(&reg_mon_lock);
784 }
785 EXPORT_SYMBOL(unregister_monitor);