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/dma-mapping.h> 9#include <linux/host1x.h> 10#include <linux/iommu.h> 11#include <linux/module.h> 12#include <linux/of.h> 13#include <linux/of_device.h> 14#include <linux/of_platform.h> 15#include <linux/platform_device.h> 16#include <linux/pm_runtime.h> 17#include <linux/reset.h> 18 19#include <soc/tegra/pmc.h> 20 21#include "drm.h" 22#include "falcon.h" 23#include "vic.h" 24 25struct vic_config { 26 const char *firmware; 27 unsigned int version; 28 bool supports_sid; 29}; 30 31struct vic { 32 struct falcon falcon; 33 bool booted; 34 35 void __iomem *regs; 36 struct tegra_drm_client client; 37 struct host1x_channel *channel; 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 46static inline struct vic *to_vic(struct tegra_drm_client *client) 47{ 48 return container_of(client, struct vic, client); 49} 50 51static void vic_writel(struct vic *vic, u32 value, unsigned int offset) 52{ 53 writel(value, vic->regs + offset); 54} 55 56static 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 75disable: 76 clk_disable_unprepare(vic->clk); 77 return err; 78} 79 80static 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 98static 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.virt; 138 fce_bin_data_offset = *(u32 *)(hdr + VIC_UCODE_FCE_DATA_OFFSET); 139 hdr = vic->falcon.firmware.virt + 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.iova + 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 162static int vic_init(struct host1x_client *client) 163{ 164 struct tegra_drm_client *drm = host1x_to_drm_client(client); 165 struct drm_device *dev = dev_get_drvdata(client->host); 166 struct tegra_drm *tegra = dev->dev_private; 167 struct vic *vic = to_vic(drm); 168 int err; 169 170 err = host1x_client_iommu_attach(client); 171 if (err < 0 && err != -ENODEV) { 172 dev_err(vic->dev, "failed to attach to domain: %d\n", err); 173 return err; 174 } 175 176 vic->channel = host1x_channel_request(client); 177 if (!vic->channel) { 178 err = -ENOMEM; 179 goto detach; 180 } 181 182 client->syncpts[0] = host1x_syncpt_request(client, 0); 183 if (!client->syncpts[0]) { 184 err = -ENOMEM; 185 goto free_channel; 186 } 187 188 err = tegra_drm_register_client(tegra, drm); 189 if (err < 0) 190 goto free_syncpt; 191 192 /* 193 * Inherit the DMA parameters (such as maximum segment size) from the 194 * parent host1x device. 195 */ 196 client->dev->dma_parms = client->host->dma_parms; 197 198 return 0; 199 200free_syncpt: 201 host1x_syncpt_free(client->syncpts[0]); 202free_channel: 203 host1x_channel_put(vic->channel); 204detach: 205 host1x_client_iommu_detach(client); 206 207 return err; 208} 209 210static int vic_exit(struct host1x_client *client) 211{ 212 struct tegra_drm_client *drm = host1x_to_drm_client(client); 213 struct drm_device *dev = dev_get_drvdata(client->host); 214 struct tegra_drm *tegra = dev->dev_private; 215 struct vic *vic = to_vic(drm); 216 int err; 217 218 /* avoid a dangling pointer just in case this disappears */ 219 client->dev->dma_parms = NULL; 220 221 err = tegra_drm_unregister_client(tegra, drm); 222 if (err < 0) 223 return err; 224 225 host1x_syncpt_free(client->syncpts[0]); 226 host1x_channel_put(vic->channel); 227 host1x_client_iommu_detach(client); 228 229 if (client->group) { 230 dma_unmap_single(vic->dev, vic->falcon.firmware.phys, 231 vic->falcon.firmware.size, DMA_TO_DEVICE); 232 tegra_drm_free(tegra, vic->falcon.firmware.size, 233 vic->falcon.firmware.virt, 234 vic->falcon.firmware.iova); 235 } else { 236 dma_free_coherent(vic->dev, vic->falcon.firmware.size, 237 vic->falcon.firmware.virt, 238 vic->falcon.firmware.iova); 239 } 240 241 return 0; 242} 243 244static const struct host1x_client_ops vic_client_ops = { 245 .init = vic_init, 246 .exit = vic_exit, 247}; 248 249static int vic_load_firmware(struct vic *vic) 250{ 251 struct host1x_client *client = &vic->client.base; 252 struct tegra_drm *tegra = vic->client.drm; 253 dma_addr_t iova; 254 size_t size; 255 void *virt; 256 int err; 257 258 if (vic->falcon.firmware.virt) 259 return 0; 260 261 err = falcon_read_firmware(&vic->falcon, vic->config->firmware); 262 if (err < 0) 263 return err; 264 265 size = vic->falcon.firmware.size; 266 267 if (!client->group) { 268 virt = dma_alloc_coherent(vic->dev, size, &iova, GFP_KERNEL); 269 if (!virt) 270 return -ENOMEM; 271 } else { 272 virt = tegra_drm_alloc(tegra, size, &iova); 273 } 274 275 vic->falcon.firmware.virt = virt; 276 vic->falcon.firmware.iova = iova; 277 278 err = falcon_load_firmware(&vic->falcon); 279 if (err < 0) 280 goto cleanup; 281 282 /* 283 * In this case we have received an IOVA from the shared domain, so we 284 * need to make sure to get the physical address so that the DMA API 285 * knows what memory pages to flush the cache for. 286 */ 287 if (client->group) { 288 dma_addr_t phys; 289 290 phys = dma_map_single(vic->dev, virt, size, DMA_TO_DEVICE); 291 292 err = dma_mapping_error(vic->dev, phys); 293 if (err < 0) 294 goto cleanup; 295 296 vic->falcon.firmware.phys = phys; 297 } 298 299 return 0; 300 301cleanup: 302 if (!client->group) 303 dma_free_coherent(vic->dev, size, virt, iova); 304 else 305 tegra_drm_free(tegra, size, virt, iova); 306 307 return err; 308} 309 310static int vic_open_channel(struct tegra_drm_client *client, 311 struct tegra_drm_context *context) 312{ 313 struct vic *vic = to_vic(client); 314 int err; 315 316 err = pm_runtime_resume_and_get(vic->dev); 317 if (err < 0) 318 return err; 319 320 err = vic_load_firmware(vic); 321 if (err < 0) 322 goto rpm_put; 323 324 err = vic_boot(vic); 325 if (err < 0) 326 goto rpm_put; 327 328 context->channel = host1x_channel_get(vic->channel); 329 if (!context->channel) { 330 err = -ENOMEM; 331 goto rpm_put; 332 } 333 334 return 0; 335 336rpm_put: 337 pm_runtime_put(vic->dev); 338 return err; 339} 340 341static void vic_close_channel(struct tegra_drm_context *context) 342{ 343 struct vic *vic = to_vic(context->client); 344 345 host1x_channel_put(context->channel); 346 347 pm_runtime_put(vic->dev); 348} 349 350static const struct tegra_drm_client_ops vic_ops = { 351 .open_channel = vic_open_channel, 352 .close_channel = vic_close_channel, 353 .submit = tegra_drm_submit, 354}; 355 356#define NVIDIA_TEGRA_124_VIC_FIRMWARE "nvidia/tegra124/vic03_ucode.bin" 357 358static const struct vic_config vic_t124_config = { 359 .firmware = NVIDIA_TEGRA_124_VIC_FIRMWARE, 360 .version = 0x40, 361 .supports_sid = false, 362}; 363 364#define NVIDIA_TEGRA_210_VIC_FIRMWARE "nvidia/tegra210/vic04_ucode.bin" 365 366static const struct vic_config vic_t210_config = { 367 .firmware = NVIDIA_TEGRA_210_VIC_FIRMWARE, 368 .version = 0x21, 369 .supports_sid = false, 370}; 371 372#define NVIDIA_TEGRA_186_VIC_FIRMWARE "nvidia/tegra186/vic04_ucode.bin" 373 374static const struct vic_config vic_t186_config = { 375 .firmware = NVIDIA_TEGRA_186_VIC_FIRMWARE, 376 .version = 0x18, 377 .supports_sid = true, 378}; 379 380#define NVIDIA_TEGRA_194_VIC_FIRMWARE "nvidia/tegra194/vic.bin" 381 382static const struct vic_config vic_t194_config = { 383 .firmware = NVIDIA_TEGRA_194_VIC_FIRMWARE, 384 .version = 0x19, 385 .supports_sid = true, 386}; 387 388static const struct of_device_id tegra_vic_of_match[] = { 389 { .compatible = "nvidia,tegra124-vic", .data = &vic_t124_config }, 390 { .compatible = "nvidia,tegra210-vic", .data = &vic_t210_config }, 391 { .compatible = "nvidia,tegra186-vic", .data = &vic_t186_config }, 392 { .compatible = "nvidia,tegra194-vic", .data = &vic_t194_config }, 393 { }, 394}; 395MODULE_DEVICE_TABLE(of, tegra_vic_of_match); 396 397static int vic_probe(struct platform_device *pdev) 398{ 399 struct device *dev = &pdev->dev; 400 struct host1x_syncpt **syncpts; 401 struct resource *regs; 402 struct vic *vic; 403 int err; 404 405 /* inherit DMA mask from host1x parent */ 406 err = dma_coerce_mask_and_coherent(dev, *dev->parent->dma_mask); 407 if (err < 0) { 408 dev_err(&pdev->dev, "failed to set DMA mask: %d\n", err); 409 return err; 410 } 411 412 vic = devm_kzalloc(dev, sizeof(*vic), GFP_KERNEL); 413 if (!vic) 414 return -ENOMEM; 415 416 vic->config = of_device_get_match_data(dev); 417 418 syncpts = devm_kzalloc(dev, sizeof(*syncpts), GFP_KERNEL); 419 if (!syncpts) 420 return -ENOMEM; 421 422 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 423 if (!regs) { 424 dev_err(&pdev->dev, "failed to get registers\n"); 425 return -ENXIO; 426 } 427 428 vic->regs = devm_ioremap_resource(dev, regs); 429 if (IS_ERR(vic->regs)) 430 return PTR_ERR(vic->regs); 431 432 vic->clk = devm_clk_get(dev, NULL); 433 if (IS_ERR(vic->clk)) { 434 dev_err(&pdev->dev, "failed to get clock\n"); 435 return PTR_ERR(vic->clk); 436 } 437 438 if (!dev->pm_domain) { 439 vic->rst = devm_reset_control_get(dev, "vic"); 440 if (IS_ERR(vic->rst)) { 441 dev_err(&pdev->dev, "failed to get reset\n"); 442 return PTR_ERR(vic->rst); 443 } 444 } 445 446 vic->falcon.dev = dev; 447 vic->falcon.regs = vic->regs; 448 449 err = falcon_init(&vic->falcon); 450 if (err < 0) 451 return err; 452 453 platform_set_drvdata(pdev, vic); 454 455 INIT_LIST_HEAD(&vic->client.base.list); 456 vic->client.base.ops = &vic_client_ops; 457 vic->client.base.dev = dev; 458 vic->client.base.class = HOST1X_CLASS_VIC; 459 vic->client.base.syncpts = syncpts; 460 vic->client.base.num_syncpts = 1; 461 vic->dev = dev; 462 463 INIT_LIST_HEAD(&vic->client.list); 464 vic->client.version = vic->config->version; 465 vic->client.ops = &vic_ops; 466 467 err = host1x_client_register(&vic->client.base); 468 if (err < 0) { 469 dev_err(dev, "failed to register host1x client: %d\n", err); 470 goto exit_falcon; 471 } 472 473 pm_runtime_enable(&pdev->dev); 474 if (!pm_runtime_enabled(&pdev->dev)) { 475 err = vic_runtime_resume(&pdev->dev); 476 if (err < 0) 477 goto unregister_client; 478 } 479 480 return 0; 481 482unregister_client: 483 host1x_client_unregister(&vic->client.base); 484exit_falcon: 485 falcon_exit(&vic->falcon); 486 487 return err; 488} 489 490static int vic_remove(struct platform_device *pdev) 491{ 492 struct vic *vic = platform_get_drvdata(pdev); 493 int err; 494 495 err = host1x_client_unregister(&vic->client.base); 496 if (err < 0) { 497 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", 498 err); 499 return err; 500 } 501 502 if (pm_runtime_enabled(&pdev->dev)) 503 pm_runtime_disable(&pdev->dev); 504 else 505 vic_runtime_suspend(&pdev->dev); 506 507 falcon_exit(&vic->falcon); 508 509 return 0; 510} 511 512static const struct dev_pm_ops vic_pm_ops = { 513 SET_RUNTIME_PM_OPS(vic_runtime_suspend, vic_runtime_resume, NULL) 514}; 515 516struct platform_driver tegra_vic_driver = { 517 .driver = { 518 .name = "tegra-vic", 519 .of_match_table = tegra_vic_of_match, 520 .pm = &vic_pm_ops 521 }, 522 .probe = vic_probe, 523 .remove = vic_remove, 524}; 525 526#if IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) 527MODULE_FIRMWARE(NVIDIA_TEGRA_124_VIC_FIRMWARE); 528#endif 529#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) 530MODULE_FIRMWARE(NVIDIA_TEGRA_210_VIC_FIRMWARE); 531#endif 532#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) 533MODULE_FIRMWARE(NVIDIA_TEGRA_186_VIC_FIRMWARE); 534#endif 535#if IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC) 536MODULE_FIRMWARE(NVIDIA_TEGRA_194_VIC_FIRMWARE); 537#endif 538