1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2015, NVIDIA Corporation. 4 */ 5 6 #include <linux/clk.h> 7 #include <linux/delay.h> 8 #include <linux/host1x.h> 9 #include <linux/iommu.h> 10 #include <linux/module.h> 11 #include <linux/of.h> 12 #include <linux/of_device.h> 13 #include <linux/of_platform.h> 14 #include <linux/platform_device.h> 15 #include <linux/pm_runtime.h> 16 #include <linux/reset.h> 17 18 #include <soc/tegra/pmc.h> 19 20 #include "drm.h" 21 #include "falcon.h" 22 #include "vic.h" 23 24 struct vic_config { 25 const char *firmware; 26 unsigned int version; 27 bool supports_sid; 28 }; 29 30 struct vic { 31 struct falcon falcon; 32 bool booted; 33 34 void __iomem *regs; 35 struct tegra_drm_client client; 36 struct host1x_channel *channel; 37 struct iommu_domain *domain; 38 struct device *dev; 39 struct clk *clk; 40 struct reset_control *rst; 41 42 /* Platform configuration */ 43 const struct vic_config *config; 44 }; 45 46 static inline struct vic *to_vic(struct tegra_drm_client *client) 47 { 48 return container_of(client, struct vic, client); 49 } 50 51 static void vic_writel(struct vic *vic, u32 value, unsigned int offset) 52 { 53 writel(value, vic->regs + offset); 54 } 55 56 static int vic_runtime_resume(struct device *dev) 57 { 58 struct vic *vic = dev_get_drvdata(dev); 59 int err; 60 61 err = clk_prepare_enable(vic->clk); 62 if (err < 0) 63 return err; 64 65 usleep_range(10, 20); 66 67 err = reset_control_deassert(vic->rst); 68 if (err < 0) 69 goto disable; 70 71 usleep_range(10, 20); 72 73 return 0; 74 75 disable: 76 clk_disable_unprepare(vic->clk); 77 return err; 78 } 79 80 static int vic_runtime_suspend(struct device *dev) 81 { 82 struct vic *vic = dev_get_drvdata(dev); 83 int err; 84 85 err = reset_control_assert(vic->rst); 86 if (err < 0) 87 return err; 88 89 usleep_range(2000, 4000); 90 91 clk_disable_unprepare(vic->clk); 92 93 vic->booted = false; 94 95 return 0; 96 } 97 98 static int vic_boot(struct vic *vic) 99 { 100 #ifdef CONFIG_IOMMU_API 101 struct iommu_fwspec *spec = dev_iommu_fwspec_get(vic->dev); 102 #endif 103 u32 fce_ucode_size, fce_bin_data_offset; 104 void *hdr; 105 int err = 0; 106 107 if (vic->booted) 108 return 0; 109 110 #ifdef CONFIG_IOMMU_API 111 if (vic->config->supports_sid && spec) { 112 u32 value; 113 114 value = TRANSCFG_ATT(1, TRANSCFG_SID_FALCON) | 115 TRANSCFG_ATT(0, TRANSCFG_SID_HW); 116 vic_writel(vic, value, VIC_TFBIF_TRANSCFG); 117 118 if (spec->num_ids > 0) { 119 value = spec->ids[0] & 0xffff; 120 121 vic_writel(vic, value, VIC_THI_STREAMID0); 122 vic_writel(vic, value, VIC_THI_STREAMID1); 123 } 124 } 125 #endif 126 127 /* setup clockgating registers */ 128 vic_writel(vic, CG_IDLE_CG_DLY_CNT(4) | 129 CG_IDLE_CG_EN | 130 CG_WAKEUP_DLY_CNT(4), 131 NV_PVIC_MISC_PRI_VIC_CG); 132 133 err = falcon_boot(&vic->falcon); 134 if (err < 0) 135 return err; 136 137 hdr = vic->falcon.firmware.vaddr; 138 fce_bin_data_offset = *(u32 *)(hdr + VIC_UCODE_FCE_DATA_OFFSET); 139 hdr = vic->falcon.firmware.vaddr + 140 *(u32 *)(hdr + VIC_UCODE_FCE_HEADER_OFFSET); 141 fce_ucode_size = *(u32 *)(hdr + FCE_UCODE_SIZE_OFFSET); 142 143 falcon_execute_method(&vic->falcon, VIC_SET_APPLICATION_ID, 1); 144 falcon_execute_method(&vic->falcon, VIC_SET_FCE_UCODE_SIZE, 145 fce_ucode_size); 146 falcon_execute_method(&vic->falcon, VIC_SET_FCE_UCODE_OFFSET, 147 (vic->falcon.firmware.paddr + fce_bin_data_offset) 148 >> 8); 149 150 err = falcon_wait_idle(&vic->falcon); 151 if (err < 0) { 152 dev_err(vic->dev, 153 "failed to set application ID and FCE base\n"); 154 return err; 155 } 156 157 vic->booted = true; 158 159 return 0; 160 } 161 162 static void *vic_falcon_alloc(struct falcon *falcon, size_t size, 163 dma_addr_t *iova) 164 { 165 struct tegra_drm *tegra = falcon->data; 166 167 return tegra_drm_alloc(tegra, size, iova); 168 } 169 170 static void vic_falcon_free(struct falcon *falcon, size_t size, 171 dma_addr_t iova, void *va) 172 { 173 struct tegra_drm *tegra = falcon->data; 174 175 return tegra_drm_free(tegra, size, va, iova); 176 } 177 178 static const struct falcon_ops vic_falcon_ops = { 179 .alloc = vic_falcon_alloc, 180 .free = vic_falcon_free 181 }; 182 183 static int vic_init(struct host1x_client *client) 184 { 185 struct tegra_drm_client *drm = host1x_to_drm_client(client); 186 struct iommu_group *group = iommu_group_get(client->dev); 187 struct drm_device *dev = dev_get_drvdata(client->parent); 188 struct tegra_drm *tegra = dev->dev_private; 189 struct vic *vic = to_vic(drm); 190 int err; 191 192 if (group && tegra->domain) { 193 err = iommu_attach_group(tegra->domain, group); 194 if (err < 0) { 195 dev_err(vic->dev, "failed to attach to domain: %d\n", 196 err); 197 return err; 198 } 199 200 vic->domain = tegra->domain; 201 } 202 203 vic->channel = host1x_channel_request(client); 204 if (!vic->channel) { 205 err = -ENOMEM; 206 goto detach; 207 } 208 209 client->syncpts[0] = host1x_syncpt_request(client, 0); 210 if (!client->syncpts[0]) { 211 err = -ENOMEM; 212 goto free_channel; 213 } 214 215 err = tegra_drm_register_client(tegra, drm); 216 if (err < 0) 217 goto free_syncpt; 218 219 /* 220 * Inherit the DMA parameters (such as maximum segment size) from the 221 * parent device. 222 */ 223 client->dev->dma_parms = client->parent->dma_parms; 224 225 return 0; 226 227 free_syncpt: 228 host1x_syncpt_free(client->syncpts[0]); 229 free_channel: 230 host1x_channel_put(vic->channel); 231 detach: 232 if (group && tegra->domain) 233 iommu_detach_group(tegra->domain, group); 234 235 return err; 236 } 237 238 static int vic_exit(struct host1x_client *client) 239 { 240 struct tegra_drm_client *drm = host1x_to_drm_client(client); 241 struct iommu_group *group = iommu_group_get(client->dev); 242 struct drm_device *dev = dev_get_drvdata(client->parent); 243 struct tegra_drm *tegra = dev->dev_private; 244 struct vic *vic = to_vic(drm); 245 int err; 246 247 /* avoid a dangling pointer just in case this disappears */ 248 client->dev->dma_parms = NULL; 249 250 err = tegra_drm_unregister_client(tegra, drm); 251 if (err < 0) 252 return err; 253 254 host1x_syncpt_free(client->syncpts[0]); 255 host1x_channel_put(vic->channel); 256 257 if (vic->domain) { 258 iommu_detach_group(vic->domain, group); 259 vic->domain = NULL; 260 } 261 262 return 0; 263 } 264 265 static const struct host1x_client_ops vic_client_ops = { 266 .init = vic_init, 267 .exit = vic_exit, 268 }; 269 270 static int vic_load_firmware(struct vic *vic) 271 { 272 int err; 273 274 if (vic->falcon.data) 275 return 0; 276 277 vic->falcon.data = vic->client.drm; 278 279 err = falcon_read_firmware(&vic->falcon, vic->config->firmware); 280 if (err < 0) 281 goto cleanup; 282 283 err = falcon_load_firmware(&vic->falcon); 284 if (err < 0) 285 goto cleanup; 286 287 return 0; 288 289 cleanup: 290 vic->falcon.data = NULL; 291 return err; 292 } 293 294 static int vic_open_channel(struct tegra_drm_client *client, 295 struct tegra_drm_context *context) 296 { 297 struct vic *vic = to_vic(client); 298 int err; 299 300 err = pm_runtime_get_sync(vic->dev); 301 if (err < 0) 302 return err; 303 304 err = vic_load_firmware(vic); 305 if (err < 0) 306 goto rpm_put; 307 308 err = vic_boot(vic); 309 if (err < 0) 310 goto rpm_put; 311 312 context->channel = host1x_channel_get(vic->channel); 313 if (!context->channel) { 314 err = -ENOMEM; 315 goto rpm_put; 316 } 317 318 return 0; 319 320 rpm_put: 321 pm_runtime_put(vic->dev); 322 return err; 323 } 324 325 static void vic_close_channel(struct tegra_drm_context *context) 326 { 327 struct vic *vic = to_vic(context->client); 328 329 host1x_channel_put(context->channel); 330 331 pm_runtime_put(vic->dev); 332 } 333 334 static const struct tegra_drm_client_ops vic_ops = { 335 .open_channel = vic_open_channel, 336 .close_channel = vic_close_channel, 337 .submit = tegra_drm_submit, 338 }; 339 340 #define NVIDIA_TEGRA_124_VIC_FIRMWARE "nvidia/tegra124/vic03_ucode.bin" 341 342 static const struct vic_config vic_t124_config = { 343 .firmware = NVIDIA_TEGRA_124_VIC_FIRMWARE, 344 .version = 0x40, 345 .supports_sid = false, 346 }; 347 348 #define NVIDIA_TEGRA_210_VIC_FIRMWARE "nvidia/tegra210/vic04_ucode.bin" 349 350 static const struct vic_config vic_t210_config = { 351 .firmware = NVIDIA_TEGRA_210_VIC_FIRMWARE, 352 .version = 0x21, 353 .supports_sid = false, 354 }; 355 356 #define NVIDIA_TEGRA_186_VIC_FIRMWARE "nvidia/tegra186/vic04_ucode.bin" 357 358 static const struct vic_config vic_t186_config = { 359 .firmware = NVIDIA_TEGRA_186_VIC_FIRMWARE, 360 .version = 0x18, 361 .supports_sid = true, 362 }; 363 364 #define NVIDIA_TEGRA_194_VIC_FIRMWARE "nvidia/tegra194/vic.bin" 365 366 static const struct vic_config vic_t194_config = { 367 .firmware = NVIDIA_TEGRA_194_VIC_FIRMWARE, 368 .version = 0x19, 369 .supports_sid = true, 370 }; 371 372 static const struct of_device_id vic_match[] = { 373 { .compatible = "nvidia,tegra124-vic", .data = &vic_t124_config }, 374 { .compatible = "nvidia,tegra210-vic", .data = &vic_t210_config }, 375 { .compatible = "nvidia,tegra186-vic", .data = &vic_t186_config }, 376 { .compatible = "nvidia,tegra194-vic", .data = &vic_t194_config }, 377 { }, 378 }; 379 380 static int vic_probe(struct platform_device *pdev) 381 { 382 struct device *dev = &pdev->dev; 383 struct host1x_syncpt **syncpts; 384 struct resource *regs; 385 struct vic *vic; 386 int err; 387 388 vic = devm_kzalloc(dev, sizeof(*vic), GFP_KERNEL); 389 if (!vic) 390 return -ENOMEM; 391 392 vic->config = of_device_get_match_data(dev); 393 394 syncpts = devm_kzalloc(dev, sizeof(*syncpts), GFP_KERNEL); 395 if (!syncpts) 396 return -ENOMEM; 397 398 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 399 if (!regs) { 400 dev_err(&pdev->dev, "failed to get registers\n"); 401 return -ENXIO; 402 } 403 404 vic->regs = devm_ioremap_resource(dev, regs); 405 if (IS_ERR(vic->regs)) 406 return PTR_ERR(vic->regs); 407 408 vic->clk = devm_clk_get(dev, NULL); 409 if (IS_ERR(vic->clk)) { 410 dev_err(&pdev->dev, "failed to get clock\n"); 411 return PTR_ERR(vic->clk); 412 } 413 414 if (!dev->pm_domain) { 415 vic->rst = devm_reset_control_get(dev, "vic"); 416 if (IS_ERR(vic->rst)) { 417 dev_err(&pdev->dev, "failed to get reset\n"); 418 return PTR_ERR(vic->rst); 419 } 420 } 421 422 vic->falcon.dev = dev; 423 vic->falcon.regs = vic->regs; 424 vic->falcon.ops = &vic_falcon_ops; 425 426 err = falcon_init(&vic->falcon); 427 if (err < 0) 428 return err; 429 430 platform_set_drvdata(pdev, vic); 431 432 INIT_LIST_HEAD(&vic->client.base.list); 433 vic->client.base.ops = &vic_client_ops; 434 vic->client.base.dev = dev; 435 vic->client.base.class = HOST1X_CLASS_VIC; 436 vic->client.base.syncpts = syncpts; 437 vic->client.base.num_syncpts = 1; 438 vic->dev = dev; 439 440 INIT_LIST_HEAD(&vic->client.list); 441 vic->client.version = vic->config->version; 442 vic->client.ops = &vic_ops; 443 444 err = host1x_client_register(&vic->client.base); 445 if (err < 0) { 446 dev_err(dev, "failed to register host1x client: %d\n", err); 447 goto exit_falcon; 448 } 449 450 pm_runtime_enable(&pdev->dev); 451 if (!pm_runtime_enabled(&pdev->dev)) { 452 err = vic_runtime_resume(&pdev->dev); 453 if (err < 0) 454 goto unregister_client; 455 } 456 457 return 0; 458 459 unregister_client: 460 host1x_client_unregister(&vic->client.base); 461 exit_falcon: 462 falcon_exit(&vic->falcon); 463 464 return err; 465 } 466 467 static int vic_remove(struct platform_device *pdev) 468 { 469 struct vic *vic = platform_get_drvdata(pdev); 470 int err; 471 472 err = host1x_client_unregister(&vic->client.base); 473 if (err < 0) { 474 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", 475 err); 476 return err; 477 } 478 479 if (pm_runtime_enabled(&pdev->dev)) 480 pm_runtime_disable(&pdev->dev); 481 else 482 vic_runtime_suspend(&pdev->dev); 483 484 falcon_exit(&vic->falcon); 485 486 return 0; 487 } 488 489 static const struct dev_pm_ops vic_pm_ops = { 490 SET_RUNTIME_PM_OPS(vic_runtime_suspend, vic_runtime_resume, NULL) 491 }; 492 493 struct platform_driver tegra_vic_driver = { 494 .driver = { 495 .name = "tegra-vic", 496 .of_match_table = vic_match, 497 .pm = &vic_pm_ops 498 }, 499 .probe = vic_probe, 500 .remove = vic_remove, 501 }; 502 503 #if IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) 504 MODULE_FIRMWARE(NVIDIA_TEGRA_124_VIC_FIRMWARE); 505 #endif 506 #if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) 507 MODULE_FIRMWARE(NVIDIA_TEGRA_210_VIC_FIRMWARE); 508 #endif 509 #if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) 510 MODULE_FIRMWARE(NVIDIA_TEGRA_186_VIC_FIRMWARE); 511 #endif 512 #if IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC) 513 MODULE_FIRMWARE(NVIDIA_TEGRA_194_VIC_FIRMWARE); 514 #endif 515