1 /* linux/drivers/iommu/exynos7_iommu.c
3 * Copyright (c) 2013-2014 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
11 #ifdef CONFIG_EXYNOS_IOMMU_DEBUG
15 #include <linux/kernel.h>
17 #include <linux/interrupt.h>
18 #include <linux/clk.h>
19 #include <linux/err.h>
20 #include <linux/errno.h>
21 #include <linux/device.h>
22 #include <linux/sched.h>
23 #include <linux/smc.h>
25 #include <asm/pgtable.h>
27 #include "exynos-iommu.h"
29 #define CFG_MASK 0x01101FBC /* Selecting bit 24, 20, 12-7, 5-2 */
31 #define PB_INFO_NUM(reg) ((reg) & 0xFF)
32 #define L1TLB_ATTR_IM (1 << 16)
34 #define REG_PT_BASE_PPN 0x00C
35 #define REG_MMU_FLUSH 0x010
36 #define REG_MMU_FLUSH_ENTRY 0x014
37 #define REG_MMU_FLUSH_RANGE 0x018
38 #define REG_FLUSH_RANGE_START 0x020
39 #define REG_FLUSH_RANGE_END 0x024
40 #define REG_MMU_CAPA 0x030
41 #define REG_INT_STATUS 0x060
42 #define REG_INT_CLEAR 0x064
43 #define REG_FAULT_AR_ADDR 0x070
44 #define REG_FAULT_AR_TRANS_INFO 0x078
45 #define REG_FAULT_AW_ADDR 0x080
46 #define REG_FAULT_AW_TRANS_INFO 0x088
47 #define REG_L1TLB_CFG 0x100 /* sysmmu v5.1 only */
48 #define REG_L1TLB_CTRL 0x108 /* sysmmu v5.1 only */
49 #define REG_L2TLB_CFG 0x200 /* sysmmu that has L2TLB only*/
50 #define REG_PB_LMM 0x300
51 #define REG_PB_INDICATE 0x308
52 #define REG_PB_CFG 0x310
53 #define REG_PB_START_ADDR 0x320
54 #define REG_PB_END_ADDR 0x328
55 #define REG_PB_INFO 0x350
56 #define REG_SW_DF_VPN 0x400 /* sysmmu v5.1 only */
57 #define REG_SW_DF_VPN_CMD_NUM 0x408 /* sysmmu v5.1 only */
58 #define REG_L1TLB_READ_ENTRY 0x750
59 #define REG_L1TLB_ENTRY_VPN 0x754
60 #define REG_L1TLB_ENTRY_PPN 0x75C
61 #define REG_L1TLB_ENTRY_ATTR 0x764
63 /* 'reg' argument must be the value of REG_MMU_CAPA register */
64 #define MMU_NUM_L1TLB_ENTRIES(reg) (reg & 0xFF)
65 #define MMU_HAVE_PB(reg) (!!((reg >> 20) & 0xF))
66 #define MMU_HAVE_L2TLB(reg) (!!((reg >> 8) & 0xFFF))
68 #define MMU_MAX_DF_CMD 8
70 #define SYSMMU_FAULTS_NUM (SYSMMU_FAULT_UNKNOWN + 1)
72 static char *sysmmu_fault_name
[SYSMMU_FAULTS_NUM
] = {
75 "L1TLB MULTI-HIT FAULT",
81 static bool has_sysmmu_capable_pbuf(void __iomem
*sfrbase
)
83 unsigned long cfg
= __raw_readl(sfrbase
+ REG_MMU_CAPA
);
85 return MMU_HAVE_PB(cfg
) ? true : false;
88 void __sysmmu_tlb_invalidate_flpdcache(void __iomem
*sfrbase
, dma_addr_t iova
)
90 if (has_sysmmu_capable_pbuf(sfrbase
))
91 __raw_writel(iova
| 0x1, sfrbase
+ REG_MMU_FLUSH_ENTRY
);
94 void __sysmmu_tlb_invalidate_entry(void __iomem
*sfrbase
, dma_addr_t iova
)
96 __raw_writel(iova
| 0x1, sfrbase
+ REG_MMU_FLUSH_ENTRY
);
99 void __sysmmu_tlb_invalidate(struct sysmmu_drvdata
*drvdata
,
100 dma_addr_t iova
, size_t size
)
102 void * __iomem sfrbase
= drvdata
->sfrbase
;
104 if (__raw_sysmmu_version(sfrbase
) >= MAKE_MMU_VER(5, 1)) {
105 __raw_writel(iova
, sfrbase
+ REG_FLUSH_RANGE_START
);
106 __raw_writel(size
- 1 + iova
, sfrbase
+ REG_FLUSH_RANGE_END
);
107 __raw_writel(0x1, sfrbase
+ REG_MMU_FLUSH_RANGE
);
108 SYSMMU_EVENT_LOG_TLB_INV_RANGE(SYSMMU_DRVDATA_TO_LOG(drvdata
),
111 if (sysmmu_block(sfrbase
)) {
112 __raw_writel(0x1, sfrbase
+ REG_MMU_FLUSH
);
113 SYSMMU_EVENT_LOG_TLB_INV_ALL(
114 SYSMMU_DRVDATA_TO_LOG(drvdata
));
116 sysmmu_unblock(sfrbase
);
120 void __sysmmu_set_ptbase(void __iomem
*sfrbase
, phys_addr_t pfn_pgtable
)
122 __raw_writel(pfn_pgtable
, sfrbase
+ REG_PT_BASE_PPN
);
124 __raw_writel(0x1, sfrbase
+ REG_MMU_FLUSH
);
127 static unsigned int find_lmm_preset(unsigned int num_pb
, unsigned int num_bufs
)
129 static char lmm_preset
[4][6] = { /* [num of PB][num of buffers] */
130 /* 1, 2, 3, 4, 5, 6 */
131 { 1, 1, 0, -1, -1, -1}, /* num of pb: 3 */
132 { 3, 2, 1, 0, -1, -1}, /* num of pb: 4 */
133 {-1, -1, -1, -1, -1, -1},
134 { 5, 5, 4, 2, 1, 0}, /* num of pb: 6 */
138 BUG_ON(num_bufs
> 6);
139 lmm
= lmm_preset
[num_pb
- 3][num_bufs
- 1];
144 static unsigned int find_num_pb(unsigned int num_pb
, unsigned int lmm
)
146 static char lmm_preset
[6][6] = { /* [pb_num - 1][pb_lmm] */
155 num_pb
= lmm_preset
[num_pb
- 1][lmm
];
160 static void __sysmmu_init_pb(void __iomem
*sfrbase
, unsigned int num_pb
)
164 for (i
= 0; i
< num_pb
; i
++) {
165 __raw_writel(i
, sfrbase
+ REG_PB_INDICATE
);
166 __raw_writel(0, sfrbase
+ REG_PB_CFG
);
169 __raw_writel(0x1, sfrbase
+ REG_MMU_FLUSH
);
172 static void __sysmmu_set_pbuf(struct sysmmu_drvdata
*drvdata
,
173 struct sysmmu_prefbuf prefbuf
[], int num_bufs
)
175 unsigned int i
, num_pb
, lmm
;
177 num_pb
= PB_INFO_NUM(__raw_readl(drvdata
->sfrbase
+ REG_PB_INFO
));
179 __sysmmu_init_pb(drvdata
->sfrbase
,
181 __raw_readl(drvdata
->sfrbase
+ REG_PB_LMM
)));
183 lmm
= find_lmm_preset(num_pb
, (unsigned int)num_bufs
);
184 num_pb
= find_num_pb(num_pb
, lmm
);
186 __raw_writel(lmm
, drvdata
->sfrbase
+ REG_PB_LMM
);
188 SYSMMU_EVENT_LOG_PBLMM(SYSMMU_DRVDATA_TO_LOG(drvdata
), lmm
, num_bufs
);
190 for (i
= 0; i
< num_pb
; i
++) {
191 __raw_writel(i
, drvdata
->sfrbase
+ REG_PB_INDICATE
);
192 if ((prefbuf
[i
].size
> 0) && (i
< num_bufs
)) {
193 __raw_writel(prefbuf
[i
].base
,
194 drvdata
->sfrbase
+ REG_PB_START_ADDR
);
195 __raw_writel(prefbuf
[i
].size
- 1 + prefbuf
[i
].base
,
196 drvdata
->sfrbase
+ REG_PB_END_ADDR
);
197 __raw_writel(prefbuf
[i
].config
| 1,
198 drvdata
->sfrbase
+ REG_PB_CFG
);
199 SYSMMU_EVENT_LOG_PBSET(SYSMMU_DRVDATA_TO_LOG(drvdata
),
200 prefbuf
[i
].config
| 1, prefbuf
[i
].base
,
201 prefbuf
[i
].size
- 1 + prefbuf
[i
].base
);
203 if (prefbuf
[i
].size
== 0) {
204 dev_err(drvdata
->sysmmu
,
205 "%s: Trying to init PB[%d/%d]with zero-size\n",
206 __func__
, i
, num_bufs
);
209 SYSMMU_EVENT_LOG_PBSET(SYSMMU_DRVDATA_TO_LOG(drvdata
),
215 static void __sysmmu_disable_pbuf(struct sysmmu_drvdata
*drvdata
)
217 unsigned int i
, num_pb
;
219 num_pb
= PB_INFO_NUM(__raw_readl(drvdata
->sfrbase
+ REG_PB_INFO
));
221 __sysmmu_init_pb(drvdata
->sfrbase
,
223 __raw_readl(drvdata
->sfrbase
+ REG_PB_LMM
)));
225 __raw_writel(0, drvdata
->sfrbase
+ REG_PB_LMM
);
227 SYSMMU_EVENT_LOG_PBLMM(SYSMMU_DRVDATA_TO_LOG(drvdata
), 0, 0);
229 for (i
= 0; i
< num_pb
; i
++) {
230 __raw_writel(i
, drvdata
->sfrbase
+ REG_PB_INDICATE
);
231 __raw_writel(0, drvdata
->sfrbase
+ REG_PB_CFG
);
232 SYSMMU_EVENT_LOG_PBSET(SYSMMU_DRVDATA_TO_LOG(drvdata
), 0, 0, 0);
236 void __exynos_sysmmu_set_prefbuf_by_region(struct sysmmu_drvdata
*drvdata
,
237 struct sysmmu_prefbuf pb_reg
[], unsigned int num_reg
)
241 struct sysmmu_prefbuf prefbuf
[6];
243 if (!has_sysmmu_capable_pbuf(drvdata
->sfrbase
))
246 if ((num_reg
== 0) || (pb_reg
== NULL
)) {
247 /* Disabling prefetch buffers */
248 __sysmmu_disable_pbuf(drvdata
);
252 for (i
= 0; i
< num_reg
; i
++) {
253 if (((pb_reg
[i
].config
& SYSMMU_PBUFCFG_WRITE
) &&
254 (drvdata
->prop
& SYSMMU_PROP_WRITE
)) ||
255 (!(pb_reg
[i
].config
& SYSMMU_PBUFCFG_WRITE
) &&
256 (drvdata
->prop
& SYSMMU_PROP_READ
)))
257 prefbuf
[num_bufs
++] = pb_reg
[i
];
260 __sysmmu_set_pbuf(drvdata
, prefbuf
, num_bufs
);
263 void __exynos_sysmmu_set_prefbuf_by_plane(struct sysmmu_drvdata
*drvdata
,
264 unsigned int inplanes
, unsigned int onplanes
,
265 unsigned int ipoption
, unsigned int opoption
)
269 struct sysmmu_prefbuf prefbuf
[6];
271 if (!has_sysmmu_capable_pbuf(drvdata
->sfrbase
))
274 num_pb
= PB_INFO_NUM(__raw_readl(drvdata
->sfrbase
+ REG_PB_INFO
));
275 if ((num_pb
!= 3) && (num_pb
!= 4) && (num_pb
!= 6)) {
276 dev_err(drvdata
->master
,
277 "%s: Read invalid PB information from %s\n",
278 __func__
, dev_name(drvdata
->sysmmu
));
282 num_bufs
= __prepare_prefetch_buffers_by_plane(drvdata
,
283 prefbuf
, num_pb
, inplanes
, onplanes
,
287 __sysmmu_disable_pbuf(drvdata
);
289 __sysmmu_set_pbuf(drvdata
, prefbuf
, num_bufs
);
292 static void __sysmmu_set_df(void __iomem
*sfrbase
,
295 __raw_writel(iova
, sfrbase
+ REG_SW_DF_VPN
);
298 void __exynos_sysmmu_set_df(struct sysmmu_drvdata
*drvdata
, dma_addr_t iova
)
300 #ifdef CONFIG_EXYNOS7_IOMMU_CHECK_DF
301 int i
, num_l1tlb
, df_cnt
= 0;
305 if (MAKE_MMU_VER(5, 1) > __raw_sysmmu_version(drvdata
->sfrbase
)) {
306 dev_err(drvdata
->sysmmu
, "%s: SW direct fetch not supported\n",
311 #ifdef CONFIG_EXYNOS7_IOMMU_CHECK_DF
312 num_l1tlb
= MMU_NUM_L1TLB_ENTRIES(__raw_readl(drvdata
->sfrbase
+
314 for (i
= 0; i
< num_l1tlb
; i
++) {
315 __raw_writel(i
, drvdata
->sfrbase
+ REG_L1TLB_READ_ENTRY
);
316 cfg
= __raw_readl(drvdata
->sfrbase
+ REG_L1TLB_ENTRY_ATTR
);
317 if (cfg
& L1TLB_ATTR_IM
)
321 if (df_cnt
== num_l1tlb
) {
322 dev_err(drvdata
->sysmmu
, "%s: All TLBs are special slots", __func__
);
326 cfg
= __raw_readl(drvdata
->sfrbase
+ REG_SW_DF_VPN_CMD_NUM
);
328 if ((cfg
& 0xFF) > 9) {
329 dev_info(drvdata
->sysmmu
,
330 "%s: DF command queue is full\n", __func__
);
335 __sysmmu_set_df(drvdata
->sfrbase
, iova
);
336 SYSMMU_EVENT_LOG_DF(SYSMMU_DRVDATA_TO_LOG(drvdata
), iova
);
340 void __exynos_sysmmu_release_df(struct sysmmu_drvdata
*drvdata
)
342 if (__raw_sysmmu_version(drvdata
->sfrbase
) >= MAKE_MMU_VER(5, 1)) {
343 __raw_writel(0x1, drvdata
->sfrbase
+ REG_L1TLB_CTRL
);
344 SYSMMU_EVENT_LOG_DF_UNLOCK_ALL(SYSMMU_DRVDATA_TO_LOG(drvdata
));
346 dev_err(drvdata
->sysmmu
, "DF is not supported");
350 void dump_sysmmu_tlb_pb(void __iomem
*sfrbase
)
352 unsigned int i
, capa
, lmm
;
359 pr_crit("---------- System MMU Status -----------------------------\n");
361 pgd
= pgd_offset_k((unsigned long)sfrbase
);
363 pr_crit("Invalid virtual address %pK\n", sfrbase
);
367 pud
= pud_offset(pgd
, (unsigned long)sfrbase
);
369 pr_crit("Invalid virtual address %pK\n", sfrbase
);
373 pmd
= pmd_offset(pud
, (unsigned long)sfrbase
);
375 pr_crit("Invalid virtual address %pK\n", sfrbase
);
379 pte
= pte_offset_kernel(pmd
, (unsigned long)sfrbase
);
381 pr_crit("Invalid virtual address %pK\n", sfrbase
);
385 capa
= __raw_readl(sfrbase
+ REG_MMU_CAPA
);
386 lmm
= MMU_RAW_VER(__raw_readl(sfrbase
+ REG_MMU_VERSION
));
388 phys
= pte_pfn(*pte
) << PAGE_SHIFT
;
389 pr_crit("ADDR: 0x%pa(VA: 0x%pK), MMU_CTRL: %#010x, PT_BASE: %#010x\n",
391 __raw_readl(sfrbase
+ REG_MMU_CTRL
),
392 __raw_readl(sfrbase
+ REG_PT_BASE_PPN
));
393 pr_crit("VERSION %d.%d, MMU_CFG: %#010x, MMU_STATUS: %#010x\n",
394 MMU_MAJ_VER(lmm
), MMU_MIN_VER(lmm
),
395 __raw_readl(sfrbase
+ REG_MMU_CFG
),
396 __raw_readl(sfrbase
+ REG_MMU_STATUS
));
398 if (lmm
== MAKE_MMU_VER(5, 1))
399 pr_crit("TLB hit notify : %s\n",
400 (__raw_readl(sfrbase
+ REG_L1TLB_CFG
) == 2) ?
403 if (MMU_HAVE_L2TLB(capa
))
404 pr_crit("Level 2 TLB: %s\n",
405 (__raw_readl(sfrbase
+ REG_L2TLB_CFG
) == 1) ?
408 pr_crit("---------- Level 1 TLB -----------------------------------\n");
410 for (i
= 0; i
< MMU_NUM_L1TLB_ENTRIES(capa
); i
++) {
411 __raw_writel(i
, sfrbase
+ REG_L1TLB_READ_ENTRY
);
412 pr_crit("[%02d] VPN: %#010x, PPN: %#010x, ATTR: %#010x\n",
413 i
, __raw_readl(sfrbase
+ REG_L1TLB_ENTRY_VPN
),
414 __raw_readl(sfrbase
+ REG_L1TLB_ENTRY_PPN
),
415 __raw_readl(sfrbase
+ REG_L1TLB_ENTRY_ATTR
));
418 if (!MMU_HAVE_PB(capa
))
421 capa
= __raw_readl(sfrbase
+ REG_PB_INFO
);
422 lmm
= __raw_readl(sfrbase
+ REG_PB_LMM
);
424 pr_crit("---------- Prefetch Buffers ------------------------------\n");
425 pr_crit("PB_INFO: %#010x, PB_LMM: %#010x\n", capa
, lmm
);
427 capa
= find_num_pb(capa
& 0xFF, lmm
);
429 for (i
= 0; i
< capa
; i
++) {
430 __raw_writel(i
, sfrbase
+ REG_PB_INDICATE
);
431 pr_crit("PB[%d] = CFG: %#010x, START: %#010x, END: %#010x\n", i
,
432 __raw_readl(sfrbase
+ REG_PB_CFG
),
433 __raw_readl(sfrbase
+ REG_PB_START_ADDR
),
434 __raw_readl(sfrbase
+ REG_PB_END_ADDR
));
437 /* Reading L2TLB is not provided by H/W */
440 static void show_fault_information(struct sysmmu_drvdata
*drvdata
,
441 int flags
, unsigned long fault_addr
)
445 int fault_id
= SYSMMU_FAULT_ID(flags
);
447 pgtable
= __raw_readl(drvdata
->sfrbase
+ REG_PT_BASE_PPN
);
448 pgtable
<<= PAGE_SHIFT
;
450 pr_crit("----------------------------------------------------------\n");
451 pr_crit("%s %s %s at %#010lx by %s (page table @ %pa)\n",
452 dev_name(drvdata
->sysmmu
),
453 (flags
& IOMMU_FAULT_WRITE
) ? "WRITE" : "READ",
454 sysmmu_fault_name
[fault_id
], fault_addr
,
455 dev_name(drvdata
->master
), &pgtable
);
457 if (fault_id
== SYSMMU_FAULT_UNKNOWN
) {
458 pr_crit("The fault is not caused by this System MMU.\n");
459 pr_crit("Please check IRQ and SFR base address.\n");
463 info
= __raw_readl(drvdata
->sfrbase
+
464 ((flags
& IOMMU_FAULT_WRITE
) ?
465 REG_FAULT_AW_TRANS_INFO
: REG_FAULT_AR_TRANS_INFO
));
466 pr_crit("AxID: %#x, AxLEN: %#x\n", info
& 0xFFFF, (info
>> 16) & 0xF);
468 if (pgtable
!= drvdata
->pgtable
)
469 pr_crit("Page table base of driver: %pa\n",
472 if (fault_id
== SYSMMU_FAULT_PTW_ACCESS
) {
473 pr_crit("System MMU has failed to access page table\n");
477 if (!pfn_valid(pgtable
>> PAGE_SHIFT
)) {
478 pr_crit("Page table base is not in a valid memory region\n");
481 ent
= section_entry(phys_to_virt(pgtable
), fault_addr
);
482 pr_crit("Lv1 entry: %#010x\n", *ent
);
484 if (lv1ent_page(ent
)) {
485 ent
= page_entry(ent
, fault_addr
);
486 pr_crit("Lv2 entry: %#010x\n", *ent
);
490 dump_sysmmu_tlb_pb(drvdata
->sfrbase
);
493 pr_crit("----------------------------------------------------------\n");
496 #define REG_INT_STATUS_WRITE_BIT 16
498 irqreturn_t
exynos_sysmmu_irq(int irq
, void *dev_id
)
500 /* SYSMMU is in blocked when interrupt occurred. */
501 struct sysmmu_drvdata
*drvdata
= dev_id
;
503 unsigned long addr
= -1;
507 if (!is_sysmmu_active(drvdata
)) {
508 /* HACK for MFC fault handling */
509 if(!strncmp("15200000.sysmmu", dev_name(drvdata
->sysmmu
), 15) ||
510 !strncmp("15210000.sysmmu", dev_name(drvdata
->sysmmu
), 15))
511 exynos_smc(0x810000DD, 0, 0, 0);
512 else if(!strncmp("15300000.sysmmu", dev_name(drvdata
->sysmmu
), 15) ||
513 !strncmp("15310000.sysmmu", dev_name(drvdata
->sysmmu
), 15))
514 exynos_smc(0x810000DD, 0, 0, 1);
515 /*----------------------------*/
517 WARN(!is_sysmmu_active(drvdata
),
518 "Fault occurred while System MMU %s is not enabled!\n",
519 dev_name(drvdata
->sysmmu
));
522 itype
= __ffs(__raw_readl(drvdata
->sfrbase
+ REG_INT_STATUS
));
523 if (itype
>= REG_INT_STATUS_WRITE_BIT
) {
524 itype
-= REG_INT_STATUS_WRITE_BIT
;
525 flags
= IOMMU_FAULT_WRITE
;
528 if (WARN_ON(!(itype
< SYSMMU_FAULT_UNKNOWN
)))
529 itype
= SYSMMU_FAULT_UNKNOWN
;
531 addr
= __raw_readl(drvdata
->sfrbase
+
532 ((flags
& IOMMU_FAULT_WRITE
) ?
533 REG_FAULT_AW_ADDR
: REG_FAULT_AR_ADDR
));
534 flags
|= SYSMMU_FAULT_FLAG(itype
);
536 show_fault_information(drvdata
, flags
, addr
);
538 if (drvdata
->domain
) /* master is set if drvdata->domain exists */
539 ret
= report_iommu_fault(drvdata
->domain
,
540 drvdata
->master
, addr
, flags
);
542 #if 0 /* Recovering System MMU fault is available from System MMU v6 */
544 ((itype
== SYSMMU_FAULT_PAGE_FAULT
) ||
545 (itype
== SYSMMU_FAULT_ACCESS
))) {
546 if (flags
& IOMMU_FAULT_WRITE
)
547 itype
+= REG_INT_STATUS_WRITE_BIT
;
548 __raw_writel(1 << itype
, drvdata
->sfrbase
+ REG_INT_CLEAR
);
550 sysmmu_unblock(drvdata
->sfrbase
);
554 panic("Unrecoverable System MMU Fault!!");
559 void __sysmmu_init_config(struct sysmmu_drvdata
*drvdata
)
563 __raw_writel(0, drvdata
->sfrbase
+ REG_MMU_CTRL
);
565 cfg
= CFG_FLPDCACHE
| CFG_ACGEN
;
566 if (!(drvdata
->qos
< 0))
567 cfg
|= CFG_QOS_OVRRIDE
| CFG_QOS(drvdata
->qos
);
569 if (has_sysmmu_capable_pbuf(drvdata
->sfrbase
))
570 __exynos_sysmmu_set_prefbuf_by_plane(drvdata
, 0, 0,
571 SYSMMU_PBUFCFG_DEFAULT_INPUT
,
572 SYSMMU_PBUFCFG_DEFAULT_OUTPUT
);
574 cfg
|= __raw_readl(drvdata
->sfrbase
+ REG_MMU_CFG
) & ~CFG_MASK
;
575 __raw_writel(cfg
, drvdata
->sfrbase
+ REG_MMU_CFG
);
578 void dump_sysmmu_ppc_cnt(struct sysmmu_drvdata
*drvdata
)
583 pr_crit("------------- System MMU PPC Status --------------\n");
584 for (i
= 0; i
< drvdata
->event_cnt
; i
++) {
585 cfg
= __raw_readl(drvdata
->sfrbase
+
586 REG_PPC_EVENT_SEL(i
));
587 pr_crit("%s %s %s CNT : %d", dev_name(drvdata
->sysmmu
),
588 cfg
& 0x10 ? "WRITE" : "READ",
589 ppc_event_name
[cfg
& 0x7],
590 __raw_readl(drvdata
->sfrbase
+ REG_PPC_PMCNT(i
)));
592 pr_crit("--------------------------------------------------\n");
595 int sysmmu_set_ppc_event(struct sysmmu_drvdata
*drvdata
, int event
)
599 if (event
< 0 || event
> TOTAL_ID_NUM
||
600 event
== READ_TLB_MISS
|| event
== WRITE_TLB_MISS
||
601 event
== READ_FLPD_MISS_PREFETCH
||
602 event
== WRITE_FLPD_MISS_PREFETCH
)
605 if (!drvdata
->event_cnt
)
606 __raw_writel(0x1, drvdata
->sfrbase
+ REG_PPC_PMNC
);
608 __raw_writel(event
, drvdata
->sfrbase
+
609 REG_PPC_EVENT_SEL(drvdata
->event_cnt
));
610 cfg
= __raw_readl(drvdata
->sfrbase
+
612 __raw_writel(cfg
| 0x1 << drvdata
->event_cnt
,
613 drvdata
->sfrbase
+ REG_PPC_CNTENS
);