forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-13 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e
kernel/drivers/gpu/drm/tegra/vic.c
....@@ -1,12 +1,11 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (c) 2015, NVIDIA Corporation.
3
- *
4
- * This program is free software; you can redistribute it and/or modify
5
- * it under the terms of the GNU General Public License version 2 as
6
- * published by the Free Software Foundation.
74 */
85
96 #include <linux/clk.h>
7
+#include <linux/delay.h>
8
+#include <linux/dma-mapping.h>
109 #include <linux/host1x.h>
1110 #include <linux/iommu.h>
1211 #include <linux/module.h>
....@@ -26,6 +25,7 @@
2625 struct vic_config {
2726 const char *firmware;
2827 unsigned int version;
28
+ bool supports_sid;
2929 };
3030
3131 struct vic {
....@@ -35,9 +35,9 @@
3535 void __iomem *regs;
3636 struct tegra_drm_client client;
3737 struct host1x_channel *channel;
38
- struct iommu_domain *domain;
3938 struct device *dev;
4039 struct clk *clk;
40
+ struct reset_control *rst;
4141
4242 /* Platform configuration */
4343 const struct vic_config *config;
....@@ -56,13 +56,37 @@
5656 static int vic_runtime_resume(struct device *dev)
5757 {
5858 struct vic *vic = dev_get_drvdata(dev);
59
+ int err;
5960
60
- return clk_prepare_enable(vic->clk);
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;
6178 }
6279
6380 static int vic_runtime_suspend(struct device *dev)
6481 {
6582 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);
6690
6791 clk_disable_unprepare(vic->clk);
6892
....@@ -73,12 +97,32 @@
7397
7498 static int vic_boot(struct vic *vic)
7599 {
100
+#ifdef CONFIG_IOMMU_API
101
+ struct iommu_fwspec *spec = dev_iommu_fwspec_get(vic->dev);
102
+#endif
76103 u32 fce_ucode_size, fce_bin_data_offset;
77104 void *hdr;
78105 int err = 0;
79106
80107 if (vic->booted)
81108 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
82126
83127 /* setup clockgating registers */
84128 vic_writel(vic, CG_IDLE_CG_DLY_CNT(4) |
....@@ -90,9 +134,9 @@
90134 if (err < 0)
91135 return err;
92136
93
- hdr = vic->falcon.firmware.vaddr;
137
+ hdr = vic->falcon.firmware.virt;
94138 fce_bin_data_offset = *(u32 *)(hdr + VIC_UCODE_FCE_DATA_OFFSET);
95
- hdr = vic->falcon.firmware.vaddr +
139
+ hdr = vic->falcon.firmware.virt +
96140 *(u32 *)(hdr + VIC_UCODE_FCE_HEADER_OFFSET);
97141 fce_ucode_size = *(u32 *)(hdr + FCE_UCODE_SIZE_OFFSET);
98142
....@@ -100,7 +144,7 @@
100144 falcon_execute_method(&vic->falcon, VIC_SET_FCE_UCODE_SIZE,
101145 fce_ucode_size);
102146 falcon_execute_method(&vic->falcon, VIC_SET_FCE_UCODE_OFFSET,
103
- (vic->falcon.firmware.paddr + fce_bin_data_offset)
147
+ (vic->falcon.firmware.iova + fce_bin_data_offset)
104148 >> 8);
105149
106150 err = falcon_wait_idle(&vic->falcon);
....@@ -115,55 +159,21 @@
115159 return 0;
116160 }
117161
118
-static void *vic_falcon_alloc(struct falcon *falcon, size_t size,
119
- dma_addr_t *iova)
120
-{
121
- struct tegra_drm *tegra = falcon->data;
122
-
123
- return tegra_drm_alloc(tegra, size, iova);
124
-}
125
-
126
-static void vic_falcon_free(struct falcon *falcon, size_t size,
127
- dma_addr_t iova, void *va)
128
-{
129
- struct tegra_drm *tegra = falcon->data;
130
-
131
- return tegra_drm_free(tegra, size, va, iova);
132
-}
133
-
134
-static const struct falcon_ops vic_falcon_ops = {
135
- .alloc = vic_falcon_alloc,
136
- .free = vic_falcon_free
137
-};
138
-
139162 static int vic_init(struct host1x_client *client)
140163 {
141164 struct tegra_drm_client *drm = host1x_to_drm_client(client);
142
- struct iommu_group *group = iommu_group_get(client->dev);
143
- struct drm_device *dev = dev_get_drvdata(client->parent);
165
+ struct drm_device *dev = dev_get_drvdata(client->host);
144166 struct tegra_drm *tegra = dev->dev_private;
145167 struct vic *vic = to_vic(drm);
146168 int err;
147169
148
- if (group && tegra->domain) {
149
- err = iommu_attach_group(tegra->domain, group);
150
- if (err < 0) {
151
- dev_err(vic->dev, "failed to attach to domain: %d\n",
152
- err);
153
- return err;
154
- }
155
-
156
- vic->domain = tegra->domain;
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;
157174 }
158175
159
- if (!vic->falcon.data) {
160
- vic->falcon.data = tegra;
161
- err = falcon_load_firmware(&vic->falcon);
162
- if (err < 0)
163
- goto detach;
164
- }
165
-
166
- vic->channel = host1x_channel_request(client->dev);
176
+ vic->channel = host1x_channel_request(client);
167177 if (!vic->channel) {
168178 err = -ENOMEM;
169179 goto detach;
....@@ -179,6 +189,12 @@
179189 if (err < 0)
180190 goto free_syncpt;
181191
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
+
182198 return 0;
183199
184200 free_syncpt:
....@@ -186,8 +202,7 @@
186202 free_channel:
187203 host1x_channel_put(vic->channel);
188204 detach:
189
- if (group && tegra->domain)
190
- iommu_detach_group(tegra->domain, group);
205
+ host1x_client_iommu_detach(client);
191206
192207 return err;
193208 }
....@@ -195,11 +210,13 @@
195210 static int vic_exit(struct host1x_client *client)
196211 {
197212 struct tegra_drm_client *drm = host1x_to_drm_client(client);
198
- struct iommu_group *group = iommu_group_get(client->dev);
199
- struct drm_device *dev = dev_get_drvdata(client->parent);
213
+ struct drm_device *dev = dev_get_drvdata(client->host);
200214 struct tegra_drm *tegra = dev->dev_private;
201215 struct vic *vic = to_vic(drm);
202216 int err;
217
+
218
+ /* avoid a dangling pointer just in case this disappears */
219
+ client->dev->dma_parms = NULL;
203220
204221 err = tegra_drm_unregister_client(tegra, drm);
205222 if (err < 0)
....@@ -207,10 +224,18 @@
207224
208225 host1x_syncpt_free(client->syncpts[0]);
209226 host1x_channel_put(vic->channel);
227
+ host1x_client_iommu_detach(client);
210228
211
- if (vic->domain) {
212
- iommu_detach_group(vic->domain, group);
213
- vic->domain = NULL;
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);
214239 }
215240
216241 return 0;
....@@ -221,29 +246,96 @@
221246 .exit = vic_exit,
222247 };
223248
249
+static 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
+
301
+cleanup:
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
+
224310 static int vic_open_channel(struct tegra_drm_client *client,
225311 struct tegra_drm_context *context)
226312 {
227313 struct vic *vic = to_vic(client);
228314 int err;
229315
230
- err = pm_runtime_get_sync(vic->dev);
316
+ err = pm_runtime_resume_and_get(vic->dev);
231317 if (err < 0)
232318 return err;
233319
320
+ err = vic_load_firmware(vic);
321
+ if (err < 0)
322
+ goto rpm_put;
323
+
234324 err = vic_boot(vic);
235
- if (err < 0) {
236
- pm_runtime_put(vic->dev);
237
- return err;
238
- }
325
+ if (err < 0)
326
+ goto rpm_put;
239327
240328 context->channel = host1x_channel_get(vic->channel);
241329 if (!context->channel) {
242
- pm_runtime_put(vic->dev);
243
- return -ENOMEM;
330
+ err = -ENOMEM;
331
+ goto rpm_put;
244332 }
245333
246334 return 0;
335
+
336
+rpm_put:
337
+ pm_runtime_put(vic->dev);
338
+ return err;
247339 }
248340
249341 static void vic_close_channel(struct tegra_drm_context *context)
....@@ -266,6 +358,7 @@
266358 static const struct vic_config vic_t124_config = {
267359 .firmware = NVIDIA_TEGRA_124_VIC_FIRMWARE,
268360 .version = 0x40,
361
+ .supports_sid = false,
269362 };
270363
271364 #define NVIDIA_TEGRA_210_VIC_FIRMWARE "nvidia/tegra210/vic04_ucode.bin"
....@@ -273,6 +366,7 @@
273366 static const struct vic_config vic_t210_config = {
274367 .firmware = NVIDIA_TEGRA_210_VIC_FIRMWARE,
275368 .version = 0x21,
369
+ .supports_sid = false,
276370 };
277371
278372 #define NVIDIA_TEGRA_186_VIC_FIRMWARE "nvidia/tegra186/vic04_ucode.bin"
....@@ -280,14 +374,25 @@
280374 static const struct vic_config vic_t186_config = {
281375 .firmware = NVIDIA_TEGRA_186_VIC_FIRMWARE,
282376 .version = 0x18,
377
+ .supports_sid = true,
283378 };
284379
285
-static const struct of_device_id vic_match[] = {
380
+#define NVIDIA_TEGRA_194_VIC_FIRMWARE "nvidia/tegra194/vic.bin"
381
+
382
+static const struct vic_config vic_t194_config = {
383
+ .firmware = NVIDIA_TEGRA_194_VIC_FIRMWARE,
384
+ .version = 0x19,
385
+ .supports_sid = true,
386
+};
387
+
388
+static const struct of_device_id tegra_vic_of_match[] = {
286389 { .compatible = "nvidia,tegra124-vic", .data = &vic_t124_config },
287390 { .compatible = "nvidia,tegra210-vic", .data = &vic_t210_config },
288391 { .compatible = "nvidia,tegra186-vic", .data = &vic_t186_config },
392
+ { .compatible = "nvidia,tegra194-vic", .data = &vic_t194_config },
289393 { },
290394 };
395
+MODULE_DEVICE_TABLE(of, tegra_vic_of_match);
291396
292397 static int vic_probe(struct platform_device *pdev)
293398 {
....@@ -296,6 +401,13 @@
296401 struct resource *regs;
297402 struct vic *vic;
298403 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
+ }
299411
300412 vic = devm_kzalloc(dev, sizeof(*vic), GFP_KERNEL);
301413 if (!vic)
....@@ -323,17 +435,20 @@
323435 return PTR_ERR(vic->clk);
324436 }
325437
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
+
326446 vic->falcon.dev = dev;
327447 vic->falcon.regs = vic->regs;
328
- vic->falcon.ops = &vic_falcon_ops;
329448
330449 err = falcon_init(&vic->falcon);
331450 if (err < 0)
332451 return err;
333
-
334
- err = falcon_read_firmware(&vic->falcon, vic->config->firmware);
335
- if (err < 0)
336
- goto exit_falcon;
337452
338453 platform_set_drvdata(pdev, vic);
339454
....@@ -352,7 +467,6 @@
352467 err = host1x_client_register(&vic->client.base);
353468 if (err < 0) {
354469 dev_err(dev, "failed to register host1x client: %d\n", err);
355
- platform_set_drvdata(pdev, NULL);
356470 goto exit_falcon;
357471 }
358472
....@@ -402,7 +516,7 @@
402516 struct platform_driver tegra_vic_driver = {
403517 .driver = {
404518 .name = "tegra-vic",
405
- .of_match_table = vic_match,
519
+ .of_match_table = tegra_vic_of_match,
406520 .pm = &vic_pm_ops
407521 },
408522 .probe = vic_probe,
....@@ -418,3 +532,6 @@
418532 #if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC)
419533 MODULE_FIRMWARE(NVIDIA_TEGRA_186_VIC_FIRMWARE);
420534 #endif
535
+#if IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC)
536
+MODULE_FIRMWARE(NVIDIA_TEGRA_194_VIC_FIRMWARE);
537
+#endif