1- /* linux/drivers/iommu/exynos_iommu.c
2- *
3- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
1+ /*
2+ * Copyright (c) 2011,2016 Samsung Electronics Co., Ltd.
43 * http://www.samsung.com
54 *
65 * This program is free software; you can redistribute it and/or modify
@@ -55,17 +54,25 @@ typedef u32 sysmmu_pte_t;
5554#define lv2ent_small (pent ) ((*(pent) & 2) == 2)
5655#define lv2ent_large (pent ) ((*(pent) & 3) == 1)
5756
58- static u32 sysmmu_page_offset (sysmmu_iova_t iova , u32 size )
59- {
60- return iova & (size - 1 );
61- }
62-
63- #define section_phys (sent ) (*(sent) & SECT_MASK)
64- #define section_offs (iova ) sysmmu_page_offset((iova), SECT_SIZE)
65- #define lpage_phys (pent ) (*(pent) & LPAGE_MASK)
66- #define lpage_offs (iova ) sysmmu_page_offset((iova), LPAGE_SIZE)
67- #define spage_phys (pent ) (*(pent) & SPAGE_MASK)
68- #define spage_offs (iova ) sysmmu_page_offset((iova), SPAGE_SIZE)
57+ /*
58+ * v1.x - v3.x SYSMMU supports 32bit physical and 32bit virtual address spaces
59+ * v5.0 introduced support for 36bit physical address space by shifting
60+ * all page entry values by 4 bits.
61+ * All SYSMMU controllers in the system support the address spaces of the same
62+ * size, so PG_ENT_SHIFT can be initialized on first SYSMMU probe to proper
63+ * value (0 or 4).
64+ */
65+ static short PG_ENT_SHIFT = -1 ;
66+ #define SYSMMU_PG_ENT_SHIFT 0
67+ #define SYSMMU_V5_PG_ENT_SHIFT 4
68+
69+ #define sect_to_phys (ent ) (((phys_addr_t) ent) << PG_ENT_SHIFT)
70+ #define section_phys (sent ) (sect_to_phys(*(sent)) & SECT_MASK)
71+ #define section_offs (iova ) (iova & (SECT_SIZE - 1))
72+ #define lpage_phys (pent ) (sect_to_phys(*(pent)) & LPAGE_MASK)
73+ #define lpage_offs (iova ) (iova & (LPAGE_SIZE - 1))
74+ #define spage_phys (pent ) (sect_to_phys(*(pent)) & SPAGE_MASK)
75+ #define spage_offs (iova ) (iova & (SPAGE_SIZE - 1))
6976
7077#define NUM_LV1ENTRIES 4096
7178#define NUM_LV2ENTRIES (SECT_SIZE / SPAGE_SIZE)
@@ -84,28 +91,36 @@ static u32 lv2ent_offset(sysmmu_iova_t iova)
8491#define LV2TABLE_SIZE (NUM_LV2ENTRIES * sizeof(sysmmu_pte_t))
8592
8693#define SPAGES_PER_LPAGE (LPAGE_SIZE / SPAGE_SIZE)
94+ #define lv2table_base (sent ) (sect_to_phys(*(sent) & 0xFFFFFFC0))
8795
88- #define lv2table_base (sent ) (*(sent) & 0xFFFFFC00)
89-
90- #define mk_lv1ent_sect (pa ) ((pa) | 2)
91- #define mk_lv1ent_page (pa ) ((pa) | 1)
92- #define mk_lv2ent_lpage (pa ) ((pa) | 1)
93- #define mk_lv2ent_spage (pa ) ((pa) | 2)
96+ #define mk_lv1ent_sect (pa ) ((pa >> PG_ENT_SHIFT) | 2)
97+ #define mk_lv1ent_page (pa ) ((pa >> PG_ENT_SHIFT) | 1)
98+ #define mk_lv2ent_lpage (pa ) ((pa >> PG_ENT_SHIFT) | 1)
99+ #define mk_lv2ent_spage (pa ) ((pa >> PG_ENT_SHIFT) | 2)
94100
95101#define CTRL_ENABLE 0x5
96102#define CTRL_BLOCK 0x7
97103#define CTRL_DISABLE 0x0
98104
99105#define CFG_LRU 0x1
100106#define CFG_QOS (n ) ((n & 0xF) << 7)
101- #define CFG_MASK 0x0150FFFF /* Selecting bit 0-15, 20, 22 and 24 */
102107#define CFG_ACGEN (1 << 24) /* System MMU 3.3 only */
103108#define CFG_SYSSEL (1 << 22) /* System MMU 3.2 only */
104109#define CFG_FLPDCACHE (1 << 20) /* System MMU 3.2+ only */
105110
111+ /* common registers */
106112#define REG_MMU_CTRL 0x000
107113#define REG_MMU_CFG 0x004
108114#define REG_MMU_STATUS 0x008
115+ #define REG_MMU_VERSION 0x034
116+
117+ #define MMU_MAJ_VER (val ) ((val) >> 7)
118+ #define MMU_MIN_VER (val ) ((val) & 0x7F)
119+ #define MMU_RAW_VER (reg ) (((reg) >> 21) & ((1 << 11) - 1)) /* 11 bits */
120+
121+ #define MAKE_MMU_VER (maj , min ) ((((maj) & 0xF) << 7) | ((min) & 0x7F))
122+
123+ /* v1.x - v3.x registers */
109124#define REG_MMU_FLUSH 0x00C
110125#define REG_MMU_FLUSH_ENTRY 0x010
111126#define REG_PT_BASE_ADDR 0x014
@@ -117,18 +132,14 @@ static u32 lv2ent_offset(sysmmu_iova_t iova)
117132#define REG_AR_FAULT_ADDR 0x02C
118133#define REG_DEFAULT_SLAVE_ADDR 0x030
119134
120- #define REG_MMU_VERSION 0x034
121-
122- #define MMU_MAJ_VER (val ) ((val) >> 7)
123- #define MMU_MIN_VER (val ) ((val) & 0x7F)
124- #define MMU_RAW_VER (reg ) (((reg) >> 21) & ((1 << 11) - 1)) /* 11 bits */
125-
126- #define MAKE_MMU_VER (maj , min ) ((((maj) & 0xF) << 7) | ((min) & 0x7F))
127-
128- #define REG_PB0_SADDR 0x04C
129- #define REG_PB0_EADDR 0x050
130- #define REG_PB1_SADDR 0x054
131- #define REG_PB1_EADDR 0x058
135+ /* v5.x registers */
136+ #define REG_V5_PT_BASE_PFN 0x00C
137+ #define REG_V5_MMU_FLUSH_ALL 0x010
138+ #define REG_V5_MMU_FLUSH_ENTRY 0x014
139+ #define REG_V5_INT_STATUS 0x060
140+ #define REG_V5_INT_CLEAR 0x064
141+ #define REG_V5_FAULT_AR_VA 0x070
142+ #define REG_V5_FAULT_AW_VA 0x080
132143
133144#define has_sysmmu (dev ) (dev->archdata.iommu != NULL)
134145
@@ -169,6 +180,19 @@ static const struct sysmmu_fault_info sysmmu_faults[] = {
169180 { 7 , REG_AW_FAULT_ADDR , "AW ACCESS PROTECTION" , IOMMU_FAULT_WRITE },
170181};
171182
183+ static const struct sysmmu_fault_info sysmmu_v5_faults [] = {
184+ { 0 , REG_V5_FAULT_AR_VA , "AR PTW" , IOMMU_FAULT_READ },
185+ { 1 , REG_V5_FAULT_AR_VA , "AR PAGE" , IOMMU_FAULT_READ },
186+ { 2 , REG_V5_FAULT_AR_VA , "AR MULTI-HIT" , IOMMU_FAULT_READ },
187+ { 3 , REG_V5_FAULT_AR_VA , "AR ACCESS PROTECTION" , IOMMU_FAULT_READ },
188+ { 4 , REG_V5_FAULT_AR_VA , "AR SECURITY PROTECTION" , IOMMU_FAULT_READ },
189+ { 16 , REG_V5_FAULT_AW_VA , "AW PTW" , IOMMU_FAULT_WRITE },
190+ { 17 , REG_V5_FAULT_AW_VA , "AW PAGE" , IOMMU_FAULT_WRITE },
191+ { 18 , REG_V5_FAULT_AW_VA , "AW MULTI-HIT" , IOMMU_FAULT_WRITE },
192+ { 19 , REG_V5_FAULT_AW_VA , "AW ACCESS PROTECTION" , IOMMU_FAULT_WRITE },
193+ { 20 , REG_V5_FAULT_AW_VA , "AW SECURITY PROTECTION" , IOMMU_FAULT_WRITE },
194+ };
195+
172196/*
173197 * This structure is attached to dev.archdata.iommu of the master device
174198 * on device add, contains a list of SYSMMU controllers defined by device tree,
@@ -205,6 +229,8 @@ struct sysmmu_drvdata {
205229 struct device * master ; /* master device (owner) */
206230 void __iomem * sfrbase ; /* our registers */
207231 struct clk * clk ; /* SYSMMU's clock */
232+ struct clk * aclk ; /* SYSMMU's aclk clock */
233+ struct clk * pclk ; /* SYSMMU's pclk clock */
208234 struct clk * clk_master ; /* master's device clock */
209235 int activations ; /* number of calls to sysmmu_enable */
210236 spinlock_t lock ; /* lock for modyfying state */
@@ -262,7 +288,10 @@ static bool sysmmu_block(struct sysmmu_drvdata *data)
262288
263289static void __sysmmu_tlb_invalidate (struct sysmmu_drvdata * data )
264290{
265- __raw_writel (0x1 , data -> sfrbase + REG_MMU_FLUSH );
291+ if (MMU_MAJ_VER (data -> version ) < 5 )
292+ __raw_writel (0x1 , data -> sfrbase + REG_MMU_FLUSH );
293+ else
294+ __raw_writel (0x1 , data -> sfrbase + REG_V5_MMU_FLUSH_ALL );
266295}
267296
268297static void __sysmmu_tlb_invalidate_entry (struct sysmmu_drvdata * data ,
@@ -271,15 +300,23 @@ static void __sysmmu_tlb_invalidate_entry(struct sysmmu_drvdata *data,
271300 unsigned int i ;
272301
273302 for (i = 0 ; i < num_inv ; i ++ ) {
274- __raw_writel ((iova & SPAGE_MASK ) | 1 ,
275- data -> sfrbase + REG_MMU_FLUSH_ENTRY );
303+ if (MMU_MAJ_VER (data -> version ) < 5 )
304+ __raw_writel ((iova & SPAGE_MASK ) | 1 ,
305+ data -> sfrbase + REG_MMU_FLUSH_ENTRY );
306+ else
307+ __raw_writel ((iova & SPAGE_MASK ) | 1 ,
308+ data -> sfrbase + REG_V5_MMU_FLUSH_ENTRY );
276309 iova += SPAGE_SIZE ;
277310 }
278311}
279312
280313static void __sysmmu_set_ptbase (struct sysmmu_drvdata * data , phys_addr_t pgd )
281314{
282- __raw_writel (pgd , data -> sfrbase + REG_PT_BASE_ADDR );
315+ if (MMU_MAJ_VER (data -> version ) < 5 )
316+ __raw_writel (pgd , data -> sfrbase + REG_PT_BASE_ADDR );
317+ else
318+ __raw_writel (pgd >> PAGE_SHIFT ,
319+ data -> sfrbase + REG_V5_PT_BASE_PFN );
283320
284321 __sysmmu_tlb_invalidate (data );
285322}
@@ -290,6 +327,8 @@ static void __sysmmu_get_version(struct sysmmu_drvdata *data)
290327
291328 clk_enable (data -> clk_master );
292329 clk_enable (data -> clk );
330+ clk_enable (data -> pclk );
331+ clk_enable (data -> aclk );
293332
294333 ver = __raw_readl (data -> sfrbase + REG_MMU_VERSION );
295334
@@ -302,6 +341,8 @@ static void __sysmmu_get_version(struct sysmmu_drvdata *data)
302341 dev_dbg (data -> sysmmu , "hardware version: %d.%d\n" ,
303342 MMU_MAJ_VER (data -> version ), MMU_MIN_VER (data -> version ));
304343
344+ clk_disable (data -> aclk );
345+ clk_disable (data -> pclk );
305346 clk_disable (data -> clk );
306347 clk_disable (data -> clk_master );
307348}
@@ -326,19 +367,31 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id)
326367{
327368 /* SYSMMU is in blocked state when interrupt occurred. */
328369 struct sysmmu_drvdata * data = dev_id ;
329- const struct sysmmu_fault_info * finfo = sysmmu_faults ;
330- int i , n = ARRAY_SIZE (sysmmu_faults );
331- unsigned int itype ;
370+ const struct sysmmu_fault_info * finfo ;
371+ unsigned int i , n , itype ;
332372 sysmmu_iova_t fault_addr = -1 ;
373+ unsigned short reg_status , reg_clear ;
333374 int ret = - ENOSYS ;
334375
335376 WARN_ON (!is_sysmmu_active (data ));
336377
378+ if (MMU_MAJ_VER (data -> version ) < 5 ) {
379+ reg_status = REG_INT_STATUS ;
380+ reg_clear = REG_INT_CLEAR ;
381+ finfo = sysmmu_faults ;
382+ n = ARRAY_SIZE (sysmmu_faults );
383+ } else {
384+ reg_status = REG_V5_INT_STATUS ;
385+ reg_clear = REG_V5_INT_CLEAR ;
386+ finfo = sysmmu_v5_faults ;
387+ n = ARRAY_SIZE (sysmmu_v5_faults );
388+ }
389+
337390 spin_lock (& data -> lock );
338391
339392 clk_enable (data -> clk_master );
340393
341- itype = __ffs (__raw_readl (data -> sfrbase + REG_INT_STATUS ));
394+ itype = __ffs (__raw_readl (data -> sfrbase + reg_status ));
342395 for (i = 0 ; i < n ; i ++ , finfo ++ )
343396 if (finfo -> bit == itype )
344397 break ;
@@ -355,7 +408,7 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id)
355408 /* fault is not recovered by fault handler */
356409 BUG_ON (ret != 0 );
357410
358- __raw_writel (1 << itype , data -> sfrbase + REG_INT_CLEAR );
411+ __raw_writel (1 << itype , data -> sfrbase + reg_clear );
359412
360413 sysmmu_unblock (data );
361414
@@ -373,6 +426,8 @@ static void __sysmmu_disable_nocount(struct sysmmu_drvdata *data)
373426 __raw_writel (CTRL_DISABLE , data -> sfrbase + REG_MMU_CTRL );
374427 __raw_writel (0 , data -> sfrbase + REG_MMU_CFG );
375428
429+ clk_disable (data -> aclk );
430+ clk_disable (data -> pclk );
376431 clk_disable (data -> clk );
377432 clk_disable (data -> clk_master );
378433}
@@ -421,6 +476,8 @@ static void __sysmmu_enable_nocount(struct sysmmu_drvdata *data)
421476{
422477 clk_enable (data -> clk_master );
423478 clk_enable (data -> clk );
479+ clk_enable (data -> pclk );
480+ clk_enable (data -> aclk );
424481
425482 __raw_writel (CTRL_BLOCK , data -> sfrbase + REG_MMU_CTRL );
426483
@@ -544,22 +601,47 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev)
544601 }
545602
546603 data -> clk = devm_clk_get (dev , "sysmmu" );
547- if (IS_ERR (data -> clk )) {
548- dev_err (dev , "Failed to get clock!\n" );
549- return PTR_ERR (data -> clk );
550- } else {
604+ if (!IS_ERR (data -> clk )) {
551605 ret = clk_prepare (data -> clk );
552606 if (ret ) {
553607 dev_err (dev , "Failed to prepare clk\n" );
554608 return ret ;
555609 }
610+ } else {
611+ data -> clk = NULL ;
612+ }
613+
614+ data -> aclk = devm_clk_get (dev , "aclk" );
615+ if (!IS_ERR (data -> aclk )) {
616+ ret = clk_prepare (data -> aclk );
617+ if (ret ) {
618+ dev_err (dev , "Failed to prepare aclk\n" );
619+ return ret ;
620+ }
621+ } else {
622+ data -> aclk = NULL ;
623+ }
624+
625+ data -> pclk = devm_clk_get (dev , "pclk" );
626+ if (!IS_ERR (data -> pclk )) {
627+ ret = clk_prepare (data -> pclk );
628+ if (ret ) {
629+ dev_err (dev , "Failed to prepare pclk\n" );
630+ return ret ;
631+ }
632+ } else {
633+ data -> pclk = NULL ;
634+ }
635+
636+ if (!data -> clk && (!data -> aclk || !data -> pclk )) {
637+ dev_err (dev , "Failed to get device clock(s)!\n" );
638+ return - ENOSYS ;
556639 }
557640
558641 data -> clk_master = devm_clk_get (dev , "master" );
559642 if (!IS_ERR (data -> clk_master )) {
560643 ret = clk_prepare (data -> clk_master );
561644 if (ret ) {
562- clk_unprepare (data -> clk );
563645 dev_err (dev , "Failed to prepare master's clk\n" );
564646 return ret ;
565647 }
@@ -573,6 +655,13 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev)
573655 platform_set_drvdata (pdev , data );
574656
575657 __sysmmu_get_version (data );
658+ if (PG_ENT_SHIFT < 0 ) {
659+ if (MMU_MAJ_VER (data -> version ) < 5 )
660+ PG_ENT_SHIFT = SYSMMU_PG_ENT_SHIFT ;
661+ else
662+ PG_ENT_SHIFT = SYSMMU_V5_PG_ENT_SHIFT ;
663+ }
664+
576665 pm_runtime_enable (dev );
577666
578667 return 0 ;
@@ -637,6 +726,8 @@ static struct iommu_domain *exynos_iommu_domain_alloc(unsigned type)
637726 dma_addr_t handle ;
638727 int i ;
639728
729+ /* Check if correct PTE offsets are initialized */
730+ BUG_ON (PG_ENT_SHIFT < 0 || !dma_dev );
640731
641732 domain = kzalloc (sizeof (* domain ), GFP_KERNEL );
642733 if (!domain )
@@ -816,7 +907,7 @@ static sysmmu_pte_t *alloc_lv2entry(struct exynos_iommu_domain *domain,
816907 bool need_flush_flpd_cache = lv1ent_zero (sent );
817908
818909 pent = kmem_cache_zalloc (lv2table_kmem_cache , GFP_ATOMIC );
819- BUG_ON ((unsigned int )pent & (LV2TABLE_SIZE - 1 ));
910+ BUG_ON ((phys_addr_t )pent & (LV2TABLE_SIZE - 1 ));
820911 if (!pent )
821912 return ERR_PTR (- ENOMEM );
822913
0 commit comments