1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2023 Linaro Ltd. 4 * Basic ARM SMMU-500 driver, assuming a pre-initialised SMMU and only IDENTITY domains 5 * this driver only implements the bare minimum to configure stream mappings for periphals 6 * used by u-boot on platforms where the SMMU can't be disabled. 7 */ 8 9#include <log.h> 10#include <cpu_func.h> 11#include <dm.h> 12#include <iommu.h> 13#include <linux/bitfield.h> 14#include <linux/list.h> 15#include <linux/err.h> 16#include <lmb.h> 17#include <memalign.h> 18#include <asm/io.h> 19 20#define ARM_SMMU_GR0 0 21#define ARM_SMMU_GR1 1 22 23#define ARM_SMMU_GR0_ID0 0x20 24#define ARM_SMMU_ID0_NUMSMRG GENMASK(7, 0) /* Number of stream mapping groups */ 25#define ARM_SMMU_GR0_ID1 0x24 26#define ARM_SMMU_ID1_PAGESIZE \ 27 BIT(31) /* Page shift is 16 bits when set, otherwise 23 */ 28#define ARM_SMMU_ID1_NUMPAGENDXB \ 29 GENMASK(30, 28) /* Number of pages before context banks */ 30#define ARM_SMMU_ID1_NUMCB GENMASK(7, 0) /* Number of context banks supported */ 31 32#define ARM_SMMU_GR1_CBAR(n) (0x0 + ((n) << 2)) 33#define ARM_SMMU_CBAR_TYPE GENMASK(17, 16) 34#define ARM_SMMU_CBAR_VMID GENMASK(7, 0) 35enum arm_smmu_cbar_type { 36 CBAR_TYPE_S2_TRANS, 37 CBAR_TYPE_S1_TRANS_S2_BYPASS, 38 CBAR_TYPE_S1_TRANS_S2_FAULT, 39 CBAR_TYPE_S1_TRANS_S2_TRANS, 40}; 41 42#define ARM_SMMU_GR1_CBA2R(n) (0x800 + ((n) << 2)) 43#define ARM_SMMU_CBA2R_VA64 BIT(0) 44 45/* Per-CB system control register */ 46#define ARM_SMMU_CB_SCTLR 0x0 47#define ARM_SMMU_SCTLR_CFCFG BIT(7) /* Stall on context fault */ 48#define ARM_SMMU_SCTLR_CFIE BIT(6) /* Context fault interrupt enable */ 49#define ARM_SMMU_SCTLR_CFRE BIT(5) /* Abort on context fault */ 50 51/* Translation Table Base, holds address of translation table in memory to be used 52 * for this context bank. Or 0 for bypass 53 */ 54#define ARM_SMMU_CB_TTBR0 0x20 55#define ARM_SMMU_CB_TTBR1 0x28 56/* Translation Control Register, configured TTBR/TLB behaviour (0 for bypass) */ 57#define ARM_SMMU_CB_TCR 0x30 58/* Memory Attribute Indirection, also 0 for bypass */ 59#define ARM_SMMU_CB_S1_MAIR0 0x38 60#define ARM_SMMU_CB_S1_MAIR1 0x3c 61 62#define ARM_SMMU_GR0_SMR(n) (0x800 + ((n) << 2)) 63#define ARM_SMMU_SMR_VALID BIT(31) 64#define ARM_SMMU_SMR_MASK GENMASK(31, 16) // Always 0 for now?? 65#define ARM_SMMU_SMR_ID GENMASK(15, 0) 66 67#define ARM_SMMU_GR0_S2CR(n) (0xc00 + ((n) << 2)) 68#define ARM_SMMU_S2CR_PRIVCFG GENMASK(25, 24) 69 70enum arm_smmu_s2cr_privcfg { 71 S2CR_PRIVCFG_DEFAULT, 72 S2CR_PRIVCFG_DIPAN, 73 S2CR_PRIVCFG_UNPRIV, 74 S2CR_PRIVCFG_PRIV, 75}; 76 77#define ARM_SMMU_S2CR_TYPE GENMASK(17, 16) 78 79enum arm_smmu_s2cr_type { 80 S2CR_TYPE_TRANS, 81 S2CR_TYPE_BYPASS, 82 S2CR_TYPE_FAULT, 83}; 84 85#define ARM_SMMU_S2CR_EXIDVALID BIT(10) 86#define ARM_SMMU_S2CR_CBNDX GENMASK(7, 0) 87 88#define VMID_UNUSED 0xff 89 90struct qcom_smmu_priv { 91 phys_addr_t base; 92 struct list_head devices; 93 struct udevice *dev; 94 95 /* Read-once config */ 96 int num_cb; 97 int num_smr; 98 u32 pgshift; 99 u32 cb_pg_offset; 100}; 101 102struct mmu_dev { 103 struct list_head li; 104 struct udevice *dev; 105 u16 sid; 106 u16 cbx; 107 u16 smr; 108}; 109 110#define page_addr(priv, page) ((priv)->base + ((page) << (priv)->pgshift)) 111 112#define smmu_readl(priv, page, offset) readl(page_addr(priv, page) + offset) 113#define gr0_readl(priv, offset) smmu_readl(priv, ARM_SMMU_GR0, offset) 114#define gr1_readl(priv, offset) smmu_readl(priv, ARM_SMMU_GR1, offset) 115#define cbx_readl(priv, cbx, offset) \ 116 smmu_readl(priv, (priv->cb_pg_offset) + cbx, offset) 117 118#define smmu_writel(priv, page, offset, value) \ 119 writel((value), page_addr(priv, page) + offset) 120#define gr0_writel(priv, offset, value) \ 121 smmu_writel(priv, ARM_SMMU_GR0, offset, (value)) 122#define gr1_writel(priv, offset, value) \ 123 smmu_writel(priv, ARM_SMMU_GR1, offset, (value)) 124#define cbx_writel(priv, cbx, offset, value) \ 125 smmu_writel(priv, (priv->cb_pg_offset) + cbx, offset, value) 126 127#define gr1_setbits(priv, offset, value) \ 128 gr1_writel(priv, offset, gr1_readl(priv, offset) | (value)) 129 130static int get_stream_id(struct udevice *dev) 131{ 132 ofnode node = dev_ofnode(dev); 133 struct ofnode_phandle_args args; 134 int count = ofnode_parse_phandle_with_args(node, "iommus", 135 "#iommu-cells", 0, 0, &args); 136 137 if (count < 0 || args.args[0] == 0) { 138 printf("Error: %s: iommus property not found or wrong number of cells\n", 139 __func__); 140 return -EINVAL; 141 } 142 143 return args.args[0]; // Some mask from bit 16 onward? 144} 145 146static struct mmu_dev *alloc_dev(struct udevice *dev) 147{ 148 struct qcom_smmu_priv *priv = dev_get_priv(dev->iommu); 149 struct mmu_dev *mmu_dev; 150 int sid; 151 152 sid = get_stream_id(dev); 153 debug("%s %s has SID %#x\n", dev->iommu->name, dev->name, sid); 154 if (sid < 0 || sid > 0xffff) { 155 printf("\tSMMU: Invalid stream ID for %s\n", dev->name); 156 return ERR_PTR(-EINVAL); 157 } 158 159 /* We only support a single SID per device for now */ 160 list_for_each_entry(mmu_dev, &priv->devices, li) { 161 if (mmu_dev->sid == sid) 162 return ERR_PTR(-EEXIST); 163 } 164 165 mmu_dev = calloc(sizeof(*mmu_dev), 1); 166 if (!mmu_dev) 167 return ERR_PTR(-ENOMEM); 168 169 mmu_dev->dev = dev; 170 mmu_dev->sid = sid; 171 172 list_add_tail(&mmu_dev->li, &priv->devices); 173 174 return mmu_dev; 175} 176 177/* Find and init the first free context bank */ 178static int alloc_cb(struct qcom_smmu_priv *priv) 179{ 180 u32 cbar, type, vmid, val; 181 182 for (int i = 0; i < priv->num_cb; i++) { 183 cbar = gr1_readl(priv, ARM_SMMU_GR1_CBAR(i)); 184 type = FIELD_GET(ARM_SMMU_CBAR_TYPE, cbar); 185 vmid = FIELD_GET(ARM_SMMU_CBAR_VMID, cbar); 186 187 /* Check that the context bank is available. We haven't reset the SMMU so 188 * we just make a best guess. 189 */ 190 if (type != CBAR_TYPE_S2_TRANS && 191 (type != CBAR_TYPE_S1_TRANS_S2_BYPASS || 192 vmid != VMID_UNUSED)) 193 continue; 194 195 debug("%s: Found free context bank %d (cbar %#x)\n", 196 priv->dev->name, i, cbar); 197 type = CBAR_TYPE_S1_TRANS_S2_BYPASS; 198 vmid = 0; 199 cbar &= ~ARM_SMMU_CBAR_TYPE & ~ARM_SMMU_CBAR_VMID; 200 cbar |= FIELD_PREP(ARM_SMMU_CBAR_TYPE, type) | 201 FIELD_PREP(ARM_SMMU_CBAR_VMID, vmid); 202 gr1_writel(priv, ARM_SMMU_GR1_CBAR(i), cbar); 203 204 val = IS_ENABLED(CONFIG_ARM64) == 1 ? ARM_SMMU_CBA2R_VA64 : 0; 205 gr1_setbits(priv, ARM_SMMU_GR1_CBA2R(i), val); 206 return i; 207 } 208 209 return -1; 210} 211 212/* Search for a context bank that is already configured for this stream 213 * returns the context bank index or -ENOENT 214 */ 215static int find_smr(struct qcom_smmu_priv *priv, u16 stream_id) 216{ 217 u32 val; 218 int i; 219 220 for (i = 0; i < priv->num_smr; i++) { 221 val = gr0_readl(priv, ARM_SMMU_GR0_SMR(i)); 222 if (!(val & ARM_SMMU_SMR_VALID) || 223 FIELD_GET(ARM_SMMU_SMR_ID, val) != stream_id) 224 continue; 225 226 return i; 227 } 228 229 return -ENOENT; 230} 231 232static int configure_smr_s2cr(struct qcom_smmu_priv *priv, struct mmu_dev *mdev) 233{ 234 u32 val; 235 int i; 236 237 for (i = 0; i < priv->num_smr; i++) { 238 /* Configure SMR */ 239 val = gr0_readl(priv, ARM_SMMU_GR0_SMR(i)); 240 if (val & ARM_SMMU_SMR_VALID) 241 continue; 242 243 val = mdev->sid | ARM_SMMU_SMR_VALID; 244 gr0_writel(priv, ARM_SMMU_GR0_SMR(i), val); 245 246 /* 247 * WARNING: Don't change this to use S2CR_TYPE_BYPASS! 248 * Some Qualcomm boards have angry hypervisor firmware 249 * that converts S2CR type BYPASS to type FAULT on write. 250 * We don't use virtual addressing for these boards in 251 * u-boot so we can get away with using S2CR_TYPE_TRANS 252 * instead 253 */ 254 val = FIELD_PREP(ARM_SMMU_S2CR_TYPE, S2CR_TYPE_TRANS) | 255 FIELD_PREP(ARM_SMMU_S2CR_CBNDX, mdev->cbx); 256 gr0_writel(priv, ARM_SMMU_GR0_S2CR(i), val); 257 258 mdev->smr = i; 259 break; 260 } 261 262 /* Make sure our writes went through */ 263 mb(); 264 265 return 0; 266} 267 268static int qcom_smmu_connect(struct udevice *dev) 269{ 270 struct mmu_dev *mdev; 271 struct qcom_smmu_priv *priv; 272 int ret; 273 274 debug("%s: %s -> %s\n", __func__, dev->name, dev->iommu->name); 275 276 priv = dev_get_priv(dev->iommu); 277 if (WARN_ON(!priv)) 278 return -EINVAL; 279 280 mdev = alloc_dev(dev); 281 if (IS_ERR(mdev) && PTR_ERR(mdev) != -EEXIST) { 282 printf("%s: %s Couldn't create mmu context\n", __func__, 283 dev->name); 284 return PTR_ERR(mdev); 285 } else if (IS_ERR(mdev)) { // -EEXIST 286 return 0; 287 } 288 289 if (find_smr(priv, mdev->sid) >= 0) { 290 debug("Found existing context bank for %s, skipping init\n", 291 dev->name); 292 return 0; 293 } 294 295 ret = alloc_cb(priv); 296 if (ret < 0 || ret > 0xff) { 297 printf("Error: %s: failed to allocate context bank for %s\n", 298 __func__, dev->name); 299 return 0; 300 } 301 mdev->cbx = ret; 302 303 /* Configure context bank registers */ 304 cbx_writel(priv, mdev->cbx, ARM_SMMU_CB_TTBR0, 0x0); 305 cbx_writel(priv, mdev->cbx, ARM_SMMU_CB_TTBR1, 0x0); 306 cbx_writel(priv, mdev->cbx, ARM_SMMU_CB_S1_MAIR0, 0x0); 307 cbx_writel(priv, mdev->cbx, ARM_SMMU_CB_S1_MAIR1, 0x0); 308 cbx_writel(priv, mdev->cbx, ARM_SMMU_CB_SCTLR, 309 ARM_SMMU_SCTLR_CFIE | ARM_SMMU_SCTLR_CFRE | 310 ARM_SMMU_SCTLR_CFCFG); 311 cbx_writel(priv, mdev->cbx, ARM_SMMU_CB_TCR, 0x0); 312 313 /* Ensure that our writes went through */ 314 mb(); 315 316 configure_smr_s2cr(priv, mdev); 317 318 return 0; 319} 320 321#ifdef DEBUG 322static inline void dump_boot_mappings(struct qcom_smmu_priv *priv) 323{ 324 u32 val; 325 int i; 326 327 debug(" SMMU dump boot mappings:\n"); 328 for (i = 0; i < priv->num_smr; i++) { 329 val = gr0_readl(priv, ARM_SMMU_GR0_SMR(i)); 330 if (val & ARM_SMMU_SMR_VALID) 331 debug("\tSMR %3d: SID: %#lx\n", i, 332 FIELD_GET(ARM_SMMU_SMR_ID, val)); 333 } 334} 335#else 336#define dump_boot_mappings(priv) \ 337 do { \ 338 } while (0) 339#endif 340 341static int qcom_smmu_probe(struct udevice *dev) 342{ 343 struct qcom_smmu_priv *priv; 344 u32 val; 345 346 priv = dev_get_priv(dev); 347 priv->dev = dev; 348 priv->base = dev_read_addr(dev); 349 INIT_LIST_HEAD(&priv->devices); 350 351 /* Read SMMU config */ 352 val = gr0_readl(priv, ARM_SMMU_GR0_ID0); 353 priv->num_smr = FIELD_GET(ARM_SMMU_ID0_NUMSMRG, val); 354 355 val = gr0_readl(priv, ARM_SMMU_GR0_ID1); 356 priv->num_cb = FIELD_GET(ARM_SMMU_ID1_NUMCB, val); 357 priv->pgshift = FIELD_GET(ARM_SMMU_ID1_PAGESIZE, val) ? 16 : 12; 358 priv->cb_pg_offset = 1 359 << (FIELD_GET(ARM_SMMU_ID1_NUMPAGENDXB, val) + 1); 360 361 dump_boot_mappings(priv); 362 363 return 0; 364} 365 366static int qcom_smmu_remove(struct udevice *dev) 367{ 368 (void)dev; 369 /* 370 * We should probably try and de-configure things here, 371 * however I'm yet to find a way to do it without crashing 372 * and it seems like Linux doesn't care at all anyway. 373 */ 374 375 return 0; 376} 377 378static struct iommu_ops qcom_smmu_ops = { 379 .connect = qcom_smmu_connect, 380}; 381 382static const struct udevice_id qcom_smmu500_ids[] = { 383 { .compatible = "qcom,sdm845-smmu-500" }, 384 { .compatible = "qcom,smmu-500", }, 385 { /* sentinel */ } 386}; 387 388U_BOOT_DRIVER(qcom_smmu500) = { 389 .name = "qcom_smmu500", 390 .id = UCLASS_IOMMU, 391 .of_match = qcom_smmu500_ids, 392 .priv_auto = sizeof(struct qcom_smmu_priv), 393 .ops = &qcom_smmu_ops, 394 .probe = qcom_smmu_probe, 395 .remove = qcom_smmu_remove, 396 .flags = DM_FLAG_OS_PREPARE, 397}; 398