Home | History | Annotate | Download | only in IoInitDxe
      1 /** @file
      2 *
      3 *  Copyright (c) 2015, Hisilicon Limited. All rights reserved.
      4 *  Copyright (c) 2015, Linaro Limited. All rights reserved.
      5 *
      6 *  This program and the accompanying materials
      7 *  are licensed and made available under the terms and conditions of the BSD License
      8 *  which accompanies this distribution.  The full text of the license may be found at
      9 *  http://opensource.org/licenses/bsd-license.php
     10 *
     11 *  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 *  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 *
     14 **/
     15 
     16 #include <Uefi.h>
     17 #include <Library/BaseLib.h>
     18 #include <Library/DebugLib.h>
     19 #include <Library/TimerLib.h>
     20 #include <Library/CacheMaintenanceLib.h>
     21 #include <Library/IoLib.h>
     22 #include <Library/MemoryAllocationLib.h>
     23 #include <Library/BaseMemoryLib.h>
     24 #include <Library/ArmLib.h>
     25 
     26 #include "Smmu.h"
     27 
     28 /* Maximum number of context banks per SMMU */
     29 #define SMMU_MAX_CBS    256
     30 
     31 #ifdef CONFIG_MM_OUTER_SHAREABLE
     32 #define SH_DOMAIN               2       /* outer shareable */
     33 #else
     34 #define SH_DOMAIN               3       /* inner shareable */
     35 #endif
     36 
     37 #define SMMU_OS_VMID    0
     38 #define SMMU_CB_NUMIRPT    8
     39 #define SMMU_S1CBT_SIZE    0x10000
     40 #define SMMU_S2CBT_SIZE    0x2000
     41 #define SMMU_S1CBT_SHIFT  16
     42 #define SMMU_S2CBT_SHIFT  12
     43 
     44 
     45 #define SMMU_CTRL_CR0      0x0
     46 #define SMMU_CTRL_ACR      0x8
     47 #define SMMU_CFG_S2CTBAR    0xc
     48 #define SMMU_IDR0      0x10
     49 #define SMMU_IDR1      0x14
     50 #define SMMU_IDR2      0x18
     51 #define SMMU_HIS_GFAR_LOW    0x20
     52 #define SMMU_HIS_GFAR_HIGH    0x24
     53 #define SMMU_RINT_GFSR      0x28
     54 #define SMMU_RINT_GFSYNR    0x2c
     55 #define SMMU_CFG_GFIM      0x30
     56 #define SMMU_CFG_CBF      0x34
     57 #define SMMU_TLBIALL      0x40
     58 #define SMMU_TLBIVMID      0x44
     59 #define SMMU_TLBISID      0x48
     60 #define SMMU_TLBIVA_LOW      0x4c
     61 #define SMMU_TLBIVA_HIGH    0x50
     62 #define SMMU_TLBGSYNC      0x54
     63 #define SMMU_TLBGSTATUS      0x58
     64 #define SMMU_CXTIALL      0x60
     65 #define SMMU_CXTIVMID      0x64
     66 #define SMMU_CXTISID      0x68
     67 #define SMMU_CXTGSYNC      0x6c
     68 #define SMMU_CXTGSTATUS      0x70
     69 #define SMMU_RINT_CB_FSR(n)    (0x100 + ((n) << 2))
     70 #define SMMU_RINT_CB_FSYNR(n)    (0x120 + ((n) << 2))
     71 #define SMMU_HIS_CB_FAR_LOW(n)    (0x140 + ((n) << 3))
     72 #define SMMU_HIS_CB_FAR_HIGH(n)    (0x144 + ((n) << 3))
     73 #define SMMU_CTRL_CB_RESUME(n)    (0x180 + ((n) << 2))
     74 #define SMMU_RINT_CB_FSYNR_MSTID  0x1a0
     75 
     76 #define SMMU_CB_S2CR(n)      (0x0  + ((n) << 5))
     77 #define SMMU_CB_CBAR(n)      (0x4  + ((n) << 5))
     78 #define SMMU_CB_S1CTBAR(n)    (0x18 + ((n) << 5))
     79 
     80 #define SMMU_S1_MAIR0      0x0
     81 #define SMMU_S1_MAIR1      0x4
     82 #define SMMU_S1_TTBR0_L      0x8
     83 #define SMMU_S1_TTBR0_H      0xc
     84 #define SMMU_S1_TTBR1_L      0x10
     85 #define SMMU_S1_TTBR1_H      0x14
     86 #define SMMU_S1_TTBCR      0x18
     87 #define SMMU_S1_SCTLR      0x1c
     88 
     89 #define CFG_CBF_S1_ORGN_WA    (1 << 12)
     90 #define CFG_CBF_S1_IRGN_WA    (1 << 10)
     91 #define CFG_CBF_S1_SHCFG    (SH_DOMAIN << 8)
     92 #define CFG_CBF_S2_ORGN_WA    (1 << 4)
     93 #define CFG_CBF_S2_IRGN_WA    (1 << 2)
     94 #define CFG_CBF_S2_SHCFG    (SH_DOMAIN << 0)
     95 
     96 /* Configuration registers */
     97 #define sCR0_CLIENTPD      (1 << 0)
     98 #define sCR0_GFRE      (1 << 1)
     99 #define sCR0_GFIE      (1 << 2)
    100 #define sCR0_GCFGFRE      (1 << 4)
    101 #define sCR0_GCFGFIE      (1 << 5)
    102 
    103 #define sACR_WC_EN      (7 << 0)
    104 
    105 #define ID0_S1TS      (1 << 30)
    106 #define ID0_S2TS      (1 << 29)
    107 #define ID0_NTS        (1 << 28)
    108 #define ID0_PTFS_SHIFT      24
    109 #define ID0_PTFS_MASK      0x2
    110 #define ID0_PTFS_V8_ONLY    0x2
    111 #define ID0_CTTW      (1 << 14)
    112 
    113 #define ID2_OAS_SHIFT      8
    114 #define ID2_OAS_MASK      0xff
    115 #define ID2_IAS_SHIFT      0
    116 #define ID2_IAS_MASK      0xff
    117 
    118 #define S2CR_TYPE_SHIFT      16
    119 #define S2CR_TYPE_MASK      0x3
    120 #define S2CR_TYPE_TRANS      (0 << S2CR_TYPE_SHIFT)
    121 #define S2CR_TYPE_BYPASS    (1 << S2CR_TYPE_SHIFT)
    122 #define S2CR_TYPE_FAULT      (2 << S2CR_TYPE_SHIFT)
    123 #define S2CR_SHCFG_NS      (3 << 8)
    124 #define S2CR_MTCFG      (1 << 11)
    125 #define S2CR_MEMATTR_OIWB    (0xf << 12)
    126 #define S2CR_MTSH_WEAKEST    (S2CR_SHCFG_NS | \
    127         S2CR_MTCFG | S2CR_MEMATTR_OIWB)
    128 
    129 /* Context bank attribute registers */
    130 #define CBAR_VMID_SHIFT      0
    131 #define CBAR_VMID_MASK      0xff
    132 #define CBAR_S1_BPSHCFG_SHIFT    8
    133 #define CBAR_S1_BPSHCFG_MASK    3
    134 #define CBAR_S1_BPSHCFG_NSH    3
    135 #define CBAR_S1_MEMATTR_SHIFT    12
    136 #define CBAR_S1_MEMATTR_MASK    0xf
    137 #define CBAR_S1_MEMATTR_WB    0xf
    138 #define CBAR_TYPE_SHIFT      16
    139 #define CBAR_TYPE_MASK      0x3
    140 #define CBAR_TYPE_S2_TRANS    (0 << CBAR_TYPE_SHIFT)
    141 #define CBAR_TYPE_S1_TRANS_S2_BYPASS  (1 << CBAR_TYPE_SHIFT)
    142 #define CBAR_TYPE_S1_TRANS_S2_FAULT  (2 << CBAR_TYPE_SHIFT)
    143 #define CBAR_TYPE_S1_TRANS_S2_TRANS  (3 << CBAR_TYPE_SHIFT)
    144 #define CBAR_IRPTNDX_SHIFT    24
    145 #define CBAR_IRPTNDX_MASK    0xff
    146 
    147 #define SMMU_CB_BASE(smmu)    ((smmu)->s1cbt)
    148 #define SMMU_CB(n)    ((n) << 5)
    149 
    150 #define sTLBGSTATUS_GSACTIVE    (1 << 0)
    151 #define TLB_LOOP_TIMEOUT    1000000  /* 1s! */
    152 
    153 #define SCTLR_WACFG_WA    (2 << 26)
    154 #define SCTLR_RACFG_RA    (2 << 24)
    155 #ifdef CONFIG_P660_2P
    156 #define SCTLR_SHCFG    (1 << 22)
    157 #else
    158 #define SCTLR_SHCFG    (2 << 22)
    159 #endif
    160 #define SCTLR_MTCFG    (1 << 20)
    161 #define SCTLR_MEMATTR_WB  (0xf << 16)
    162 #define SCTLR_MEMATTR_NC  (0x5 << 16)
    163 #define SCTLR_MEMATTR_NGNRE  (0x1 << 16)
    164 #define SCTLR_CACHE_WBRAWA  (SCTLR_WACFG_WA | SCTLR_RACFG_RA | \
    165       SCTLR_SHCFG | SCTLR_MTCFG | SCTLR_MEMATTR_WB)
    166 #define SCTLR_CACHE_NC    (SCTLR_SHCFG | \
    167       SCTLR_MTCFG | SCTLR_MEMATTR_NC)
    168 #define SCTLR_CACHE_NGNRE  (SCTLR_SHCFG | \
    169       SCTLR_MTCFG | SCTLR_MEMATTR_NGNRE)
    170 
    171 #define SCTLR_CFCFG      (1 << 7)
    172 #define SCTLR_CFIE      (1 << 6)
    173 #define SCTLR_CFRE      (1 << 5)
    174 #define SCTLR_E        (1 << 4)
    175 #define SCTLR_AFED      (1 << 3)
    176 #define SCTLR_M        (1 << 0)
    177 #define SCTLR_EAE_SBOP      (SCTLR_AFED)
    178 
    179 #define RESUME_RETRY      (0 << 0)
    180 #define RESUME_TERMINATE    (1 << 0)
    181 
    182 #define TTBCR_TG0_4K      (0 << 14)
    183 #define TTBCR_TG0_64K      (3 << 14)
    184 
    185 #define TTBCR_SH0_SHIFT      12
    186 #define TTBCR_SH0_MASK      0x3
    187 #define TTBCR_SH_NS      0
    188 #define TTBCR_SH_OS      2
    189 #define TTBCR_SH_IS      3
    190 #define TTBCR_ORGN0_SHIFT    10
    191 #define TTBCR_IRGN0_SHIFT    8
    192 #define TTBCR_RGN_MASK      0x3
    193 #define TTBCR_RGN_NC      0
    194 #define TTBCR_RGN_WBWA      1
    195 #define TTBCR_RGN_WT      2
    196 #define TTBCR_RGN_WB      3
    197 #define TTBCR_T1SZ_SHIFT    16
    198 #define TTBCR_T0SZ_SHIFT    0
    199 #define TTBCR_SZ_MASK      0xf
    200 
    201 #define MAIR_ATTR_SHIFT(n)    ((n) << 3)
    202 #define MAIR_ATTR_MASK      0xff
    203 #define MAIR_ATTR_DEVICE    0x04
    204 #define MAIR_ATTR_NC      0x44
    205 #define MAIR_ATTR_WBRWA      0xff
    206 #define MAIR_ATTR_IDX_NC    0
    207 #define MAIR_ATTR_IDX_CACHE    1
    208 #define MAIR_ATTR_IDX_DEV    2
    209 
    210 #define FSR_MULTI    (1 << 31)
    211 #define FSR_EF      (1 << 4)
    212 #define FSR_PF      (1 << 3)
    213 #define FSR_AFF      (1 << 2)
    214 #define FSR_TF      (1 << 1)
    215 #define FSR_IGN      (FSR_AFF)
    216 #define FSR_FAULT    (FSR_MULTI | FSR_EF | FSR_PF | FSR_TF | FSR_IGN)
    217 
    218 #define FSYNR0_ASID(n)      (0xff & ((n) >> 24))
    219 #define FSYNR0_VMID(n)      (0xff & ((n) >> 16))
    220 #define FSYNR0_WNR      (1 << 4)
    221 #define FSYNR0_SS      (1 << 2)
    222 #define FSYNR0_CF      (1 << 0)
    223 
    224 #define SMMU_FEAT_COHERENT_WALK    (1 << 0)
    225 #define SMMU_FEAT_STREAM_MATCH    (1 << 1)
    226 #define SMMU_FEAT_TRANS_S1    (1 << 2)
    227 #define SMMU_FEAT_TRANS_S2    (1 << 3)
    228 #define SMMU_FEAT_TRANS_NESTED    (1 << 4)
    229 
    230 static UINT32 hisi_bypass_vmid = 0xff;
    231 
    232 VOID writel_relaxed (UINT32 Value, UINTN Base)
    233 {
    234   MmioWrite32 (Base, Value);
    235 }
    236 
    237 UINT32 readl_relaxed (UINTN Base)
    238 {
    239   return MmioRead32 (Base);
    240 }
    241 
    242 /* Wait for any pending TLB invalidations to complete */
    243 static void hisi_smmu_tlb_sync(SMMU_DEVICE *smmu)
    244 {
    245   int count = 0;
    246   UINTN gr0_base = smmu->Base;
    247 
    248   writel_relaxed(0, gr0_base + SMMU_TLBGSYNC);
    249   while (readl_relaxed(gr0_base + SMMU_TLBGSTATUS)
    250          & sTLBGSTATUS_GSACTIVE) {
    251     if (++count == TLB_LOOP_TIMEOUT) {
    252       DEBUG ((EFI_D_ERROR, "TLB sync timed out -- SMMU (0x%p) may be deadlocked\n", gr0_base));
    253       return;
    254     }
    255     MicroSecondDelay (1);
    256   }
    257 }
    258 
    259 
    260 VOID *
    261 SmmuAllocateTable (
    262   UINTN Size,
    263   UINTN Alignment
    264   )
    265 {
    266   return AllocateAlignedReservedPages (EFI_SIZE_TO_PAGES (Size), Alignment);
    267 }
    268 
    269 
    270 EFI_STATUS
    271 SmmuInit (
    272   SMMU_DEVICE       *Smmu
    273   )
    274 {
    275   UINT32 Value;
    276   UINTN  Base = Smmu->Base;
    277   UINTN  Index;
    278 
    279   /* Clear Global FSR */
    280   Value = MmioRead32 (Base + SMMU_RINT_GFSR);
    281   MmioWrite32 (Base + SMMU_RINT_GFSR, Value);
    282 
    283   /* mask all global interrupt */
    284   MmioWrite32 (Base + SMMU_CFG_GFIM, 0xFFFFFFFF);
    285 
    286   Value  = CFG_CBF_S1_ORGN_WA | CFG_CBF_S1_IRGN_WA | CFG_CBF_S1_SHCFG;
    287   Value |= CFG_CBF_S2_ORGN_WA | CFG_CBF_S2_IRGN_WA | CFG_CBF_S2_SHCFG;
    288   MmioWrite32 (Base + SMMU_CFG_CBF, Value);
    289 
    290   /* Clear CB_FSR  */
    291   for (Index = 0; Index < SMMU_CB_NUMIRPT; Index++) {
    292     MmioWrite32 (Base + SMMU_RINT_CB_FSR(Index), FSR_FAULT);
    293   }
    294 
    295   return EFI_SUCCESS;
    296 }
    297 
    298 VOID *
    299 SmmuCreateS2Cbt (VOID)
    300 {
    301   VOID  *Table;
    302   UINTN  Index;
    303 
    304   Table = SmmuAllocateTable (SMMU_S2CBT_SIZE, LShiftU64 (1, SMMU_S2CBT_SHIFT));
    305   if (Table == NULL) {
    306     DEBUG ((EFI_D_ERROR, "[%a]:[%dL] Allocate table failed!\n", __FUNCTION__, __LINE__));
    307     return NULL;
    308   }
    309   ZeroMem (Table, SMMU_S2CBT_SIZE);
    310 
    311   for (Index = 0; Index < SMMU_MAX_CBS; Index++) {
    312     MmioWrite32 ((UINTN)Table + SMMU_CB_S1CTBAR(Index), 0);
    313     MmioWrite32 ((UINTN)Table + SMMU_CB_S2CR(Index), S2CR_TYPE_BYPASS);
    314   }
    315   return Table;
    316 }
    317 
    318 VOID *
    319 SmmuCreateS1Cbt (VOID)
    320 {
    321   VOID  *Table;
    322 
    323   Table = SmmuAllocateTable (SMMU_S1CBT_SIZE, LShiftU64 (1, SMMU_S1CBT_SHIFT));
    324   if (Table == NULL) {
    325     DEBUG ((EFI_D_ERROR, "[%a]:[%dL] Allocate table failed!\n", __FUNCTION__, __LINE__));
    326     return NULL;
    327   }
    328   ZeroMem (Table, SMMU_S1CBT_SIZE);
    329 
    330   return Table;
    331 }
    332 
    333 EFI_STATUS
    334 SmmuConfigSwitch (
    335   SMMU_DEVICE       *Smmu
    336   )
    337 {
    338   VOID*  S2;
    339   VOID*  S1;
    340   UINT32 reg;
    341 
    342   S2 = SmmuCreateS2Cbt ();
    343   if (S2 == NULL) {
    344     return EFI_OUT_OF_RESOURCES;
    345   }
    346   Smmu->S2Cbt = (UINTN) S2;
    347 
    348   S1 = SmmuCreateS1Cbt ();
    349   if (S1 == NULL) {
    350     return EFI_OUT_OF_RESOURCES;
    351   }
    352 
    353   MmioWrite32 (Smmu->S2Cbt + SMMU_CB_S1CTBAR(SMMU_OS_VMID), (UINT32) RShiftU64 ((UINT64)S1, SMMU_S1CBT_SHIFT));
    354 
    355   // Force device for VMID 0 ASID 0
    356   MmioWrite32 ((UINTN)S1 + SMMU_CB(0) + SMMU_S1_SCTLR, SCTLR_CACHE_WBRAWA);
    357   // Force device for VMID 0 ASID 1
    358   MmioWrite32 ((UINTN)S1 + SMMU_CB(1) + SMMU_S1_SCTLR, SCTLR_CACHE_NGNRE);
    359 
    360   /*
    361    * Use the weakest attribute, so no impact stage 1 output attribute.
    362    */
    363   reg = CBAR_TYPE_S1_TRANS_S2_BYPASS |
    364     (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) |
    365     (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT);
    366   MmioWrite32 (Smmu->S2Cbt + SMMU_CB_CBAR(SMMU_OS_VMID), reg);
    367 
    368   /* Mark S2CR as translation */
    369   reg = S2CR_TYPE_TRANS | S2CR_MTSH_WEAKEST;
    370   MmioWrite32 (Smmu->S2Cbt + SMMU_CB_S2CR(SMMU_OS_VMID), reg);
    371 
    372   /* Bypass need use another S2CR */
    373   reg = S2CR_TYPE_BYPASS;
    374   MmioWrite32 (Smmu->S2Cbt + SMMU_CB_S2CR(hisi_bypass_vmid), reg);
    375 
    376   return EFI_SUCCESS;
    377 }
    378 
    379 EFI_STATUS
    380 SmmuFlushCbt (
    381   SMMU_DEVICE       *Smmu
    382   )
    383 {
    384   UINTN Index;
    385 
    386   if (Smmu->S2Cbt == 0) {
    387     DEBUG ((EFI_D_ERROR, "[%a]:[%dL] S2Cbt is null!\n", __FUNCTION__, __LINE__));
    388     return EFI_INVALID_PARAMETER;
    389   }
    390 
    391   WriteBackInvalidateDataCacheRange ((VOID *)Smmu->S2Cbt, SMMU_S2CBT_SIZE);
    392   for (Index = 0; Index < SMMU_MAX_CBS; Index++) {
    393     UINTN S1Ctb = MmioRead32 (Smmu->S2Cbt + SMMU_CB_S1CTBAR(SMMU_OS_VMID));
    394     if (S1Ctb) {
    395       // TODO: shall we really need to flush 64KB? Or 8KB is enough?
    396       WriteBackInvalidateDataCacheRange ((VOID *)LShiftU64 (S1Ctb, SMMU_S1CBT_SHIFT), SMMU_S1CBT_SIZE);
    397     }
    398   }
    399 
    400   return EFI_SUCCESS;
    401 }
    402 
    403 EFI_STATUS
    404 SmmuEnableTable (
    405   SMMU_DEVICE       *Smmu
    406   )
    407 {
    408   UINT32 reg;
    409   UINTN  gr0_base = Smmu->Base;
    410 
    411   (VOID) SmmuFlushCbt (Smmu);
    412 
    413   /* Clear Global FSR */
    414   reg = readl_relaxed(gr0_base + SMMU_RINT_GFSR);
    415   writel_relaxed(reg, gr0_base + SMMU_RINT_GFSR);
    416 
    417   /* unmask all global interrupt */
    418   writel_relaxed(0, gr0_base + SMMU_CFG_GFIM);
    419 
    420   reg  = CFG_CBF_S1_ORGN_WA | CFG_CBF_S1_IRGN_WA | CFG_CBF_S1_SHCFG;
    421   reg |= CFG_CBF_S2_ORGN_WA | CFG_CBF_S2_IRGN_WA | CFG_CBF_S2_SHCFG;
    422   writel_relaxed(reg, gr0_base + SMMU_CFG_CBF);
    423 
    424   reg = (UINT32) RShiftU64 (Smmu->S2Cbt, SMMU_S2CBT_SHIFT);
    425   writel_relaxed(reg, gr0_base + SMMU_CFG_S2CTBAR);
    426 
    427   /* Invalidate all TLB, just in case */
    428   writel_relaxed(0, gr0_base + SMMU_TLBIALL);
    429   hisi_smmu_tlb_sync(Smmu);
    430 
    431   writel_relaxed(sACR_WC_EN, gr0_base + SMMU_CTRL_ACR);
    432 
    433   /* Enable fault reporting */
    434   reg  = (sCR0_GFRE | sCR0_GFIE | sCR0_GCFGFRE | sCR0_GCFGFIE);
    435   reg &= ~sCR0_CLIENTPD;
    436 
    437   writel_relaxed(reg, gr0_base + SMMU_CTRL_CR0);
    438   ArmDataSynchronizationBarrier ();
    439 
    440   return EFI_SUCCESS;
    441 };
    442 
    443