1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2021 Mark Kettenis <kettenis@openbsd.org>
4  */
5 
6 #define LOG_CATEGORY UCLASS_IOMMU
7 
8 #include <common.h>
9 #include <dm.h>
10 #include <iommu.h>
11 #include <malloc.h>
12 #include <phys2bus.h>
13 #include <asm/io.h>
14 
15 #if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA))
16 
17 #if CONFIG_IS_ENABLED(PCI)
dev_pci_iommu_enable(struct udevice * dev)18 static int dev_pci_iommu_enable(struct udevice *dev)
19 {
20 	struct udevice *parent = dev->parent;
21 	struct udevice *dev_iommu;
22 	u32 *iommu_map;
23 	u32 iommu_map_mask, length, phandle, rid, rid_base;
24 	int i, count, len, ret;
25 
26 	while (parent) {
27 		len = dev_read_size(parent, "iommu-map");
28 		if (len > 0)
29 			break;
30 		parent = parent->parent;
31 	}
32 
33 	if (len <= 0)
34 		return 0;
35 
36 	iommu_map = malloc(len);
37 	if (!iommu_map)
38 		return -ENOMEM;
39 
40 	count = len / sizeof(u32);
41 	ret = dev_read_u32_array(parent, "iommu-map", iommu_map, count);
42 	if (ret < 0) {
43 		free(iommu_map);
44 		return 0;
45 	}
46 
47 	iommu_map_mask = dev_read_u32_default(parent, "iommu-map-mask", ~0);
48 	rid = (dm_pci_get_bdf(dev) >> 8) & iommu_map_mask;
49 
50 	/* Loop over entries until mapping is found. */
51 	for (i = 0; i < count; i += 4) {
52 		rid_base = iommu_map[i];
53 		phandle = iommu_map[i + 1];
54 		length = iommu_map[i + 3];
55 
56 		if (rid < rid_base || rid >= rid_base + length)
57 			continue;
58 
59 		ret = uclass_get_device_by_phandle_id(UCLASS_IOMMU, phandle,
60 						      &dev_iommu);
61 		if (ret) {
62 			debug("%s: uclass_get_device_by_ofnode failed: %d\n",
63 			      __func__, ret);
64 			free(iommu_map);
65 			return ret;
66 		}
67 		dev->iommu = dev_iommu;
68 		break;
69 	}
70 
71 	free(iommu_map);
72 	return 0;
73 }
74 #endif
75 
dev_iommu_enable(struct udevice * dev)76 int dev_iommu_enable(struct udevice *dev)
77 {
78 	struct ofnode_phandle_args args;
79 	struct udevice *dev_iommu;
80 	int i, count, ret = 0;
81 
82 	count = dev_count_phandle_with_args(dev, "iommus",
83 					    "#iommu-cells", 0);
84 	for (i = 0; i < count; i++) {
85 		ret = dev_read_phandle_with_args(dev, "iommus",
86 						 "#iommu-cells", 0, i, &args);
87 		if (ret) {
88 			debug("%s: dev_read_phandle_with_args failed: %d\n",
89 			      __func__, ret);
90 			return ret;
91 		}
92 
93 		ret = uclass_get_device_by_ofnode(UCLASS_IOMMU, args.node,
94 						  &dev_iommu);
95 		if (ret) {
96 			debug("%s: uclass_get_device_by_ofnode failed: %d\n",
97 			      __func__, ret);
98 			return ret;
99 		}
100 		dev->iommu = dev_iommu;
101 	}
102 
103 	if (CONFIG_IS_ENABLED(PCI) && count < 0 &&
104 	    device_is_on_pci_bus(dev))
105 		return dev_pci_iommu_enable(dev);
106 
107 	return 0;
108 }
109 #endif
110 
dev_iommu_dma_map(struct udevice * dev,void * addr,size_t size)111 dma_addr_t dev_iommu_dma_map(struct udevice *dev, void *addr, size_t size)
112 {
113 	const struct iommu_ops *ops;
114 
115 	if (dev->iommu) {
116 		ops = device_get_ops(dev->iommu);
117 		if (ops && ops->map)
118 			return ops->map(dev->iommu, addr, size);
119 	}
120 
121 	return dev_phys_to_bus(dev, virt_to_phys(addr));
122 }
123 
dev_iommu_dma_unmap(struct udevice * dev,dma_addr_t addr,size_t size)124 void dev_iommu_dma_unmap(struct udevice *dev, dma_addr_t addr, size_t size)
125 {
126 	const struct iommu_ops *ops;
127 
128 	if (dev->iommu) {
129 		ops = device_get_ops(dev->iommu);
130 		if (ops && ops->unmap)
131 			ops->unmap(dev->iommu, addr, size);
132 	}
133 }
134 
135 UCLASS_DRIVER(iommu) = {
136 	.id		= UCLASS_IOMMU,
137 	.name		= "iommu",
138 };
139