xref: /openbmc/linux/drivers/gpu/host1x/dev.c (revision 388f6966)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Tegra host1x driver
4  *
5  * Copyright (c) 2010-2013, NVIDIA Corporation.
6  */
7 
8 #include <linux/clk.h>
9 #include <linux/dma-mapping.h>
10 #include <linux/io.h>
11 #include <linux/list.h>
12 #include <linux/module.h>
13 #include <linux/of_device.h>
14 #include <linux/of.h>
15 #include <linux/slab.h>
16 
17 #define CREATE_TRACE_POINTS
18 #include <trace/events/host1x.h>
19 #undef CREATE_TRACE_POINTS
20 
21 #include "bus.h"
22 #include "channel.h"
23 #include "debug.h"
24 #include "dev.h"
25 #include "intr.h"
26 
27 #include "hw/host1x01.h"
28 #include "hw/host1x02.h"
29 #include "hw/host1x04.h"
30 #include "hw/host1x05.h"
31 #include "hw/host1x06.h"
32 #include "hw/host1x07.h"
33 
34 void host1x_hypervisor_writel(struct host1x *host1x, u32 v, u32 r)
35 {
36 	writel(v, host1x->hv_regs + r);
37 }
38 
39 u32 host1x_hypervisor_readl(struct host1x *host1x, u32 r)
40 {
41 	return readl(host1x->hv_regs + r);
42 }
43 
44 void host1x_sync_writel(struct host1x *host1x, u32 v, u32 r)
45 {
46 	void __iomem *sync_regs = host1x->regs + host1x->info->sync_offset;
47 
48 	writel(v, sync_regs + r);
49 }
50 
51 u32 host1x_sync_readl(struct host1x *host1x, u32 r)
52 {
53 	void __iomem *sync_regs = host1x->regs + host1x->info->sync_offset;
54 
55 	return readl(sync_regs + r);
56 }
57 
58 void host1x_ch_writel(struct host1x_channel *ch, u32 v, u32 r)
59 {
60 	writel(v, ch->regs + r);
61 }
62 
63 u32 host1x_ch_readl(struct host1x_channel *ch, u32 r)
64 {
65 	return readl(ch->regs + r);
66 }
67 
68 static const struct host1x_info host1x01_info = {
69 	.nb_channels = 8,
70 	.nb_pts = 32,
71 	.nb_mlocks = 16,
72 	.nb_bases = 8,
73 	.init = host1x01_init,
74 	.sync_offset = 0x3000,
75 	.dma_mask = DMA_BIT_MASK(32),
76 	.has_wide_gather = false,
77 	.has_hypervisor = false,
78 	.num_sid_entries = 0,
79 	.sid_table = NULL,
80 };
81 
82 static const struct host1x_info host1x02_info = {
83 	.nb_channels = 9,
84 	.nb_pts = 32,
85 	.nb_mlocks = 16,
86 	.nb_bases = 12,
87 	.init = host1x02_init,
88 	.sync_offset = 0x3000,
89 	.dma_mask = DMA_BIT_MASK(32),
90 	.has_wide_gather = false,
91 	.has_hypervisor = false,
92 	.num_sid_entries = 0,
93 	.sid_table = NULL,
94 };
95 
96 static const struct host1x_info host1x04_info = {
97 	.nb_channels = 12,
98 	.nb_pts = 192,
99 	.nb_mlocks = 16,
100 	.nb_bases = 64,
101 	.init = host1x04_init,
102 	.sync_offset = 0x2100,
103 	.dma_mask = DMA_BIT_MASK(34),
104 	.has_wide_gather = false,
105 	.has_hypervisor = false,
106 	.num_sid_entries = 0,
107 	.sid_table = NULL,
108 };
109 
110 static const struct host1x_info host1x05_info = {
111 	.nb_channels = 14,
112 	.nb_pts = 192,
113 	.nb_mlocks = 16,
114 	.nb_bases = 64,
115 	.init = host1x05_init,
116 	.sync_offset = 0x2100,
117 	.dma_mask = DMA_BIT_MASK(34),
118 	.has_wide_gather = false,
119 	.has_hypervisor = false,
120 	.num_sid_entries = 0,
121 	.sid_table = NULL,
122 };
123 
124 static const struct host1x_sid_entry tegra186_sid_table[] = {
125 	{
126 		/* VIC */
127 		.base = 0x1af0,
128 		.offset = 0x30,
129 		.limit = 0x34
130 	},
131 };
132 
133 static const struct host1x_info host1x06_info = {
134 	.nb_channels = 63,
135 	.nb_pts = 576,
136 	.nb_mlocks = 24,
137 	.nb_bases = 16,
138 	.init = host1x06_init,
139 	.sync_offset = 0x0,
140 	.dma_mask = DMA_BIT_MASK(40),
141 	.has_wide_gather = true,
142 	.has_hypervisor = true,
143 	.num_sid_entries = ARRAY_SIZE(tegra186_sid_table),
144 	.sid_table = tegra186_sid_table,
145 };
146 
147 static const struct host1x_sid_entry tegra194_sid_table[] = {
148 	{
149 		/* VIC */
150 		.base = 0x1af0,
151 		.offset = 0x30,
152 		.limit = 0x34
153 	},
154 };
155 
156 static const struct host1x_info host1x07_info = {
157 	.nb_channels = 63,
158 	.nb_pts = 704,
159 	.nb_mlocks = 32,
160 	.nb_bases = 0,
161 	.init = host1x07_init,
162 	.sync_offset = 0x0,
163 	.dma_mask = DMA_BIT_MASK(40),
164 	.has_wide_gather = true,
165 	.has_hypervisor = true,
166 	.num_sid_entries = ARRAY_SIZE(tegra194_sid_table),
167 	.sid_table = tegra194_sid_table,
168 };
169 
170 static const struct of_device_id host1x_of_match[] = {
171 	{ .compatible = "nvidia,tegra194-host1x", .data = &host1x07_info, },
172 	{ .compatible = "nvidia,tegra186-host1x", .data = &host1x06_info, },
173 	{ .compatible = "nvidia,tegra210-host1x", .data = &host1x05_info, },
174 	{ .compatible = "nvidia,tegra124-host1x", .data = &host1x04_info, },
175 	{ .compatible = "nvidia,tegra114-host1x", .data = &host1x02_info, },
176 	{ .compatible = "nvidia,tegra30-host1x", .data = &host1x01_info, },
177 	{ .compatible = "nvidia,tegra20-host1x", .data = &host1x01_info, },
178 	{ },
179 };
180 MODULE_DEVICE_TABLE(of, host1x_of_match);
181 
182 static void host1x_setup_sid_table(struct host1x *host)
183 {
184 	const struct host1x_info *info = host->info;
185 	unsigned int i;
186 
187 	for (i = 0; i < info->num_sid_entries; i++) {
188 		const struct host1x_sid_entry *entry = &info->sid_table[i];
189 
190 		host1x_hypervisor_writel(host, entry->offset, entry->base);
191 		host1x_hypervisor_writel(host, entry->limit, entry->base + 4);
192 	}
193 }
194 
195 static struct iommu_domain *host1x_iommu_attach(struct host1x *host)
196 {
197 	struct iommu_domain *domain = iommu_get_domain_for_dev(host->dev);
198 	int err;
199 
200 	/*
201 	 * If the host1x firewall is enabled, there's no need to enable IOMMU
202 	 * support. Similarly, if host1x is already attached to an IOMMU (via
203 	 * the DMA API), don't try to attach again.
204 	 */
205 	if (IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL) || domain)
206 		return domain;
207 
208 	host->group = iommu_group_get(host->dev);
209 	if (host->group) {
210 		struct iommu_domain_geometry *geometry;
211 		dma_addr_t start, end;
212 		unsigned long order;
213 
214 		err = iova_cache_get();
215 		if (err < 0)
216 			goto put_group;
217 
218 		host->domain = iommu_domain_alloc(&platform_bus_type);
219 		if (!host->domain) {
220 			err = -ENOMEM;
221 			goto put_cache;
222 		}
223 
224 		err = iommu_attach_group(host->domain, host->group);
225 		if (err) {
226 			if (err == -ENODEV)
227 				err = 0;
228 
229 			goto free_domain;
230 		}
231 
232 		geometry = &host->domain->geometry;
233 		start = geometry->aperture_start & host->info->dma_mask;
234 		end = geometry->aperture_end & host->info->dma_mask;
235 
236 		order = __ffs(host->domain->pgsize_bitmap);
237 		init_iova_domain(&host->iova, 1UL << order, start >> order);
238 		host->iova_end = end;
239 
240 		domain = host->domain;
241 	}
242 
243 	return domain;
244 
245 free_domain:
246 	iommu_domain_free(host->domain);
247 	host->domain = NULL;
248 put_cache:
249 	iova_cache_put();
250 put_group:
251 	iommu_group_put(host->group);
252 	host->group = NULL;
253 
254 	return ERR_PTR(err);
255 }
256 
257 static int host1x_iommu_init(struct host1x *host)
258 {
259 	u64 mask = host->info->dma_mask;
260 	struct iommu_domain *domain;
261 	int err;
262 
263 	domain = host1x_iommu_attach(host);
264 	if (IS_ERR(domain)) {
265 		err = PTR_ERR(domain);
266 		dev_err(host->dev, "failed to attach to IOMMU: %d\n", err);
267 		return err;
268 	}
269 
270 	/*
271 	 * If we're not behind an IOMMU make sure we don't get push buffers
272 	 * that are allocated outside of the range addressable by the GATHER
273 	 * opcode.
274 	 *
275 	 * Newer generations of Tegra (Tegra186 and later) support a wide
276 	 * variant of the GATHER opcode that allows addressing more bits.
277 	 */
278 	if (!domain && !host->info->has_wide_gather)
279 		mask = DMA_BIT_MASK(32);
280 
281 	err = dma_coerce_mask_and_coherent(host->dev, mask);
282 	if (err < 0) {
283 		dev_err(host->dev, "failed to set DMA mask: %d\n", err);
284 		return err;
285 	}
286 
287 	return 0;
288 }
289 
290 static void host1x_iommu_exit(struct host1x *host)
291 {
292 	if (host->domain) {
293 		put_iova_domain(&host->iova);
294 		iommu_detach_group(host->domain, host->group);
295 
296 		iommu_domain_free(host->domain);
297 		host->domain = NULL;
298 
299 		iova_cache_put();
300 
301 		iommu_group_put(host->group);
302 		host->group = NULL;
303 	}
304 }
305 
306 static int host1x_probe(struct platform_device *pdev)
307 {
308 	struct host1x *host;
309 	struct resource *regs, *hv_regs = NULL;
310 	int syncpt_irq;
311 	int err;
312 
313 	host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
314 	if (!host)
315 		return -ENOMEM;
316 
317 	host->info = of_device_get_match_data(&pdev->dev);
318 
319 	if (host->info->has_hypervisor) {
320 		regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vm");
321 		if (!regs) {
322 			dev_err(&pdev->dev, "failed to get vm registers\n");
323 			return -ENXIO;
324 		}
325 
326 		hv_regs = platform_get_resource_byname(pdev, IORESOURCE_MEM,
327 						       "hypervisor");
328 		if (!hv_regs) {
329 			dev_err(&pdev->dev,
330 				"failed to get hypervisor registers\n");
331 			return -ENXIO;
332 		}
333 	} else {
334 		regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
335 		if (!regs) {
336 			dev_err(&pdev->dev, "failed to get registers\n");
337 			return -ENXIO;
338 		}
339 	}
340 
341 	syncpt_irq = platform_get_irq(pdev, 0);
342 	if (syncpt_irq < 0)
343 		return syncpt_irq;
344 
345 	mutex_init(&host->devices_lock);
346 	INIT_LIST_HEAD(&host->devices);
347 	INIT_LIST_HEAD(&host->list);
348 	host->dev = &pdev->dev;
349 
350 	/* set common host1x device data */
351 	platform_set_drvdata(pdev, host);
352 
353 	host->regs = devm_ioremap_resource(&pdev->dev, regs);
354 	if (IS_ERR(host->regs))
355 		return PTR_ERR(host->regs);
356 
357 	if (host->info->has_hypervisor) {
358 		host->hv_regs = devm_ioremap_resource(&pdev->dev, hv_regs);
359 		if (IS_ERR(host->hv_regs))
360 			return PTR_ERR(host->hv_regs);
361 	}
362 
363 	host->dev->dma_parms = &host->dma_parms;
364 	dma_set_max_seg_size(host->dev, UINT_MAX);
365 
366 	if (host->info->init) {
367 		err = host->info->init(host);
368 		if (err)
369 			return err;
370 	}
371 
372 	host->clk = devm_clk_get(&pdev->dev, NULL);
373 	if (IS_ERR(host->clk)) {
374 		err = PTR_ERR(host->clk);
375 
376 		if (err != -EPROBE_DEFER)
377 			dev_err(&pdev->dev, "failed to get clock: %d\n", err);
378 
379 		return err;
380 	}
381 
382 	host->rst = devm_reset_control_get(&pdev->dev, "host1x");
383 	if (IS_ERR(host->rst)) {
384 		err = PTR_ERR(host->rst);
385 		dev_err(&pdev->dev, "failed to get reset: %d\n", err);
386 		return err;
387 	}
388 
389 	err = host1x_iommu_init(host);
390 	if (err < 0) {
391 		dev_err(&pdev->dev, "failed to setup IOMMU: %d\n", err);
392 		return err;
393 	}
394 
395 	err = host1x_channel_list_init(&host->channel_list,
396 				       host->info->nb_channels);
397 	if (err) {
398 		dev_err(&pdev->dev, "failed to initialize channel list\n");
399 		goto iommu_exit;
400 	}
401 
402 	err = clk_prepare_enable(host->clk);
403 	if (err < 0) {
404 		dev_err(&pdev->dev, "failed to enable clock\n");
405 		goto free_channels;
406 	}
407 
408 	err = reset_control_deassert(host->rst);
409 	if (err < 0) {
410 		dev_err(&pdev->dev, "failed to deassert reset: %d\n", err);
411 		goto unprepare_disable;
412 	}
413 
414 	err = host1x_syncpt_init(host);
415 	if (err) {
416 		dev_err(&pdev->dev, "failed to initialize syncpts\n");
417 		goto reset_assert;
418 	}
419 
420 	err = host1x_intr_init(host, syncpt_irq);
421 	if (err) {
422 		dev_err(&pdev->dev, "failed to initialize interrupts\n");
423 		goto deinit_syncpt;
424 	}
425 
426 	host1x_debug_init(host);
427 
428 	if (host->info->has_hypervisor)
429 		host1x_setup_sid_table(host);
430 
431 	err = host1x_register(host);
432 	if (err < 0)
433 		goto deinit_intr;
434 
435 	return 0;
436 
437 deinit_intr:
438 	host1x_intr_deinit(host);
439 deinit_syncpt:
440 	host1x_syncpt_deinit(host);
441 reset_assert:
442 	reset_control_assert(host->rst);
443 unprepare_disable:
444 	clk_disable_unprepare(host->clk);
445 free_channels:
446 	host1x_channel_list_free(&host->channel_list);
447 iommu_exit:
448 	host1x_iommu_exit(host);
449 
450 	return err;
451 }
452 
453 static int host1x_remove(struct platform_device *pdev)
454 {
455 	struct host1x *host = platform_get_drvdata(pdev);
456 
457 	host1x_unregister(host);
458 	host1x_debug_deinit(host);
459 	host1x_intr_deinit(host);
460 	host1x_syncpt_deinit(host);
461 	reset_control_assert(host->rst);
462 	clk_disable_unprepare(host->clk);
463 	host1x_iommu_exit(host);
464 
465 	return 0;
466 }
467 
468 static struct platform_driver tegra_host1x_driver = {
469 	.driver = {
470 		.name = "tegra-host1x",
471 		.of_match_table = host1x_of_match,
472 	},
473 	.probe = host1x_probe,
474 	.remove = host1x_remove,
475 };
476 
477 static struct platform_driver * const drivers[] = {
478 	&tegra_host1x_driver,
479 	&tegra_mipi_driver,
480 };
481 
482 static int __init tegra_host1x_init(void)
483 {
484 	int err;
485 
486 	err = bus_register(&host1x_bus_type);
487 	if (err < 0)
488 		return err;
489 
490 	err = platform_register_drivers(drivers, ARRAY_SIZE(drivers));
491 	if (err < 0)
492 		bus_unregister(&host1x_bus_type);
493 
494 	return err;
495 }
496 module_init(tegra_host1x_init);
497 
498 static void __exit tegra_host1x_exit(void)
499 {
500 	platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
501 	bus_unregister(&host1x_bus_type);
502 }
503 module_exit(tegra_host1x_exit);
504 
505 MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
506 MODULE_AUTHOR("Terje Bergstrom <tbergstrom@nvidia.com>");
507 MODULE_DESCRIPTION("Host1x driver for Tegra products");
508 MODULE_LICENSE("GPL");
509