1 // SPDX-License-Identifier: GPL-2.0-only OR MIT 2 /* 3 * Apple SART device driver 4 * Copyright (C) The Asahi Linux Contributors 5 * 6 * Apple SART is a simple address filter for some DMA transactions. 7 * Regions of physical memory must be added to the SART's allow 8 * list before any DMA can target these. Unlike a proper 9 * IOMMU no remapping can be done and special support in the 10 * consumer driver is required since not all DMA transactions of 11 * a single device are subject to SART filtering. 12 */ 13 14 #include <linux/soc/apple/sart.h> 15 #include <linux/atomic.h> 16 #include <linux/bits.h> 17 #include <linux/bitfield.h> 18 #include <linux/device.h> 19 #include <linux/io.h> 20 #include <linux/module.h> 21 #include <linux/of.h> 22 #include <linux/of_platform.h> 23 #include <linux/platform_device.h> 24 #include <linux/types.h> 25 26 #define APPLE_SART_MAX_ENTRIES 16 27 28 /* SARTv0 registers */ 29 #define APPLE_SART0_CONFIG(idx) (0x00 + 4 * (idx)) 30 #define APPLE_SART0_CONFIG_FLAGS GENMASK(28, 24) 31 #define APPLE_SART0_CONFIG_SIZE GENMASK(18, 0) 32 #define APPLE_SART0_CONFIG_SIZE_SHIFT 12 33 #define APPLE_SART0_CONFIG_SIZE_MAX GENMASK(18, 0) 34 35 #define APPLE_SART0_PADDR(idx) (0x40 + 4 * (idx)) 36 #define APPLE_SART0_PADDR_SHIFT 12 37 38 #define APPLE_SART0_FLAGS_ALLOW 0xf 39 40 /* SARTv2 registers */ 41 #define APPLE_SART2_CONFIG(idx) (0x00 + 4 * (idx)) 42 #define APPLE_SART2_CONFIG_FLAGS GENMASK(31, 24) 43 #define APPLE_SART2_CONFIG_SIZE GENMASK(23, 0) 44 #define APPLE_SART2_CONFIG_SIZE_SHIFT 12 45 #define APPLE_SART2_CONFIG_SIZE_MAX GENMASK(23, 0) 46 47 #define APPLE_SART2_PADDR(idx) (0x40 + 4 * (idx)) 48 #define APPLE_SART2_PADDR_SHIFT 12 49 50 #define APPLE_SART2_FLAGS_ALLOW 0xff 51 52 /* SARTv3 registers */ 53 #define APPLE_SART3_CONFIG(idx) (0x00 + 4 * (idx)) 54 55 #define APPLE_SART3_PADDR(idx) (0x40 + 4 * (idx)) 56 #define APPLE_SART3_PADDR_SHIFT 12 57 58 #define APPLE_SART3_SIZE(idx) (0x80 + 4 * (idx)) 59 #define APPLE_SART3_SIZE_SHIFT 12 60 #define APPLE_SART3_SIZE_MAX GENMASK(29, 0) 61 62 #define APPLE_SART3_FLAGS_ALLOW 0xff 63 64 struct apple_sart_ops { 65 void (*get_entry)(struct apple_sart *sart, int index, u8 *flags, 66 phys_addr_t *paddr, size_t *size); 67 void (*set_entry)(struct apple_sart *sart, int index, u8 flags, 68 phys_addr_t paddr_shifted, size_t size_shifted); 69 /* This is probably a bitfield but the exact meaning of each bit is unknown. */ 70 unsigned int flags_allow; 71 unsigned int size_shift; 72 unsigned int paddr_shift; 73 size_t size_max; 74 }; 75 76 struct apple_sart { 77 struct device *dev; 78 void __iomem *regs; 79 80 const struct apple_sart_ops *ops; 81 82 unsigned long protected_entries; 83 unsigned long used_entries; 84 }; 85 86 static void sart0_get_entry(struct apple_sart *sart, int index, u8 *flags, 87 phys_addr_t *paddr, size_t *size) 88 { 89 u32 cfg = readl(sart->regs + APPLE_SART0_CONFIG(index)); 90 phys_addr_t paddr_ = readl(sart->regs + APPLE_SART0_PADDR(index)); 91 size_t size_ = FIELD_GET(APPLE_SART0_CONFIG_SIZE, cfg); 92 93 *flags = FIELD_GET(APPLE_SART0_CONFIG_FLAGS, cfg); 94 *size = size_ << APPLE_SART0_CONFIG_SIZE_SHIFT; 95 *paddr = paddr_ << APPLE_SART0_PADDR_SHIFT; 96 } 97 98 static void sart0_set_entry(struct apple_sart *sart, int index, u8 flags, 99 phys_addr_t paddr_shifted, size_t size_shifted) 100 { 101 u32 cfg; 102 103 cfg = FIELD_PREP(APPLE_SART0_CONFIG_FLAGS, flags); 104 cfg |= FIELD_PREP(APPLE_SART0_CONFIG_SIZE, size_shifted); 105 106 writel(paddr_shifted, sart->regs + APPLE_SART0_PADDR(index)); 107 writel(cfg, sart->regs + APPLE_SART0_CONFIG(index)); 108 } 109 110 static struct apple_sart_ops sart_ops_v0 = { 111 .get_entry = sart0_get_entry, 112 .set_entry = sart0_set_entry, 113 .flags_allow = APPLE_SART0_FLAGS_ALLOW, 114 .size_shift = APPLE_SART0_CONFIG_SIZE_SHIFT, 115 .paddr_shift = APPLE_SART0_PADDR_SHIFT, 116 .size_max = APPLE_SART0_CONFIG_SIZE_MAX, 117 }; 118 119 static void sart2_get_entry(struct apple_sart *sart, int index, u8 *flags, 120 phys_addr_t *paddr, size_t *size) 121 { 122 u32 cfg = readl(sart->regs + APPLE_SART2_CONFIG(index)); 123 phys_addr_t paddr_ = readl(sart->regs + APPLE_SART2_PADDR(index)); 124 size_t size_ = FIELD_GET(APPLE_SART2_CONFIG_SIZE, cfg); 125 126 *flags = FIELD_GET(APPLE_SART2_CONFIG_FLAGS, cfg); 127 *size = size_ << APPLE_SART2_CONFIG_SIZE_SHIFT; 128 *paddr = paddr_ << APPLE_SART2_PADDR_SHIFT; 129 } 130 131 static void sart2_set_entry(struct apple_sart *sart, int index, u8 flags, 132 phys_addr_t paddr_shifted, size_t size_shifted) 133 { 134 u32 cfg; 135 136 cfg = FIELD_PREP(APPLE_SART2_CONFIG_FLAGS, flags); 137 cfg |= FIELD_PREP(APPLE_SART2_CONFIG_SIZE, size_shifted); 138 139 writel(paddr_shifted, sart->regs + APPLE_SART2_PADDR(index)); 140 writel(cfg, sart->regs + APPLE_SART2_CONFIG(index)); 141 } 142 143 static struct apple_sart_ops sart_ops_v2 = { 144 .get_entry = sart2_get_entry, 145 .set_entry = sart2_set_entry, 146 .flags_allow = APPLE_SART2_FLAGS_ALLOW, 147 .size_shift = APPLE_SART2_CONFIG_SIZE_SHIFT, 148 .paddr_shift = APPLE_SART2_PADDR_SHIFT, 149 .size_max = APPLE_SART2_CONFIG_SIZE_MAX, 150 }; 151 152 static void sart3_get_entry(struct apple_sart *sart, int index, u8 *flags, 153 phys_addr_t *paddr, size_t *size) 154 { 155 phys_addr_t paddr_ = readl(sart->regs + APPLE_SART3_PADDR(index)); 156 size_t size_ = readl(sart->regs + APPLE_SART3_SIZE(index)); 157 158 *flags = readl(sart->regs + APPLE_SART3_CONFIG(index)); 159 *size = size_ << APPLE_SART3_SIZE_SHIFT; 160 *paddr = paddr_ << APPLE_SART3_PADDR_SHIFT; 161 } 162 163 static void sart3_set_entry(struct apple_sart *sart, int index, u8 flags, 164 phys_addr_t paddr_shifted, size_t size_shifted) 165 { 166 writel(paddr_shifted, sart->regs + APPLE_SART3_PADDR(index)); 167 writel(size_shifted, sart->regs + APPLE_SART3_SIZE(index)); 168 writel(flags, sart->regs + APPLE_SART3_CONFIG(index)); 169 } 170 171 static struct apple_sart_ops sart_ops_v3 = { 172 .get_entry = sart3_get_entry, 173 .set_entry = sart3_set_entry, 174 .flags_allow = APPLE_SART3_FLAGS_ALLOW, 175 .size_shift = APPLE_SART3_SIZE_SHIFT, 176 .paddr_shift = APPLE_SART3_PADDR_SHIFT, 177 .size_max = APPLE_SART3_SIZE_MAX, 178 }; 179 180 static int apple_sart_probe(struct platform_device *pdev) 181 { 182 int i; 183 struct apple_sart *sart; 184 struct device *dev = &pdev->dev; 185 186 sart = devm_kzalloc(dev, sizeof(*sart), GFP_KERNEL); 187 if (!sart) 188 return -ENOMEM; 189 190 sart->dev = dev; 191 sart->ops = of_device_get_match_data(dev); 192 193 sart->regs = devm_platform_ioremap_resource(pdev, 0); 194 if (IS_ERR(sart->regs)) 195 return PTR_ERR(sart->regs); 196 197 for (i = 0; i < APPLE_SART_MAX_ENTRIES; ++i) { 198 u8 flags; 199 size_t size; 200 phys_addr_t paddr; 201 202 sart->ops->get_entry(sart, i, &flags, &paddr, &size); 203 204 if (!flags) 205 continue; 206 207 dev_dbg(sart->dev, 208 "SART bootloader entry: index %02d; flags: 0x%02x; paddr: %pa; size: 0x%zx\n", 209 i, flags, &paddr, size); 210 set_bit(i, &sart->protected_entries); 211 } 212 213 platform_set_drvdata(pdev, sart); 214 return 0; 215 } 216 217 static void apple_sart_put_device(void *dev) 218 { 219 put_device(dev); 220 } 221 222 struct apple_sart *devm_apple_sart_get(struct device *dev) 223 { 224 struct device_node *sart_node; 225 struct platform_device *sart_pdev; 226 struct apple_sart *sart; 227 int ret; 228 229 sart_node = of_parse_phandle(dev->of_node, "apple,sart", 0); 230 if (!sart_node) 231 return ERR_PTR(-ENODEV); 232 233 sart_pdev = of_find_device_by_node(sart_node); 234 of_node_put(sart_node); 235 236 if (!sart_pdev) 237 return ERR_PTR(-ENODEV); 238 239 sart = dev_get_drvdata(&sart_pdev->dev); 240 if (!sart) { 241 put_device(&sart_pdev->dev); 242 return ERR_PTR(-EPROBE_DEFER); 243 } 244 245 ret = devm_add_action_or_reset(dev, apple_sart_put_device, 246 &sart_pdev->dev); 247 if (ret) 248 return ERR_PTR(ret); 249 250 device_link_add(dev, &sart_pdev->dev, 251 DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_SUPPLIER); 252 253 return sart; 254 } 255 EXPORT_SYMBOL_GPL(devm_apple_sart_get); 256 257 static int sart_set_entry(struct apple_sart *sart, int index, u8 flags, 258 phys_addr_t paddr, size_t size) 259 { 260 if (size & ((1 << sart->ops->size_shift) - 1)) 261 return -EINVAL; 262 if (paddr & ((1 << sart->ops->paddr_shift) - 1)) 263 return -EINVAL; 264 265 paddr >>= sart->ops->size_shift; 266 size >>= sart->ops->paddr_shift; 267 268 if (size > sart->ops->size_max) 269 return -EINVAL; 270 271 sart->ops->set_entry(sart, index, flags, paddr, size); 272 return 0; 273 } 274 275 int apple_sart_add_allowed_region(struct apple_sart *sart, phys_addr_t paddr, 276 size_t size) 277 { 278 int i, ret; 279 280 for (i = 0; i < APPLE_SART_MAX_ENTRIES; ++i) { 281 if (test_bit(i, &sart->protected_entries)) 282 continue; 283 if (test_and_set_bit(i, &sart->used_entries)) 284 continue; 285 286 ret = sart_set_entry(sart, i, sart->ops->flags_allow, paddr, 287 size); 288 if (ret) { 289 dev_dbg(sart->dev, 290 "unable to set entry %d to [%pa, 0x%zx]\n", 291 i, &paddr, size); 292 clear_bit(i, &sart->used_entries); 293 return ret; 294 } 295 296 dev_dbg(sart->dev, "wrote [%pa, 0x%zx] to %d\n", &paddr, size, 297 i); 298 return 0; 299 } 300 301 dev_warn(sart->dev, 302 "no free entries left to add [paddr: 0x%pa, size: 0x%zx]\n", 303 &paddr, size); 304 305 return -EBUSY; 306 } 307 EXPORT_SYMBOL_GPL(apple_sart_add_allowed_region); 308 309 int apple_sart_remove_allowed_region(struct apple_sart *sart, phys_addr_t paddr, 310 size_t size) 311 { 312 int i; 313 314 dev_dbg(sart->dev, 315 "will remove [paddr: %pa, size: 0x%zx] from allowed regions\n", 316 &paddr, size); 317 318 for (i = 0; i < APPLE_SART_MAX_ENTRIES; ++i) { 319 u8 eflags; 320 size_t esize; 321 phys_addr_t epaddr; 322 323 if (test_bit(i, &sart->protected_entries)) 324 continue; 325 326 sart->ops->get_entry(sart, i, &eflags, &epaddr, &esize); 327 328 if (epaddr != paddr || esize != size) 329 continue; 330 331 sart->ops->set_entry(sart, i, 0, 0, 0); 332 333 clear_bit(i, &sart->used_entries); 334 dev_dbg(sart->dev, "cleared entry %d\n", i); 335 return 0; 336 } 337 338 dev_warn(sart->dev, "entry [paddr: 0x%pa, size: 0x%zx] not found\n", 339 &paddr, size); 340 341 return -EINVAL; 342 } 343 EXPORT_SYMBOL_GPL(apple_sart_remove_allowed_region); 344 345 static void apple_sart_shutdown(struct platform_device *pdev) 346 { 347 struct apple_sart *sart = dev_get_drvdata(&pdev->dev); 348 int i; 349 350 for (i = 0; i < APPLE_SART_MAX_ENTRIES; ++i) { 351 if (test_bit(i, &sart->protected_entries)) 352 continue; 353 354 sart->ops->set_entry(sart, i, 0, 0, 0); 355 } 356 } 357 358 static const struct of_device_id apple_sart_of_match[] = { 359 { 360 .compatible = "apple,t6000-sart", 361 .data = &sart_ops_v3, 362 }, 363 { 364 .compatible = "apple,t8103-sart", 365 .data = &sart_ops_v2, 366 }, 367 { 368 .compatible = "apple,t8015-sart", 369 .data = &sart_ops_v0, 370 }, 371 {} 372 }; 373 MODULE_DEVICE_TABLE(of, apple_sart_of_match); 374 375 static struct platform_driver apple_sart_driver = { 376 .driver = { 377 .name = "apple-sart", 378 .of_match_table = apple_sart_of_match, 379 }, 380 .probe = apple_sart_probe, 381 .shutdown = apple_sart_shutdown, 382 }; 383 module_platform_driver(apple_sart_driver); 384 385 MODULE_LICENSE("Dual MIT/GPL"); 386 MODULE_AUTHOR("Sven Peter <sven@svenpeter.dev>"); 387 MODULE_DESCRIPTION("Apple SART driver"); 388