1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2017 Linaro Ltd. 4 */ 5 6 #include <linux/device.h> 7 #include <linux/firmware.h> 8 #include <linux/kernel.h> 9 #include <linux/iommu.h> 10 #include <linux/io.h> 11 #include <linux/of.h> 12 #include <linux/of_reserved_mem.h> 13 #include <linux/platform_device.h> 14 #include <linux/of_device.h> 15 #include <linux/firmware/qcom/qcom_scm.h> 16 #include <linux/sizes.h> 17 #include <linux/soc/qcom/mdt_loader.h> 18 19 #include "core.h" 20 #include "firmware.h" 21 #include "hfi_venus_io.h" 22 23 #define VENUS_PAS_ID 9 24 #define VENUS_FW_MEM_SIZE (6 * SZ_1M) 25 #define VENUS_FW_START_ADDR 0x0 26 27 static void venus_reset_cpu(struct venus_core *core) 28 { 29 u32 fw_size = core->fw.mapped_mem_size; 30 void __iomem *wrapper_base; 31 32 if (IS_IRIS2(core) || IS_IRIS2_1(core)) 33 wrapper_base = core->wrapper_tz_base; 34 else 35 wrapper_base = core->wrapper_base; 36 37 writel(0, wrapper_base + WRAPPER_FW_START_ADDR); 38 writel(fw_size, wrapper_base + WRAPPER_FW_END_ADDR); 39 writel(0, wrapper_base + WRAPPER_CPA_START_ADDR); 40 writel(fw_size, wrapper_base + WRAPPER_CPA_END_ADDR); 41 writel(fw_size, wrapper_base + WRAPPER_NONPIX_START_ADDR); 42 writel(fw_size, wrapper_base + WRAPPER_NONPIX_END_ADDR); 43 44 if (IS_IRIS2(core) || IS_IRIS2_1(core)) { 45 /* Bring XTSS out of reset */ 46 writel(0, wrapper_base + WRAPPER_TZ_XTSS_SW_RESET); 47 } else { 48 writel(0x0, wrapper_base + WRAPPER_CPU_CGC_DIS); 49 writel(0x0, wrapper_base + WRAPPER_CPU_CLOCK_CONFIG); 50 51 /* Bring ARM9 out of reset */ 52 writel(0, wrapper_base + WRAPPER_A9SS_SW_RESET); 53 } 54 } 55 56 int venus_set_hw_state(struct venus_core *core, bool resume) 57 { 58 int ret; 59 60 if (core->use_tz) { 61 ret = qcom_scm_set_remote_state(resume, 0); 62 if (resume && ret == -EINVAL) 63 ret = 0; 64 return ret; 65 } 66 67 if (resume) { 68 venus_reset_cpu(core); 69 } else { 70 if (IS_IRIS2(core) || IS_IRIS2_1(core)) 71 writel(WRAPPER_XTSS_SW_RESET_BIT, 72 core->wrapper_tz_base + WRAPPER_TZ_XTSS_SW_RESET); 73 else 74 writel(WRAPPER_A9SS_SW_RESET_BIT, 75 core->wrapper_base + WRAPPER_A9SS_SW_RESET); 76 } 77 78 return 0; 79 } 80 81 static int venus_load_fw(struct venus_core *core, const char *fwname, 82 phys_addr_t *mem_phys, size_t *mem_size) 83 { 84 const struct firmware *mdt; 85 struct resource res; 86 struct device *dev; 87 ssize_t fw_size; 88 void *mem_va; 89 int ret; 90 91 *mem_phys = 0; 92 *mem_size = 0; 93 94 dev = core->dev; 95 ret = of_reserved_mem_region_to_resource(dev->of_node, 0, &res); 96 if (ret) { 97 dev_err(dev, "failed to lookup reserved memory-region\n"); 98 return -EINVAL; 99 } 100 101 ret = request_firmware(&mdt, fwname, dev); 102 if (ret < 0) 103 return ret; 104 105 fw_size = qcom_mdt_get_size(mdt); 106 if (fw_size < 0) { 107 ret = fw_size; 108 goto err_release_fw; 109 } 110 111 *mem_phys = res.start; 112 *mem_size = resource_size(&res); 113 114 if (*mem_size < fw_size || fw_size > VENUS_FW_MEM_SIZE) { 115 ret = -EINVAL; 116 goto err_release_fw; 117 } 118 119 mem_va = memremap(*mem_phys, *mem_size, MEMREMAP_WC); 120 if (!mem_va) { 121 dev_err(dev, "unable to map memory region %pa size %#zx\n", mem_phys, *mem_size); 122 ret = -ENOMEM; 123 goto err_release_fw; 124 } 125 126 if (core->use_tz) 127 ret = qcom_mdt_load(dev, mdt, fwname, VENUS_PAS_ID, 128 mem_va, *mem_phys, *mem_size, NULL); 129 else 130 ret = qcom_mdt_load_no_init(dev, mdt, fwname, mem_va, 131 *mem_phys, *mem_size, NULL); 132 133 memunmap(mem_va); 134 err_release_fw: 135 release_firmware(mdt); 136 return ret; 137 } 138 139 static int venus_boot_no_tz(struct venus_core *core, phys_addr_t mem_phys, 140 size_t mem_size) 141 { 142 struct iommu_domain *iommu; 143 struct device *dev; 144 int ret; 145 146 dev = core->fw.dev; 147 if (!dev) 148 return -EPROBE_DEFER; 149 150 iommu = core->fw.iommu_domain; 151 core->fw.mapped_mem_size = mem_size; 152 153 ret = iommu_map(iommu, VENUS_FW_START_ADDR, mem_phys, mem_size, 154 IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV, GFP_KERNEL); 155 if (ret) { 156 dev_err(dev, "could not map video firmware region\n"); 157 return ret; 158 } 159 160 venus_reset_cpu(core); 161 162 return 0; 163 } 164 165 static int venus_shutdown_no_tz(struct venus_core *core) 166 { 167 const size_t mapped = core->fw.mapped_mem_size; 168 struct iommu_domain *iommu; 169 size_t unmapped; 170 u32 reg; 171 struct device *dev = core->fw.dev; 172 void __iomem *wrapper_base = core->wrapper_base; 173 void __iomem *wrapper_tz_base = core->wrapper_tz_base; 174 175 if (IS_IRIS2(core) || IS_IRIS2_1(core)) { 176 /* Assert the reset to XTSS */ 177 reg = readl(wrapper_tz_base + WRAPPER_TZ_XTSS_SW_RESET); 178 reg |= WRAPPER_XTSS_SW_RESET_BIT; 179 writel(reg, wrapper_tz_base + WRAPPER_TZ_XTSS_SW_RESET); 180 } else { 181 /* Assert the reset to ARM9 */ 182 reg = readl(wrapper_base + WRAPPER_A9SS_SW_RESET); 183 reg |= WRAPPER_A9SS_SW_RESET_BIT; 184 writel(reg, wrapper_base + WRAPPER_A9SS_SW_RESET); 185 } 186 187 iommu = core->fw.iommu_domain; 188 189 if (core->fw.mapped_mem_size && iommu) { 190 unmapped = iommu_unmap(iommu, VENUS_FW_START_ADDR, mapped); 191 192 if (unmapped != mapped) 193 dev_err(dev, "failed to unmap firmware\n"); 194 else 195 core->fw.mapped_mem_size = 0; 196 } 197 198 return 0; 199 } 200 201 int venus_firmware_cfg(struct venus_core *core) 202 { 203 void __iomem *cpu_cs_base = core->cpu_cs_base; 204 205 if (IS_AR50_LITE(core)) 206 writel(CPU_CS_VCICMD_ARP_OFF, cpu_cs_base + CPU_CS_VCICMD); 207 208 return 0; 209 } 210 211 int venus_boot(struct venus_core *core) 212 { 213 struct device *dev = core->dev; 214 const struct venus_resources *res = core->res; 215 const char *fwpath = NULL; 216 phys_addr_t mem_phys; 217 size_t mem_size; 218 int ret; 219 220 if (!IS_ENABLED(CONFIG_QCOM_MDT_LOADER) || 221 (core->use_tz && !qcom_scm_is_available())) 222 return -EPROBE_DEFER; 223 224 ret = of_property_read_string_index(dev->of_node, "firmware-name", 0, 225 &fwpath); 226 if (ret) 227 fwpath = core->res->fwname; 228 229 ret = venus_load_fw(core, fwpath, &mem_phys, &mem_size); 230 if (ret) { 231 dev_err(dev, "fail to load video firmware\n"); 232 return -EINVAL; 233 } 234 235 core->fw.mem_size = mem_size; 236 core->fw.mem_phys = mem_phys; 237 238 if (core->use_tz) 239 ret = qcom_scm_pas_auth_and_reset(VENUS_PAS_ID); 240 else 241 ret = venus_boot_no_tz(core, mem_phys, mem_size); 242 243 if (ret) 244 return ret; 245 246 if (core->use_tz && res->cp_size) { 247 /* 248 * Clues for porting using downstream data: 249 * cp_start = 0 250 * cp_size = venus_ns/virtual-addr-pool[0] - yes, address and not size! 251 * This works, as the non-secure context bank is placed 252 * contiguously right after the Content Protection region. 253 * 254 * cp_nonpixel_start = venus_sec_non_pixel/virtual-addr-pool[0] 255 * cp_nonpixel_size = venus_sec_non_pixel/virtual-addr-pool[1] 256 */ 257 ret = qcom_scm_mem_protect_video_var(res->cp_start, 258 res->cp_size, 259 res->cp_nonpixel_start, 260 res->cp_nonpixel_size); 261 if (ret) { 262 qcom_scm_pas_shutdown(VENUS_PAS_ID); 263 dev_err(dev, "set virtual address ranges fail (%d)\n", 264 ret); 265 return ret; 266 } 267 } 268 269 return 0; 270 } 271 272 int venus_shutdown(struct venus_core *core) 273 { 274 int ret; 275 276 if (core->use_tz) 277 ret = qcom_scm_pas_shutdown(VENUS_PAS_ID); 278 else 279 ret = venus_shutdown_no_tz(core); 280 281 return ret; 282 } 283 284 int venus_firmware_check(struct venus_core *core) 285 { 286 const struct firmware_version *req = core->res->min_fw; 287 const struct firmware_version *run = &core->venus_ver; 288 289 if (!req) 290 return 0; 291 292 if (!is_fw_rev_or_newer(core, req->major, req->minor, req->rev)) 293 goto error; 294 295 return 0; 296 error: 297 dev_err(core->dev, "Firmware v%d.%d.%d < v%d.%d.%d\n", 298 run->major, run->minor, run->rev, 299 req->major, req->minor, req->rev); 300 301 return -EINVAL; 302 } 303 304 int venus_firmware_init(struct venus_core *core) 305 { 306 struct platform_device_info info; 307 struct iommu_domain *iommu_dom; 308 struct platform_device *pdev; 309 struct device_node *np; 310 int ret; 311 312 np = of_get_child_by_name(core->dev->of_node, "video-firmware"); 313 if (!np) { 314 core->use_tz = true; 315 return 0; 316 } 317 318 memset(&info, 0, sizeof(info)); 319 info.fwnode = &np->fwnode; 320 info.parent = core->dev; 321 info.name = np->name; 322 info.dma_mask = DMA_BIT_MASK(32); 323 324 pdev = platform_device_register_full(&info); 325 if (IS_ERR(pdev)) { 326 of_node_put(np); 327 return PTR_ERR(pdev); 328 } 329 330 pdev->dev.of_node = np; 331 332 ret = of_dma_configure(&pdev->dev, np, true); 333 if (ret) { 334 dev_err(core->dev, "dma configure fail\n"); 335 goto err_unregister; 336 } 337 338 core->fw.dev = &pdev->dev; 339 340 iommu_dom = iommu_paging_domain_alloc(core->fw.dev); 341 if (IS_ERR(iommu_dom)) { 342 dev_err(core->fw.dev, "Failed to allocate iommu domain\n"); 343 ret = PTR_ERR(iommu_dom); 344 goto err_unregister; 345 } 346 347 ret = iommu_attach_device(iommu_dom, core->fw.dev); 348 if (ret) { 349 dev_err(core->fw.dev, "could not attach device\n"); 350 goto err_iommu_free; 351 } 352 353 core->fw.iommu_domain = iommu_dom; 354 355 of_node_put(np); 356 357 return 0; 358 359 err_iommu_free: 360 iommu_domain_free(iommu_dom); 361 err_unregister: 362 platform_device_unregister(pdev); 363 of_node_put(np); 364 return ret; 365 } 366 367 void venus_firmware_deinit(struct venus_core *core) 368 { 369 struct iommu_domain *iommu; 370 371 if (!core->fw.dev) 372 return; 373 374 iommu = core->fw.iommu_domain; 375 376 iommu_detach_device(iommu, core->fw.dev); 377 378 if (core->fw.iommu_domain) { 379 iommu_domain_free(iommu); 380 core->fw.iommu_domain = NULL; 381 } 382 383 platform_device_unregister(to_platform_device(core->fw.dev)); 384 } 385