lantiq: move lantiq_board_detect() to 03_preinit_board.sh
[openwrt/openwrt.git] / target / linux / layerscape / patches-4.4 / 7147-staging-fsl-mc-Extended-MC-bus-allocator-to-include-.patch
1 From 23b09c6b4162a8264b600f35d7048256a7afc0cd Mon Sep 17 00:00:00 2001
2 From: "J. German Rivera" <German.Rivera@freescale.com>
3 Date: Wed, 6 Jan 2016 16:03:23 -0600
4 Subject: [PATCH 147/226] staging: fsl-mc: Extended MC bus allocator to
5 include IRQs
6
7 All the IRQs for DPAA2 objects in the same DPRC must use
8 the ICID of that DPRC, as their device Id in the GIC-ITS.
9 Thus, all these IRQs must share the same ITT table in the GIC.
10 As a result, a pool of IRQs with the same device Id must be
11 preallocated per DPRC (fsl-mc bus instance). So, the fsl-mc
12 bus object allocator is extended to also provide services
13 to allocate IRQs to DPAA2 devices, from their parent fsl-mc bus
14 IRQ pool.
15
16 Signed-off-by: J. German Rivera <German.Rivera@freescale.com>
17 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
18 ---
19 drivers/staging/fsl-mc/bus/mc-allocator.c | 199 +++++++++++++++++++++++++++
20 drivers/staging/fsl-mc/include/mc-private.h | 15 ++
21 drivers/staging/fsl-mc/include/mc.h | 9 ++
22 3 files changed, 223 insertions(+)
23
24 --- a/drivers/staging/fsl-mc/bus/mc-allocator.c
25 +++ b/drivers/staging/fsl-mc/bus/mc-allocator.c
26 @@ -15,6 +15,7 @@
27 #include "../include/dpcon-cmd.h"
28 #include "dpmcp-cmd.h"
29 #include "dpmcp.h"
30 +#include <linux/msi.h>
31
32 /**
33 * fsl_mc_resource_pool_add_device - add allocatable device to a resource
34 @@ -160,6 +161,7 @@ static const char *const fsl_mc_pool_typ
35 [FSL_MC_POOL_DPMCP] = "dpmcp",
36 [FSL_MC_POOL_DPBP] = "dpbp",
37 [FSL_MC_POOL_DPCON] = "dpcon",
38 + [FSL_MC_POOL_IRQ] = "irq",
39 };
40
41 static int __must_check object_type_to_pool_type(const char *object_type,
42 @@ -465,6 +467,203 @@ void fsl_mc_object_free(struct fsl_mc_de
43 }
44 EXPORT_SYMBOL_GPL(fsl_mc_object_free);
45
46 +/*
47 + * Initialize the interrupt pool associated with a MC bus.
48 + * It allocates a block of IRQs from the GIC-ITS
49 + */
50 +int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
51 + unsigned int irq_count)
52 +{
53 + unsigned int i;
54 + struct msi_desc *msi_desc;
55 + struct fsl_mc_device_irq *irq_resources;
56 + struct fsl_mc_device_irq *mc_dev_irq;
57 + int error;
58 + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
59 + struct fsl_mc_resource_pool *res_pool =
60 + &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
61 +
62 + if (WARN_ON(irq_count == 0 ||
63 + irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS))
64 + return -EINVAL;
65 +
66 + error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count);
67 + if (error < 0)
68 + return error;
69 +
70 + irq_resources = devm_kzalloc(&mc_bus_dev->dev,
71 + sizeof(*irq_resources) * irq_count,
72 + GFP_KERNEL);
73 + if (!irq_resources) {
74 + error = -ENOMEM;
75 + goto cleanup_msi_irqs;
76 + }
77 +
78 + for (i = 0; i < irq_count; i++) {
79 + mc_dev_irq = &irq_resources[i];
80 +
81 + /*
82 + * NOTE: This mc_dev_irq's MSI addr/value pair will be set
83 + * by the fsl_mc_msi_write_msg() callback
84 + */
85 + mc_dev_irq->resource.type = res_pool->type;
86 + mc_dev_irq->resource.data = mc_dev_irq;
87 + mc_dev_irq->resource.parent_pool = res_pool;
88 + INIT_LIST_HEAD(&mc_dev_irq->resource.node);
89 + list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list);
90 + }
91 +
92 + for_each_msi_entry(msi_desc, &mc_bus_dev->dev) {
93 + mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index];
94 + mc_dev_irq->msi_desc = msi_desc;
95 + mc_dev_irq->resource.id = msi_desc->irq;
96 + }
97 +
98 + res_pool->max_count = irq_count;
99 + res_pool->free_count = irq_count;
100 + mc_bus->irq_resources = irq_resources;
101 + return 0;
102 +
103 +cleanup_msi_irqs:
104 + fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
105 + return error;
106 +}
107 +EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool);
108 +
109 +/**
110 + * Teardown the interrupt pool associated with an MC bus.
111 + * It frees the IRQs that were allocated to the pool, back to the GIC-ITS.
112 + */
113 +void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus)
114 +{
115 + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
116 + struct fsl_mc_resource_pool *res_pool =
117 + &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
118 +
119 + if (WARN_ON(!mc_bus->irq_resources))
120 + return;
121 +
122 + if (WARN_ON(res_pool->max_count == 0))
123 + return;
124 +
125 + if (WARN_ON(res_pool->free_count != res_pool->max_count))
126 + return;
127 +
128 + INIT_LIST_HEAD(&res_pool->free_list);
129 + res_pool->max_count = 0;
130 + res_pool->free_count = 0;
131 + mc_bus->irq_resources = NULL;
132 + fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
133 +}
134 +EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool);
135 +
136 +/**
137 + * It allocates the IRQs required by a given MC object device. The
138 + * IRQs are allocated from the interrupt pool associated with the
139 + * MC bus that contains the device, if the device is not a DPRC device.
140 + * Otherwise, the IRQs are allocated from the interrupt pool associated
141 + * with the MC bus that represents the DPRC device itself.
142 + */
143 +int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev)
144 +{
145 + int i;
146 + int irq_count;
147 + int res_allocated_count = 0;
148 + int error = -EINVAL;
149 + struct fsl_mc_device_irq **irqs = NULL;
150 + struct fsl_mc_bus *mc_bus;
151 + struct fsl_mc_resource_pool *res_pool;
152 +
153 + if (WARN_ON(mc_dev->irqs))
154 + return -EINVAL;
155 +
156 + irq_count = mc_dev->obj_desc.irq_count;
157 + if (WARN_ON(irq_count == 0))
158 + return -EINVAL;
159 +
160 + if (strcmp(mc_dev->obj_desc.type, "dprc") == 0)
161 + mc_bus = to_fsl_mc_bus(mc_dev);
162 + else
163 + mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
164 +
165 + if (WARN_ON(!mc_bus->irq_resources))
166 + return -EINVAL;
167 +
168 + res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
169 + if (res_pool->free_count < irq_count) {
170 + dev_err(&mc_dev->dev,
171 + "Not able to allocate %u irqs for device\n", irq_count);
172 + return -ENOSPC;
173 + }
174 +
175 + irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]),
176 + GFP_KERNEL);
177 + if (!irqs)
178 + return -ENOMEM;
179 +
180 + for (i = 0; i < irq_count; i++) {
181 + struct fsl_mc_resource *resource;
182 +
183 + error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ,
184 + &resource);
185 + if (error < 0)
186 + goto error_resource_alloc;
187 +
188 + irqs[i] = to_fsl_mc_irq(resource);
189 + res_allocated_count++;
190 +
191 + WARN_ON(irqs[i]->mc_dev);
192 + irqs[i]->mc_dev = mc_dev;
193 + irqs[i]->dev_irq_index = i;
194 + }
195 +
196 + mc_dev->irqs = irqs;
197 + return 0;
198 +
199 +error_resource_alloc:
200 + for (i = 0; i < res_allocated_count; i++) {
201 + irqs[i]->mc_dev = NULL;
202 + fsl_mc_resource_free(&irqs[i]->resource);
203 + }
204 +
205 + return error;
206 +}
207 +EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs);
208 +
209 +/*
210 + * It frees the IRQs that were allocated for a MC object device, by
211 + * returning them to the corresponding interrupt pool.
212 + */
213 +void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev)
214 +{
215 + int i;
216 + int irq_count;
217 + struct fsl_mc_bus *mc_bus;
218 + struct fsl_mc_device_irq **irqs = mc_dev->irqs;
219 +
220 + if (WARN_ON(!irqs))
221 + return;
222 +
223 + irq_count = mc_dev->obj_desc.irq_count;
224 +
225 + if (strcmp(mc_dev->obj_desc.type, "dprc") == 0)
226 + mc_bus = to_fsl_mc_bus(mc_dev);
227 + else
228 + mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
229 +
230 + if (WARN_ON(!mc_bus->irq_resources))
231 + return;
232 +
233 + for (i = 0; i < irq_count; i++) {
234 + WARN_ON(!irqs[i]->mc_dev);
235 + irqs[i]->mc_dev = NULL;
236 + fsl_mc_resource_free(&irqs[i]->resource);
237 + }
238 +
239 + mc_dev->irqs = NULL;
240 +}
241 +EXPORT_SYMBOL_GPL(fsl_mc_free_irqs);
242 +
243 /**
244 * fsl_mc_allocator_probe - callback invoked when an allocatable device is
245 * being added to the system
246 --- a/drivers/staging/fsl-mc/include/mc-private.h
247 +++ b/drivers/staging/fsl-mc/include/mc-private.h
248 @@ -30,6 +30,16 @@ struct irq_domain;
249 struct msi_domain_info;
250
251 /**
252 + * Maximum number of total IRQs that can be pre-allocated for an MC bus'
253 + * IRQ pool
254 + */
255 +#define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256
256 +
257 +struct device_node;
258 +struct irq_domain;
259 +struct msi_domain_info;
260 +
261 +/**
262 * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device
263 * @root_mc_bus_dev: MC object device representing the root DPRC
264 * @num_translation_ranges: number of entries in addr_translation_ranges
265 @@ -137,4 +147,9 @@ int __init its_fsl_mc_msi_init(void);
266
267 void its_fsl_mc_msi_cleanup(void);
268
269 +int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
270 + unsigned int irq_count);
271 +
272 +void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus);
273 +
274 #endif /* _FSL_MC_PRIVATE_H_ */
275 --- a/drivers/staging/fsl-mc/include/mc.h
276 +++ b/drivers/staging/fsl-mc/include/mc.h
277 @@ -14,12 +14,14 @@
278 #include <linux/device.h>
279 #include <linux/mod_devicetable.h>
280 #include <linux/list.h>
281 +#include <linux/interrupt.h>
282 #include "../include/dprc.h"
283
284 #define FSL_MC_VENDOR_FREESCALE 0x1957
285
286 struct fsl_mc_device;
287 struct fsl_mc_io;
288 +struct fsl_mc_bus;
289
290 /**
291 * struct fsl_mc_driver - MC object device driver object
292 @@ -75,6 +77,7 @@ enum fsl_mc_pool_type {
293 FSL_MC_POOL_DPMCP = 0x0, /* corresponds to "dpmcp" in the MC */
294 FSL_MC_POOL_DPBP, /* corresponds to "dpbp" in the MC */
295 FSL_MC_POOL_DPCON, /* corresponds to "dpcon" in the MC */
296 + FSL_MC_POOL_IRQ,
297
298 /*
299 * NOTE: New resource pool types must be added before this entry
300 @@ -141,6 +144,7 @@ struct fsl_mc_device_irq {
301 * NULL if none.
302 * @obj_desc: MC description of the DPAA device
303 * @regions: pointer to array of MMIO region entries
304 + * @irqs: pointer to array of pointers to interrupts allocated to this device
305 * @resource: generic resource associated with this MC object device, if any.
306 *
307 * Generic device object for MC object devices that are "attached" to a
308 @@ -172,6 +176,7 @@ struct fsl_mc_device {
309 struct fsl_mc_io *mc_io;
310 struct dprc_obj_desc obj_desc;
311 struct resource *regions;
312 + struct fsl_mc_device_irq **irqs;
313 struct fsl_mc_resource *resource;
314 };
315
316 @@ -215,6 +220,10 @@ int __must_check fsl_mc_object_allocate(
317
318 void fsl_mc_object_free(struct fsl_mc_device *mc_adev);
319
320 +int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev);
321 +
322 +void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev);
323 +
324 extern struct bus_type fsl_mc_bus_type;
325
326 #endif /* _FSL_MC_H_ */