Merge tag 'v3.10.55' into update
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / arm / mach-mt8127 / emi_mpu.c
1 #include <linux/kernel.h>
2 #include <linux/module.h>
3 #include <linux/interrupt.h>
4 #include <linux/device.h>
5 #include <linux/platform_device.h>
6 #include <linux/mm.h>
7 #include <linux/uaccess.h>
8 #include <linux/slab.h>
9 #include <linux/spinlock.h>
10 #include <linux/irq.h>
11 #include <linux/sched.h>
12 #include <linux/list.h>
13 #ifdef CONFIG_MTK_AEE_FEATURE
14 #include <linux/aee.h>
15 #endif
16 #include <linux/timer.h>
17 #include <linux/workqueue.h>
18
19 #include <mach/mt_reg_base.h>
20 #include <mach/emi_mpu.h>
21 #include <mach/mt_device_apc.h>
22 #include <mach/sync_write.h>
23 #include <mach/irqs.h>
24 #include <mach/dma.h>
25
26 #define NR_REGION_ABORT 8
27 #define MAX_EMI_MPU_STORE_CMD_LEN 128
28 #define ABORT_EMI_BUS_INTERFACE 0x00800000 //DEVAPC0_D0_VIO_STA_0, idx:23
29 #define ABORT_EMI 0x00002000 //DEVAPC0_D0_VIO_STA_3, idx:13
30 #define TIMEOUT 100
31 #define AXI_VIO_MONITOR_TIME (1 * HZ)
32
33 static struct work_struct emi_mpu_work;
34 static struct workqueue_struct * emi_mpu_workqueue = NULL;
35
36 static unsigned int vio_addr;
37
38 struct mst_tbl_entry
39 {
40 u32 master;
41 u32 port;
42 u32 id_mask;
43 u32 id_val;
44 char *name;
45 };
46
47 struct emi_mpu_notifier_block
48 {
49 struct list_head list;
50 emi_mpu_notifier notifier;
51 };
52
53 static const struct mst_tbl_entry mst_tbl[] =
54 {
55 /* apmcu */
56 { .master = MST_ID_APMCU_0, .port = 0x0, .id_mask = 0b11111100, .id_val = 0b00000000, .name = "APMCU: Processor Non-Cacheable or STREX" },
57 { .master = MST_ID_APMCU_1, .port = 0x0, .id_mask = 0b11111100, .id_val = 0b00000100, .name = "APMCU: Processor write to device and Strongly_ordered memory" },
58 { .master = MST_ID_APMCU_2, .port = 0x0, .id_mask = 0b11111100, .id_val = 0b00001000, .name = "APMCU: Processor write portion of the barrier transactions" },
59 { .master = MST_ID_APMCU_3, .port = 0x0, .id_mask = 0b11111111, .id_val = 0b00001111, .name = "APMCU: Write portion of barrier caused by external DVM synchronization" },
60 { .master = MST_ID_APMCU_4, .port = 0x0, .id_mask = 0b11110000, .id_val = 0b00010000, .name = "APMCU: Write to cacheable memory from write address buffer" },
61
62 /* MM */
63 { .master = MST_ID_MM_0, .port = 0x1, .id_mask = 0b11100000, .id_val = 0b01100000, .name = "Larb0 MM Master, MMSYS" },
64 { .master = MST_ID_MM_1, .port = 0x1, .id_mask = 0b11100000, .id_val = 0b01000000, .name = "Larb1 MM Master, VDEC" },
65 { .master = MST_ID_MM_2, .port = 0x1, .id_mask = 0b11100000, .id_val = 0b00100000, .name = "Larb2 MM Master, ISP+VENC" },
66 { .master = MST_ID_MM_3, .port = 0x1, .id_mask = 0b11100000, .id_val = 0b00000000, .name = "G3D Master" },
67 { .master = MST_ID_MM_4, .port = 0x1, .id_mask = 0b11111111, .id_val = 0b11111101, .name = "M4U" },
68 { .master = MST_ID_MM_5, .port = 0x1, .id_mask = 0b11111111, .id_val = 0b11111110, .name = "M4U" },
69 { .master = MST_ID_MM_6, .port = 0x1, .id_mask = 0b11111111, .id_val = 0b11111100, .name = "M4U" },
70
71 /* Periperal */
72 { .master = MST_ID_PERI_0, .port = 0x2, .id_mask = 0b11111111, .id_val = 0b00000000, .name = "NFI" },
73 { .master = MST_ID_PERI_1, .port = 0x2, .id_mask = 0b11111111, .id_val = 0b00001000, .name = "MSDC0" }, /* MT6582:ask MSDC owner to remove emi_mpu_notifier_register and modify enum name */
74 { .master = MST_ID_PERI_2, .port = 0x2, .id_mask = 0b11111111, .id_val = 0b00010000, .name = "Audio" },
75 { .master = MST_ID_PERI_3, .port = 0x2, .id_mask = 0b11111111, .id_val = 0b00011000, .name = "USB2.0" },
76 { .master = MST_ID_PERI_4, .port = 0x2, .id_mask = 0b11111111, .id_val = 0b00000010, .name = "PWM" },
77 { .master = MST_ID_PERI_5, .port = 0x2, .id_mask = 0b11111111, .id_val = 0b00001010, .name = "MSDC1" },
78 { .master = MST_ID_PERI_6, .port = 0x2, .id_mask = 0b11111111, .id_val = 0b00010010, .name = "MSDC2" },
79 { .master = MST_ID_PERI_7, .port = 0x2, .id_mask = 0b11111111, .id_val = 0b00011010, .name = "SPI0" },
80 { .master = MST_ID_PERI_8, .port = 0x2, .id_mask = 0b11111111, .id_val = 0b00000100, .name = "MD" },
81 { .master = MST_ID_PERI_9, .port = 0x2, .id_mask = 0b11111111, .id_val = 0b00001100, .name = "SPM,FHCTL" },
82 { .master = MST_ID_PERI_10, .port = 0x2, .id_mask = 0b11111111, .id_val = 0b00010100, .name = "DBG" },
83 { .master = MST_ID_PERI_11, .port = 0x2, .id_mask = 0b11111111, .id_val = 0b00011100, .name = "THERM" },
84 { .master = MST_ID_PERI_12, .port = 0x2, .id_mask = 0b11111111, .id_val = 0b00000110, .name = "DMA" },
85 { .master = MST_ID_PERI_13, .port = 0x2, .id_mask = 0b11111111, .id_val = 0b00000001, .name = "Conn2AP" },
86
87 /* Modem */
88 { .master = MST_ID_MDMCU_0, .port = 0x3, .id_mask = 0b00000000, .id_val = 0b00000000, .name = "MDMCU" },
89
90 /* Modem HW (2G/3G) */
91 { .master = MST_ID_MDHW_0, .port = 0x4, .id_mask = 0b00000000, .id_val = 0b00000000, .name = "MDHW" },
92 };
93
94 //struct list_head emi_mpu_notifier_list[NR_MST];
95 static const char *UNKNOWN_MASTER = "unknown";
96 static spinlock_t emi_mpu_lock;
97
98 struct timer_list emi_axi_vio_timer;
99
100 char *smi_larb0_port[9] = {"disp_ovl_0", "disp_rdma", "disp_wdma", "mm_cmdq", "mdp_rdma", "mdp_wdma", "mdp_roto", "mdp_rotco", "mdp_rotvo"};
101 char *smi_larb1_port[7] = {"hw_vdec_mc_ext", "hw_vdec_pp_ext", "hw_vdec_avc_mv_ext", "hw_vdec_pred_rd_ext", "hw_vdec_pred_wr_ext", "hw_vdec_vld_ext", "hw_vdec_pp_int" };
102 char *smi_larb2_port[17] = {"cam_imgo", "cam_img2o", "cam_lsci", "cam_imgi", "cam_esfko", "cam_aao", "jpgenc_rdma", "jpgenc_bsdma", "venc_rd_comv", "venc_sv_comv",
103 "venc_rcpu", "venc_rec_frm", "venc_ref_luma", "venc_ref_chroma", "venc_bsdma", "venc_cur_luma", "venc_cur_chroma"};
104
105 static int __match_id(u32 axi_id, int tbl_idx, u32 port_ID)
106 {
107 u32 mm_larb;
108 u32 smi_port;
109
110 if (((axi_id & mst_tbl[tbl_idx].id_mask) == mst_tbl[tbl_idx].id_val) && (port_ID == mst_tbl[tbl_idx].port))
111 {
112 switch(port_ID)
113 {
114 case 0: /* ARM */
115 case 2: /* Peripheral */
116 case 3: /* MD */
117 case 4: /* MD HW (2G/3G) */
118 printk(KERN_CRIT "Violation master name is %s.\n", mst_tbl[tbl_idx].name);
119 break;
120 case 1: /* MM */
121 mm_larb = axi_id>>5;
122 smi_port = axi_id & 0x1F;
123 if(mm_larb == 0x3)
124 {
125 if(smi_port >= ARRAY_SIZE(smi_larb0_port))
126 {
127 printk(KERN_CRIT "[EMI MPU ERROR] Invalidate master ID! lookup smi table failed!\n");
128 return 0;
129 }
130 printk(KERN_CRIT "Violation master name is %s (%s).\n", mst_tbl[tbl_idx].name, smi_larb0_port[smi_port]);
131 }
132 else if(mm_larb == 0x2)
133 {
134 if(smi_port >= ARRAY_SIZE(smi_larb1_port))
135 {
136 printk(KERN_CRIT "[EMI MPU ERROR] Invalidate master ID! lookup smi table failed!\n");
137 return 0;
138 }
139 printk(KERN_CRIT "Violation master name is %s (%s).\n", mst_tbl[tbl_idx].name, smi_larb1_port[smi_port]);
140 }
141 else if(mm_larb == 0x1)
142 {
143 if(smi_port >= ARRAY_SIZE(smi_larb2_port))
144 {
145 printk(KERN_CRIT "[EMI MPU ERROR] Invalidate master ID! lookup smi table failed!\n");
146 return 0;
147 }
148 printk(KERN_CRIT "Violation master name is %s (%s).\n", mst_tbl[tbl_idx].name, smi_larb2_port[smi_port]);
149 }
150 else /*Peripheral*/
151 {
152 printk(KERN_CRIT "Violation master name is %s.\n", mst_tbl[tbl_idx].name);
153 }
154 break;
155 default:
156 printk(KERN_CRIT "[EMI MPU ERROR] Invalidate port ID! lookup bus ID table failed!\n");
157 break;
158 }
159 return 1;
160 }
161 else
162 {
163 return 0;
164 }
165 }
166
167 #if 1 //#ifndef CONFIG_MT8127_EVB_BOARD
168 static u32 __id2mst(u32 id)
169 {
170 int i;
171 u32 axi_ID;
172 u32 port_ID;
173
174 axi_ID = (id >> 3) & 0x000000FF;
175 port_ID = id & 0x00000007;
176
177 printk("[EMI MPU] axi_id = %x, port_id = %x\n", axi_ID, port_ID);
178
179 for (i = 0; i < ARRAY_SIZE(mst_tbl); i++) {
180 if (__match_id(axi_ID, i, port_ID)) {
181 return mst_tbl[i].master;
182 }
183 }
184 return MST_INVALID;
185 }
186 #endif
187
188 static char *__id2name(u32 id)
189 {
190 int i;
191 u32 axi_ID;
192 u32 port_ID;
193
194 axi_ID = (id >> 3) & 0x000000FF;
195 port_ID = id & 0x00000007;
196
197 printk("[EMI MPU] axi_id = %x, port_id = %x\n", axi_ID, port_ID);
198
199 for (i = 0; i < ARRAY_SIZE(mst_tbl); i++) {
200 if (__match_id(axi_ID, i, port_ID))
201 {
202 return mst_tbl[i].name;
203 }
204 }
205
206 return (char *)UNKNOWN_MASTER;
207 }
208
209 static void __clear_emi_mpu_vio(void)
210 {
211 u32 dbg_s, dbg_t;
212
213 /* clear violation status */
214 mt65xx_reg_sync_writel(0x000003FF, EMI_MPUP);
215 mt65xx_reg_sync_writel(0x000003FF, EMI_MPUQ);
216 mt65xx_reg_sync_writel(0x000003FF, EMI_MPUR);
217 mt65xx_reg_sync_writel(0x000003FF, EMI_MPUY);
218
219 /* clear debug info */
220 mt65xx_reg_sync_writel(0x80000000 , EMI_MPUS);
221 dbg_s = readl(IOMEM(EMI_MPUS));
222 dbg_t = readl(IOMEM(EMI_MPUT));
223
224 /* MT6582 EMI hw bug that EMI_MPUS[10:0] and EMI_MPUT can't be cleared */
225 dbg_s &= 0xFFFF0000;
226 if (dbg_s) {
227 printk(KERN_CRIT "Fail to clear EMI MPU violation\n");
228 printk(KERN_CRIT "EMI_MPUS = %x, EMI_MPUT = %x", dbg_s, dbg_t);
229 }
230 }
231
232 /*EMI MPU violation handler*/
233 #if 1 //#ifndef CONFIG_MT8127_EVB_BOARD
234 static irqreturn_t mpu_violation_irq(int irq, void *dev_id)
235 {
236 u32 dbg_s, dbg_t, dbg_pqry;
237 u32 master_ID, domain_ID, wr_vio;
238 s32 region;
239 int i;
240 char *master_name;
241
242 // Hong-Rong: need DEVAPC owner porting
243 if ((readl(IOMEM(DEVAPC0_D0_VIO_STA_0)) & ABORT_EMI_BUS_INTERFACE) == 0
244 && (readl(IOMEM(DEVAPC0_D0_VIO_STA_3)) & ABORT_EMI) == 0) {
245 printk(KERN_INFO "Not EMI MPU violation.\n");
246 return IRQ_NONE;
247 }
248
249
250 dbg_s = readl(IOMEM(EMI_MPUS));
251 dbg_t = readl(IOMEM(EMI_MPUT));
252
253 master_ID = dbg_s & 0x000007FF;
254 domain_ID = (dbg_s >> 12) & 0x00000003;
255 wr_vio = (dbg_s >> 28) & 0x00000003;
256 region = (dbg_s >> 16) & 0xFF;
257
258 for (i = 0 ; i < NR_REGION_ABORT; i++) {
259 if ((region >> i) & 1) {
260 break;
261 }
262 }
263 region = (i >= NR_REGION_ABORT)? -1: i;
264
265 switch (domain_ID) {
266 case 0:
267 dbg_pqry = readl(IOMEM(EMI_MPUP));
268 break;
269 case 1:
270 dbg_pqry = readl(IOMEM(EMI_MPUQ));
271 break;
272 case 2:
273 dbg_pqry = readl(IOMEM(EMI_MPUR));
274 break;
275 case 3:
276 dbg_pqry = readl(IOMEM(EMI_MPUY));
277 break;
278 default:
279 dbg_pqry = 0;
280 break;
281 }
282
283 /*TBD: print the abort region*/
284
285 printk(KERN_CRIT "EMI MPU violation.\n");
286 printk(KERN_CRIT "[EMI MPU] Debug info start ----------------------------------------\n");
287
288 printk(KERN_CRIT "EMI_MPUS = %x, EMI_MPUT = %x.\n", dbg_s, dbg_t);
289 printk(KERN_CRIT "Current process is \"%s \" (pid: %i).\n", current->comm, current->pid);
290 printk(KERN_CRIT "Violation address is 0x%x.\n", dbg_t + EMI_PHY_OFFSET);
291 printk(KERN_CRIT "Violation master ID is 0x%x.\n", master_ID);
292 /*print out the murderer name*/
293 master_name = __id2name(master_ID);
294 printk(KERN_CRIT "Violation domain ID is 0x%x.\n", domain_ID);
295 printk(KERN_CRIT "%s violation.\n", (wr_vio == 1)? "Write": "Read");
296 printk(KERN_CRIT "Corrupted region is %d\n\r", region);
297 if (dbg_pqry & OOR_VIO) {
298 printk(KERN_CRIT "Out of range violation.\n");
299 }
300 printk(KERN_CRIT "[EMI MPU] Debug info end------------------------------------------\n");
301
302 #ifdef CONFIG_MTK_AEE_FEATURE
303 //aee_kernel_exception("EMI MPU", "EMI MPU violation.\nEMP_MPUS = 0x%x, EMI_MPUT = 0x%x, EMI_MPU(PQR).\n", dbg_s, dbg_t+EMI_PHY_OFFSET, dbg_pqry);
304 aee_kernel_exception("EMI MPU", "EMI MPU violation.\nEMP_MPUS = 0x%x, EMI_MPUT = 0x%x, module is %s.\n", dbg_s, dbg_t+EMI_PHY_OFFSET, master_name);
305 #endif
306
307 __clear_emi_mpu_vio();
308
309
310 if ((readl(IOMEM(DEVAPC0_D0_VIO_STA_0)) & ABORT_EMI_BUS_INTERFACE) != 0)
311 {
312 mt65xx_reg_sync_writel(ABORT_EMI_BUS_INTERFACE, DEVAPC0_D0_VIO_STA_0);
313 }
314
315 if ((readl(IOMEM(DEVAPC0_D0_VIO_STA_3)) & ABORT_EMI) != 0)
316 {
317 mt65xx_reg_sync_writel(ABORT_EMI, DEVAPC0_D0_VIO_STA_3);
318 }
319
320 printk("[EMI MPU] _id2mst = %d\n", __id2mst(master_ID));
321
322 #if 0 //Marcos(MT6582): Each hw module has an unique ID. There is no need to use notifier function to distinguish different hw module which has the same bus ID.
323 list_for_each(p, &(emi_mpu_notifier_list[__id2mst(master_ID)])) {
324 block = list_entry(p, struct emi_mpu_notifier_block, list);
325 block->notifier(dbg_t + EMI_PHY_OFFSET, wr_vio);
326 }
327 #endif
328
329 vio_addr = dbg_t + EMI_PHY_OFFSET;
330
331 return IRQ_HANDLED;
332 }
333 #endif
334
335 /*
336 * emi_mpu_set_region_protection: protect a region.
337 * @start: start address of the region
338 * @end: end address of the region
339 * @region: EMI MPU region id
340 * @access_permission: EMI MPU access permission
341 * Return 0 for success, otherwise negative status code.
342 */
343 int emi_mpu_set_region_protection(unsigned int start, unsigned int end, int region, unsigned int access_permission)
344 {
345 int ret = 0;
346 unsigned int tmp;
347 unsigned long flags;
348
349 if((end != 0) || (start !=0)) {
350 /*Address 64KB alignment*/
351 start -= EMI_PHY_OFFSET;
352 end -= EMI_PHY_OFFSET;
353 start = start >> 16;
354 end = end >> 16;
355
356 if (end <= start) {
357 return -EINVAL;
358 }
359 }
360
361 spin_lock_irqsave(&emi_mpu_lock, flags);
362
363 switch (region) {
364 case 0:
365 //Marcos: Clear access right before setting MPU address (Mt6582 design)
366 tmp = readl(IOMEM(EMI_MPUI)) & 0xFFFF0000;
367 mt65xx_reg_sync_writel(0, EMI_MPUI);
368 mt65xx_reg_sync_writel((start << 16) | end, EMI_MPUA);
369 mt65xx_reg_sync_writel(tmp | access_permission, EMI_MPUI);
370 break;
371
372 case 1:
373 //Marcos: Clear access right before setting MPU address (Mt6582 design)
374 tmp = readl(IOMEM(EMI_MPUI)) & 0x0000FFFF;
375 mt65xx_reg_sync_writel(0, EMI_MPUI);
376 mt65xx_reg_sync_writel((start << 16) | end, EMI_MPUB);
377 mt65xx_reg_sync_writel(tmp | (access_permission << 16), EMI_MPUI);
378 break;
379
380 case 2:
381 //Marcos: Clear access right before setting MPU address (Mt6582 design)
382 tmp = readl(IOMEM(EMI_MPUJ)) & 0xFFFF0000;
383 mt65xx_reg_sync_writel(0, EMI_MPUJ);
384 mt65xx_reg_sync_writel((start << 16) | end, EMI_MPUC);
385 mt65xx_reg_sync_writel(tmp | access_permission, EMI_MPUJ);
386 break;
387
388 case 3:
389 //Marcos: Clear access right before setting MPU address (Mt6582 design)
390 tmp = readl(IOMEM(EMI_MPUJ)) & 0x0000FFFF;
391 mt65xx_reg_sync_writel(0, EMI_MPUJ);
392 mt65xx_reg_sync_writel((start << 16) | end, EMI_MPUD);
393 mt65xx_reg_sync_writel(tmp | (access_permission << 16), EMI_MPUJ);
394 break;
395
396 case 4:
397 //Marcos: Clear access right before setting MPU address (Mt6582 design)
398 tmp = readl(IOMEM(EMI_MPUK)) & 0xFFFF0000;
399 mt65xx_reg_sync_writel(0, EMI_MPUK);
400 mt65xx_reg_sync_writel((start << 16) | end, EMI_MPUE);
401 mt65xx_reg_sync_writel(tmp | access_permission, EMI_MPUK);
402 break;
403
404 case 5:
405 //Marcos: Clear access right before setting MPU address (Mt6582 design)
406 tmp = readl(IOMEM(EMI_MPUK)) & 0x0000FFFF;
407 mt65xx_reg_sync_writel(0, EMI_MPUK);
408 mt65xx_reg_sync_writel((start << 16) | end, EMI_MPUF);
409 mt65xx_reg_sync_writel(tmp | (access_permission << 16), EMI_MPUK);
410 break;
411
412 case 6:
413 //Marcos: Clear access right before setting MPU address (Mt6582 design)
414 tmp = readl(IOMEM(EMI_MPUL)) & 0xFFFF0000;
415 mt65xx_reg_sync_writel(0, EMI_MPUL);
416 mt65xx_reg_sync_writel((start << 16) | end, EMI_MPUG);
417 mt65xx_reg_sync_writel(tmp | access_permission, EMI_MPUL);
418 break;
419
420 case 7:
421 //Marcos: Clear access right before setting MPU address (Mt6582 design)
422 tmp = readl(IOMEM(EMI_MPUL)) & 0x0000FFFF;
423 mt65xx_reg_sync_writel(0, EMI_MPUL);
424 mt65xx_reg_sync_writel((start << 16) | end, EMI_MPUH);
425 mt65xx_reg_sync_writel(tmp | (access_permission << 16), EMI_MPUL);
426 break;
427
428 default:
429 ret = -EINVAL;
430 break;
431 }
432
433 spin_unlock_irqrestore(&emi_mpu_lock, flags);
434
435 return ret;
436 }
437
438 /*
439 * emi_mpu_notifier_register: register a notifier.
440 * master: MST_ID_xxx
441 * notifier: the callback function
442 * Return 0 for success, otherwise negative error code.
443 */
444 #if 0
445 int emi_mpu_notifier_register(int master, emi_mpu_notifier notifier)
446 {
447 struct emi_mpu_notifier_block *block;
448 static int emi_mpu_notifier_init = 0;
449 int i;
450
451 if (master >= MST_INVALID) {
452 return -EINVAL;
453 }
454
455 block = kmalloc(sizeof(struct emi_mpu_notifier_block), GFP_KERNEL);
456 if (!block) {
457 return -ENOMEM;
458 }
459
460 if (!emi_mpu_notifier_init) {
461 for (i = 0; i < NR_MST; i++) {
462 INIT_LIST_HEAD(&(emi_mpu_notifier_list[i]));
463 }
464 emi_mpu_notifier_init = 1;
465 }
466
467 block->notifier = notifier;
468 list_add(&(block->list), &(emi_mpu_notifier_list[master]));
469
470 return 0;
471 }
472 #endif
473
474 static ssize_t emi_mpu_show(struct device_driver *driver, char *buf)
475 {
476 char *ptr = buf;
477 unsigned int start, end;
478 unsigned int reg_value;
479 unsigned int d0, d1, d2, d3;
480 static const char *permission[6] =
481 {
482 "No protect",
483 "Only R/W for secure access",
484 "Only R/W for secure access, and non-secure read access",
485 "Only R/W for secure access, and non-secure write access",
486 "Only R for secure/non-secure",
487 "Both R/W are forbidden"
488 };
489
490 reg_value = readl(IOMEM(EMI_MPUA));
491 start = ((reg_value >> 16) << 16) + EMI_PHY_OFFSET;
492 end = ((reg_value & 0xFFFF) << 16) + EMI_PHY_OFFSET;
493 ptr += sprintf(ptr, "Region 0 --> 0x%x to 0x%x\n", start, end);
494
495 reg_value = readl(IOMEM(EMI_MPUB));
496 start = ((reg_value >> 16) << 16) + EMI_PHY_OFFSET;
497 end = ((reg_value & 0xFFFF) << 16) + EMI_PHY_OFFSET;
498 ptr += sprintf(ptr, "Region 1 --> 0x%x to 0x%x\n", start, end);
499
500 reg_value = readl(IOMEM(EMI_MPUC));
501 start = ((reg_value >> 16) << 16) + EMI_PHY_OFFSET;
502 end = ((reg_value & 0xFFFF) << 16) + EMI_PHY_OFFSET;
503 ptr += sprintf(ptr, "Region 2 --> 0x%x to 0x%x\n", start, end);
504
505 reg_value = readl(IOMEM(EMI_MPUD));
506 start = ((reg_value >> 16) << 16) + EMI_PHY_OFFSET;
507 end = ((reg_value & 0xFFFF) << 16) + EMI_PHY_OFFSET;
508 ptr += sprintf(ptr, "Region 3 --> 0x%x to 0x%x\n", start, end);
509
510 reg_value = readl(IOMEM(EMI_MPUE));
511 start = ((reg_value >> 16) << 16) + EMI_PHY_OFFSET;
512 end = ((reg_value & 0xFFFF) << 16) + EMI_PHY_OFFSET;
513 ptr += sprintf(ptr, "Region 4 --> 0x%x to 0x%x\n", start, end);
514
515 reg_value = readl(IOMEM(EMI_MPUF));
516 start = ((reg_value >> 16) << 16) + EMI_PHY_OFFSET;
517 end = ((reg_value & 0xFFFF) << 16) + EMI_PHY_OFFSET;
518 ptr += sprintf(ptr, "Region 5 --> 0x%x to 0x%x\n", start, end);
519
520 reg_value = readl(IOMEM(EMI_MPUG));
521 start = ((reg_value >> 16) << 16) + EMI_PHY_OFFSET;
522 end = ((reg_value & 0xFFFF) << 16) + EMI_PHY_OFFSET;
523 ptr += sprintf(ptr, "Region 6 --> 0x%x to 0x%x\n", start, end);
524
525 reg_value = readl(IOMEM(EMI_MPUH));
526 start = ((reg_value >> 16) << 16) + EMI_PHY_OFFSET;
527 end = ((reg_value & 0xFFFF) << 16) + EMI_PHY_OFFSET;
528 ptr += sprintf(ptr, "Region 7 --> 0x%x to 0x%x\n", start, end);
529
530 ptr += sprintf (ptr, "\n");
531
532 reg_value = readl(IOMEM(EMI_MPUI));
533 d0 = (reg_value & 0x7);
534 d1 = (reg_value >> 3) & 0x7;
535 d2 = (reg_value >> 6) & 0x7;
536 d3 = (reg_value >> 9) & 0x7;
537 ptr += sprintf(ptr, "Region 0 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", permission[d0], permission[d1], permission[d2], permission[d3]);
538
539 d0 = ((reg_value>>16) & 0x7);
540 d1 = ((reg_value>>16) >> 3) & 0x7;
541 d2 = ((reg_value>>16) >> 6) & 0x7;
542 d3 = ((reg_value>>16) >> 9) & 0x7;
543 ptr += sprintf(ptr, "Region 1 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", permission[d0], permission[d1], permission[d2], permission[d3]);
544
545 reg_value = readl(IOMEM(EMI_MPUJ));
546 d0 = (reg_value & 0x7);
547 d1 = (reg_value >> 3) & 0x7;
548 d2 = (reg_value >> 6) & 0x7;
549 d3 = (reg_value >> 9) & 0x7;
550 ptr += sprintf(ptr, "Region 2 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", permission[d0], permission[d1], permission[d2], permission[d3]);
551
552 d0 = ((reg_value>>16) & 0x7);
553 d1 = ((reg_value>>16) >> 3) & 0x7;
554 d2 = ((reg_value>>16) >> 6) & 0x7;
555 d3 = ((reg_value>>16) >> 9) & 0x7;
556 ptr += sprintf(ptr, "Region 3 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", permission[d0], permission[d1], permission[d2], permission[d3]);
557
558 reg_value = readl(IOMEM(EMI_MPUK));
559 d0 = (reg_value & 0x7);
560 d1 = (reg_value >> 3) & 0x7;
561 d2 = (reg_value >> 6) & 0x7;
562 d3 = (reg_value >> 9) & 0x7;
563 ptr += sprintf(ptr, "Region 4 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", permission[d0], permission[d1], permission[d2], permission[d3]);
564
565 d0 = ((reg_value>>16) & 0x7);
566 d1 = ((reg_value>>16) >> 3) & 0x7;
567 d2 = ((reg_value>>16) >> 6) & 0x7;
568 d3 = ((reg_value>>16) >> 9) & 0x7;
569 ptr += sprintf(ptr, "Region 5 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", permission[d0], permission[d1], permission[d2], permission[d3]);
570
571 reg_value = readl(IOMEM(EMI_MPUL));
572 d0 = (reg_value & 0x7);
573 d1 = (reg_value >> 3) & 0x7;
574 d2 = (reg_value >> 6) & 0x7;
575 d3 = (reg_value >> 9) & 0x7;
576 ptr += sprintf(ptr, "Region 6 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", permission[d0], permission[d1], permission[d2], permission[d3]);
577
578 d0 = ((reg_value>>16) & 0x7);
579 d1 = ((reg_value>>16) >> 3) & 0x7;
580 d2 = ((reg_value>>16) >> 6) & 0x7;
581 d3 = ((reg_value>>16) >> 9) & 0x7;
582 ptr += sprintf(ptr, "Region 7 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", permission[d0], permission[d1], permission[d2], permission[d3]);
583
584 return strlen(buf);
585 }
586
587 static ssize_t emi_mpu_store(struct device_driver *driver, const char *buf, size_t count)
588 {
589 int i;
590 unsigned int start_addr;
591 unsigned int end_addr;
592 unsigned int region;
593 unsigned int access_permission;
594 char *command;
595 char *ptr;
596 char *token [5];
597
598 if ((strlen(buf) + 1) > MAX_EMI_MPU_STORE_CMD_LEN) {
599 printk(KERN_CRIT "emi_mpu_store command overflow.");
600 return count;
601 }
602 printk(KERN_CRIT "emi_mpu_store: %s\n", buf);
603
604 command = kmalloc((size_t)MAX_EMI_MPU_STORE_CMD_LEN, GFP_KERNEL);
605 if (!command) {
606 return count;
607 }
608 strcpy(command, buf);
609 ptr = (char *)buf;
610
611 if (!strncmp(buf, EN_MPU_STR, strlen(EN_MPU_STR))) {
612 i = 0;
613 while (ptr != NULL) {
614 ptr = strsep(&command, " ");
615 token[i] = ptr;
616 printk(KERN_DEBUG "token[%d] = %s\n", i, token[i]);
617 i++;
618 }
619 for (i = 0; i < 5; i++) {
620 printk(KERN_DEBUG "token[%d] = %s\n", i, token[i]);
621 }
622
623 start_addr = simple_strtoul(token[1], &token[1], 16);
624 end_addr = simple_strtoul(token[2], &token[2], 16);
625 region = simple_strtoul(token[3], &token[3], 16);
626 access_permission = simple_strtoul(token[4], &token[4], 16);
627 emi_mpu_set_region_protection(start_addr, end_addr, region, access_permission);
628 printk(KERN_CRIT "Set EMI_MPU: start: 0x%x, end: 0x%x, region: %d, permission: 0x%x.\n", start_addr, end_addr, region, access_permission);
629 } else if (!strncmp(buf, DIS_MPU_STR, strlen(DIS_MPU_STR))) {
630 i = 0;
631 while (ptr != NULL) {
632 ptr = strsep (&command, " ");
633 token[i] = ptr;
634 printk(KERN_DEBUG "token[%d] = %s\n", i, token[i]);
635 i++;
636 }
637 for (i = 0;i < 5; i++) {
638 printk(KERN_DEBUG "token[%d] = %s\n", i, token[i]);
639 }
640
641 start_addr = simple_strtoul(token[1], &token[1], 16);
642 end_addr = simple_strtoul(token[2], &token[2], 16);
643 region = simple_strtoul(token[3], &token[3], 16);
644 emi_mpu_set_region_protection(0x0, 0x0, region, SET_ACCESS_PERMISSON(NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION));
645 printk("set EMI MPU: start: 0x%x, end: 0x%x, region: %d, permission: 0x%x\n", 0, 0, region, SET_ACCESS_PERMISSON(NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION));
646 } else {
647 printk(KERN_CRIT "Unknown emi_mpu command.\n");
648 }
649
650 kfree(command);
651
652 return count;
653 }
654
655 DRIVER_ATTR(mpu_config, 0644, emi_mpu_show, emi_mpu_store);
656
657 void mtk_search_full_pgtab(void)
658 {
659 pgd_t *pgd;
660 pud_t *pud;
661 pmd_t *pmd;
662 pte_t *pte;
663 unsigned long addr;
664 unsigned long addr_2nd, addr_2nd_end;
665 unsigned int v_addr = vio_addr;
666
667 /*FIXME: testing*/
668 //vio_addr = 0x9DE0D000;
669
670 for(addr=0xC0000000; addr<0xFFF00000; addr+=0x100000)
671 {
672 pgd = pgd_offset(&init_mm, addr);
673 if (pgd_none(*pgd) || !pgd_present(*pgd))
674 {
675 continue;
676 }
677
678 pud = pud_offset(pgd, addr);
679 if (pud_none(*pud) || !pud_present(*pud))
680 {
681 continue;
682 }
683
684 pmd = pmd_offset(pud, addr);
685 if (pmd_none(*pmd) || !pmd_present(*pmd))
686 {
687 continue;
688 }
689
690 //printk("[EMI MPU] ============= addr = %x\n", addr);
691
692 #ifndef CONFIG_ARM_LPAE
693 if ((pmd_val(*pmd) & PMD_TYPE_MASK) == PMD_TYPE_TABLE)
694 {
695 /* Page table entry*/
696 //printk("[EMI MPU] 2nd Entry pmd: %lx, *pmd = %lx\n", (unsigned long)(pmd), (unsigned long)pmd_val(*(pmd)));
697 addr_2nd = addr;
698 addr_2nd_end = addr_2nd + 0x100000;
699 for(; addr_2nd<(addr_2nd_end); addr_2nd+=0x1000)
700 {
701 pte = pte_offset_map(pmd, addr_2nd);
702 //printk("[EMI MPU] pmd: %x, pte: %x, *pte = %x, addr_2nd = 0x%x, addr_2nd_end = 0x%x\n", (unsigned long)(pmd), (unsigned long)(pte), (unsigned long)pte_val(*(pte)), addr_2nd, addr_2nd_end);
703 if(((unsigned long)v_addr & PAGE_MASK) == ((unsigned long)pte_val(*(pte)) & PAGE_MASK))
704 {
705 printk("[EMI MPU] Find page entry section at pte: %lx. violation address = 0x%x\n", (unsigned long)(pte), v_addr);
706 return;
707 }
708 }
709 }
710 else
711 {
712 //printk("[EMI MPU] Section pmd: %x, addr = 0x%x\n", (unsigned long)(pmd), addr);
713 /* Section */
714 //if(v_addr>>20 == (unsigned long)pmd_val(*(pmd))>>20)
715 if(((unsigned long)pmd_val(*(pmd)) & SECTION_MASK) == ((unsigned long)v_addr & SECTION_MASK))
716 {
717 printk("[EMI MPU] Find page entry section at pmd: %lx. violation address = 0x%x\n", (unsigned long)(pmd), v_addr);
718 return;
719 }
720 }
721 #else
722 /* TBD */
723 #endif
724 }
725 printk("[EMI MPU] ****** Can not find page table entry! violation address = 0x%x ******\n", v_addr);
726
727 return;
728 }
729
730 void emi_mpu_work_callback(struct work_struct *work)
731 {
732 printk("[EMI MPU] Enter EMI MPU workqueue!\n");
733 mtk_search_full_pgtab();
734 printk("[EMI MPU] Exit EMI MPU workqueue!\n");
735 }
736
737 static ssize_t pgt_scan_show(struct device_driver *driver, char *buf)
738 {
739 return 0;
740 }
741
742 static ssize_t pgt_scan_store(struct device_driver *driver, const char *buf, size_t count)
743 {
744 unsigned int value;
745 unsigned int ret;
746
747 if (unlikely(sscanf(buf, "%u", &value) != 1))
748 return -EINVAL;
749
750 if(value == 1)
751 {
752 ret = queue_work(emi_mpu_workqueue, &emi_mpu_work);
753 if(!ret)
754 {
755 printk(KERN_DEBUG "[EMI MPU] submit workqueue failed, ret = %d\n", ret);
756 }
757 }
758
759 return count;
760 }
761 DRIVER_ATTR(pgt_scan, 0644, pgt_scan_show, pgt_scan_store);
762
763 static void emi_axi_set_chker(const unsigned int setting)
764 {
765 int value;
766
767 value = readl(IOMEM(EMI_CHKER));
768 value &= ~0x7;
769 value |= setting;
770
771 mt65xx_reg_sync_writel(value, EMI_CHKER);
772 }
773
774 static void emi_axi_set_master(const unsigned int setting)
775 {
776 int value;
777
778 value = readl(IOMEM(EMI_CHKER));
779 value &= ~(MASTER_ALL << AXI_NON_ALIGN_CHK_MST);
780 value |= (setting & 0x7) << AXI_NON_ALIGN_CHK_MST;
781
782 mt65xx_reg_sync_writel(value, EMI_CHKER);
783 }
784
785 static void emi_axi_dump_info(int aee_ke_en)
786 {
787 int value, master_ID;
788 char *master_name;
789
790 value = readl(IOMEM(EMI_CHKER));
791 master_ID = (value & 0x07FF0000) >> 16;
792
793 if (value & 0x7FFF0000)
794 {
795 printk(KERN_CRIT "AXI violation.\n");
796 printk(KERN_CRIT "[EMI MPU AXI] Debug info start ----------------------------------------\n");
797
798 printk(KERN_CRIT "EMI_CHKER = %x.\n", value);
799 printk(KERN_CRIT "Violation address is 0x%x.\n", readl(IOMEM(EMI_CHKER_ADR)));
800 printk(KERN_CRIT "Violation master ID is 0x%x.\n", master_ID);
801 printk(KERN_CRIT "Violation type is: AXI_ADR_CHK_EN(%d), AXI_LOCK_CHK_EN(%d), AXI_NON_ALIGN_CHK_EN(%d).\n",
802 (value & (1 << AXI_ADR_CHK_EN)) ? 1 : 0, (value & (1 << AXI_LOCK_CHK_EN)) ? 1 : 0, (value & (1 << AXI_NON_ALIGN_CHK_EN)) ? 1 : 0);
803 printk(KERN_CRIT "%s violation.\n", (value & AXI_VIO_WR)? "Write": "Read");
804
805 printk(KERN_CRIT "[EMI MPU AXI] Debug info end ----------------------------------------\n");
806
807 master_name = __id2name(master_ID);
808 #ifdef CONFIG_MTK_AEE_FEATURE
809 if (aee_ke_en)
810 aee_kernel_exception("EMI MPU AXI", "AXI violation.\EMI_CHKER = 0x%x, module is %s.\n", value, master_name);
811 #endif
812 // clear AXI checker status
813 mt65xx_reg_sync_writel((1 << AXI_VIO_CLR) | readl(IOMEM(EMI_CHKER)), EMI_CHKER);
814 }
815 }
816
817 static void emi_axi_vio_timer_func(unsigned long a)
818 {
819 emi_axi_dump_info(1);
820
821 mod_timer(&emi_axi_vio_timer, jiffies + AXI_VIO_MONITOR_TIME);
822 }
823
824 static ssize_t emi_axi_vio_show(struct device_driver *driver, char *buf)
825 {
826 int value;
827
828 value = readl(IOMEM(EMI_CHKER));
829
830 emi_axi_dump_info(0);
831
832 return snprintf(buf, PAGE_SIZE, "AXI vio setting is: ADR_CHK_EN %s, LOCK_CHK_EN %s, NON_ALIGN_CHK_EN %s\n", (value & (1 << AXI_ADR_CHK_EN)) ? "ON" : "OFF",
833 (value & (1 << AXI_LOCK_CHK_EN)) ? "ON" : "OFF",
834 (value & (1 << AXI_NON_ALIGN_CHK_EN)) ? "ON" : "OFF");
835 }
836
837 ssize_t emi_axi_vio_store(struct device_driver *driver, const char *buf, size_t count)
838 {
839 int value;
840 int cpu = 0; //assign timer to CPU0 to avoid CPU plug-out and timer will be unavailable
841
842 value = readl(IOMEM(EMI_CHKER));
843
844 if (!strncmp(buf, "ADR_CHK_ON", strlen("ADR_CHK_ON"))) {
845 emi_axi_set_chker(1 << AXI_ADR_CHK_EN);
846 add_timer_on(&emi_axi_vio_timer, cpu);
847 } else if (!strncmp(buf, "LOCK_CHK_ON", strlen("LOCK_CHK_ON"))) {
848 emi_axi_set_chker(1 << AXI_LOCK_CHK_EN);
849 add_timer_on(&emi_axi_vio_timer, cpu);
850 } else if (!strncmp(buf, "NON_ALIGN_CHK_ON", strlen("NON_ALIGN_CHK_ON"))) {
851 emi_axi_set_chker(1 << AXI_NON_ALIGN_CHK_EN);
852 add_timer_on(&emi_axi_vio_timer, cpu);
853 } else if (!strncmp(buf, "OFF", strlen("OFF"))) {
854 emi_axi_set_chker(0);
855 del_timer(&emi_axi_vio_timer);
856 } else {
857 printk("invalid setting\n");
858 }
859
860 return count;
861 }
862
863 DRIVER_ATTR(emi_axi_vio, 0644, emi_axi_vio_show, emi_axi_vio_store);
864
865 /*
866 static int emi_mpu_panic_cb(struct notifier_block *this, unsigned long event, void *ptr)
867 {
868 emi_axi_dump_info(1);
869
870 return NOTIFY_DONE;
871 }*/
872
873 #if 1 //#if !defined(USER_BUILD_KERNEL) || !defined(CONFIG_MT8127_EVB_BOARD)
874 static struct device_driver emi_mpu_ctrl =
875 {
876 .name = "emi_mpu_ctrl",
877 .bus = &platform_bus_type,
878 .owner = THIS_MODULE,
879 };
880 #endif
881 /*
882 static struct notifier_block emi_mpu_blk = {
883 .notifier_call = emi_mpu_panic_cb,
884 };*/
885
886 static int __init emi_mpu_mod_init(void)
887 {
888 #if 1 //#if !defined(USER_BUILD_KERNEL) || !defined(CONFIG_MT8127_EVB_BOARD)
889 int ret;
890 #endif
891
892 printk(KERN_INFO "Initialize EMI MPU.\n");
893
894 spin_lock_init(&emi_mpu_lock);
895
896 __clear_emi_mpu_vio();
897
898 #ifndef CONFIG_MTK_IN_HOUSE_TEE_SUPPORT
899 //Set Device APC for EMI-MPU.
900 mt65xx_reg_sync_writel(readl(IOMEM(DEVAPC0_APC_CON)) & (0xFFFFFFFF ^ (1<<2)), DEVAPC0_APC_CON);
901 mt65xx_reg_sync_writel(readl(IOMEM(DEVAPC0_PD_APC_CON)) & (0xFFFFFFFF ^ (1<<2)), DEVAPC0_PD_APC_CON);
902
903 mt65xx_reg_sync_writel(ABORT_EMI_BUS_INTERFACE, DEVAPC0_D0_VIO_STA_0);
904 mt65xx_reg_sync_writel(readl(IOMEM(DEVAPC0_D0_VIO_MASK_0)) & (0xFFFFFFFF ^ (1<<23)), DEVAPC0_D0_VIO_MASK_0);
905 mt65xx_reg_sync_writel(ABORT_EMI, DEVAPC0_D0_VIO_STA_3);
906 mt65xx_reg_sync_writel(readl(IOMEM(DEVAPC0_D0_VIO_MASK_3)) & (0xFFFFFFFF ^ (1<<13)), DEVAPC0_D0_VIO_MASK_3);
907 #endif
908
909 /*
910 * NoteXXX: Interrupts of vilation (including SPC in SMI, or EMI MPU)
911 * are triggered by the device APC.
912 * Need to share the interrupt with the SPC driver.
913 */
914 #if 1 //#ifndef CONFIG_MT8127_EVB_BOARD
915 ret = request_irq(MT_APARM_DOMAIN_IRQ_ID, (irq_handler_t)mpu_violation_irq, IRQF_TRIGGER_LOW | IRQF_SHARED, "mt_emi_mpu", &emi_mpu_ctrl);
916 if (ret != 0) {
917 printk(KERN_CRIT "Fail to request EMI_MPU interrupt. Error = %d.\n", ret);
918 return ret;
919 }
920 #endif
921
922 /* AXI violation monitor setting and timer function create */
923 mt65xx_reg_sync_writel((1 << AXI_VIO_CLR) | readl(IOMEM(EMI_CHKER)), EMI_CHKER);
924 emi_axi_set_master(MASTER_ALL);
925 init_timer(&emi_axi_vio_timer);
926 emi_axi_vio_timer.expires = jiffies + AXI_VIO_MONITOR_TIME;
927 emi_axi_vio_timer.function = &emi_axi_vio_timer_func;
928 emi_axi_vio_timer.data = ((unsigned long) 0 );
929
930 #if !defined(USER_BUILD_KERNEL)
931 /* Enable AXI 4KB boundary violation monitor timer */
932 emi_axi_set_chker(1 << AXI_ADR_CHK_EN);
933 //add_timer_on(&emi_axi_vio_timer, 0);
934
935 /* register driver and create sysfs files */
936 ret = driver_register(&emi_mpu_ctrl);
937 if (ret) {
938 printk(KERN_CRIT "Fail to register EMI_MPU driver.\n");
939 }
940 ret = driver_create_file(&emi_mpu_ctrl, &driver_attr_mpu_config);
941 ret = driver_create_file(&emi_mpu_ctrl, &driver_attr_emi_axi_vio);
942 ret = driver_create_file(&emi_mpu_ctrl, &driver_attr_pgt_scan);
943 if (ret) {
944 printk(KERN_CRIT "Fail to create AXI violation monitor sysfs file.\n");
945 }
946 #endif
947
948 //atomic_notifier_chain_register(&panic_notifier_list, &emi_mpu_blk);
949
950 /* Create a workqueue to search pagetable entry */
951 emi_mpu_workqueue = create_singlethread_workqueue("emi_mpu");
952 INIT_WORK(&emi_mpu_work, emi_mpu_work_callback);
953 /*Init for testing*/
954 //emi_mpu_set_region_protection(0x9c000000,
955 // 0x9d7fffff, /*MD_IMG_REGION_LEN*/
956 // 0, /*region*/
957 // SET_ACCESS_PERMISSON(SEC_R_NSEC_R, SEC_R_NSEC_R, SEC_R_NSEC_R, SEC_R_NSEC_R));
958
959 return 0;
960 }
961
962 static void __exit emi_mpu_mod_exit(void)
963 {
964 }
965
966 module_init(emi_mpu_mod_init);
967 module_exit(emi_mpu_mod_exit);
968
969 EXPORT_SYMBOL(emi_mpu_set_region_protection);
970 //EXPORT_SYMBOL(start_mm_mau_protect);