0c7fd01ec859f112577b3cf12c09318320119a92
[openwrt/staging/nbd.git] /
1 From 7bc393e32a785f1e5c00dc8190b9baf87e0fe453 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.org>
3 Date: Tue, 29 Jan 2019 16:13:25 +0000
4 Subject: [PATCH] staging: vchiq_arm: Set up dma ranges on child devices
5
6 The VCHIQ driver now loads the audio, camera, codec, and vc-sm
7 drivers as platform drivers. However they were not being given
8 the correct DMA configuration.
9
10 Call of_dma_configure with the parent (VCHIQ) parameters to be
11 inherited by the child.
12
13 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
14
15 staging: vchiq: Use the old dma controller for OF config on platform devices
16
17 vchiq on Pi4 is no longer under the soc node, therefore it
18 doesn't get the dma-ranges for the VPU.
19
20 Switch to using the configuration of the old dma controller as
21 that will set the dma-ranges correctly.
22
23 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
24
25 staging: vchiq_arm: Give vchiq children DT nodes
26
27 vchiq kernel clients are now instantiated as platform drivers rather
28 than using DT, but the children of the vchiq interface may still
29 benefit from access to DT properties. Give them the option of a
30 a sub-node of the vchiq parent for configuration and to allow
31 them to be disabled.
32
33 Signed-off-by: Phil Elwell <phil@raspberrypi.com>
34
35 staging: vchiq_arm: Add 36-bit address support
36
37 Conditional on a new compatible string, change the pagelist encoding
38 such that the top 24 bits are the pfn, leaving 8 bits for run length
39 (-1), giving a 36-bit address range.
40
41 Manage the split between addresses for the VPU and addresses for the
42 40-bit DMA controller with a dedicated DMA device pointer that on non-
43 BCM2711 platforms is the same as the main VCHIQ device. This allows
44 the VCHIQ node to stay in the usual place in the DT.
45
46 Signed-off-by: Phil Elwell <phil@raspberrypi.com>
47
48 staging: vchiq_arm: children inherit DMA config
49
50 Although it is no longer necessary for vchiq's children to have a
51 different DMA configuration to the parent, they do still need to
52 explicitly to have their DMA configuration set - to be that of the
53 parent.
54
55 Signed-off-by: Phil Elwell <phil@raspberrypi.com>
56 ---
57 .../interface/vchiq_arm/vchiq_arm.c | 105 ++++++++++++++----
58 .../interface/vchiq_arm/vchiq_arm.h | 1 +
59 2 files changed, 87 insertions(+), 19 deletions(-)
60
61 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
62 +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
63 @@ -20,6 +20,7 @@
64 #include <linux/completion.h>
65 #include <linux/list.h>
66 #include <linux/of.h>
67 +#include <linux/of_platform.h>
68 #include <linux/platform_device.h>
69 #include <linux/compat.h>
70 #include <linux/dma-mapping.h>
71 @@ -77,6 +78,11 @@ static const struct vchiq_platform_info
72 .cache_line_size = 64,
73 };
74
75 +static const struct vchiq_platform_info bcm2711_info = {
76 + .cache_line_size = 64,
77 + .use_36bit_addrs = true,
78 +};
79 +
80 struct vchiq_arm_state {
81 /* Keepalive-related data */
82 struct task_struct *ka_thread;
83 @@ -123,6 +129,9 @@ struct vchiq_pagelist_info {
84 unsigned int scatterlist_mapped;
85 };
86
87 +static unsigned int g_use_36bit_addrs = 0;
88 +static struct device *g_dma_dev;
89 +
90 static int
91 vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handle, void *data,
92 unsigned int size, enum vchiq_bulk_dir dir);
93 @@ -152,7 +161,7 @@ static void
94 cleanup_pagelistinfo(struct vchiq_instance *instance, struct vchiq_pagelist_info *pagelistinfo)
95 {
96 if (pagelistinfo->scatterlist_mapped) {
97 - dma_unmap_sg(instance->state->dev, pagelistinfo->scatterlist,
98 + dma_unmap_sg(g_dma_dev, pagelistinfo->scatterlist,
99 pagelistinfo->num_pages, pagelistinfo->dma_dir);
100 }
101
102 @@ -364,7 +373,7 @@ create_pagelist(struct vchiq_instance *i
103 count -= len;
104 }
105
106 - dma_buffers = dma_map_sg(instance->state->dev,
107 + dma_buffers = dma_map_sg(g_dma_dev,
108 scatterlist,
109 num_pages,
110 pagelistinfo->dma_dir);
111 @@ -378,22 +387,58 @@ create_pagelist(struct vchiq_instance *i
112
113 /* Combine adjacent blocks for performance */
114 k = 0;
115 - for_each_sg(scatterlist, sg, dma_buffers, i) {
116 - unsigned int len = sg_dma_len(sg);
117 - dma_addr_t addr = sg_dma_address(sg);
118 -
119 - /* Note: addrs is the address + page_count - 1
120 - * The firmware expects blocks after the first to be page-
121 - * aligned and a multiple of the page size
122 - */
123 - WARN_ON(len == 0);
124 - WARN_ON(i && (i != (dma_buffers - 1)) && (len & ~PAGE_MASK));
125 - WARN_ON(i && (addr & ~PAGE_MASK));
126 - if (is_adjacent_block(addrs, addr, k))
127 - addrs[k - 1] += ((len + PAGE_SIZE - 1) >> PAGE_SHIFT);
128 - else
129 - addrs[k++] = (addr & PAGE_MASK) |
130 - (((len + PAGE_SIZE - 1) >> PAGE_SHIFT) - 1);
131 + if (g_use_36bit_addrs) {
132 + for_each_sg(scatterlist, sg, dma_buffers, i) {
133 + unsigned int len = sg_dma_len(sg);
134 + dma_addr_t addr = sg_dma_address(sg);
135 + u32 page_id = (u32)((addr >> 4) & ~0xff);
136 + u32 sg_pages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
137 +
138 + /* Note: addrs is the address + page_count - 1
139 + * The firmware expects blocks after the first to be page-
140 + * aligned and a multiple of the page size
141 + */
142 + WARN_ON(len == 0);
143 + WARN_ON(i &&
144 + (i != (dma_buffers - 1)) && (len & ~PAGE_MASK));
145 + WARN_ON(i && (addr & ~PAGE_MASK));
146 + WARN_ON(upper_32_bits(addr) > 0xf);
147 +
148 + if (k > 0 &&
149 + ((addrs[k - 1] & ~0xff) +
150 + (((addrs[k - 1] & 0xff) + 1) << 8)
151 + == page_id)) {
152 + u32 inc_pages = min(sg_pages,
153 + 0xff - (addrs[k - 1] & 0xff));
154 + addrs[k - 1] += inc_pages;
155 + page_id += inc_pages << 8;
156 + sg_pages -= inc_pages;
157 + }
158 + while (sg_pages) {
159 + u32 inc_pages = min(sg_pages, 0x100u);
160 + addrs[k++] = page_id | (inc_pages - 1);
161 + page_id += inc_pages << 8;
162 + sg_pages -= inc_pages;
163 + }
164 + }
165 + } else {
166 + for_each_sg(scatterlist, sg, dma_buffers, i) {
167 + unsigned int len = sg_dma_len(sg);
168 + dma_addr_t addr = sg_dma_address(sg);
169 +
170 + /* Note: addrs is the address + page_count - 1
171 + * The firmware expects blocks after the first to be page-
172 + * aligned and a multiple of the page size
173 + */
174 + WARN_ON(len == 0);
175 + WARN_ON(i && (i != (dma_buffers - 1)) && (len & ~PAGE_MASK));
176 + WARN_ON(i && (addr & ~PAGE_MASK));
177 + if (is_adjacent_block(addrs, addr, k))
178 + addrs[k - 1] += ((len + PAGE_SIZE - 1) >> PAGE_SHIFT);
179 + else
180 + addrs[k++] = (addr & PAGE_MASK) |
181 + (((len + PAGE_SIZE - 1) >> PAGE_SHIFT) - 1);
182 + }
183 }
184
185 /* Partial cache lines (fragments) require special measures */
186 @@ -439,7 +484,7 @@ free_pagelist(struct vchiq_instance *ins
187 * NOTE: dma_unmap_sg must be called before the
188 * cpu can touch any of the data/pages.
189 */
190 - dma_unmap_sg(instance->state->dev, pagelistinfo->scatterlist,
191 + dma_unmap_sg(g_dma_dev, pagelistinfo->scatterlist,
192 pagelistinfo->num_pages, pagelistinfo->dma_dir);
193 pagelistinfo->scatterlist_mapped = 0;
194
195 @@ -494,6 +539,7 @@ free_pagelist(struct vchiq_instance *ins
196 static int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state *state)
197 {
198 struct device *dev = &pdev->dev;
199 + struct device *dma_dev = NULL;
200 struct vchiq_drv_mgmt *drv_mgmt = platform_get_drvdata(pdev);
201 struct rpi_firmware *fw = drv_mgmt->fw;
202 struct vchiq_slot_zero *vchiq_slot_zero;
203 @@ -514,6 +560,24 @@ static int vchiq_platform_init(struct pl
204
205 drv_mgmt->fragments_size = 2 * drv_mgmt->info->cache_line_size;
206
207 + if (drv_mgmt->info->use_36bit_addrs) {
208 + struct device_node *dma_node =
209 + of_find_compatible_node(NULL, NULL, "brcm,bcm2711-dma");
210 +
211 + if (dma_node) {
212 + struct platform_device *pdev;
213 +
214 + pdev = of_find_device_by_node(dma_node);
215 + if (pdev)
216 + dma_dev = &pdev->dev;
217 + of_node_put(dma_node);
218 + g_use_36bit_addrs = true;
219 + } else {
220 + dev_err(dev, "40-bit DMA controller not found\n");
221 + return -EINVAL;
222 + }
223 + }
224 +
225 /* Allocate space for the channels in coherent memory */
226 slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE);
227 frag_mem_size = PAGE_ALIGN(drv_mgmt->fragments_size * MAX_FRAGMENTS);
228 @@ -581,6 +645,8 @@ static int vchiq_platform_init(struct pl
229 return -ENXIO;
230 }
231
232 + g_dma_dev = dma_dev ?: dev;
233 +
234 dev_dbg(&pdev->dev, "arm: vchiq_init - done (slots %pK, phys %pad)\n",
235 vchiq_slot_zero, &slot_phys);
236
237 @@ -1711,6 +1777,7 @@ void vchiq_platform_conn_state_changed(s
238 static const struct of_device_id vchiq_of_match[] = {
239 { .compatible = "brcm,bcm2835-vchiq", .data = &bcm2835_info },
240 { .compatible = "brcm,bcm2836-vchiq", .data = &bcm2836_info },
241 + { .compatible = "brcm,bcm2711-vchiq", .data = &bcm2711_info },
242 {},
243 };
244 MODULE_DEVICE_TABLE(of, vchiq_of_match);
245 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
246 +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
247 @@ -32,6 +32,7 @@ enum USE_TYPE_E {
248
249 struct vchiq_platform_info {
250 unsigned int cache_line_size;
251 + bool use_36bit_addrs;
252 };
253
254 struct vchiq_drv_mgmt {