OpenWrt – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | From 2aaf8e8caef3ec4c2c155421f62f983892c49387 Mon Sep 17 00:00:00 2001 |
2 | From: Biwen Li <biwen.li@nxp.com> |
||
3 | Date: Fri, 16 Nov 2018 12:20:04 +0800 |
||
4 | Subject: [PATCH 13/39] mc-bus: support layerscape |
||
5 | This is an integrated patch of mc-bus for layerscape |
||
6 | |||
7 | Signed-off-by: Bharat Bhushan <Bharat.Bhushan@nxp.com> |
||
8 | Signed-off-by: Bogdan Purcareata <bogdan.purcareata@nxp.com> |
||
9 | Signed-off-by: Cristian Sovaiala <cristian.sovaiala@freescale.com> |
||
10 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
||
11 | Signed-off-by: Guanhua Gao <guanhua.gao@nxp.com> |
||
12 | Signed-off-by: Horia Geantă <horia.geanta@nxp.com> |
||
13 | Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com> |
||
14 | Signed-off-by: Ioana Radulescu <ruxandra.radulescu@nxp.com> |
||
15 | Signed-off-by: J. German Rivera <German.Rivera@freescale.com> |
||
16 | Signed-off-by: Laurentiu Tudor <laurentiu.tudor@nxp.com> |
||
17 | Signed-off-by: Lijun Pan <Lijun.Pan@freescale.com> |
||
18 | Signed-off-by: Nipun Gupta <nipun.gupta@nxp.com> |
||
19 | Signed-off-by: Radu Alexe <radu.alexe@nxp.com> |
||
20 | Signed-off-by: Razvan Stefanescu <razvan.stefanescu@nxp.com> |
||
21 | Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com> |
||
22 | Signed-off-by: Stuart Yoder <stuyoder@gmail.com> |
||
23 | Signed-off-by: Biwen Li <biwen.li@nxp.com> |
||
24 | --- |
||
25 | drivers/bus/Kconfig | 2 + |
||
26 | drivers/bus/Makefile | 4 + |
||
27 | drivers/bus/fsl-mc/Kconfig | 23 + |
||
28 | drivers/bus/fsl-mc/Makefile | 21 + |
||
29 | .../{staging/fsl-mc/bus => bus/fsl-mc}/dpbp.c | 97 +- |
||
30 | .../fsl-mc/bus => bus/fsl-mc}/dpcon.c | 103 +- |
||
31 | drivers/bus/fsl-mc/dpmcp.c | 99 ++ |
||
32 | .../fsl-mc/bus => bus/fsl-mc}/dprc-driver.c | 96 +- |
||
33 | .../{staging/fsl-mc/bus => bus/fsl-mc}/dprc.c | 288 +---- |
||
34 | .../bus => bus/fsl-mc}/fsl-mc-allocator.c | 112 +- |
||
35 | .../fsl-mc/bus => bus/fsl-mc}/fsl-mc-bus.c | 305 ++++- |
||
36 | .../fsl-mc/bus => bus/fsl-mc}/fsl-mc-msi.c | 16 +- |
||
37 | drivers/bus/fsl-mc/fsl-mc-private.h | 223 ++++ |
||
38 | drivers/bus/fsl-mc/fsl-mc-restool.c | 219 ++++ |
||
39 | .../fsl-mc/bus => bus/fsl-mc}/mc-io.c | 36 +- |
||
40 | .../fsl-mc/bus => bus/fsl-mc}/mc-sys.c | 33 +- |
||
41 | drivers/irqchip/Kconfig | 6 + |
||
42 | drivers/irqchip/Makefile | 1 + |
||
43 | drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c | 98 ++ |
||
44 | drivers/staging/fsl-dpaa2/ethernet/README | 2 +- |
||
45 | .../staging/fsl-dpaa2/ethernet/dpaa2-eth.c | 2 +- |
||
46 | .../staging/fsl-dpaa2/ethernet/dpaa2-eth.h | 3 +- |
||
47 | drivers/staging/fsl-dpaa2/ethernet/dpni.c | 2 +- |
||
48 | drivers/staging/fsl-mc/TODO | 18 - |
||
49 | drivers/staging/fsl-mc/bus/Kconfig | 16 +- |
||
50 | drivers/staging/fsl-mc/bus/Makefile | 13 - |
||
51 | drivers/staging/fsl-mc/bus/dpio/dpio-driver.c | 2 +- |
||
52 | .../staging/fsl-mc/bus/dpio/dpio-service.c | 2 +- |
||
53 | drivers/staging/fsl-mc/bus/dpio/dpio.c | 14 +- |
||
54 | drivers/staging/fsl-mc/bus/dpmcp-cmd.h | 56 - |
||
55 | drivers/staging/fsl-mc/bus/dpmcp.h | 60 - |
||
56 | drivers/staging/fsl-mc/bus/dpmng-cmd.h | 58 - |
||
57 | drivers/staging/fsl-mc/bus/dprc-cmd.h | 451 -------- |
||
58 | drivers/staging/fsl-mc/bus/dprc.h | 268 ----- |
||
59 | .../fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c | 1 + |
||
60 | include/linux/fsl/mc.h | 1020 +++++++++++++++++ |
||
61 | include/uapi/linux/fsl_mc.h | 31 + |
||
62 | 37 files changed, 2255 insertions(+), 1546 deletions(-) |
||
63 | create mode 100644 drivers/bus/fsl-mc/Kconfig |
||
64 | create mode 100644 drivers/bus/fsl-mc/Makefile |
||
65 | rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpbp.c (67%) |
||
66 | rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpcon.c (70%) |
||
67 | create mode 100644 drivers/bus/fsl-mc/dpmcp.c |
||
68 | rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dprc-driver.c (93%) |
||
69 | rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dprc.c (68%) |
||
70 | rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-allocator.c (84%) |
||
71 | rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-bus.c (76%) |
||
72 | rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-msi.c (96%) |
||
73 | create mode 100644 drivers/bus/fsl-mc/fsl-mc-private.h |
||
74 | create mode 100644 drivers/bus/fsl-mc/fsl-mc-restool.c |
||
75 | rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/mc-io.c (89%) |
||
76 | rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/mc-sys.c (90%) |
||
77 | create mode 100644 drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c |
||
78 | delete mode 100644 drivers/staging/fsl-mc/TODO |
||
79 | delete mode 100644 drivers/staging/fsl-mc/bus/dpmcp-cmd.h |
||
80 | delete mode 100644 drivers/staging/fsl-mc/bus/dpmcp.h |
||
81 | delete mode 100644 drivers/staging/fsl-mc/bus/dpmng-cmd.h |
||
82 | delete mode 100644 drivers/staging/fsl-mc/bus/dprc-cmd.h |
||
83 | delete mode 100644 drivers/staging/fsl-mc/bus/dprc.h |
||
84 | create mode 100644 include/linux/fsl/mc.h |
||
85 | create mode 100644 include/uapi/linux/fsl_mc.h |
||
86 | |||
87 | --- a/drivers/bus/Kconfig |
||
88 | +++ b/drivers/bus/Kconfig |
||
89 | @@ -184,4 +184,6 @@ config DA8XX_MSTPRI |
||
90 | configuration. Allows to adjust the priorities of all master |
||
91 | peripherals. |
||
92 | |||
93 | +source "drivers/bus/fsl-mc/Kconfig" |
||
94 | + |
||
95 | endmenu |
||
96 | --- a/drivers/bus/Makefile |
||
97 | +++ b/drivers/bus/Makefile |
||
98 | @@ -8,6 +8,10 @@ obj-$(CONFIG_ARM_CCI) += arm-cci.o |
||
99 | obj-$(CONFIG_ARM_CCN) += arm-ccn.o |
||
100 | |||
101 | obj-$(CONFIG_BRCMSTB_GISB_ARB) += brcmstb_gisb.o |
||
102 | + |
||
103 | +# DPAA2 fsl-mc bus |
||
104 | +obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/ |
||
105 | + |
||
106 | obj-$(CONFIG_IMX_WEIM) += imx-weim.o |
||
107 | obj-$(CONFIG_MIPS_CDMM) += mips_cdmm.o |
||
108 | obj-$(CONFIG_MVEBU_MBUS) += mvebu-mbus.o |
||
109 | --- /dev/null |
||
110 | +++ b/drivers/bus/fsl-mc/Kconfig |
||
111 | @@ -0,0 +1,23 @@ |
||
112 | +# SPDX-License-Identifier: GPL-2.0 |
||
113 | +# |
||
114 | +# DPAA2 fsl-mc bus |
||
115 | +# |
||
116 | +# Copyright (C) 2014-2016 Freescale Semiconductor, Inc. |
||
117 | +# |
||
118 | + |
||
119 | +config FSL_MC_BUS |
||
120 | + bool "QorIQ DPAA2 fsl-mc bus driver" |
||
121 | + depends on OF && (ARCH_LAYERSCAPE || (COMPILE_TEST && (ARM || ARM64 || X86 || PPC))) |
||
122 | + select GENERIC_MSI_IRQ_DOMAIN |
||
123 | + help |
||
124 | + Driver to enable the bus infrastructure for the QorIQ DPAA2 |
||
125 | + architecture. The fsl-mc bus driver handles discovery of |
||
126 | + DPAA2 objects (which are represented as Linux devices) and |
||
127 | + binding objects to drivers. |
||
128 | + |
||
129 | +config FSL_MC_RESTOOL |
||
130 | + bool "Management Complex (MC) restool support" |
||
131 | + depends on FSL_MC_BUS |
||
132 | + help |
||
133 | + Provides kernel support for the Management Complex resource |
||
134 | + manager user-space tool - restool. |
||
135 | --- /dev/null |
||
136 | +++ b/drivers/bus/fsl-mc/Makefile |
||
137 | @@ -0,0 +1,21 @@ |
||
138 | +# SPDX-License-Identifier: GPL-2.0 |
||
139 | +# |
||
140 | +# Freescale Management Complex (MC) bus drivers |
||
141 | +# |
||
142 | +# Copyright (C) 2014 Freescale Semiconductor, Inc. |
||
143 | +# |
||
144 | +obj-$(CONFIG_FSL_MC_BUS) += mc-bus-driver.o |
||
145 | + |
||
146 | +mc-bus-driver-objs := fsl-mc-bus.o \ |
||
147 | + mc-sys.o \ |
||
148 | + mc-io.o \ |
||
149 | + dpbp.o \ |
||
150 | + dpcon.o \ |
||
151 | + dprc.o \ |
||
152 | + dprc-driver.o \ |
||
153 | + fsl-mc-allocator.o \ |
||
154 | + fsl-mc-msi.o \ |
||
155 | + dpmcp.o |
||
156 | + |
||
157 | +# MC restool kernel support |
||
158 | +obj-$(CONFIG_FSL_MC_RESTOOL) += fsl-mc-restool.o |
||
159 | --- a/drivers/staging/fsl-mc/bus/dpbp.c |
||
160 | +++ /dev/null |
||
161 | @@ -1,253 +0,0 @@ |
||
162 | -// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) |
||
163 | -/* |
||
164 | - * Copyright 2013-2016 Freescale Semiconductor Inc. |
||
165 | - * |
||
166 | - */ |
||
167 | -#include <linux/kernel.h> |
||
168 | -#include "../include/mc.h" |
||
169 | -#include "../include/dpbp.h" |
||
170 | - |
||
171 | -#include "dpbp-cmd.h" |
||
172 | - |
||
173 | -/** |
||
174 | - * dpbp_open() - Open a control session for the specified object. |
||
175 | - * @mc_io: Pointer to MC portal's I/O object |
||
176 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
177 | - * @dpbp_id: DPBP unique ID |
||
178 | - * @token: Returned token; use in subsequent API calls |
||
179 | - * |
||
180 | - * This function can be used to open a control session for an |
||
181 | - * already created object; an object may have been declared in |
||
182 | - * the DPL or by calling the dpbp_create function. |
||
183 | - * This function returns a unique authentication token, |
||
184 | - * associated with the specific object ID and the specific MC |
||
185 | - * portal; this token must be used in all subsequent commands for |
||
186 | - * this specific object |
||
187 | - * |
||
188 | - * Return: '0' on Success; Error code otherwise. |
||
189 | - */ |
||
190 | -int dpbp_open(struct fsl_mc_io *mc_io, |
||
191 | - u32 cmd_flags, |
||
192 | - int dpbp_id, |
||
193 | - u16 *token) |
||
194 | -{ |
||
195 | - struct mc_command cmd = { 0 }; |
||
196 | - struct dpbp_cmd_open *cmd_params; |
||
197 | - int err; |
||
198 | - |
||
199 | - /* prepare command */ |
||
200 | - cmd.header = mc_encode_cmd_header(DPBP_CMDID_OPEN, |
||
201 | - cmd_flags, 0); |
||
202 | - cmd_params = (struct dpbp_cmd_open *)cmd.params; |
||
203 | - cmd_params->dpbp_id = cpu_to_le32(dpbp_id); |
||
204 | - |
||
205 | - /* send command to mc*/ |
||
206 | - err = mc_send_command(mc_io, &cmd); |
||
207 | - if (err) |
||
208 | - return err; |
||
209 | - |
||
210 | - /* retrieve response parameters */ |
||
211 | - *token = mc_cmd_hdr_read_token(&cmd); |
||
212 | - |
||
213 | - return err; |
||
214 | -} |
||
215 | -EXPORT_SYMBOL(dpbp_open); |
||
216 | - |
||
217 | -/** |
||
218 | - * dpbp_close() - Close the control session of the object |
||
219 | - * @mc_io: Pointer to MC portal's I/O object |
||
220 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
221 | - * @token: Token of DPBP object |
||
222 | - * |
||
223 | - * After this function is called, no further operations are |
||
224 | - * allowed on the object without opening a new control session. |
||
225 | - * |
||
226 | - * Return: '0' on Success; Error code otherwise. |
||
227 | - */ |
||
228 | -int dpbp_close(struct fsl_mc_io *mc_io, |
||
229 | - u32 cmd_flags, |
||
230 | - u16 token) |
||
231 | -{ |
||
232 | - struct mc_command cmd = { 0 }; |
||
233 | - |
||
234 | - /* prepare command */ |
||
235 | - cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLOSE, cmd_flags, |
||
236 | - token); |
||
237 | - |
||
238 | - /* send command to mc*/ |
||
239 | - return mc_send_command(mc_io, &cmd); |
||
240 | -} |
||
241 | -EXPORT_SYMBOL(dpbp_close); |
||
242 | - |
||
243 | -/** |
||
244 | - * dpbp_enable() - Enable the DPBP. |
||
245 | - * @mc_io: Pointer to MC portal's I/O object |
||
246 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
247 | - * @token: Token of DPBP object |
||
248 | - * |
||
249 | - * Return: '0' on Success; Error code otherwise. |
||
250 | - */ |
||
251 | -int dpbp_enable(struct fsl_mc_io *mc_io, |
||
252 | - u32 cmd_flags, |
||
253 | - u16 token) |
||
254 | -{ |
||
255 | - struct mc_command cmd = { 0 }; |
||
256 | - |
||
257 | - /* prepare command */ |
||
258 | - cmd.header = mc_encode_cmd_header(DPBP_CMDID_ENABLE, cmd_flags, |
||
259 | - token); |
||
260 | - |
||
261 | - /* send command to mc*/ |
||
262 | - return mc_send_command(mc_io, &cmd); |
||
263 | -} |
||
264 | -EXPORT_SYMBOL(dpbp_enable); |
||
265 | - |
||
266 | -/** |
||
267 | - * dpbp_disable() - Disable the DPBP. |
||
268 | - * @mc_io: Pointer to MC portal's I/O object |
||
269 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
270 | - * @token: Token of DPBP object |
||
271 | - * |
||
272 | - * Return: '0' on Success; Error code otherwise. |
||
273 | - */ |
||
274 | -int dpbp_disable(struct fsl_mc_io *mc_io, |
||
275 | - u32 cmd_flags, |
||
276 | - u16 token) |
||
277 | -{ |
||
278 | - struct mc_command cmd = { 0 }; |
||
279 | - |
||
280 | - /* prepare command */ |
||
281 | - cmd.header = mc_encode_cmd_header(DPBP_CMDID_DISABLE, |
||
282 | - cmd_flags, token); |
||
283 | - |
||
284 | - /* send command to mc*/ |
||
285 | - return mc_send_command(mc_io, &cmd); |
||
286 | -} |
||
287 | -EXPORT_SYMBOL(dpbp_disable); |
||
288 | - |
||
289 | -/** |
||
290 | - * dpbp_is_enabled() - Check if the DPBP is enabled. |
||
291 | - * @mc_io: Pointer to MC portal's I/O object |
||
292 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
293 | - * @token: Token of DPBP object |
||
294 | - * @en: Returns '1' if object is enabled; '0' otherwise |
||
295 | - * |
||
296 | - * Return: '0' on Success; Error code otherwise. |
||
297 | - */ |
||
298 | -int dpbp_is_enabled(struct fsl_mc_io *mc_io, |
||
299 | - u32 cmd_flags, |
||
300 | - u16 token, |
||
301 | - int *en) |
||
302 | -{ |
||
303 | - struct mc_command cmd = { 0 }; |
||
304 | - struct dpbp_rsp_is_enabled *rsp_params; |
||
305 | - int err; |
||
306 | - /* prepare command */ |
||
307 | - cmd.header = mc_encode_cmd_header(DPBP_CMDID_IS_ENABLED, cmd_flags, |
||
308 | - token); |
||
309 | - |
||
310 | - /* send command to mc*/ |
||
311 | - err = mc_send_command(mc_io, &cmd); |
||
312 | - if (err) |
||
313 | - return err; |
||
314 | - |
||
315 | - /* retrieve response parameters */ |
||
316 | - rsp_params = (struct dpbp_rsp_is_enabled *)cmd.params; |
||
317 | - *en = rsp_params->enabled & DPBP_ENABLE; |
||
318 | - |
||
319 | - return 0; |
||
320 | -} |
||
321 | -EXPORT_SYMBOL(dpbp_is_enabled); |
||
322 | - |
||
323 | -/** |
||
324 | - * dpbp_reset() - Reset the DPBP, returns the object to initial state. |
||
325 | - * @mc_io: Pointer to MC portal's I/O object |
||
326 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
327 | - * @token: Token of DPBP object |
||
328 | - * |
||
329 | - * Return: '0' on Success; Error code otherwise. |
||
330 | - */ |
||
331 | -int dpbp_reset(struct fsl_mc_io *mc_io, |
||
332 | - u32 cmd_flags, |
||
333 | - u16 token) |
||
334 | -{ |
||
335 | - struct mc_command cmd = { 0 }; |
||
336 | - |
||
337 | - /* prepare command */ |
||
338 | - cmd.header = mc_encode_cmd_header(DPBP_CMDID_RESET, |
||
339 | - cmd_flags, token); |
||
340 | - |
||
341 | - /* send command to mc*/ |
||
342 | - return mc_send_command(mc_io, &cmd); |
||
343 | -} |
||
344 | -EXPORT_SYMBOL(dpbp_reset); |
||
345 | - |
||
346 | -/** |
||
347 | - * dpbp_get_attributes - Retrieve DPBP attributes. |
||
348 | - * |
||
349 | - * @mc_io: Pointer to MC portal's I/O object |
||
350 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
351 | - * @token: Token of DPBP object |
||
352 | - * @attr: Returned object's attributes |
||
353 | - * |
||
354 | - * Return: '0' on Success; Error code otherwise. |
||
355 | - */ |
||
356 | -int dpbp_get_attributes(struct fsl_mc_io *mc_io, |
||
357 | - u32 cmd_flags, |
||
358 | - u16 token, |
||
359 | - struct dpbp_attr *attr) |
||
360 | -{ |
||
361 | - struct mc_command cmd = { 0 }; |
||
362 | - struct dpbp_rsp_get_attributes *rsp_params; |
||
363 | - int err; |
||
364 | - |
||
365 | - /* prepare command */ |
||
366 | - cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_ATTR, |
||
367 | - cmd_flags, token); |
||
368 | - |
||
369 | - /* send command to mc*/ |
||
370 | - err = mc_send_command(mc_io, &cmd); |
||
371 | - if (err) |
||
372 | - return err; |
||
373 | - |
||
374 | - /* retrieve response parameters */ |
||
375 | - rsp_params = (struct dpbp_rsp_get_attributes *)cmd.params; |
||
376 | - attr->bpid = le16_to_cpu(rsp_params->bpid); |
||
377 | - attr->id = le32_to_cpu(rsp_params->id); |
||
378 | - |
||
379 | - return 0; |
||
380 | -} |
||
381 | -EXPORT_SYMBOL(dpbp_get_attributes); |
||
382 | - |
||
383 | -/** |
||
384 | - * dpbp_get_api_version - Get Data Path Buffer Pool API version |
||
385 | - * @mc_io: Pointer to Mc portal's I/O object |
||
386 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
387 | - * @major_ver: Major version of Buffer Pool API |
||
388 | - * @minor_ver: Minor version of Buffer Pool API |
||
389 | - * |
||
390 | - * Return: '0' on Success; Error code otherwise. |
||
391 | - */ |
||
392 | -int dpbp_get_api_version(struct fsl_mc_io *mc_io, |
||
393 | - u32 cmd_flags, |
||
394 | - u16 *major_ver, |
||
395 | - u16 *minor_ver) |
||
396 | -{ |
||
397 | - struct mc_command cmd = { 0 }; |
||
398 | - int err; |
||
399 | - |
||
400 | - /* prepare command */ |
||
401 | - cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_API_VERSION, |
||
402 | - cmd_flags, 0); |
||
403 | - |
||
404 | - /* send command to mc */ |
||
405 | - err = mc_send_command(mc_io, &cmd); |
||
406 | - if (err) |
||
407 | - return err; |
||
408 | - |
||
409 | - /* retrieve response parameters */ |
||
410 | - mc_cmd_read_api_version(&cmd, major_ver, minor_ver); |
||
411 | - |
||
412 | - return 0; |
||
413 | -} |
||
414 | -EXPORT_SYMBOL(dpbp_get_api_version); |
||
415 | --- /dev/null |
||
416 | +++ b/drivers/bus/fsl-mc/dpbp.c |
||
417 | @@ -0,0 +1,186 @@ |
||
418 | +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) |
||
419 | +/* |
||
420 | + * Copyright 2013-2016 Freescale Semiconductor Inc. |
||
421 | + * |
||
422 | + */ |
||
423 | +#include <linux/kernel.h> |
||
424 | +#include <linux/fsl/mc.h> |
||
425 | +#include <linux/fsl/mc.h> |
||
426 | + |
||
427 | +#include "fsl-mc-private.h" |
||
428 | + |
||
429 | +/** |
||
430 | + * dpbp_open() - Open a control session for the specified object. |
||
431 | + * @mc_io: Pointer to MC portal's I/O object |
||
432 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
433 | + * @dpbp_id: DPBP unique ID |
||
434 | + * @token: Returned token; use in subsequent API calls |
||
435 | + * |
||
436 | + * This function can be used to open a control session for an |
||
437 | + * already created object; an object may have been declared in |
||
438 | + * the DPL or by calling the dpbp_create function. |
||
439 | + * This function returns a unique authentication token, |
||
440 | + * associated with the specific object ID and the specific MC |
||
441 | + * portal; this token must be used in all subsequent commands for |
||
442 | + * this specific object |
||
443 | + * |
||
444 | + * Return: '0' on Success; Error code otherwise. |
||
445 | + */ |
||
446 | +int dpbp_open(struct fsl_mc_io *mc_io, |
||
447 | + u32 cmd_flags, |
||
448 | + int dpbp_id, |
||
449 | + u16 *token) |
||
450 | +{ |
||
451 | + struct fsl_mc_command cmd = { 0 }; |
||
452 | + struct dpbp_cmd_open *cmd_params; |
||
453 | + int err; |
||
454 | + |
||
455 | + /* prepare command */ |
||
456 | + cmd.header = mc_encode_cmd_header(DPBP_CMDID_OPEN, |
||
457 | + cmd_flags, 0); |
||
458 | + cmd_params = (struct dpbp_cmd_open *)cmd.params; |
||
459 | + cmd_params->dpbp_id = cpu_to_le32(dpbp_id); |
||
460 | + |
||
461 | + /* send command to mc*/ |
||
462 | + err = mc_send_command(mc_io, &cmd); |
||
463 | + if (err) |
||
464 | + return err; |
||
465 | + |
||
466 | + /* retrieve response parameters */ |
||
467 | + *token = mc_cmd_hdr_read_token(&cmd); |
||
468 | + |
||
469 | + return err; |
||
470 | +} |
||
471 | +EXPORT_SYMBOL_GPL(dpbp_open); |
||
472 | + |
||
473 | +/** |
||
474 | + * dpbp_close() - Close the control session of the object |
||
475 | + * @mc_io: Pointer to MC portal's I/O object |
||
476 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
477 | + * @token: Token of DPBP object |
||
478 | + * |
||
479 | + * After this function is called, no further operations are |
||
480 | + * allowed on the object without opening a new control session. |
||
481 | + * |
||
482 | + * Return: '0' on Success; Error code otherwise. |
||
483 | + */ |
||
484 | +int dpbp_close(struct fsl_mc_io *mc_io, |
||
485 | + u32 cmd_flags, |
||
486 | + u16 token) |
||
487 | +{ |
||
488 | + struct fsl_mc_command cmd = { 0 }; |
||
489 | + |
||
490 | + /* prepare command */ |
||
491 | + cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLOSE, cmd_flags, |
||
492 | + token); |
||
493 | + |
||
494 | + /* send command to mc*/ |
||
495 | + return mc_send_command(mc_io, &cmd); |
||
496 | +} |
||
497 | +EXPORT_SYMBOL_GPL(dpbp_close); |
||
498 | + |
||
499 | +/** |
||
500 | + * dpbp_enable() - Enable the DPBP. |
||
501 | + * @mc_io: Pointer to MC portal's I/O object |
||
502 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
503 | + * @token: Token of DPBP object |
||
504 | + * |
||
505 | + * Return: '0' on Success; Error code otherwise. |
||
506 | + */ |
||
507 | +int dpbp_enable(struct fsl_mc_io *mc_io, |
||
508 | + u32 cmd_flags, |
||
509 | + u16 token) |
||
510 | +{ |
||
511 | + struct fsl_mc_command cmd = { 0 }; |
||
512 | + |
||
513 | + /* prepare command */ |
||
514 | + cmd.header = mc_encode_cmd_header(DPBP_CMDID_ENABLE, cmd_flags, |
||
515 | + token); |
||
516 | + |
||
517 | + /* send command to mc*/ |
||
518 | + return mc_send_command(mc_io, &cmd); |
||
519 | +} |
||
520 | +EXPORT_SYMBOL_GPL(dpbp_enable); |
||
521 | + |
||
522 | +/** |
||
523 | + * dpbp_disable() - Disable the DPBP. |
||
524 | + * @mc_io: Pointer to MC portal's I/O object |
||
525 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
526 | + * @token: Token of DPBP object |
||
527 | + * |
||
528 | + * Return: '0' on Success; Error code otherwise. |
||
529 | + */ |
||
530 | +int dpbp_disable(struct fsl_mc_io *mc_io, |
||
531 | + u32 cmd_flags, |
||
532 | + u16 token) |
||
533 | +{ |
||
534 | + struct fsl_mc_command cmd = { 0 }; |
||
535 | + |
||
536 | + /* prepare command */ |
||
537 | + cmd.header = mc_encode_cmd_header(DPBP_CMDID_DISABLE, |
||
538 | + cmd_flags, token); |
||
539 | + |
||
540 | + /* send command to mc*/ |
||
541 | + return mc_send_command(mc_io, &cmd); |
||
542 | +} |
||
543 | +EXPORT_SYMBOL_GPL(dpbp_disable); |
||
544 | + |
||
545 | +/** |
||
546 | + * dpbp_reset() - Reset the DPBP, returns the object to initial state. |
||
547 | + * @mc_io: Pointer to MC portal's I/O object |
||
548 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
549 | + * @token: Token of DPBP object |
||
550 | + * |
||
551 | + * Return: '0' on Success; Error code otherwise. |
||
552 | + */ |
||
553 | +int dpbp_reset(struct fsl_mc_io *mc_io, |
||
554 | + u32 cmd_flags, |
||
555 | + u16 token) |
||
556 | +{ |
||
557 | + struct fsl_mc_command cmd = { 0 }; |
||
558 | + |
||
559 | + /* prepare command */ |
||
560 | + cmd.header = mc_encode_cmd_header(DPBP_CMDID_RESET, |
||
561 | + cmd_flags, token); |
||
562 | + |
||
563 | + /* send command to mc*/ |
||
564 | + return mc_send_command(mc_io, &cmd); |
||
565 | +} |
||
566 | +EXPORT_SYMBOL_GPL(dpbp_reset); |
||
567 | + |
||
568 | +/** |
||
569 | + * dpbp_get_attributes - Retrieve DPBP attributes. |
||
570 | + * |
||
571 | + * @mc_io: Pointer to MC portal's I/O object |
||
572 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
573 | + * @token: Token of DPBP object |
||
574 | + * @attr: Returned object's attributes |
||
575 | + * |
||
576 | + * Return: '0' on Success; Error code otherwise. |
||
577 | + */ |
||
578 | +int dpbp_get_attributes(struct fsl_mc_io *mc_io, |
||
579 | + u32 cmd_flags, |
||
580 | + u16 token, |
||
581 | + struct dpbp_attr *attr) |
||
582 | +{ |
||
583 | + struct fsl_mc_command cmd = { 0 }; |
||
584 | + struct dpbp_rsp_get_attributes *rsp_params; |
||
585 | + int err; |
||
586 | + |
||
587 | + /* prepare command */ |
||
588 | + cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_ATTR, |
||
589 | + cmd_flags, token); |
||
590 | + |
||
591 | + /* send command to mc*/ |
||
592 | + err = mc_send_command(mc_io, &cmd); |
||
593 | + if (err) |
||
594 | + return err; |
||
595 | + |
||
596 | + /* retrieve response parameters */ |
||
597 | + rsp_params = (struct dpbp_rsp_get_attributes *)cmd.params; |
||
598 | + attr->bpid = le16_to_cpu(rsp_params->bpid); |
||
599 | + attr->id = le32_to_cpu(rsp_params->id); |
||
600 | + |
||
601 | + return 0; |
||
602 | +} |
||
603 | +EXPORT_SYMBOL_GPL(dpbp_get_attributes); |
||
604 | --- a/drivers/staging/fsl-mc/bus/dpcon.c |
||
605 | +++ /dev/null |
||
606 | @@ -1,291 +0,0 @@ |
||
607 | -// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) |
||
608 | -/* |
||
609 | - * Copyright 2013-2016 Freescale Semiconductor Inc. |
||
610 | - * |
||
611 | - */ |
||
612 | -#include <linux/kernel.h> |
||
613 | -#include "../include/mc.h" |
||
614 | -#include "../include/dpcon.h" |
||
615 | - |
||
616 | -#include "dpcon-cmd.h" |
||
617 | - |
||
618 | -/** |
||
619 | - * dpcon_open() - Open a control session for the specified object |
||
620 | - * @mc_io: Pointer to MC portal's I/O object |
||
621 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
622 | - * @dpcon_id: DPCON unique ID |
||
623 | - * @token: Returned token; use in subsequent API calls |
||
624 | - * |
||
625 | - * This function can be used to open a control session for an |
||
626 | - * already created object; an object may have been declared in |
||
627 | - * the DPL or by calling the dpcon_create() function. |
||
628 | - * This function returns a unique authentication token, |
||
629 | - * associated with the specific object ID and the specific MC |
||
630 | - * portal; this token must be used in all subsequent commands for |
||
631 | - * this specific object. |
||
632 | - * |
||
633 | - * Return: '0' on Success; Error code otherwise. |
||
634 | - */ |
||
635 | -int dpcon_open(struct fsl_mc_io *mc_io, |
||
636 | - u32 cmd_flags, |
||
637 | - int dpcon_id, |
||
638 | - u16 *token) |
||
639 | -{ |
||
640 | - struct mc_command cmd = { 0 }; |
||
641 | - struct dpcon_cmd_open *dpcon_cmd; |
||
642 | - int err; |
||
643 | - |
||
644 | - /* prepare command */ |
||
645 | - cmd.header = mc_encode_cmd_header(DPCON_CMDID_OPEN, |
||
646 | - cmd_flags, |
||
647 | - 0); |
||
648 | - dpcon_cmd = (struct dpcon_cmd_open *)cmd.params; |
||
649 | - dpcon_cmd->dpcon_id = cpu_to_le32(dpcon_id); |
||
650 | - |
||
651 | - /* send command to mc*/ |
||
652 | - err = mc_send_command(mc_io, &cmd); |
||
653 | - if (err) |
||
654 | - return err; |
||
655 | - |
||
656 | - /* retrieve response parameters */ |
||
657 | - *token = mc_cmd_hdr_read_token(&cmd); |
||
658 | - |
||
659 | - return 0; |
||
660 | -} |
||
661 | -EXPORT_SYMBOL(dpcon_open); |
||
662 | - |
||
663 | -/** |
||
664 | - * dpcon_close() - Close the control session of the object |
||
665 | - * @mc_io: Pointer to MC portal's I/O object |
||
666 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
667 | - * @token: Token of DPCON object |
||
668 | - * |
||
669 | - * After this function is called, no further operations are |
||
670 | - * allowed on the object without opening a new control session. |
||
671 | - * |
||
672 | - * Return: '0' on Success; Error code otherwise. |
||
673 | - */ |
||
674 | -int dpcon_close(struct fsl_mc_io *mc_io, |
||
675 | - u32 cmd_flags, |
||
676 | - u16 token) |
||
677 | -{ |
||
678 | - struct mc_command cmd = { 0 }; |
||
679 | - |
||
680 | - /* prepare command */ |
||
681 | - cmd.header = mc_encode_cmd_header(DPCON_CMDID_CLOSE, |
||
682 | - cmd_flags, |
||
683 | - token); |
||
684 | - |
||
685 | - /* send command to mc*/ |
||
686 | - return mc_send_command(mc_io, &cmd); |
||
687 | -} |
||
688 | -EXPORT_SYMBOL(dpcon_close); |
||
689 | - |
||
690 | -/** |
||
691 | - * dpcon_enable() - Enable the DPCON |
||
692 | - * @mc_io: Pointer to MC portal's I/O object |
||
693 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
694 | - * @token: Token of DPCON object |
||
695 | - * |
||
696 | - * Return: '0' on Success; Error code otherwise |
||
697 | - */ |
||
698 | -int dpcon_enable(struct fsl_mc_io *mc_io, |
||
699 | - u32 cmd_flags, |
||
700 | - u16 token) |
||
701 | -{ |
||
702 | - struct mc_command cmd = { 0 }; |
||
703 | - |
||
704 | - /* prepare command */ |
||
705 | - cmd.header = mc_encode_cmd_header(DPCON_CMDID_ENABLE, |
||
706 | - cmd_flags, |
||
707 | - token); |
||
708 | - |
||
709 | - /* send command to mc*/ |
||
710 | - return mc_send_command(mc_io, &cmd); |
||
711 | -} |
||
712 | -EXPORT_SYMBOL(dpcon_enable); |
||
713 | - |
||
714 | -/** |
||
715 | - * dpcon_disable() - Disable the DPCON |
||
716 | - * @mc_io: Pointer to MC portal's I/O object |
||
717 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
718 | - * @token: Token of DPCON object |
||
719 | - * |
||
720 | - * Return: '0' on Success; Error code otherwise |
||
721 | - */ |
||
722 | -int dpcon_disable(struct fsl_mc_io *mc_io, |
||
723 | - u32 cmd_flags, |
||
724 | - u16 token) |
||
725 | -{ |
||
726 | - struct mc_command cmd = { 0 }; |
||
727 | - |
||
728 | - /* prepare command */ |
||
729 | - cmd.header = mc_encode_cmd_header(DPCON_CMDID_DISABLE, |
||
730 | - cmd_flags, |
||
731 | - token); |
||
732 | - |
||
733 | - /* send command to mc*/ |
||
734 | - return mc_send_command(mc_io, &cmd); |
||
735 | -} |
||
736 | -EXPORT_SYMBOL(dpcon_disable); |
||
737 | - |
||
738 | -/** |
||
739 | - * dpcon_is_enabled() - Check if the DPCON is enabled. |
||
740 | - * @mc_io: Pointer to MC portal's I/O object |
||
741 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
742 | - * @token: Token of DPCON object |
||
743 | - * @en: Returns '1' if object is enabled; '0' otherwise |
||
744 | - * |
||
745 | - * Return: '0' on Success; Error code otherwise. |
||
746 | - */ |
||
747 | -int dpcon_is_enabled(struct fsl_mc_io *mc_io, |
||
748 | - u32 cmd_flags, |
||
749 | - u16 token, |
||
750 | - int *en) |
||
751 | -{ |
||
752 | - struct mc_command cmd = { 0 }; |
||
753 | - struct dpcon_rsp_is_enabled *dpcon_rsp; |
||
754 | - int err; |
||
755 | - |
||
756 | - /* prepare command */ |
||
757 | - cmd.header = mc_encode_cmd_header(DPCON_CMDID_IS_ENABLED, |
||
758 | - cmd_flags, |
||
759 | - token); |
||
760 | - |
||
761 | - /* send command to mc*/ |
||
762 | - err = mc_send_command(mc_io, &cmd); |
||
763 | - if (err) |
||
764 | - return err; |
||
765 | - |
||
766 | - /* retrieve response parameters */ |
||
767 | - dpcon_rsp = (struct dpcon_rsp_is_enabled *)cmd.params; |
||
768 | - *en = dpcon_rsp->enabled & DPCON_ENABLE; |
||
769 | - |
||
770 | - return 0; |
||
771 | -} |
||
772 | -EXPORT_SYMBOL(dpcon_is_enabled); |
||
773 | - |
||
774 | -/** |
||
775 | - * dpcon_reset() - Reset the DPCON, returns the object to initial state. |
||
776 | - * @mc_io: Pointer to MC portal's I/O object |
||
777 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
778 | - * @token: Token of DPCON object |
||
779 | - * |
||
780 | - * Return: '0' on Success; Error code otherwise. |
||
781 | - */ |
||
782 | -int dpcon_reset(struct fsl_mc_io *mc_io, |
||
783 | - u32 cmd_flags, |
||
784 | - u16 token) |
||
785 | -{ |
||
786 | - struct mc_command cmd = { 0 }; |
||
787 | - |
||
788 | - /* prepare command */ |
||
789 | - cmd.header = mc_encode_cmd_header(DPCON_CMDID_RESET, |
||
790 | - cmd_flags, token); |
||
791 | - |
||
792 | - /* send command to mc*/ |
||
793 | - return mc_send_command(mc_io, &cmd); |
||
794 | -} |
||
795 | -EXPORT_SYMBOL(dpcon_reset); |
||
796 | - |
||
797 | -/** |
||
798 | - * dpcon_get_attributes() - Retrieve DPCON attributes. |
||
799 | - * @mc_io: Pointer to MC portal's I/O object |
||
800 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
801 | - * @token: Token of DPCON object |
||
802 | - * @attr: Object's attributes |
||
803 | - * |
||
804 | - * Return: '0' on Success; Error code otherwise. |
||
805 | - */ |
||
806 | -int dpcon_get_attributes(struct fsl_mc_io *mc_io, |
||
807 | - u32 cmd_flags, |
||
808 | - u16 token, |
||
809 | - struct dpcon_attr *attr) |
||
810 | -{ |
||
811 | - struct mc_command cmd = { 0 }; |
||
812 | - struct dpcon_rsp_get_attr *dpcon_rsp; |
||
813 | - int err; |
||
814 | - |
||
815 | - /* prepare command */ |
||
816 | - cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_ATTR, |
||
817 | - cmd_flags, |
||
818 | - token); |
||
819 | - |
||
820 | - /* send command to mc*/ |
||
821 | - err = mc_send_command(mc_io, &cmd); |
||
822 | - if (err) |
||
823 | - return err; |
||
824 | - |
||
825 | - /* retrieve response parameters */ |
||
826 | - dpcon_rsp = (struct dpcon_rsp_get_attr *)cmd.params; |
||
827 | - attr->id = le32_to_cpu(dpcon_rsp->id); |
||
828 | - attr->qbman_ch_id = le16_to_cpu(dpcon_rsp->qbman_ch_id); |
||
829 | - attr->num_priorities = dpcon_rsp->num_priorities; |
||
830 | - |
||
831 | - return 0; |
||
832 | -} |
||
833 | -EXPORT_SYMBOL(dpcon_get_attributes); |
||
834 | - |
||
835 | -/** |
||
836 | - * dpcon_set_notification() - Set DPCON notification destination |
||
837 | - * @mc_io: Pointer to MC portal's I/O object |
||
838 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
839 | - * @token: Token of DPCON object |
||
840 | - * @cfg: Notification parameters |
||
841 | - * |
||
842 | - * Return: '0' on Success; Error code otherwise |
||
843 | - */ |
||
844 | -int dpcon_set_notification(struct fsl_mc_io *mc_io, |
||
845 | - u32 cmd_flags, |
||
846 | - u16 token, |
||
847 | - struct dpcon_notification_cfg *cfg) |
||
848 | -{ |
||
849 | - struct mc_command cmd = { 0 }; |
||
850 | - struct dpcon_cmd_set_notification *dpcon_cmd; |
||
851 | - |
||
852 | - /* prepare command */ |
||
853 | - cmd.header = mc_encode_cmd_header(DPCON_CMDID_SET_NOTIFICATION, |
||
854 | - cmd_flags, |
||
855 | - token); |
||
856 | - dpcon_cmd = (struct dpcon_cmd_set_notification *)cmd.params; |
||
857 | - dpcon_cmd->dpio_id = cpu_to_le32(cfg->dpio_id); |
||
858 | - dpcon_cmd->priority = cfg->priority; |
||
859 | - dpcon_cmd->user_ctx = cpu_to_le64(cfg->user_ctx); |
||
860 | - |
||
861 | - /* send command to mc*/ |
||
862 | - return mc_send_command(mc_io, &cmd); |
||
863 | -} |
||
864 | -EXPORT_SYMBOL(dpcon_set_notification); |
||
865 | - |
||
866 | -/** |
||
867 | - * dpcon_get_api_version - Get Data Path Concentrator API version |
||
868 | - * @mc_io: Pointer to MC portal's DPCON object |
||
869 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
870 | - * @major_ver: Major version of DPCON API |
||
871 | - * @minor_ver: Minor version of DPCON API |
||
872 | - * |
||
873 | - * Return: '0' on Success; Error code otherwise |
||
874 | - */ |
||
875 | -int dpcon_get_api_version(struct fsl_mc_io *mc_io, |
||
876 | - u32 cmd_flags, |
||
877 | - u16 *major_ver, |
||
878 | - u16 *minor_ver) |
||
879 | -{ |
||
880 | - struct mc_command cmd = { 0 }; |
||
881 | - int err; |
||
882 | - |
||
883 | - /* prepare command */ |
||
884 | - cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_API_VERSION, |
||
885 | - cmd_flags, 0); |
||
886 | - |
||
887 | - /* send command to mc */ |
||
888 | - err = mc_send_command(mc_io, &cmd); |
||
889 | - if (err) |
||
890 | - return err; |
||
891 | - |
||
892 | - /* retrieve response parameters */ |
||
893 | - mc_cmd_read_api_version(&cmd, major_ver, minor_ver); |
||
894 | - |
||
895 | - return 0; |
||
896 | -} |
||
897 | -EXPORT_SYMBOL(dpcon_get_api_version); |
||
898 | --- /dev/null |
||
899 | +++ b/drivers/bus/fsl-mc/dpcon.c |
||
900 | @@ -0,0 +1,222 @@ |
||
901 | +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) |
||
902 | +/* |
||
903 | + * Copyright 2013-2016 Freescale Semiconductor Inc. |
||
904 | + * |
||
905 | + */ |
||
906 | +#include <linux/kernel.h> |
||
907 | +#include <linux/fsl/mc.h> |
||
908 | +#include <linux/fsl/mc.h> |
||
909 | + |
||
910 | +#include "fsl-mc-private.h" |
||
911 | + |
||
912 | +/** |
||
913 | + * dpcon_open() - Open a control session for the specified object |
||
914 | + * @mc_io: Pointer to MC portal's I/O object |
||
915 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
916 | + * @dpcon_id: DPCON unique ID |
||
917 | + * @token: Returned token; use in subsequent API calls |
||
918 | + * |
||
919 | + * This function can be used to open a control session for an |
||
920 | + * already created object; an object may have been declared in |
||
921 | + * the DPL or by calling the dpcon_create() function. |
||
922 | + * This function returns a unique authentication token, |
||
923 | + * associated with the specific object ID and the specific MC |
||
924 | + * portal; this token must be used in all subsequent commands for |
||
925 | + * this specific object. |
||
926 | + * |
||
927 | + * Return: '0' on Success; Error code otherwise. |
||
928 | + */ |
||
929 | +int dpcon_open(struct fsl_mc_io *mc_io, |
||
930 | + u32 cmd_flags, |
||
931 | + int dpcon_id, |
||
932 | + u16 *token) |
||
933 | +{ |
||
934 | + struct fsl_mc_command cmd = { 0 }; |
||
935 | + struct dpcon_cmd_open *dpcon_cmd; |
||
936 | + int err; |
||
937 | + |
||
938 | + /* prepare command */ |
||
939 | + cmd.header = mc_encode_cmd_header(DPCON_CMDID_OPEN, |
||
940 | + cmd_flags, |
||
941 | + 0); |
||
942 | + dpcon_cmd = (struct dpcon_cmd_open *)cmd.params; |
||
943 | + dpcon_cmd->dpcon_id = cpu_to_le32(dpcon_id); |
||
944 | + |
||
945 | + /* send command to mc*/ |
||
946 | + err = mc_send_command(mc_io, &cmd); |
||
947 | + if (err) |
||
948 | + return err; |
||
949 | + |
||
950 | + /* retrieve response parameters */ |
||
951 | + *token = mc_cmd_hdr_read_token(&cmd); |
||
952 | + |
||
953 | + return 0; |
||
954 | +} |
||
955 | +EXPORT_SYMBOL_GPL(dpcon_open); |
||
956 | + |
||
957 | +/** |
||
958 | + * dpcon_close() - Close the control session of the object |
||
959 | + * @mc_io: Pointer to MC portal's I/O object |
||
960 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
961 | + * @token: Token of DPCON object |
||
962 | + * |
||
963 | + * After this function is called, no further operations are |
||
964 | + * allowed on the object without opening a new control session. |
||
965 | + * |
||
966 | + * Return: '0' on Success; Error code otherwise. |
||
967 | + */ |
||
968 | +int dpcon_close(struct fsl_mc_io *mc_io, |
||
969 | + u32 cmd_flags, |
||
970 | + u16 token) |
||
971 | +{ |
||
972 | + struct fsl_mc_command cmd = { 0 }; |
||
973 | + |
||
974 | + /* prepare command */ |
||
975 | + cmd.header = mc_encode_cmd_header(DPCON_CMDID_CLOSE, |
||
976 | + cmd_flags, |
||
977 | + token); |
||
978 | + |
||
979 | + /* send command to mc*/ |
||
980 | + return mc_send_command(mc_io, &cmd); |
||
981 | +} |
||
982 | +EXPORT_SYMBOL_GPL(dpcon_close); |
||
983 | + |
||
984 | +/** |
||
985 | + * dpcon_enable() - Enable the DPCON |
||
986 | + * @mc_io: Pointer to MC portal's I/O object |
||
987 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
988 | + * @token: Token of DPCON object |
||
989 | + * |
||
990 | + * Return: '0' on Success; Error code otherwise |
||
991 | + */ |
||
992 | +int dpcon_enable(struct fsl_mc_io *mc_io, |
||
993 | + u32 cmd_flags, |
||
994 | + u16 token) |
||
995 | +{ |
||
996 | + struct fsl_mc_command cmd = { 0 }; |
||
997 | + |
||
998 | + /* prepare command */ |
||
999 | + cmd.header = mc_encode_cmd_header(DPCON_CMDID_ENABLE, |
||
1000 | + cmd_flags, |
||
1001 | + token); |
||
1002 | + |
||
1003 | + /* send command to mc*/ |
||
1004 | + return mc_send_command(mc_io, &cmd); |
||
1005 | +} |
||
1006 | +EXPORT_SYMBOL_GPL(dpcon_enable); |
||
1007 | + |
||
1008 | +/** |
||
1009 | + * dpcon_disable() - Disable the DPCON |
||
1010 | + * @mc_io: Pointer to MC portal's I/O object |
||
1011 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
1012 | + * @token: Token of DPCON object |
||
1013 | + * |
||
1014 | + * Return: '0' on Success; Error code otherwise |
||
1015 | + */ |
||
1016 | +int dpcon_disable(struct fsl_mc_io *mc_io, |
||
1017 | + u32 cmd_flags, |
||
1018 | + u16 token) |
||
1019 | +{ |
||
1020 | + struct fsl_mc_command cmd = { 0 }; |
||
1021 | + |
||
1022 | + /* prepare command */ |
||
1023 | + cmd.header = mc_encode_cmd_header(DPCON_CMDID_DISABLE, |
||
1024 | + cmd_flags, |
||
1025 | + token); |
||
1026 | + |
||
1027 | + /* send command to mc*/ |
||
1028 | + return mc_send_command(mc_io, &cmd); |
||
1029 | +} |
||
1030 | +EXPORT_SYMBOL_GPL(dpcon_disable); |
||
1031 | + |
||
1032 | +/** |
||
1033 | + * dpcon_reset() - Reset the DPCON, returns the object to initial state. |
||
1034 | + * @mc_io: Pointer to MC portal's I/O object |
||
1035 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
1036 | + * @token: Token of DPCON object |
||
1037 | + * |
||
1038 | + * Return: '0' on Success; Error code otherwise. |
||
1039 | + */ |
||
1040 | +int dpcon_reset(struct fsl_mc_io *mc_io, |
||
1041 | + u32 cmd_flags, |
||
1042 | + u16 token) |
||
1043 | +{ |
||
1044 | + struct fsl_mc_command cmd = { 0 }; |
||
1045 | + |
||
1046 | + /* prepare command */ |
||
1047 | + cmd.header = mc_encode_cmd_header(DPCON_CMDID_RESET, |
||
1048 | + cmd_flags, token); |
||
1049 | + |
||
1050 | + /* send command to mc*/ |
||
1051 | + return mc_send_command(mc_io, &cmd); |
||
1052 | +} |
||
1053 | +EXPORT_SYMBOL_GPL(dpcon_reset); |
||
1054 | + |
||
1055 | +/** |
||
1056 | + * dpcon_get_attributes() - Retrieve DPCON attributes. |
||
1057 | + * @mc_io: Pointer to MC portal's I/O object |
||
1058 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
1059 | + * @token: Token of DPCON object |
||
1060 | + * @attr: Object's attributes |
||
1061 | + * |
||
1062 | + * Return: '0' on Success; Error code otherwise. |
||
1063 | + */ |
||
1064 | +int dpcon_get_attributes(struct fsl_mc_io *mc_io, |
||
1065 | + u32 cmd_flags, |
||
1066 | + u16 token, |
||
1067 | + struct dpcon_attr *attr) |
||
1068 | +{ |
||
1069 | + struct fsl_mc_command cmd = { 0 }; |
||
1070 | + struct dpcon_rsp_get_attr *dpcon_rsp; |
||
1071 | + int err; |
||
1072 | + |
||
1073 | + /* prepare command */ |
||
1074 | + cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_ATTR, |
||
1075 | + cmd_flags, |
||
1076 | + token); |
||
1077 | + |
||
1078 | + /* send command to mc*/ |
||
1079 | + err = mc_send_command(mc_io, &cmd); |
||
1080 | + if (err) |
||
1081 | + return err; |
||
1082 | + |
||
1083 | + /* retrieve response parameters */ |
||
1084 | + dpcon_rsp = (struct dpcon_rsp_get_attr *)cmd.params; |
||
1085 | + attr->id = le32_to_cpu(dpcon_rsp->id); |
||
1086 | + attr->qbman_ch_id = le16_to_cpu(dpcon_rsp->qbman_ch_id); |
||
1087 | + attr->num_priorities = dpcon_rsp->num_priorities; |
||
1088 | + |
||
1089 | + return 0; |
||
1090 | +} |
||
1091 | +EXPORT_SYMBOL_GPL(dpcon_get_attributes); |
||
1092 | + |
||
1093 | +/** |
||
1094 | + * dpcon_set_notification() - Set DPCON notification destination |
||
1095 | + * @mc_io: Pointer to MC portal's I/O object |
||
1096 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
1097 | + * @token: Token of DPCON object |
||
1098 | + * @cfg: Notification parameters |
||
1099 | + * |
||
1100 | + * Return: '0' on Success; Error code otherwise |
||
1101 | + */ |
||
1102 | +int dpcon_set_notification(struct fsl_mc_io *mc_io, |
||
1103 | + u32 cmd_flags, |
||
1104 | + u16 token, |
||
1105 | + struct dpcon_notification_cfg *cfg) |
||
1106 | +{ |
||
1107 | + struct fsl_mc_command cmd = { 0 }; |
||
1108 | + struct dpcon_cmd_set_notification *dpcon_cmd; |
||
1109 | + |
||
1110 | + /* prepare command */ |
||
1111 | + cmd.header = mc_encode_cmd_header(DPCON_CMDID_SET_NOTIFICATION, |
||
1112 | + cmd_flags, |
||
1113 | + token); |
||
1114 | + dpcon_cmd = (struct dpcon_cmd_set_notification *)cmd.params; |
||
1115 | + dpcon_cmd->dpio_id = cpu_to_le32(cfg->dpio_id); |
||
1116 | + dpcon_cmd->priority = cfg->priority; |
||
1117 | + dpcon_cmd->user_ctx = cpu_to_le64(cfg->user_ctx); |
||
1118 | + |
||
1119 | + /* send command to mc*/ |
||
1120 | + return mc_send_command(mc_io, &cmd); |
||
1121 | +} |
||
1122 | +EXPORT_SYMBOL_GPL(dpcon_set_notification); |
||
1123 | --- /dev/null |
||
1124 | +++ b/drivers/bus/fsl-mc/dpmcp.c |
||
1125 | @@ -0,0 +1,99 @@ |
||
1126 | +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) |
||
1127 | +/* |
||
1128 | + * Copyright 2013-2016 Freescale Semiconductor Inc. |
||
1129 | + * |
||
1130 | + */ |
||
1131 | +#include <linux/kernel.h> |
||
1132 | +#include <linux/fsl/mc.h> |
||
1133 | + |
||
1134 | +#include "fsl-mc-private.h" |
||
1135 | + |
||
1136 | +/** |
||
1137 | + * dpmcp_open() - Open a control session for the specified object. |
||
1138 | + * @mc_io: Pointer to MC portal's I/O object |
||
1139 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
1140 | + * @dpmcp_id: DPMCP unique ID |
||
1141 | + * @token: Returned token; use in subsequent API calls |
||
1142 | + * |
||
1143 | + * This function can be used to open a control session for an |
||
1144 | + * already created object; an object may have been declared in |
||
1145 | + * the DPL or by calling the dpmcp_create function. |
||
1146 | + * This function returns a unique authentication token, |
||
1147 | + * associated with the specific object ID and the specific MC |
||
1148 | + * portal; this token must be used in all subsequent commands for |
||
1149 | + * this specific object |
||
1150 | + * |
||
1151 | + * Return: '0' on Success; Error code otherwise. |
||
1152 | + */ |
||
1153 | +int dpmcp_open(struct fsl_mc_io *mc_io, |
||
1154 | + u32 cmd_flags, |
||
1155 | + int dpmcp_id, |
||
1156 | + u16 *token) |
||
1157 | +{ |
||
1158 | + struct fsl_mc_command cmd = { 0 }; |
||
1159 | + struct dpmcp_cmd_open *cmd_params; |
||
1160 | + int err; |
||
1161 | + |
||
1162 | + /* prepare command */ |
||
1163 | + cmd.header = mc_encode_cmd_header(DPMCP_CMDID_OPEN, |
||
1164 | + cmd_flags, 0); |
||
1165 | + cmd_params = (struct dpmcp_cmd_open *)cmd.params; |
||
1166 | + cmd_params->dpmcp_id = cpu_to_le32(dpmcp_id); |
||
1167 | + |
||
1168 | + /* send command to mc*/ |
||
1169 | + err = mc_send_command(mc_io, &cmd); |
||
1170 | + if (err) |
||
1171 | + return err; |
||
1172 | + |
||
1173 | + /* retrieve response parameters */ |
||
1174 | + *token = mc_cmd_hdr_read_token(&cmd); |
||
1175 | + |
||
1176 | + return err; |
||
1177 | +} |
||
1178 | + |
||
1179 | +/** |
||
1180 | + * dpmcp_close() - Close the control session of the object |
||
1181 | + * @mc_io: Pointer to MC portal's I/O object |
||
1182 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
1183 | + * @token: Token of DPMCP object |
||
1184 | + * |
||
1185 | + * After this function is called, no further operations are |
||
1186 | + * allowed on the object without opening a new control session. |
||
1187 | + * |
||
1188 | + * Return: '0' on Success; Error code otherwise. |
||
1189 | + */ |
||
1190 | +int dpmcp_close(struct fsl_mc_io *mc_io, |
||
1191 | + u32 cmd_flags, |
||
1192 | + u16 token) |
||
1193 | +{ |
||
1194 | + struct fsl_mc_command cmd = { 0 }; |
||
1195 | + |
||
1196 | + /* prepare command */ |
||
1197 | + cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CLOSE, |
||
1198 | + cmd_flags, token); |
||
1199 | + |
||
1200 | + /* send command to mc*/ |
||
1201 | + return mc_send_command(mc_io, &cmd); |
||
1202 | +} |
||
1203 | + |
||
1204 | +/** |
||
1205 | + * dpmcp_reset() - Reset the DPMCP, returns the object to initial state. |
||
1206 | + * @mc_io: Pointer to MC portal's I/O object |
||
1207 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
1208 | + * @token: Token of DPMCP object |
||
1209 | + * |
||
1210 | + * Return: '0' on Success; Error code otherwise. |
||
1211 | + */ |
||
1212 | +int dpmcp_reset(struct fsl_mc_io *mc_io, |
||
1213 | + u32 cmd_flags, |
||
1214 | + u16 token) |
||
1215 | +{ |
||
1216 | + struct fsl_mc_command cmd = { 0 }; |
||
1217 | + |
||
1218 | + /* prepare command */ |
||
1219 | + cmd.header = mc_encode_cmd_header(DPMCP_CMDID_RESET, |
||
1220 | + cmd_flags, token); |
||
1221 | + |
||
1222 | + /* send command to mc*/ |
||
1223 | + return mc_send_command(mc_io, &cmd); |
||
1224 | +} |
||
1225 | --- a/drivers/staging/fsl-mc/bus/dprc-driver.c |
||
1226 | +++ /dev/null |
||
1227 | @@ -1,813 +0,0 @@ |
||
1228 | -// SPDX-License-Identifier: GPL-2.0 |
||
1229 | -/* |
||
1230 | - * Freescale data path resource container (DPRC) driver |
||
1231 | - * |
||
1232 | - * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. |
||
1233 | - * Author: German Rivera <German.Rivera@freescale.com> |
||
1234 | - * |
||
1235 | - */ |
||
1236 | - |
||
1237 | -#include <linux/module.h> |
||
1238 | -#include <linux/slab.h> |
||
1239 | -#include <linux/interrupt.h> |
||
1240 | -#include <linux/msi.h> |
||
1241 | -#include "../include/mc.h" |
||
1242 | - |
||
1243 | -#include "dprc-cmd.h" |
||
1244 | -#include "fsl-mc-private.h" |
||
1245 | - |
||
1246 | -#define FSL_MC_DPRC_DRIVER_NAME "fsl_mc_dprc" |
||
1247 | - |
||
1248 | -struct fsl_mc_child_objs { |
||
1249 | - int child_count; |
||
1250 | - struct fsl_mc_obj_desc *child_array; |
||
1251 | -}; |
||
1252 | - |
||
1253 | -static bool fsl_mc_device_match(struct fsl_mc_device *mc_dev, |
||
1254 | - struct fsl_mc_obj_desc *obj_desc) |
||
1255 | -{ |
||
1256 | - return mc_dev->obj_desc.id == obj_desc->id && |
||
1257 | - strcmp(mc_dev->obj_desc.type, obj_desc->type) == 0; |
||
1258 | - |
||
1259 | -} |
||
1260 | - |
||
1261 | -static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data) |
||
1262 | -{ |
||
1263 | - int i; |
||
1264 | - struct fsl_mc_child_objs *objs; |
||
1265 | - struct fsl_mc_device *mc_dev; |
||
1266 | - |
||
1267 | - WARN_ON(!dev); |
||
1268 | - WARN_ON(!data); |
||
1269 | - mc_dev = to_fsl_mc_device(dev); |
||
1270 | - objs = data; |
||
1271 | - |
||
1272 | - for (i = 0; i < objs->child_count; i++) { |
||
1273 | - struct fsl_mc_obj_desc *obj_desc = &objs->child_array[i]; |
||
1274 | - |
||
1275 | - if (strlen(obj_desc->type) != 0 && |
||
1276 | - fsl_mc_device_match(mc_dev, obj_desc)) |
||
1277 | - break; |
||
1278 | - } |
||
1279 | - |
||
1280 | - if (i == objs->child_count) |
||
1281 | - fsl_mc_device_remove(mc_dev); |
||
1282 | - |
||
1283 | - return 0; |
||
1284 | -} |
||
1285 | - |
||
1286 | -static int __fsl_mc_device_remove(struct device *dev, void *data) |
||
1287 | -{ |
||
1288 | - WARN_ON(!dev); |
||
1289 | - WARN_ON(data); |
||
1290 | - fsl_mc_device_remove(to_fsl_mc_device(dev)); |
||
1291 | - return 0; |
||
1292 | -} |
||
1293 | - |
||
1294 | -/** |
||
1295 | - * dprc_remove_devices - Removes devices for objects removed from a DPRC |
||
1296 | - * |
||
1297 | - * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object |
||
1298 | - * @obj_desc_array: array of object descriptors for child objects currently |
||
1299 | - * present in the DPRC in the MC. |
||
1300 | - * @num_child_objects_in_mc: number of entries in obj_desc_array |
||
1301 | - * |
||
1302 | - * Synchronizes the state of the Linux bus driver with the actual state of |
||
1303 | - * the MC by removing devices that represent MC objects that have |
||
1304 | - * been dynamically removed in the physical DPRC. |
||
1305 | - */ |
||
1306 | -static void dprc_remove_devices(struct fsl_mc_device *mc_bus_dev, |
||
1307 | - struct fsl_mc_obj_desc *obj_desc_array, |
||
1308 | - int num_child_objects_in_mc) |
||
1309 | -{ |
||
1310 | - if (num_child_objects_in_mc != 0) { |
||
1311 | - /* |
||
1312 | - * Remove child objects that are in the DPRC in Linux, |
||
1313 | - * but not in the MC: |
||
1314 | - */ |
||
1315 | - struct fsl_mc_child_objs objs; |
||
1316 | - |
||
1317 | - objs.child_count = num_child_objects_in_mc; |
||
1318 | - objs.child_array = obj_desc_array; |
||
1319 | - device_for_each_child(&mc_bus_dev->dev, &objs, |
||
1320 | - __fsl_mc_device_remove_if_not_in_mc); |
||
1321 | - } else { |
||
1322 | - /* |
||
1323 | - * There are no child objects for this DPRC in the MC. |
||
1324 | - * So, remove all the child devices from Linux: |
||
1325 | - */ |
||
1326 | - device_for_each_child(&mc_bus_dev->dev, NULL, |
||
1327 | - __fsl_mc_device_remove); |
||
1328 | - } |
||
1329 | -} |
||
1330 | - |
||
1331 | -static int __fsl_mc_device_match(struct device *dev, void *data) |
||
1332 | -{ |
||
1333 | - struct fsl_mc_obj_desc *obj_desc = data; |
||
1334 | - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); |
||
1335 | - |
||
1336 | - return fsl_mc_device_match(mc_dev, obj_desc); |
||
1337 | -} |
||
1338 | - |
||
1339 | -static struct fsl_mc_device *fsl_mc_device_lookup(struct fsl_mc_obj_desc |
||
1340 | - *obj_desc, |
||
1341 | - struct fsl_mc_device |
||
1342 | - *mc_bus_dev) |
||
1343 | -{ |
||
1344 | - struct device *dev; |
||
1345 | - |
||
1346 | - dev = device_find_child(&mc_bus_dev->dev, obj_desc, |
||
1347 | - __fsl_mc_device_match); |
||
1348 | - |
||
1349 | - return dev ? to_fsl_mc_device(dev) : NULL; |
||
1350 | -} |
||
1351 | - |
||
1352 | -/** |
||
1353 | - * check_plugged_state_change - Check change in an MC object's plugged state |
||
1354 | - * |
||
1355 | - * @mc_dev: pointer to the fsl-mc device for a given MC object |
||
1356 | - * @obj_desc: pointer to the MC object's descriptor in the MC |
||
1357 | - * |
||
1358 | - * If the plugged state has changed from unplugged to plugged, the fsl-mc |
||
1359 | - * device is bound to the corresponding device driver. |
||
1360 | - * If the plugged state has changed from plugged to unplugged, the fsl-mc |
||
1361 | - * device is unbound from the corresponding device driver. |
||
1362 | - */ |
||
1363 | -static void check_plugged_state_change(struct fsl_mc_device *mc_dev, |
||
1364 | - struct fsl_mc_obj_desc *obj_desc) |
||
1365 | -{ |
||
1366 | - int error; |
||
1367 | - u32 plugged_flag_at_mc = |
||
1368 | - obj_desc->state & FSL_MC_OBJ_STATE_PLUGGED; |
||
1369 | - |
||
1370 | - if (plugged_flag_at_mc != |
||
1371 | - (mc_dev->obj_desc.state & FSL_MC_OBJ_STATE_PLUGGED)) { |
||
1372 | - if (plugged_flag_at_mc) { |
||
1373 | - mc_dev->obj_desc.state |= FSL_MC_OBJ_STATE_PLUGGED; |
||
1374 | - error = device_attach(&mc_dev->dev); |
||
1375 | - if (error < 0) { |
||
1376 | - dev_err(&mc_dev->dev, |
||
1377 | - "device_attach() failed: %d\n", |
||
1378 | - error); |
||
1379 | - } |
||
1380 | - } else { |
||
1381 | - mc_dev->obj_desc.state &= ~FSL_MC_OBJ_STATE_PLUGGED; |
||
1382 | - device_release_driver(&mc_dev->dev); |
||
1383 | - } |
||
1384 | - } |
||
1385 | -} |
||
1386 | - |
||
1387 | -/** |
||
1388 | - * dprc_add_new_devices - Adds devices to the logical bus for a DPRC |
||
1389 | - * |
||
1390 | - * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object |
||
1391 | - * @obj_desc_array: array of device descriptors for child devices currently |
||
1392 | - * present in the physical DPRC. |
||
1393 | - * @num_child_objects_in_mc: number of entries in obj_desc_array |
||
1394 | - * |
||
1395 | - * Synchronizes the state of the Linux bus driver with the actual |
||
1396 | - * state of the MC by adding objects that have been newly discovered |
||
1397 | - * in the physical DPRC. |
||
1398 | - */ |
||
1399 | -static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev, |
||
1400 | - struct fsl_mc_obj_desc *obj_desc_array, |
||
1401 | - int num_child_objects_in_mc) |
||
1402 | -{ |
||
1403 | - int error; |
||
1404 | - int i; |
||
1405 | - |
||
1406 | - for (i = 0; i < num_child_objects_in_mc; i++) { |
||
1407 | - struct fsl_mc_device *child_dev; |
||
1408 | - struct fsl_mc_obj_desc *obj_desc = &obj_desc_array[i]; |
||
1409 | - |
||
1410 | - if (strlen(obj_desc->type) == 0) |
||
1411 | - continue; |
||
1412 | - |
||
1413 | - /* |
||
1414 | - * Check if device is already known to Linux: |
||
1415 | - */ |
||
1416 | - child_dev = fsl_mc_device_lookup(obj_desc, mc_bus_dev); |
||
1417 | - if (child_dev) { |
||
1418 | - check_plugged_state_change(child_dev, obj_desc); |
||
1419 | - put_device(&child_dev->dev); |
||
1420 | - continue; |
||
1421 | - } |
||
1422 | - |
||
1423 | - error = fsl_mc_device_add(obj_desc, NULL, &mc_bus_dev->dev, |
||
1424 | - &child_dev); |
||
1425 | - if (error < 0) |
||
1426 | - continue; |
||
1427 | - } |
||
1428 | -} |
||
1429 | - |
||
1430 | -/** |
||
1431 | - * dprc_scan_objects - Discover objects in a DPRC |
||
1432 | - * |
||
1433 | - * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object |
||
1434 | - * @total_irq_count: total number of IRQs needed by objects in the DPRC. |
||
1435 | - * |
||
1436 | - * Detects objects added and removed from a DPRC and synchronizes the |
||
1437 | - * state of the Linux bus driver, MC by adding and removing |
||
1438 | - * devices accordingly. |
||
1439 | - * Two types of devices can be found in a DPRC: allocatable objects (e.g., |
||
1440 | - * dpbp, dpmcp) and non-allocatable devices (e.g., dprc, dpni). |
||
1441 | - * All allocatable devices needed to be probed before all non-allocatable |
||
1442 | - * devices, to ensure that device drivers for non-allocatable |
||
1443 | - * devices can allocate any type of allocatable devices. |
||
1444 | - * That is, we need to ensure that the corresponding resource pools are |
||
1445 | - * populated before they can get allocation requests from probe callbacks |
||
1446 | - * of the device drivers for the non-allocatable devices. |
||
1447 | - */ |
||
1448 | -static int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, |
||
1449 | - unsigned int *total_irq_count) |
||
1450 | -{ |
||
1451 | - int num_child_objects; |
||
1452 | - int dprc_get_obj_failures; |
||
1453 | - int error; |
||
1454 | - unsigned int irq_count = mc_bus_dev->obj_desc.irq_count; |
||
1455 | - struct fsl_mc_obj_desc *child_obj_desc_array = NULL; |
||
1456 | - |
||
1457 | - error = dprc_get_obj_count(mc_bus_dev->mc_io, |
||
1458 | - 0, |
||
1459 | - mc_bus_dev->mc_handle, |
||
1460 | - &num_child_objects); |
||
1461 | - if (error < 0) { |
||
1462 | - dev_err(&mc_bus_dev->dev, "dprc_get_obj_count() failed: %d\n", |
||
1463 | - error); |
||
1464 | - return error; |
||
1465 | - } |
||
1466 | - |
||
1467 | - if (num_child_objects != 0) { |
||
1468 | - int i; |
||
1469 | - |
||
1470 | - child_obj_desc_array = |
||
1471 | - devm_kmalloc_array(&mc_bus_dev->dev, num_child_objects, |
||
1472 | - sizeof(*child_obj_desc_array), |
||
1473 | - GFP_KERNEL); |
||
1474 | - if (!child_obj_desc_array) |
||
1475 | - return -ENOMEM; |
||
1476 | - |
||
1477 | - /* |
||
1478 | - * Discover objects currently present in the physical DPRC: |
||
1479 | - */ |
||
1480 | - dprc_get_obj_failures = 0; |
||
1481 | - for (i = 0; i < num_child_objects; i++) { |
||
1482 | - struct fsl_mc_obj_desc *obj_desc = |
||
1483 | - &child_obj_desc_array[i]; |
||
1484 | - |
||
1485 | - error = dprc_get_obj(mc_bus_dev->mc_io, |
||
1486 | - 0, |
||
1487 | - mc_bus_dev->mc_handle, |
||
1488 | - i, obj_desc); |
||
1489 | - if (error < 0) { |
||
1490 | - dev_err(&mc_bus_dev->dev, |
||
1491 | - "dprc_get_obj(i=%d) failed: %d\n", |
||
1492 | - i, error); |
||
1493 | - /* |
||
1494 | - * Mark the obj entry as "invalid", by using the |
||
1495 | - * empty string as obj type: |
||
1496 | - */ |
||
1497 | - obj_desc->type[0] = '\0'; |
||
1498 | - obj_desc->id = error; |
||
1499 | - dprc_get_obj_failures++; |
||
1500 | - continue; |
||
1501 | - } |
||
1502 | - |
||
1503 | - /* |
||
1504 | - * add a quirk for all versions of dpsec < 4.0...none |
||
1505 | - * are coherent regardless of what the MC reports. |
||
1506 | - */ |
||
1507 | - if ((strcmp(obj_desc->type, "dpseci") == 0) && |
||
1508 | - (obj_desc->ver_major < 4)) |
||
1509 | - obj_desc->flags |= |
||
1510 | - FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY; |
||
1511 | - |
||
1512 | - irq_count += obj_desc->irq_count; |
||
1513 | - dev_dbg(&mc_bus_dev->dev, |
||
1514 | - "Discovered object: type %s, id %d\n", |
||
1515 | - obj_desc->type, obj_desc->id); |
||
1516 | - } |
||
1517 | - |
||
1518 | - if (dprc_get_obj_failures != 0) { |
||
1519 | - dev_err(&mc_bus_dev->dev, |
||
1520 | - "%d out of %d devices could not be retrieved\n", |
||
1521 | - dprc_get_obj_failures, num_child_objects); |
||
1522 | - } |
||
1523 | - } |
||
1524 | - |
||
1525 | - *total_irq_count = irq_count; |
||
1526 | - dprc_remove_devices(mc_bus_dev, child_obj_desc_array, |
||
1527 | - num_child_objects); |
||
1528 | - |
||
1529 | - dprc_add_new_devices(mc_bus_dev, child_obj_desc_array, |
||
1530 | - num_child_objects); |
||
1531 | - |
||
1532 | - if (child_obj_desc_array) |
||
1533 | - devm_kfree(&mc_bus_dev->dev, child_obj_desc_array); |
||
1534 | - |
||
1535 | - return 0; |
||
1536 | -} |
||
1537 | - |
||
1538 | -/** |
||
1539 | - * dprc_scan_container - Scans a physical DPRC and synchronizes Linux bus state |
||
1540 | - * |
||
1541 | - * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object |
||
1542 | - * |
||
1543 | - * Scans the physical DPRC and synchronizes the state of the Linux |
||
1544 | - * bus driver with the actual state of the MC by adding and removing |
||
1545 | - * devices as appropriate. |
||
1546 | - */ |
||
1547 | -static int dprc_scan_container(struct fsl_mc_device *mc_bus_dev) |
||
1548 | -{ |
||
1549 | - int error; |
||
1550 | - unsigned int irq_count; |
||
1551 | - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); |
||
1552 | - |
||
1553 | - fsl_mc_init_all_resource_pools(mc_bus_dev); |
||
1554 | - |
||
1555 | - /* |
||
1556 | - * Discover objects in the DPRC: |
||
1557 | - */ |
||
1558 | - mutex_lock(&mc_bus->scan_mutex); |
||
1559 | - error = dprc_scan_objects(mc_bus_dev, &irq_count); |
||
1560 | - mutex_unlock(&mc_bus->scan_mutex); |
||
1561 | - if (error < 0) |
||
1562 | - goto error; |
||
1563 | - |
||
1564 | - if (dev_get_msi_domain(&mc_bus_dev->dev) && !mc_bus->irq_resources) { |
||
1565 | - if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) { |
||
1566 | - dev_warn(&mc_bus_dev->dev, |
||
1567 | - "IRQs needed (%u) exceed IRQs preallocated (%u)\n", |
||
1568 | - irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); |
||
1569 | - } |
||
1570 | - |
||
1571 | - error = fsl_mc_populate_irq_pool( |
||
1572 | - mc_bus, |
||
1573 | - FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); |
||
1574 | - if (error < 0) |
||
1575 | - goto error; |
||
1576 | - } |
||
1577 | - |
||
1578 | - return 0; |
||
1579 | -error: |
||
1580 | - fsl_mc_cleanup_all_resource_pools(mc_bus_dev); |
||
1581 | - return error; |
||
1582 | -} |
||
1583 | - |
||
1584 | -/** |
||
1585 | - * dprc_irq0_handler - Regular ISR for DPRC interrupt 0 |
||
1586 | - * |
||
1587 | - * @irq: IRQ number of the interrupt being handled |
||
1588 | - * @arg: Pointer to device structure |
||
1589 | - */ |
||
1590 | -static irqreturn_t dprc_irq0_handler(int irq_num, void *arg) |
||
1591 | -{ |
||
1592 | - return IRQ_WAKE_THREAD; |
||
1593 | -} |
||
1594 | - |
||
1595 | -/** |
||
1596 | - * dprc_irq0_handler_thread - Handler thread function for DPRC interrupt 0 |
||
1597 | - * |
||
1598 | - * @irq: IRQ number of the interrupt being handled |
||
1599 | - * @arg: Pointer to device structure |
||
1600 | - */ |
||
1601 | -static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg) |
||
1602 | -{ |
||
1603 | - int error; |
||
1604 | - u32 status; |
||
1605 | - struct device *dev = arg; |
||
1606 | - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); |
||
1607 | - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); |
||
1608 | - struct fsl_mc_io *mc_io = mc_dev->mc_io; |
||
1609 | - struct msi_desc *msi_desc = mc_dev->irqs[0]->msi_desc; |
||
1610 | - |
||
1611 | - dev_dbg(dev, "DPRC IRQ %d triggered on CPU %u\n", |
||
1612 | - irq_num, smp_processor_id()); |
||
1613 | - |
||
1614 | - if (WARN_ON(!(mc_dev->flags & FSL_MC_IS_DPRC))) |
||
1615 | - return IRQ_HANDLED; |
||
1616 | - |
||
1617 | - mutex_lock(&mc_bus->scan_mutex); |
||
1618 | - if (WARN_ON(!msi_desc || msi_desc->irq != (u32)irq_num)) |
||
1619 | - goto out; |
||
1620 | - |
||
1621 | - status = 0; |
||
1622 | - error = dprc_get_irq_status(mc_io, 0, mc_dev->mc_handle, 0, |
||
1623 | - &status); |
||
1624 | - if (error < 0) { |
||
1625 | - dev_err(dev, |
||
1626 | - "dprc_get_irq_status() failed: %d\n", error); |
||
1627 | - goto out; |
||
1628 | - } |
||
1629 | - |
||
1630 | - error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, |
||
1631 | - status); |
||
1632 | - if (error < 0) { |
||
1633 | - dev_err(dev, |
||
1634 | - "dprc_clear_irq_status() failed: %d\n", error); |
||
1635 | - goto out; |
||
1636 | - } |
||
1637 | - |
||
1638 | - if (status & (DPRC_IRQ_EVENT_OBJ_ADDED | |
||
1639 | - DPRC_IRQ_EVENT_OBJ_REMOVED | |
||
1640 | - DPRC_IRQ_EVENT_CONTAINER_DESTROYED | |
||
1641 | - DPRC_IRQ_EVENT_OBJ_DESTROYED | |
||
1642 | - DPRC_IRQ_EVENT_OBJ_CREATED)) { |
||
1643 | - unsigned int irq_count; |
||
1644 | - |
||
1645 | - error = dprc_scan_objects(mc_dev, &irq_count); |
||
1646 | - if (error < 0) { |
||
1647 | - /* |
||
1648 | - * If the error is -ENXIO, we ignore it, as it indicates |
||
1649 | - * that the object scan was aborted, as we detected that |
||
1650 | - * an object was removed from the DPRC in the MC, while |
||
1651 | - * we were scanning the DPRC. |
||
1652 | - */ |
||
1653 | - if (error != -ENXIO) { |
||
1654 | - dev_err(dev, "dprc_scan_objects() failed: %d\n", |
||
1655 | - error); |
||
1656 | - } |
||
1657 | - |
||
1658 | - goto out; |
||
1659 | - } |
||
1660 | - |
||
1661 | - if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) { |
||
1662 | - dev_warn(dev, |
||
1663 | - "IRQs needed (%u) exceed IRQs preallocated (%u)\n", |
||
1664 | - irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); |
||
1665 | - } |
||
1666 | - } |
||
1667 | - |
||
1668 | -out: |
||
1669 | - mutex_unlock(&mc_bus->scan_mutex); |
||
1670 | - return IRQ_HANDLED; |
||
1671 | -} |
||
1672 | - |
||
1673 | -/* |
||
1674 | - * Disable and clear interrupt for a given DPRC object |
||
1675 | - */ |
||
1676 | -static int disable_dprc_irq(struct fsl_mc_device *mc_dev) |
||
1677 | -{ |
||
1678 | - int error; |
||
1679 | - struct fsl_mc_io *mc_io = mc_dev->mc_io; |
||
1680 | - |
||
1681 | - WARN_ON(mc_dev->obj_desc.irq_count != 1); |
||
1682 | - |
||
1683 | - /* |
||
1684 | - * Disable generation of interrupt, while we configure it: |
||
1685 | - */ |
||
1686 | - error = dprc_set_irq_enable(mc_io, 0, mc_dev->mc_handle, 0, 0); |
||
1687 | - if (error < 0) { |
||
1688 | - dev_err(&mc_dev->dev, |
||
1689 | - "Disabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n", |
||
1690 | - error); |
||
1691 | - return error; |
||
1692 | - } |
||
1693 | - |
||
1694 | - /* |
||
1695 | - * Disable all interrupt causes for the interrupt: |
||
1696 | - */ |
||
1697 | - error = dprc_set_irq_mask(mc_io, 0, mc_dev->mc_handle, 0, 0x0); |
||
1698 | - if (error < 0) { |
||
1699 | - dev_err(&mc_dev->dev, |
||
1700 | - "Disabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n", |
||
1701 | - error); |
||
1702 | - return error; |
||
1703 | - } |
||
1704 | - |
||
1705 | - /* |
||
1706 | - * Clear any leftover interrupts: |
||
1707 | - */ |
||
1708 | - error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, ~0x0U); |
||
1709 | - if (error < 0) { |
||
1710 | - dev_err(&mc_dev->dev, |
||
1711 | - "Disabling DPRC IRQ failed: dprc_clear_irq_status() failed: %d\n", |
||
1712 | - error); |
||
1713 | - return error; |
||
1714 | - } |
||
1715 | - |
||
1716 | - return 0; |
||
1717 | -} |
||
1718 | - |
||
1719 | -static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev) |
||
1720 | -{ |
||
1721 | - int error; |
||
1722 | - struct fsl_mc_device_irq *irq = mc_dev->irqs[0]; |
||
1723 | - |
||
1724 | - WARN_ON(mc_dev->obj_desc.irq_count != 1); |
||
1725 | - |
||
1726 | - /* |
||
1727 | - * NOTE: devm_request_threaded_irq() invokes the device-specific |
||
1728 | - * function that programs the MSI physically in the device |
||
1729 | - */ |
||
1730 | - error = devm_request_threaded_irq(&mc_dev->dev, |
||
1731 | - irq->msi_desc->irq, |
||
1732 | - dprc_irq0_handler, |
||
1733 | - dprc_irq0_handler_thread, |
||
1734 | - IRQF_NO_SUSPEND | IRQF_ONESHOT, |
||
1735 | - dev_name(&mc_dev->dev), |
||
1736 | - &mc_dev->dev); |
||
1737 | - if (error < 0) { |
||
1738 | - dev_err(&mc_dev->dev, |
||
1739 | - "devm_request_threaded_irq() failed: %d\n", |
||
1740 | - error); |
||
1741 | - return error; |
||
1742 | - } |
||
1743 | - |
||
1744 | - return 0; |
||
1745 | -} |
||
1746 | - |
||
1747 | -static int enable_dprc_irq(struct fsl_mc_device *mc_dev) |
||
1748 | -{ |
||
1749 | - int error; |
||
1750 | - |
||
1751 | - /* |
||
1752 | - * Enable all interrupt causes for the interrupt: |
||
1753 | - */ |
||
1754 | - error = dprc_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, |
||
1755 | - ~0x0u); |
||
1756 | - if (error < 0) { |
||
1757 | - dev_err(&mc_dev->dev, |
||
1758 | - "Enabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n", |
||
1759 | - error); |
||
1760 | - |
||
1761 | - return error; |
||
1762 | - } |
||
1763 | - |
||
1764 | - /* |
||
1765 | - * Enable generation of the interrupt: |
||
1766 | - */ |
||
1767 | - error = dprc_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, 1); |
||
1768 | - if (error < 0) { |
||
1769 | - dev_err(&mc_dev->dev, |
||
1770 | - "Enabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n", |
||
1771 | - error); |
||
1772 | - |
||
1773 | - return error; |
||
1774 | - } |
||
1775 | - |
||
1776 | - return 0; |
||
1777 | -} |
||
1778 | - |
||
1779 | -/* |
||
1780 | - * Setup interrupt for a given DPRC device |
||
1781 | - */ |
||
1782 | -static int dprc_setup_irq(struct fsl_mc_device *mc_dev) |
||
1783 | -{ |
||
1784 | - int error; |
||
1785 | - |
||
1786 | - error = fsl_mc_allocate_irqs(mc_dev); |
||
1787 | - if (error < 0) |
||
1788 | - return error; |
||
1789 | - |
||
1790 | - error = disable_dprc_irq(mc_dev); |
||
1791 | - if (error < 0) |
||
1792 | - goto error_free_irqs; |
||
1793 | - |
||
1794 | - error = register_dprc_irq_handler(mc_dev); |
||
1795 | - if (error < 0) |
||
1796 | - goto error_free_irqs; |
||
1797 | - |
||
1798 | - error = enable_dprc_irq(mc_dev); |
||
1799 | - if (error < 0) |
||
1800 | - goto error_free_irqs; |
||
1801 | - |
||
1802 | - return 0; |
||
1803 | - |
||
1804 | -error_free_irqs: |
||
1805 | - fsl_mc_free_irqs(mc_dev); |
||
1806 | - return error; |
||
1807 | -} |
||
1808 | - |
||
1809 | -/** |
||
1810 | - * dprc_probe - callback invoked when a DPRC is being bound to this driver |
||
1811 | - * |
||
1812 | - * @mc_dev: Pointer to fsl-mc device representing a DPRC |
||
1813 | - * |
||
1814 | - * It opens the physical DPRC in the MC. |
||
1815 | - * It scans the DPRC to discover the MC objects contained in it. |
||
1816 | - * It creates the interrupt pool for the MC bus associated with the DPRC. |
||
1817 | - * It configures the interrupts for the DPRC device itself. |
||
1818 | - */ |
||
1819 | -static int dprc_probe(struct fsl_mc_device *mc_dev) |
||
1820 | -{ |
||
1821 | - int error; |
||
1822 | - size_t region_size; |
||
1823 | - struct device *parent_dev = mc_dev->dev.parent; |
||
1824 | - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); |
||
1825 | - bool mc_io_created = false; |
||
1826 | - bool msi_domain_set = false; |
||
1827 | - u16 major_ver, minor_ver; |
||
1828 | - |
||
1829 | - if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0)) |
||
1830 | - return -EINVAL; |
||
1831 | - |
||
1832 | - if (WARN_ON(dev_get_msi_domain(&mc_dev->dev))) |
||
1833 | - return -EINVAL; |
||
1834 | - |
||
1835 | - if (!mc_dev->mc_io) { |
||
1836 | - /* |
||
1837 | - * This is a child DPRC: |
||
1838 | - */ |
||
1839 | - if (WARN_ON(!dev_is_fsl_mc(parent_dev))) |
||
1840 | - return -EINVAL; |
||
1841 | - |
||
1842 | - if (WARN_ON(mc_dev->obj_desc.region_count == 0)) |
||
1843 | - return -EINVAL; |
||
1844 | - |
||
1845 | - region_size = resource_size(mc_dev->regions); |
||
1846 | - |
||
1847 | - error = fsl_create_mc_io(&mc_dev->dev, |
||
1848 | - mc_dev->regions[0].start, |
||
1849 | - region_size, |
||
1850 | - NULL, |
||
1851 | - FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, |
||
1852 | - &mc_dev->mc_io); |
||
1853 | - if (error < 0) |
||
1854 | - return error; |
||
1855 | - |
||
1856 | - mc_io_created = true; |
||
1857 | - |
||
1858 | - /* |
||
1859 | - * Inherit parent MSI domain: |
||
1860 | - */ |
||
1861 | - dev_set_msi_domain(&mc_dev->dev, |
||
1862 | - dev_get_msi_domain(parent_dev)); |
||
1863 | - msi_domain_set = true; |
||
1864 | - } else { |
||
1865 | - /* |
||
1866 | - * This is a root DPRC |
||
1867 | - */ |
||
1868 | - struct irq_domain *mc_msi_domain; |
||
1869 | - |
||
1870 | - if (WARN_ON(dev_is_fsl_mc(parent_dev))) |
||
1871 | - return -EINVAL; |
||
1872 | - |
||
1873 | - error = fsl_mc_find_msi_domain(parent_dev, |
||
1874 | - &mc_msi_domain); |
||
1875 | - if (error < 0) { |
||
1876 | - dev_warn(&mc_dev->dev, |
||
1877 | - "WARNING: MC bus without interrupt support\n"); |
||
1878 | - } else { |
||
1879 | - dev_set_msi_domain(&mc_dev->dev, mc_msi_domain); |
||
1880 | - msi_domain_set = true; |
||
1881 | - } |
||
1882 | - } |
||
1883 | - |
||
1884 | - error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id, |
||
1885 | - &mc_dev->mc_handle); |
||
1886 | - if (error < 0) { |
||
1887 | - dev_err(&mc_dev->dev, "dprc_open() failed: %d\n", error); |
||
1888 | - goto error_cleanup_msi_domain; |
||
1889 | - } |
||
1890 | - |
||
1891 | - error = dprc_get_attributes(mc_dev->mc_io, 0, mc_dev->mc_handle, |
||
1892 | - &mc_bus->dprc_attr); |
||
1893 | - if (error < 0) { |
||
1894 | - dev_err(&mc_dev->dev, "dprc_get_attributes() failed: %d\n", |
||
1895 | - error); |
||
1896 | - goto error_cleanup_open; |
||
1897 | - } |
||
1898 | - |
||
1899 | - error = dprc_get_api_version(mc_dev->mc_io, 0, |
||
1900 | - &major_ver, |
||
1901 | - &minor_ver); |
||
1902 | - if (error < 0) { |
||
1903 | - dev_err(&mc_dev->dev, "dprc_get_api_version() failed: %d\n", |
||
1904 | - error); |
||
1905 | - goto error_cleanup_open; |
||
1906 | - } |
||
1907 | - |
||
1908 | - if (major_ver < DPRC_MIN_VER_MAJOR || |
||
1909 | - (major_ver == DPRC_MIN_VER_MAJOR && |
||
1910 | - minor_ver < DPRC_MIN_VER_MINOR)) { |
||
1911 | - dev_err(&mc_dev->dev, |
||
1912 | - "ERROR: DPRC version %d.%d not supported\n", |
||
1913 | - major_ver, minor_ver); |
||
1914 | - error = -ENOTSUPP; |
||
1915 | - goto error_cleanup_open; |
||
1916 | - } |
||
1917 | - |
||
1918 | - mutex_init(&mc_bus->scan_mutex); |
||
1919 | - |
||
1920 | - /* |
||
1921 | - * Discover MC objects in DPRC object: |
||
1922 | - */ |
||
1923 | - error = dprc_scan_container(mc_dev); |
||
1924 | - if (error < 0) |
||
1925 | - goto error_cleanup_open; |
||
1926 | - |
||
1927 | - /* |
||
1928 | - * Configure interrupt for the DPRC object associated with this MC bus: |
||
1929 | - */ |
||
1930 | - error = dprc_setup_irq(mc_dev); |
||
1931 | - if (error < 0) |
||
1932 | - goto error_cleanup_open; |
||
1933 | - |
||
1934 | - dev_info(&mc_dev->dev, "DPRC device bound to driver"); |
||
1935 | - return 0; |
||
1936 | - |
||
1937 | -error_cleanup_open: |
||
1938 | - (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); |
||
1939 | - |
||
1940 | -error_cleanup_msi_domain: |
||
1941 | - if (msi_domain_set) |
||
1942 | - dev_set_msi_domain(&mc_dev->dev, NULL); |
||
1943 | - |
||
1944 | - if (mc_io_created) { |
||
1945 | - fsl_destroy_mc_io(mc_dev->mc_io); |
||
1946 | - mc_dev->mc_io = NULL; |
||
1947 | - } |
||
1948 | - |
||
1949 | - return error; |
||
1950 | -} |
||
1951 | - |
||
1952 | -/* |
||
1953 | - * Tear down interrupt for a given DPRC object |
||
1954 | - */ |
||
1955 | -static void dprc_teardown_irq(struct fsl_mc_device *mc_dev) |
||
1956 | -{ |
||
1957 | - struct fsl_mc_device_irq *irq = mc_dev->irqs[0]; |
||
1958 | - |
||
1959 | - (void)disable_dprc_irq(mc_dev); |
||
1960 | - |
||
1961 | - devm_free_irq(&mc_dev->dev, irq->msi_desc->irq, &mc_dev->dev); |
||
1962 | - |
||
1963 | - fsl_mc_free_irqs(mc_dev); |
||
1964 | -} |
||
1965 | - |
||
1966 | -/** |
||
1967 | - * dprc_remove - callback invoked when a DPRC is being unbound from this driver |
||
1968 | - * |
||
1969 | - * @mc_dev: Pointer to fsl-mc device representing the DPRC |
||
1970 | - * |
||
1971 | - * It removes the DPRC's child objects from Linux (not from the MC) and |
||
1972 | - * closes the DPRC device in the MC. |
||
1973 | - * It tears down the interrupts that were configured for the DPRC device. |
||
1974 | - * It destroys the interrupt pool associated with this MC bus. |
||
1975 | - */ |
||
1976 | -static int dprc_remove(struct fsl_mc_device *mc_dev) |
||
1977 | -{ |
||
1978 | - int error; |
||
1979 | - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); |
||
1980 | - |
||
1981 | - if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0)) |
||
1982 | - return -EINVAL; |
||
1983 | - if (WARN_ON(!mc_dev->mc_io)) |
||
1984 | - return -EINVAL; |
||
1985 | - |
||
1986 | - if (WARN_ON(!mc_bus->irq_resources)) |
||
1987 | - return -EINVAL; |
||
1988 | - |
||
1989 | - if (dev_get_msi_domain(&mc_dev->dev)) |
||
1990 | - dprc_teardown_irq(mc_dev); |
||
1991 | - |
||
1992 | - device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove); |
||
1993 | - |
||
1994 | - if (dev_get_msi_domain(&mc_dev->dev)) { |
||
1995 | - fsl_mc_cleanup_irq_pool(mc_bus); |
||
1996 | - dev_set_msi_domain(&mc_dev->dev, NULL); |
||
1997 | - } |
||
1998 | - |
||
1999 | - fsl_mc_cleanup_all_resource_pools(mc_dev); |
||
2000 | - |
||
2001 | - error = dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); |
||
2002 | - if (error < 0) |
||
2003 | - dev_err(&mc_dev->dev, "dprc_close() failed: %d\n", error); |
||
2004 | - |
||
2005 | - if (!fsl_mc_is_root_dprc(&mc_dev->dev)) { |
||
2006 | - fsl_destroy_mc_io(mc_dev->mc_io); |
||
2007 | - mc_dev->mc_io = NULL; |
||
2008 | - } |
||
2009 | - |
||
2010 | - dev_info(&mc_dev->dev, "DPRC device unbound from driver"); |
||
2011 | - return 0; |
||
2012 | -} |
||
2013 | - |
||
2014 | -static const struct fsl_mc_device_id match_id_table[] = { |
||
2015 | - { |
||
2016 | - .vendor = FSL_MC_VENDOR_FREESCALE, |
||
2017 | - .obj_type = "dprc"}, |
||
2018 | - {.vendor = 0x0}, |
||
2019 | -}; |
||
2020 | - |
||
2021 | -static struct fsl_mc_driver dprc_driver = { |
||
2022 | - .driver = { |
||
2023 | - .name = FSL_MC_DPRC_DRIVER_NAME, |
||
2024 | - .owner = THIS_MODULE, |
||
2025 | - .pm = NULL, |
||
2026 | - }, |
||
2027 | - .match_id_table = match_id_table, |
||
2028 | - .probe = dprc_probe, |
||
2029 | - .remove = dprc_remove, |
||
2030 | -}; |
||
2031 | - |
||
2032 | -int __init dprc_driver_init(void) |
||
2033 | -{ |
||
2034 | - return fsl_mc_driver_register(&dprc_driver); |
||
2035 | -} |
||
2036 | - |
||
2037 | -void dprc_driver_exit(void) |
||
2038 | -{ |
||
2039 | - fsl_mc_driver_unregister(&dprc_driver); |
||
2040 | -} |
||
2041 | --- /dev/null |
||
2042 | +++ b/drivers/bus/fsl-mc/dprc-driver.c |
||
2043 | @@ -0,0 +1,815 @@ |
||
2044 | +// SPDX-License-Identifier: GPL-2.0 |
||
2045 | +/* |
||
2046 | + * Freescale data path resource container (DPRC) driver |
||
2047 | + * |
||
2048 | + * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. |
||
2049 | + * Author: German Rivera <German.Rivera@freescale.com> |
||
2050 | + * |
||
2051 | + */ |
||
2052 | + |
||
2053 | +#include <linux/module.h> |
||
2054 | +#include <linux/slab.h> |
||
2055 | +#include <linux/interrupt.h> |
||
2056 | +#include <linux/msi.h> |
||
2057 | +#include <linux/fsl/mc.h> |
||
2058 | + |
||
2059 | +#include "fsl-mc-private.h" |
||
2060 | + |
||
2061 | +#define FSL_MC_DPRC_DRIVER_NAME "fsl_mc_dprc" |
||
2062 | + |
||
2063 | +struct fsl_mc_child_objs { |
||
2064 | + int child_count; |
||
2065 | + struct fsl_mc_obj_desc *child_array; |
||
2066 | +}; |
||
2067 | + |
||
2068 | +static bool fsl_mc_device_match(struct fsl_mc_device *mc_dev, |
||
2069 | + struct fsl_mc_obj_desc *obj_desc) |
||
2070 | +{ |
||
2071 | + return mc_dev->obj_desc.id == obj_desc->id && |
||
2072 | + strcmp(mc_dev->obj_desc.type, obj_desc->type) == 0; |
||
2073 | + |
||
2074 | +} |
||
2075 | + |
||
2076 | +static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data) |
||
2077 | +{ |
||
2078 | + int i; |
||
2079 | + struct fsl_mc_child_objs *objs; |
||
2080 | + struct fsl_mc_device *mc_dev; |
||
2081 | + |
||
2082 | + mc_dev = to_fsl_mc_device(dev); |
||
2083 | + objs = data; |
||
2084 | + |
||
2085 | + for (i = 0; i < objs->child_count; i++) { |
||
2086 | + struct fsl_mc_obj_desc *obj_desc = &objs->child_array[i]; |
||
2087 | + |
||
2088 | + if (strlen(obj_desc->type) != 0 && |
||
2089 | + fsl_mc_device_match(mc_dev, obj_desc)) |
||
2090 | + break; |
||
2091 | + } |
||
2092 | + |
||
2093 | + if (i == objs->child_count) |
||
2094 | + fsl_mc_device_remove(mc_dev); |
||
2095 | + |
||
2096 | + return 0; |
||
2097 | +} |
||
2098 | + |
||
2099 | +static int __fsl_mc_device_remove(struct device *dev, void *data) |
||
2100 | +{ |
||
2101 | + fsl_mc_device_remove(to_fsl_mc_device(dev)); |
||
2102 | + return 0; |
||
2103 | +} |
||
2104 | + |
||
2105 | +/** |
||
2106 | + * dprc_remove_devices - Removes devices for objects removed from a DPRC |
||
2107 | + * |
||
2108 | + * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object |
||
2109 | + * @obj_desc_array: array of object descriptors for child objects currently |
||
2110 | + * present in the DPRC in the MC. |
||
2111 | + * @num_child_objects_in_mc: number of entries in obj_desc_array |
||
2112 | + * |
||
2113 | + * Synchronizes the state of the Linux bus driver with the actual state of |
||
2114 | + * the MC by removing devices that represent MC objects that have |
||
2115 | + * been dynamically removed in the physical DPRC. |
||
2116 | + */ |
||
2117 | +static void dprc_remove_devices(struct fsl_mc_device *mc_bus_dev, |
||
2118 | + struct fsl_mc_obj_desc *obj_desc_array, |
||
2119 | + int num_child_objects_in_mc) |
||
2120 | +{ |
||
2121 | + if (num_child_objects_in_mc != 0) { |
||
2122 | + /* |
||
2123 | + * Remove child objects that are in the DPRC in Linux, |
||
2124 | + * but not in the MC: |
||
2125 | + */ |
||
2126 | + struct fsl_mc_child_objs objs; |
||
2127 | + |
||
2128 | + objs.child_count = num_child_objects_in_mc; |
||
2129 | + objs.child_array = obj_desc_array; |
||
2130 | + device_for_each_child(&mc_bus_dev->dev, &objs, |
||
2131 | + __fsl_mc_device_remove_if_not_in_mc); |
||
2132 | + } else { |
||
2133 | + /* |
||
2134 | + * There are no child objects for this DPRC in the MC. |
||
2135 | + * So, remove all the child devices from Linux: |
||
2136 | + */ |
||
2137 | + device_for_each_child(&mc_bus_dev->dev, NULL, |
||
2138 | + __fsl_mc_device_remove); |
||
2139 | + } |
||
2140 | +} |
||
2141 | + |
||
2142 | +static int __fsl_mc_device_match(struct device *dev, void *data) |
||
2143 | +{ |
||
2144 | + struct fsl_mc_obj_desc *obj_desc = data; |
||
2145 | + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); |
||
2146 | + |
||
2147 | + return fsl_mc_device_match(mc_dev, obj_desc); |
||
2148 | +} |
||
2149 | + |
||
2150 | +static struct fsl_mc_device *fsl_mc_device_lookup(struct fsl_mc_obj_desc |
||
2151 | + *obj_desc, |
||
2152 | + struct fsl_mc_device |
||
2153 | + *mc_bus_dev) |
||
2154 | +{ |
||
2155 | + struct device *dev; |
||
2156 | + |
||
2157 | + dev = device_find_child(&mc_bus_dev->dev, obj_desc, |
||
2158 | + __fsl_mc_device_match); |
||
2159 | + |
||
2160 | + return dev ? to_fsl_mc_device(dev) : NULL; |
||
2161 | +} |
||
2162 | + |
||
2163 | +/** |
||
2164 | + * check_plugged_state_change - Check change in an MC object's plugged state |
||
2165 | + * |
||
2166 | + * @mc_dev: pointer to the fsl-mc device for a given MC object |
||
2167 | + * @obj_desc: pointer to the MC object's descriptor in the MC |
||
2168 | + * |
||
2169 | + * If the plugged state has changed from unplugged to plugged, the fsl-mc |
||
2170 | + * device is bound to the corresponding device driver. |
||
2171 | + * If the plugged state has changed from plugged to unplugged, the fsl-mc |
||
2172 | + * device is unbound from the corresponding device driver. |
||
2173 | + */ |
||
2174 | +static void check_plugged_state_change(struct fsl_mc_device *mc_dev, |
||
2175 | + struct fsl_mc_obj_desc *obj_desc) |
||
2176 | +{ |
||
2177 | + int error; |
||
2178 | + u32 plugged_flag_at_mc = |
||
2179 | + obj_desc->state & FSL_MC_OBJ_STATE_PLUGGED; |
||
2180 | + |
||
2181 | + if (plugged_flag_at_mc != |
||
2182 | + (mc_dev->obj_desc.state & FSL_MC_OBJ_STATE_PLUGGED)) { |
||
2183 | + if (plugged_flag_at_mc) { |
||
2184 | + mc_dev->obj_desc.state |= FSL_MC_OBJ_STATE_PLUGGED; |
||
2185 | + error = device_attach(&mc_dev->dev); |
||
2186 | + if (error < 0) { |
||
2187 | + dev_err(&mc_dev->dev, |
||
2188 | + "device_attach() failed: %d\n", |
||
2189 | + error); |
||
2190 | + } |
||
2191 | + } else { |
||
2192 | + mc_dev->obj_desc.state &= ~FSL_MC_OBJ_STATE_PLUGGED; |
||
2193 | + device_release_driver(&mc_dev->dev); |
||
2194 | + } |
||
2195 | + } |
||
2196 | +} |
||
2197 | + |
||
2198 | +/** |
||
2199 | + * dprc_add_new_devices - Adds devices to the logical bus for a DPRC |
||
2200 | + * |
||
2201 | + * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object |
||
2202 | + * @driver_override: driver override to apply to new objects found in the |
||
2203 | + * DPRC, or NULL, if none. |
||
2204 | + * @obj_desc_array: array of device descriptors for child devices currently |
||
2205 | + * present in the physical DPRC. |
||
2206 | + * @num_child_objects_in_mc: number of entries in obj_desc_array |
||
2207 | + * |
||
2208 | + * Synchronizes the state of the Linux bus driver with the actual |
||
2209 | + * state of the MC by adding objects that have been newly discovered |
||
2210 | + * in the physical DPRC. |
||
2211 | + */ |
||
2212 | +static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev, |
||
2213 | + const char *driver_override, |
||
2214 | + struct fsl_mc_obj_desc *obj_desc_array, |
||
2215 | + int num_child_objects_in_mc) |
||
2216 | +{ |
||
2217 | + int error; |
||
2218 | + int i; |
||
2219 | + |
||
2220 | + for (i = 0; i < num_child_objects_in_mc; i++) { |
||
2221 | + struct fsl_mc_device *child_dev; |
||
2222 | + struct fsl_mc_obj_desc *obj_desc = &obj_desc_array[i]; |
||
2223 | + |
||
2224 | + if (strlen(obj_desc->type) == 0) |
||
2225 | + continue; |
||
2226 | + |
||
2227 | + /* |
||
2228 | + * Check if device is already known to Linux: |
||
2229 | + */ |
||
2230 | + child_dev = fsl_mc_device_lookup(obj_desc, mc_bus_dev); |
||
2231 | + if (child_dev) { |
||
2232 | + check_plugged_state_change(child_dev, obj_desc); |
||
2233 | + put_device(&child_dev->dev); |
||
2234 | + continue; |
||
2235 | + } |
||
2236 | + |
||
2237 | + error = fsl_mc_device_add(obj_desc, NULL, &mc_bus_dev->dev, |
||
2238 | + driver_override, &child_dev); |
||
2239 | + if (error < 0) |
||
2240 | + continue; |
||
2241 | + } |
||
2242 | +} |
||
2243 | + |
||
2244 | +/** |
||
2245 | + * dprc_scan_objects - Discover objects in a DPRC |
||
2246 | + * |
||
2247 | + * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object |
||
2248 | + * @driver_override: driver override to apply to new objects found in the |
||
2249 | + * DPRC, or NULL, if none. |
||
2250 | + * @total_irq_count: If argument is provided the function populates the |
||
2251 | + * total number of IRQs created by objects in the DPRC. |
||
2252 | + * |
||
2253 | + * Detects objects added and removed from a DPRC and synchronizes the |
||
2254 | + * state of the Linux bus driver, MC by adding and removing |
||
2255 | + * devices accordingly. |
||
2256 | + * Two types of devices can be found in a DPRC: allocatable objects (e.g., |
||
2257 | + * dpbp, dpmcp) and non-allocatable devices (e.g., dprc, dpni). |
||
2258 | + * All allocatable devices needed to be probed before all non-allocatable |
||
2259 | + * devices, to ensure that device drivers for non-allocatable |
||
2260 | + * devices can allocate any type of allocatable devices. |
||
2261 | + * That is, we need to ensure that the corresponding resource pools are |
||
2262 | + * populated before they can get allocation requests from probe callbacks |
||
2263 | + * of the device drivers for the non-allocatable devices. |
||
2264 | + */ |
||
2265 | +int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, |
||
2266 | + const char *driver_override, |
||
2267 | + unsigned int *total_irq_count) |
||
2268 | +{ |
||
2269 | + int num_child_objects; |
||
2270 | + int dprc_get_obj_failures; |
||
2271 | + int error; |
||
2272 | + unsigned int irq_count = mc_bus_dev->obj_desc.irq_count; |
||
2273 | + struct fsl_mc_obj_desc *child_obj_desc_array = NULL; |
||
2274 | + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); |
||
2275 | + |
||
2276 | + error = dprc_get_obj_count(mc_bus_dev->mc_io, |
||
2277 | + 0, |
||
2278 | + mc_bus_dev->mc_handle, |
||
2279 | + &num_child_objects); |
||
2280 | + if (error < 0) { |
||
2281 | + dev_err(&mc_bus_dev->dev, "dprc_get_obj_count() failed: %d\n", |
||
2282 | + error); |
||
2283 | + return error; |
||
2284 | + } |
||
2285 | + |
||
2286 | + if (num_child_objects != 0) { |
||
2287 | + int i; |
||
2288 | + |
||
2289 | + child_obj_desc_array = |
||
2290 | + devm_kmalloc_array(&mc_bus_dev->dev, num_child_objects, |
||
2291 | + sizeof(*child_obj_desc_array), |
||
2292 | + GFP_KERNEL); |
||
2293 | + if (!child_obj_desc_array) |
||
2294 | + return -ENOMEM; |
||
2295 | + |
||
2296 | + /* |
||
2297 | + * Discover objects currently present in the physical DPRC: |
||
2298 | + */ |
||
2299 | + dprc_get_obj_failures = 0; |
||
2300 | + for (i = 0; i < num_child_objects; i++) { |
||
2301 | + struct fsl_mc_obj_desc *obj_desc = |
||
2302 | + &child_obj_desc_array[i]; |
||
2303 | + |
||
2304 | + error = dprc_get_obj(mc_bus_dev->mc_io, |
||
2305 | + 0, |
||
2306 | + mc_bus_dev->mc_handle, |
||
2307 | + i, obj_desc); |
||
2308 | + if (error < 0) { |
||
2309 | + dev_err(&mc_bus_dev->dev, |
||
2310 | + "dprc_get_obj(i=%d) failed: %d\n", |
||
2311 | + i, error); |
||
2312 | + /* |
||
2313 | + * Mark the obj entry as "invalid", by using the |
||
2314 | + * empty string as obj type: |
||
2315 | + */ |
||
2316 | + obj_desc->type[0] = '\0'; |
||
2317 | + obj_desc->id = error; |
||
2318 | + dprc_get_obj_failures++; |
||
2319 | + continue; |
||
2320 | + } |
||
2321 | + |
||
2322 | + /* |
||
2323 | + * add a quirk for all versions of dpsec < 4.0...none |
||
2324 | + * are coherent regardless of what the MC reports. |
||
2325 | + */ |
||
2326 | + if ((strcmp(obj_desc->type, "dpseci") == 0) && |
||
2327 | + (obj_desc->ver_major < 4)) |
||
2328 | + obj_desc->flags |= |
||
2329 | + FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY; |
||
2330 | + |
||
2331 | + irq_count += obj_desc->irq_count; |
||
2332 | + dev_dbg(&mc_bus_dev->dev, |
||
2333 | + "Discovered object: type %s, id %d\n", |
||
2334 | + obj_desc->type, obj_desc->id); |
||
2335 | + } |
||
2336 | + |
||
2337 | + if (dprc_get_obj_failures != 0) { |
||
2338 | + dev_err(&mc_bus_dev->dev, |
||
2339 | + "%d out of %d devices could not be retrieved\n", |
||
2340 | + dprc_get_obj_failures, num_child_objects); |
||
2341 | + } |
||
2342 | + } |
||
2343 | + |
||
2344 | + /* |
||
2345 | + * Allocate IRQ's before binding the scanned devices with their |
||
2346 | + * respective drivers. |
||
2347 | + */ |
||
2348 | + if (dev_get_msi_domain(&mc_bus_dev->dev) && !mc_bus->irq_resources) { |
||
2349 | + if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) { |
||
2350 | + dev_warn(&mc_bus_dev->dev, |
||
2351 | + "IRQs needed (%u) exceed IRQs preallocated (%u)\n", |
||
2352 | + irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); |
||
2353 | + } |
||
2354 | + |
||
2355 | + error = fsl_mc_populate_irq_pool(mc_bus, |
||
2356 | + FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); |
||
2357 | + if (error < 0) |
||
2358 | + return error; |
||
2359 | + } |
||
2360 | + |
||
2361 | + if (total_irq_count) |
||
2362 | + *total_irq_count = irq_count; |
||
2363 | + |
||
2364 | + dprc_remove_devices(mc_bus_dev, child_obj_desc_array, |
||
2365 | + num_child_objects); |
||
2366 | + |
||
2367 | + dprc_add_new_devices(mc_bus_dev, driver_override, child_obj_desc_array, |
||
2368 | + num_child_objects); |
||
2369 | + |
||
2370 | + if (child_obj_desc_array) |
||
2371 | + devm_kfree(&mc_bus_dev->dev, child_obj_desc_array); |
||
2372 | + |
||
2373 | + return 0; |
||
2374 | +} |
||
2375 | + |
||
2376 | +/** |
||
2377 | + * dprc_scan_container - Scans a physical DPRC and synchronizes Linux bus state |
||
2378 | + * |
||
2379 | + * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object |
||
2380 | + * |
||
2381 | + * Scans the physical DPRC and synchronizes the state of the Linux |
||
2382 | + * bus driver with the actual state of the MC by adding and removing |
||
2383 | + * devices as appropriate. |
||
2384 | + */ |
||
2385 | +static int dprc_scan_container(struct fsl_mc_device *mc_bus_dev) |
||
2386 | +{ |
||
2387 | + int error; |
||
2388 | + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); |
||
2389 | + |
||
2390 | + fsl_mc_init_all_resource_pools(mc_bus_dev); |
||
2391 | + |
||
2392 | + /* |
||
2393 | + * Discover objects in the DPRC: |
||
2394 | + */ |
||
2395 | + mutex_lock(&mc_bus->scan_mutex); |
||
2396 | + error = dprc_scan_objects(mc_bus_dev, NULL, NULL); |
||
2397 | + mutex_unlock(&mc_bus->scan_mutex); |
||
2398 | + if (error < 0) { |
||
2399 | + fsl_mc_cleanup_all_resource_pools(mc_bus_dev); |
||
2400 | + return error; |
||
2401 | + } |
||
2402 | + |
||
2403 | + return 0; |
||
2404 | +} |
||
2405 | + |
||
2406 | +/** |
||
2407 | + * dprc_irq0_handler - Regular ISR for DPRC interrupt 0 |
||
2408 | + * |
||
2409 | + * @irq: IRQ number of the interrupt being handled |
||
2410 | + * @arg: Pointer to device structure |
||
2411 | + */ |
||
2412 | +static irqreturn_t dprc_irq0_handler(int irq_num, void *arg) |
||
2413 | +{ |
||
2414 | + return IRQ_WAKE_THREAD; |
||
2415 | +} |
||
2416 | + |
||
2417 | +/** |
||
2418 | + * dprc_irq0_handler_thread - Handler thread function for DPRC interrupt 0 |
||
2419 | + * |
||
2420 | + * @irq: IRQ number of the interrupt being handled |
||
2421 | + * @arg: Pointer to device structure |
||
2422 | + */ |
||
2423 | +static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg) |
||
2424 | +{ |
||
2425 | + int error; |
||
2426 | + u32 status; |
||
2427 | + struct device *dev = arg; |
||
2428 | + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); |
||
2429 | + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); |
||
2430 | + struct fsl_mc_io *mc_io = mc_dev->mc_io; |
||
2431 | + struct msi_desc *msi_desc = mc_dev->irqs[0]->msi_desc; |
||
2432 | + |
||
2433 | + dev_dbg(dev, "DPRC IRQ %d triggered on CPU %u\n", |
||
2434 | + irq_num, smp_processor_id()); |
||
2435 | + |
||
2436 | + if (!(mc_dev->flags & FSL_MC_IS_DPRC)) |
||
2437 | + return IRQ_HANDLED; |
||
2438 | + |
||
2439 | + mutex_lock(&mc_bus->scan_mutex); |
||
2440 | + if (!msi_desc || msi_desc->irq != (u32)irq_num) |
||
2441 | + goto out; |
||
2442 | + |
||
2443 | + status = 0; |
||
2444 | + error = dprc_get_irq_status(mc_io, 0, mc_dev->mc_handle, 0, |
||
2445 | + &status); |
||
2446 | + if (error < 0) { |
||
2447 | + dev_err(dev, |
||
2448 | + "dprc_get_irq_status() failed: %d\n", error); |
||
2449 | + goto out; |
||
2450 | + } |
||
2451 | + |
||
2452 | + error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, |
||
2453 | + status); |
||
2454 | + if (error < 0) { |
||
2455 | + dev_err(dev, |
||
2456 | + "dprc_clear_irq_status() failed: %d\n", error); |
||
2457 | + goto out; |
||
2458 | + } |
||
2459 | + |
||
2460 | + if (status & (DPRC_IRQ_EVENT_OBJ_ADDED | |
||
2461 | + DPRC_IRQ_EVENT_OBJ_REMOVED | |
||
2462 | + DPRC_IRQ_EVENT_CONTAINER_DESTROYED | |
||
2463 | + DPRC_IRQ_EVENT_OBJ_DESTROYED | |
||
2464 | + DPRC_IRQ_EVENT_OBJ_CREATED)) { |
||
2465 | + unsigned int irq_count; |
||
2466 | + |
||
2467 | + error = dprc_scan_objects(mc_dev, NULL, &irq_count); |
||
2468 | + if (error < 0) { |
||
2469 | + /* |
||
2470 | + * If the error is -ENXIO, we ignore it, as it indicates |
||
2471 | + * that the object scan was aborted, as we detected that |
||
2472 | + * an object was removed from the DPRC in the MC, while |
||
2473 | + * we were scanning the DPRC. |
||
2474 | + */ |
||
2475 | + if (error != -ENXIO) { |
||
2476 | + dev_err(dev, "dprc_scan_objects() failed: %d\n", |
||
2477 | + error); |
||
2478 | + } |
||
2479 | + |
||
2480 | + goto out; |
||
2481 | + } |
||
2482 | + |
||
2483 | + if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) { |
||
2484 | + dev_warn(dev, |
||
2485 | + "IRQs needed (%u) exceed IRQs preallocated (%u)\n", |
||
2486 | + irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); |
||
2487 | + } |
||
2488 | + } |
||
2489 | + |
||
2490 | +out: |
||
2491 | + mutex_unlock(&mc_bus->scan_mutex); |
||
2492 | + return IRQ_HANDLED; |
||
2493 | +} |
||
2494 | + |
||
2495 | +/* |
||
2496 | + * Disable and clear interrupt for a given DPRC object |
||
2497 | + */ |
||
2498 | +static int disable_dprc_irq(struct fsl_mc_device *mc_dev) |
||
2499 | +{ |
||
2500 | + int error; |
||
2501 | + struct fsl_mc_io *mc_io = mc_dev->mc_io; |
||
2502 | + |
||
2503 | + /* |
||
2504 | + * Disable generation of interrupt, while we configure it: |
||
2505 | + */ |
||
2506 | + error = dprc_set_irq_enable(mc_io, 0, mc_dev->mc_handle, 0, 0); |
||
2507 | + if (error < 0) { |
||
2508 | + dev_err(&mc_dev->dev, |
||
2509 | + "Disabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n", |
||
2510 | + error); |
||
2511 | + return error; |
||
2512 | + } |
||
2513 | + |
||
2514 | + /* |
||
2515 | + * Disable all interrupt causes for the interrupt: |
||
2516 | + */ |
||
2517 | + error = dprc_set_irq_mask(mc_io, 0, mc_dev->mc_handle, 0, 0x0); |
||
2518 | + if (error < 0) { |
||
2519 | + dev_err(&mc_dev->dev, |
||
2520 | + "Disabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n", |
||
2521 | + error); |
||
2522 | + return error; |
||
2523 | + } |
||
2524 | + |
||
2525 | + /* |
||
2526 | + * Clear any leftover interrupts: |
||
2527 | + */ |
||
2528 | + error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, ~0x0U); |
||
2529 | + if (error < 0) { |
||
2530 | + dev_err(&mc_dev->dev, |
||
2531 | + "Disabling DPRC IRQ failed: dprc_clear_irq_status() failed: %d\n", |
||
2532 | + error); |
||
2533 | + return error; |
||
2534 | + } |
||
2535 | + |
||
2536 | + return 0; |
||
2537 | +} |
||
2538 | + |
||
2539 | +static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev) |
||
2540 | +{ |
||
2541 | + int error; |
||
2542 | + struct fsl_mc_device_irq *irq = mc_dev->irqs[0]; |
||
2543 | + |
||
2544 | + /* |
||
2545 | + * NOTE: devm_request_threaded_irq() invokes the device-specific |
||
2546 | + * function that programs the MSI physically in the device |
||
2547 | + */ |
||
2548 | + error = devm_request_threaded_irq(&mc_dev->dev, |
||
2549 | + irq->msi_desc->irq, |
||
2550 | + dprc_irq0_handler, |
||
2551 | + dprc_irq0_handler_thread, |
||
2552 | + IRQF_NO_SUSPEND | IRQF_ONESHOT, |
||
2553 | + dev_name(&mc_dev->dev), |
||
2554 | + &mc_dev->dev); |
||
2555 | + if (error < 0) { |
||
2556 | + dev_err(&mc_dev->dev, |
||
2557 | + "devm_request_threaded_irq() failed: %d\n", |
||
2558 | + error); |
||
2559 | + return error; |
||
2560 | + } |
||
2561 | + |
||
2562 | + return 0; |
||
2563 | +} |
||
2564 | + |
||
2565 | +static int enable_dprc_irq(struct fsl_mc_device *mc_dev) |
||
2566 | +{ |
||
2567 | + int error; |
||
2568 | + |
||
2569 | + /* |
||
2570 | + * Enable all interrupt causes for the interrupt: |
||
2571 | + */ |
||
2572 | + error = dprc_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, |
||
2573 | + ~0x0u); |
||
2574 | + if (error < 0) { |
||
2575 | + dev_err(&mc_dev->dev, |
||
2576 | + "Enabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n", |
||
2577 | + error); |
||
2578 | + |
||
2579 | + return error; |
||
2580 | + } |
||
2581 | + |
||
2582 | + /* |
||
2583 | + * Enable generation of the interrupt: |
||
2584 | + */ |
||
2585 | + error = dprc_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, 1); |
||
2586 | + if (error < 0) { |
||
2587 | + dev_err(&mc_dev->dev, |
||
2588 | + "Enabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n", |
||
2589 | + error); |
||
2590 | + |
||
2591 | + return error; |
||
2592 | + } |
||
2593 | + |
||
2594 | + return 0; |
||
2595 | +} |
||
2596 | + |
||
2597 | +/* |
||
2598 | + * Setup interrupt for a given DPRC device |
||
2599 | + */ |
||
2600 | +static int dprc_setup_irq(struct fsl_mc_device *mc_dev) |
||
2601 | +{ |
||
2602 | + int error; |
||
2603 | + |
||
2604 | + error = fsl_mc_allocate_irqs(mc_dev); |
||
2605 | + if (error < 0) |
||
2606 | + return error; |
||
2607 | + |
||
2608 | + error = disable_dprc_irq(mc_dev); |
||
2609 | + if (error < 0) |
||
2610 | + goto error_free_irqs; |
||
2611 | + |
||
2612 | + error = register_dprc_irq_handler(mc_dev); |
||
2613 | + if (error < 0) |
||
2614 | + goto error_free_irqs; |
||
2615 | + |
||
2616 | + error = enable_dprc_irq(mc_dev); |
||
2617 | + if (error < 0) |
||
2618 | + goto error_free_irqs; |
||
2619 | + |
||
2620 | + return 0; |
||
2621 | + |
||
2622 | +error_free_irqs: |
||
2623 | + fsl_mc_free_irqs(mc_dev); |
||
2624 | + return error; |
||
2625 | +} |
||
2626 | + |
||
2627 | +/** |
||
2628 | + * dprc_probe - callback invoked when a DPRC is being bound to this driver |
||
2629 | + * |
||
2630 | + * @mc_dev: Pointer to fsl-mc device representing a DPRC |
||
2631 | + * |
||
2632 | + * It opens the physical DPRC in the MC. |
||
2633 | + * It scans the DPRC to discover the MC objects contained in it. |
||
2634 | + * It creates the interrupt pool for the MC bus associated with the DPRC. |
||
2635 | + * It configures the interrupts for the DPRC device itself. |
||
2636 | + */ |
||
2637 | +static int dprc_probe(struct fsl_mc_device *mc_dev) |
||
2638 | +{ |
||
2639 | + int error; |
||
2640 | + size_t region_size; |
||
2641 | + struct device *parent_dev = mc_dev->dev.parent; |
||
2642 | + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); |
||
2643 | + bool mc_io_created = false; |
||
2644 | + bool msi_domain_set = false; |
||
2645 | + u16 major_ver, minor_ver; |
||
2646 | + |
||
2647 | + if (!is_fsl_mc_bus_dprc(mc_dev)) |
||
2648 | + return -EINVAL; |
||
2649 | + |
||
2650 | + if (dev_get_msi_domain(&mc_dev->dev)) |
||
2651 | + return -EINVAL; |
||
2652 | + |
||
2653 | + if (!mc_dev->mc_io) { |
||
2654 | + /* |
||
2655 | + * This is a child DPRC: |
||
2656 | + */ |
||
2657 | + if (!dev_is_fsl_mc(parent_dev)) |
||
2658 | + return -EINVAL; |
||
2659 | + |
||
2660 | + if (mc_dev->obj_desc.region_count == 0) |
||
2661 | + return -EINVAL; |
||
2662 | + |
||
2663 | + region_size = resource_size(mc_dev->regions); |
||
2664 | + |
||
2665 | + error = fsl_create_mc_io(&mc_dev->dev, |
||
2666 | + mc_dev->regions[0].start, |
||
2667 | + region_size, |
||
2668 | + NULL, |
||
2669 | + FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, |
||
2670 | + &mc_dev->mc_io); |
||
2671 | + if (error < 0) |
||
2672 | + return error; |
||
2673 | + |
||
2674 | + mc_io_created = true; |
||
2675 | + |
||
2676 | + /* |
||
2677 | + * Inherit parent MSI domain: |
||
2678 | + */ |
||
2679 | + dev_set_msi_domain(&mc_dev->dev, |
||
2680 | + dev_get_msi_domain(parent_dev)); |
||
2681 | + msi_domain_set = true; |
||
2682 | + } else { |
||
2683 | + /* |
||
2684 | + * This is a root DPRC |
||
2685 | + */ |
||
2686 | + struct irq_domain *mc_msi_domain; |
||
2687 | + |
||
2688 | + if (dev_is_fsl_mc(parent_dev)) |
||
2689 | + return -EINVAL; |
||
2690 | + |
||
2691 | + error = fsl_mc_find_msi_domain(parent_dev, |
||
2692 | + &mc_msi_domain); |
||
2693 | + if (error < 0) { |
||
2694 | + dev_warn(&mc_dev->dev, |
||
2695 | + "WARNING: MC bus without interrupt support\n"); |
||
2696 | + } else { |
||
2697 | + dev_set_msi_domain(&mc_dev->dev, mc_msi_domain); |
||
2698 | + msi_domain_set = true; |
||
2699 | + } |
||
2700 | + } |
||
2701 | + |
||
2702 | + error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id, |
||
2703 | + &mc_dev->mc_handle); |
||
2704 | + if (error < 0) { |
||
2705 | + dev_err(&mc_dev->dev, "dprc_open() failed: %d\n", error); |
||
2706 | + goto error_cleanup_msi_domain; |
||
2707 | + } |
||
2708 | + |
||
2709 | + error = dprc_get_attributes(mc_dev->mc_io, 0, mc_dev->mc_handle, |
||
2710 | + &mc_bus->dprc_attr); |
||
2711 | + if (error < 0) { |
||
2712 | + dev_err(&mc_dev->dev, "dprc_get_attributes() failed: %d\n", |
||
2713 | + error); |
||
2714 | + goto error_cleanup_open; |
||
2715 | + } |
||
2716 | + |
||
2717 | + error = dprc_get_api_version(mc_dev->mc_io, 0, |
||
2718 | + &major_ver, |
||
2719 | + &minor_ver); |
||
2720 | + if (error < 0) { |
||
2721 | + dev_err(&mc_dev->dev, "dprc_get_api_version() failed: %d\n", |
||
2722 | + error); |
||
2723 | + goto error_cleanup_open; |
||
2724 | + } |
||
2725 | + |
||
2726 | + if (major_ver < DPRC_MIN_VER_MAJOR || |
||
2727 | + (major_ver == DPRC_MIN_VER_MAJOR && |
||
2728 | + minor_ver < DPRC_MIN_VER_MINOR)) { |
||
2729 | + dev_err(&mc_dev->dev, |
||
2730 | + "ERROR: DPRC version %d.%d not supported\n", |
||
2731 | + major_ver, minor_ver); |
||
2732 | + error = -ENOTSUPP; |
||
2733 | + goto error_cleanup_open; |
||
2734 | + } |
||
2735 | + |
||
2736 | + mutex_init(&mc_bus->scan_mutex); |
||
2737 | + |
||
2738 | + /* |
||
2739 | + * Discover MC objects in DPRC object: |
||
2740 | + */ |
||
2741 | + error = dprc_scan_container(mc_dev); |
||
2742 | + if (error < 0) |
||
2743 | + goto error_cleanup_open; |
||
2744 | + |
||
2745 | + /* |
||
2746 | + * Configure interrupt for the DPRC object associated with this MC bus: |
||
2747 | + */ |
||
2748 | + error = dprc_setup_irq(mc_dev); |
||
2749 | + if (error < 0) |
||
2750 | + goto error_cleanup_open; |
||
2751 | + |
||
2752 | + dev_info(&mc_dev->dev, "DPRC device bound to driver"); |
||
2753 | + return 0; |
||
2754 | + |
||
2755 | +error_cleanup_open: |
||
2756 | + (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); |
||
2757 | + |
||
2758 | +error_cleanup_msi_domain: |
||
2759 | + if (msi_domain_set) |
||
2760 | + dev_set_msi_domain(&mc_dev->dev, NULL); |
||
2761 | + |
||
2762 | + if (mc_io_created) { |
||
2763 | + fsl_destroy_mc_io(mc_dev->mc_io); |
||
2764 | + mc_dev->mc_io = NULL; |
||
2765 | + } |
||
2766 | + |
||
2767 | + return error; |
||
2768 | +} |
||
2769 | + |
||
2770 | +/* |
||
2771 | + * Tear down interrupt for a given DPRC object |
||
2772 | + */ |
||
2773 | +static void dprc_teardown_irq(struct fsl_mc_device *mc_dev) |
||
2774 | +{ |
||
2775 | + struct fsl_mc_device_irq *irq = mc_dev->irqs[0]; |
||
2776 | + |
||
2777 | + (void)disable_dprc_irq(mc_dev); |
||
2778 | + |
||
2779 | + devm_free_irq(&mc_dev->dev, irq->msi_desc->irq, &mc_dev->dev); |
||
2780 | + |
||
2781 | + fsl_mc_free_irqs(mc_dev); |
||
2782 | +} |
||
2783 | + |
||
2784 | +/** |
||
2785 | + * dprc_remove - callback invoked when a DPRC is being unbound from this driver |
||
2786 | + * |
||
2787 | + * @mc_dev: Pointer to fsl-mc device representing the DPRC |
||
2788 | + * |
||
2789 | + * It removes the DPRC's child objects from Linux (not from the MC) and |
||
2790 | + * closes the DPRC device in the MC. |
||
2791 | + * It tears down the interrupts that were configured for the DPRC device. |
||
2792 | + * It destroys the interrupt pool associated with this MC bus. |
||
2793 | + */ |
||
2794 | +static int dprc_remove(struct fsl_mc_device *mc_dev) |
||
2795 | +{ |
||
2796 | + int error; |
||
2797 | + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); |
||
2798 | + |
||
2799 | + if (!is_fsl_mc_bus_dprc(mc_dev)) |
||
2800 | + return -EINVAL; |
||
2801 | + if (!mc_dev->mc_io) |
||
2802 | + return -EINVAL; |
||
2803 | + |
||
2804 | + if (!mc_bus->irq_resources) |
||
2805 | + return -EINVAL; |
||
2806 | + |
||
2807 | + if (dev_get_msi_domain(&mc_dev->dev)) |
||
2808 | + dprc_teardown_irq(mc_dev); |
||
2809 | + |
||
2810 | + device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove); |
||
2811 | + |
||
2812 | + if (dev_get_msi_domain(&mc_dev->dev)) { |
||
2813 | + fsl_mc_cleanup_irq_pool(mc_bus); |
||
2814 | + dev_set_msi_domain(&mc_dev->dev, NULL); |
||
2815 | + } |
||
2816 | + |
||
2817 | + fsl_mc_cleanup_all_resource_pools(mc_dev); |
||
2818 | + |
||
2819 | + error = dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); |
||
2820 | + if (error < 0) |
||
2821 | + dev_err(&mc_dev->dev, "dprc_close() failed: %d\n", error); |
||
2822 | + |
||
2823 | + if (!fsl_mc_is_root_dprc(&mc_dev->dev)) { |
||
2824 | + fsl_destroy_mc_io(mc_dev->mc_io); |
||
2825 | + mc_dev->mc_io = NULL; |
||
2826 | + } |
||
2827 | + |
||
2828 | + dev_info(&mc_dev->dev, "DPRC device unbound from driver"); |
||
2829 | + return 0; |
||
2830 | +} |
||
2831 | + |
||
2832 | +static const struct fsl_mc_device_id match_id_table[] = { |
||
2833 | + { |
||
2834 | + .vendor = FSL_MC_VENDOR_FREESCALE, |
||
2835 | + .obj_type = "dprc"}, |
||
2836 | + {.vendor = 0x0}, |
||
2837 | +}; |
||
2838 | + |
||
2839 | +static struct fsl_mc_driver dprc_driver = { |
||
2840 | + .driver = { |
||
2841 | + .name = FSL_MC_DPRC_DRIVER_NAME, |
||
2842 | + .owner = THIS_MODULE, |
||
2843 | + .pm = NULL, |
||
2844 | + }, |
||
2845 | + .match_id_table = match_id_table, |
||
2846 | + .probe = dprc_probe, |
||
2847 | + .remove = dprc_remove, |
||
2848 | +}; |
||
2849 | + |
||
2850 | +int __init dprc_driver_init(void) |
||
2851 | +{ |
||
2852 | + return fsl_mc_driver_register(&dprc_driver); |
||
2853 | +} |
||
2854 | + |
||
2855 | +void dprc_driver_exit(void) |
||
2856 | +{ |
||
2857 | + fsl_mc_driver_unregister(&dprc_driver); |
||
2858 | +} |
||
2859 | --- a/drivers/staging/fsl-mc/bus/dprc.c |
||
2860 | +++ /dev/null |
||
2861 | @@ -1,757 +0,0 @@ |
||
2862 | -// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) |
||
2863 | -/* |
||
2864 | - * Copyright 2013-2016 Freescale Semiconductor Inc. |
||
2865 | - * |
||
2866 | - */ |
||
2867 | -#include <linux/kernel.h> |
||
2868 | -#include "../include/mc.h" |
||
2869 | -#include "dprc.h" |
||
2870 | - |
||
2871 | -#include "dprc-cmd.h" |
||
2872 | - |
||
2873 | -/** |
||
2874 | - * dprc_open() - Open DPRC object for use |
||
2875 | - * @mc_io: Pointer to MC portal's I/O object |
||
2876 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
2877 | - * @container_id: Container ID to open |
||
2878 | - * @token: Returned token of DPRC object |
||
2879 | - * |
||
2880 | - * Return: '0' on Success; Error code otherwise. |
||
2881 | - * |
||
2882 | - * @warning Required before any operation on the object. |
||
2883 | - */ |
||
2884 | -int dprc_open(struct fsl_mc_io *mc_io, |
||
2885 | - u32 cmd_flags, |
||
2886 | - int container_id, |
||
2887 | - u16 *token) |
||
2888 | -{ |
||
2889 | - struct mc_command cmd = { 0 }; |
||
2890 | - struct dprc_cmd_open *cmd_params; |
||
2891 | - int err; |
||
2892 | - |
||
2893 | - /* prepare command */ |
||
2894 | - cmd.header = mc_encode_cmd_header(DPRC_CMDID_OPEN, cmd_flags, |
||
2895 | - 0); |
||
2896 | - cmd_params = (struct dprc_cmd_open *)cmd.params; |
||
2897 | - cmd_params->container_id = cpu_to_le32(container_id); |
||
2898 | - |
||
2899 | - /* send command to mc*/ |
||
2900 | - err = mc_send_command(mc_io, &cmd); |
||
2901 | - if (err) |
||
2902 | - return err; |
||
2903 | - |
||
2904 | - /* retrieve response parameters */ |
||
2905 | - *token = mc_cmd_hdr_read_token(&cmd); |
||
2906 | - |
||
2907 | - return 0; |
||
2908 | -} |
||
2909 | -EXPORT_SYMBOL(dprc_open); |
||
2910 | - |
||
2911 | -/** |
||
2912 | - * dprc_close() - Close the control session of the object |
||
2913 | - * @mc_io: Pointer to MC portal's I/O object |
||
2914 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
2915 | - * @token: Token of DPRC object |
||
2916 | - * |
||
2917 | - * After this function is called, no further operations are |
||
2918 | - * allowed on the object without opening a new control session. |
||
2919 | - * |
||
2920 | - * Return: '0' on Success; Error code otherwise. |
||
2921 | - */ |
||
2922 | -int dprc_close(struct fsl_mc_io *mc_io, |
||
2923 | - u32 cmd_flags, |
||
2924 | - u16 token) |
||
2925 | -{ |
||
2926 | - struct mc_command cmd = { 0 }; |
||
2927 | - |
||
2928 | - /* prepare command */ |
||
2929 | - cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLOSE, cmd_flags, |
||
2930 | - token); |
||
2931 | - |
||
2932 | - /* send command to mc*/ |
||
2933 | - return mc_send_command(mc_io, &cmd); |
||
2934 | -} |
||
2935 | -EXPORT_SYMBOL(dprc_close); |
||
2936 | - |
||
2937 | -/** |
||
2938 | - * dprc_get_irq() - Get IRQ information from the DPRC. |
||
2939 | - * @mc_io: Pointer to MC portal's I/O object |
||
2940 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
2941 | - * @token: Token of DPRC object |
||
2942 | - * @irq_index: The interrupt index to configure |
||
2943 | - * @type: Interrupt type: 0 represents message interrupt |
||
2944 | - * type (both irq_addr and irq_val are valid) |
||
2945 | - * @irq_cfg: IRQ attributes |
||
2946 | - * |
||
2947 | - * Return: '0' on Success; Error code otherwise. |
||
2948 | - */ |
||
2949 | -int dprc_get_irq(struct fsl_mc_io *mc_io, |
||
2950 | - u32 cmd_flags, |
||
2951 | - u16 token, |
||
2952 | - u8 irq_index, |
||
2953 | - int *type, |
||
2954 | - struct dprc_irq_cfg *irq_cfg) |
||
2955 | -{ |
||
2956 | - struct mc_command cmd = { 0 }; |
||
2957 | - struct dprc_cmd_get_irq *cmd_params; |
||
2958 | - struct dprc_rsp_get_irq *rsp_params; |
||
2959 | - int err; |
||
2960 | - |
||
2961 | - /* prepare command */ |
||
2962 | - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ, |
||
2963 | - cmd_flags, |
||
2964 | - token); |
||
2965 | - cmd_params = (struct dprc_cmd_get_irq *)cmd.params; |
||
2966 | - cmd_params->irq_index = irq_index; |
||
2967 | - |
||
2968 | - /* send command to mc*/ |
||
2969 | - err = mc_send_command(mc_io, &cmd); |
||
2970 | - if (err) |
||
2971 | - return err; |
||
2972 | - |
||
2973 | - /* retrieve response parameters */ |
||
2974 | - rsp_params = (struct dprc_rsp_get_irq *)cmd.params; |
||
2975 | - irq_cfg->val = le32_to_cpu(rsp_params->irq_val); |
||
2976 | - irq_cfg->paddr = le64_to_cpu(rsp_params->irq_addr); |
||
2977 | - irq_cfg->irq_num = le32_to_cpu(rsp_params->irq_num); |
||
2978 | - *type = le32_to_cpu(rsp_params->type); |
||
2979 | - |
||
2980 | - return 0; |
||
2981 | -} |
||
2982 | - |
||
2983 | -/** |
||
2984 | - * dprc_set_irq() - Set IRQ information for the DPRC to trigger an interrupt. |
||
2985 | - * @mc_io: Pointer to MC portal's I/O object |
||
2986 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
2987 | - * @token: Token of DPRC object |
||
2988 | - * @irq_index: Identifies the interrupt index to configure |
||
2989 | - * @irq_cfg: IRQ configuration |
||
2990 | - * |
||
2991 | - * Return: '0' on Success; Error code otherwise. |
||
2992 | - */ |
||
2993 | -int dprc_set_irq(struct fsl_mc_io *mc_io, |
||
2994 | - u32 cmd_flags, |
||
2995 | - u16 token, |
||
2996 | - u8 irq_index, |
||
2997 | - struct dprc_irq_cfg *irq_cfg) |
||
2998 | -{ |
||
2999 | - struct mc_command cmd = { 0 }; |
||
3000 | - struct dprc_cmd_set_irq *cmd_params; |
||
3001 | - |
||
3002 | - /* prepare command */ |
||
3003 | - cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ, |
||
3004 | - cmd_flags, |
||
3005 | - token); |
||
3006 | - cmd_params = (struct dprc_cmd_set_irq *)cmd.params; |
||
3007 | - cmd_params->irq_val = cpu_to_le32(irq_cfg->val); |
||
3008 | - cmd_params->irq_index = irq_index; |
||
3009 | - cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr); |
||
3010 | - cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num); |
||
3011 | - |
||
3012 | - /* send command to mc*/ |
||
3013 | - return mc_send_command(mc_io, &cmd); |
||
3014 | -} |
||
3015 | - |
||
3016 | -/** |
||
3017 | - * dprc_get_irq_enable() - Get overall interrupt state. |
||
3018 | - * @mc_io: Pointer to MC portal's I/O object |
||
3019 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3020 | - * @token: Token of DPRC object |
||
3021 | - * @irq_index: The interrupt index to configure |
||
3022 | - * @en: Returned interrupt state - enable = 1, disable = 0 |
||
3023 | - * |
||
3024 | - * Return: '0' on Success; Error code otherwise. |
||
3025 | - */ |
||
3026 | -int dprc_get_irq_enable(struct fsl_mc_io *mc_io, |
||
3027 | - u32 cmd_flags, |
||
3028 | - u16 token, |
||
3029 | - u8 irq_index, |
||
3030 | - u8 *en) |
||
3031 | -{ |
||
3032 | - struct mc_command cmd = { 0 }; |
||
3033 | - struct dprc_cmd_get_irq_enable *cmd_params; |
||
3034 | - struct dprc_rsp_get_irq_enable *rsp_params; |
||
3035 | - int err; |
||
3036 | - |
||
3037 | - /* prepare command */ |
||
3038 | - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_ENABLE, |
||
3039 | - cmd_flags, token); |
||
3040 | - cmd_params = (struct dprc_cmd_get_irq_enable *)cmd.params; |
||
3041 | - cmd_params->irq_index = irq_index; |
||
3042 | - |
||
3043 | - /* send command to mc*/ |
||
3044 | - err = mc_send_command(mc_io, &cmd); |
||
3045 | - if (err) |
||
3046 | - return err; |
||
3047 | - |
||
3048 | - /* retrieve response parameters */ |
||
3049 | - rsp_params = (struct dprc_rsp_get_irq_enable *)cmd.params; |
||
3050 | - *en = rsp_params->enabled & DPRC_ENABLE; |
||
3051 | - |
||
3052 | - return 0; |
||
3053 | -} |
||
3054 | - |
||
3055 | -/** |
||
3056 | - * dprc_set_irq_enable() - Set overall interrupt state. |
||
3057 | - * @mc_io: Pointer to MC portal's I/O object |
||
3058 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3059 | - * @token: Token of DPRC object |
||
3060 | - * @irq_index: The interrupt index to configure |
||
3061 | - * @en: Interrupt state - enable = 1, disable = 0 |
||
3062 | - * |
||
3063 | - * Allows GPP software to control when interrupts are generated. |
||
3064 | - * Each interrupt can have up to 32 causes. The enable/disable control's the |
||
3065 | - * overall interrupt state. if the interrupt is disabled no causes will cause |
||
3066 | - * an interrupt. |
||
3067 | - * |
||
3068 | - * Return: '0' on Success; Error code otherwise. |
||
3069 | - */ |
||
3070 | -int dprc_set_irq_enable(struct fsl_mc_io *mc_io, |
||
3071 | - u32 cmd_flags, |
||
3072 | - u16 token, |
||
3073 | - u8 irq_index, |
||
3074 | - u8 en) |
||
3075 | -{ |
||
3076 | - struct mc_command cmd = { 0 }; |
||
3077 | - struct dprc_cmd_set_irq_enable *cmd_params; |
||
3078 | - |
||
3079 | - /* prepare command */ |
||
3080 | - cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_ENABLE, |
||
3081 | - cmd_flags, token); |
||
3082 | - cmd_params = (struct dprc_cmd_set_irq_enable *)cmd.params; |
||
3083 | - cmd_params->enable = en & DPRC_ENABLE; |
||
3084 | - cmd_params->irq_index = irq_index; |
||
3085 | - |
||
3086 | - /* send command to mc*/ |
||
3087 | - return mc_send_command(mc_io, &cmd); |
||
3088 | -} |
||
3089 | - |
||
3090 | -/** |
||
3091 | - * dprc_get_irq_mask() - Get interrupt mask. |
||
3092 | - * @mc_io: Pointer to MC portal's I/O object |
||
3093 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3094 | - * @token: Token of DPRC object |
||
3095 | - * @irq_index: The interrupt index to configure |
||
3096 | - * @mask: Returned event mask to trigger interrupt |
||
3097 | - * |
||
3098 | - * Every interrupt can have up to 32 causes and the interrupt model supports |
||
3099 | - * masking/unmasking each cause independently |
||
3100 | - * |
||
3101 | - * Return: '0' on Success; Error code otherwise. |
||
3102 | - */ |
||
3103 | -int dprc_get_irq_mask(struct fsl_mc_io *mc_io, |
||
3104 | - u32 cmd_flags, |
||
3105 | - u16 token, |
||
3106 | - u8 irq_index, |
||
3107 | - u32 *mask) |
||
3108 | -{ |
||
3109 | - struct mc_command cmd = { 0 }; |
||
3110 | - struct dprc_cmd_get_irq_mask *cmd_params; |
||
3111 | - struct dprc_rsp_get_irq_mask *rsp_params; |
||
3112 | - int err; |
||
3113 | - |
||
3114 | - /* prepare command */ |
||
3115 | - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_MASK, |
||
3116 | - cmd_flags, token); |
||
3117 | - cmd_params = (struct dprc_cmd_get_irq_mask *)cmd.params; |
||
3118 | - cmd_params->irq_index = irq_index; |
||
3119 | - |
||
3120 | - /* send command to mc*/ |
||
3121 | - err = mc_send_command(mc_io, &cmd); |
||
3122 | - if (err) |
||
3123 | - return err; |
||
3124 | - |
||
3125 | - /* retrieve response parameters */ |
||
3126 | - rsp_params = (struct dprc_rsp_get_irq_mask *)cmd.params; |
||
3127 | - *mask = le32_to_cpu(rsp_params->mask); |
||
3128 | - |
||
3129 | - return 0; |
||
3130 | -} |
||
3131 | - |
||
3132 | -/** |
||
3133 | - * dprc_set_irq_mask() - Set interrupt mask. |
||
3134 | - * @mc_io: Pointer to MC portal's I/O object |
||
3135 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3136 | - * @token: Token of DPRC object |
||
3137 | - * @irq_index: The interrupt index to configure |
||
3138 | - * @mask: event mask to trigger interrupt; |
||
3139 | - * each bit: |
||
3140 | - * 0 = ignore event |
||
3141 | - * 1 = consider event for asserting irq |
||
3142 | - * |
||
3143 | - * Every interrupt can have up to 32 causes and the interrupt model supports |
||
3144 | - * masking/unmasking each cause independently |
||
3145 | - * |
||
3146 | - * Return: '0' on Success; Error code otherwise. |
||
3147 | - */ |
||
3148 | -int dprc_set_irq_mask(struct fsl_mc_io *mc_io, |
||
3149 | - u32 cmd_flags, |
||
3150 | - u16 token, |
||
3151 | - u8 irq_index, |
||
3152 | - u32 mask) |
||
3153 | -{ |
||
3154 | - struct mc_command cmd = { 0 }; |
||
3155 | - struct dprc_cmd_set_irq_mask *cmd_params; |
||
3156 | - |
||
3157 | - /* prepare command */ |
||
3158 | - cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_MASK, |
||
3159 | - cmd_flags, token); |
||
3160 | - cmd_params = (struct dprc_cmd_set_irq_mask *)cmd.params; |
||
3161 | - cmd_params->mask = cpu_to_le32(mask); |
||
3162 | - cmd_params->irq_index = irq_index; |
||
3163 | - |
||
3164 | - /* send command to mc*/ |
||
3165 | - return mc_send_command(mc_io, &cmd); |
||
3166 | -} |
||
3167 | - |
||
3168 | -/** |
||
3169 | - * dprc_get_irq_status() - Get the current status of any pending interrupts. |
||
3170 | - * @mc_io: Pointer to MC portal's I/O object |
||
3171 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3172 | - * @token: Token of DPRC object |
||
3173 | - * @irq_index: The interrupt index to configure |
||
3174 | - * @status: Returned interrupts status - one bit per cause: |
||
3175 | - * 0 = no interrupt pending |
||
3176 | - * 1 = interrupt pending |
||
3177 | - * |
||
3178 | - * Return: '0' on Success; Error code otherwise. |
||
3179 | - */ |
||
3180 | -int dprc_get_irq_status(struct fsl_mc_io *mc_io, |
||
3181 | - u32 cmd_flags, |
||
3182 | - u16 token, |
||
3183 | - u8 irq_index, |
||
3184 | - u32 *status) |
||
3185 | -{ |
||
3186 | - struct mc_command cmd = { 0 }; |
||
3187 | - struct dprc_cmd_get_irq_status *cmd_params; |
||
3188 | - struct dprc_rsp_get_irq_status *rsp_params; |
||
3189 | - int err; |
||
3190 | - |
||
3191 | - /* prepare command */ |
||
3192 | - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_STATUS, |
||
3193 | - cmd_flags, token); |
||
3194 | - cmd_params = (struct dprc_cmd_get_irq_status *)cmd.params; |
||
3195 | - cmd_params->status = cpu_to_le32(*status); |
||
3196 | - cmd_params->irq_index = irq_index; |
||
3197 | - |
||
3198 | - /* send command to mc*/ |
||
3199 | - err = mc_send_command(mc_io, &cmd); |
||
3200 | - if (err) |
||
3201 | - return err; |
||
3202 | - |
||
3203 | - /* retrieve response parameters */ |
||
3204 | - rsp_params = (struct dprc_rsp_get_irq_status *)cmd.params; |
||
3205 | - *status = le32_to_cpu(rsp_params->status); |
||
3206 | - |
||
3207 | - return 0; |
||
3208 | -} |
||
3209 | - |
||
3210 | -/** |
||
3211 | - * dprc_clear_irq_status() - Clear a pending interrupt's status |
||
3212 | - * @mc_io: Pointer to MC portal's I/O object |
||
3213 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3214 | - * @token: Token of DPRC object |
||
3215 | - * @irq_index: The interrupt index to configure |
||
3216 | - * @status: bits to clear (W1C) - one bit per cause: |
||
3217 | - * 0 = don't change |
||
3218 | - * 1 = clear status bit |
||
3219 | - * |
||
3220 | - * Return: '0' on Success; Error code otherwise. |
||
3221 | - */ |
||
3222 | -int dprc_clear_irq_status(struct fsl_mc_io *mc_io, |
||
3223 | - u32 cmd_flags, |
||
3224 | - u16 token, |
||
3225 | - u8 irq_index, |
||
3226 | - u32 status) |
||
3227 | -{ |
||
3228 | - struct mc_command cmd = { 0 }; |
||
3229 | - struct dprc_cmd_clear_irq_status *cmd_params; |
||
3230 | - |
||
3231 | - /* prepare command */ |
||
3232 | - cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLEAR_IRQ_STATUS, |
||
3233 | - cmd_flags, token); |
||
3234 | - cmd_params = (struct dprc_cmd_clear_irq_status *)cmd.params; |
||
3235 | - cmd_params->status = cpu_to_le32(status); |
||
3236 | - cmd_params->irq_index = irq_index; |
||
3237 | - |
||
3238 | - /* send command to mc*/ |
||
3239 | - return mc_send_command(mc_io, &cmd); |
||
3240 | -} |
||
3241 | - |
||
3242 | -/** |
||
3243 | - * dprc_get_attributes() - Obtains container attributes |
||
3244 | - * @mc_io: Pointer to MC portal's I/O object |
||
3245 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3246 | - * @token: Token of DPRC object |
||
3247 | - * @attributes Returned container attributes |
||
3248 | - * |
||
3249 | - * Return: '0' on Success; Error code otherwise. |
||
3250 | - */ |
||
3251 | -int dprc_get_attributes(struct fsl_mc_io *mc_io, |
||
3252 | - u32 cmd_flags, |
||
3253 | - u16 token, |
||
3254 | - struct dprc_attributes *attr) |
||
3255 | -{ |
||
3256 | - struct mc_command cmd = { 0 }; |
||
3257 | - struct dprc_rsp_get_attributes *rsp_params; |
||
3258 | - int err; |
||
3259 | - |
||
3260 | - /* prepare command */ |
||
3261 | - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_ATTR, |
||
3262 | - cmd_flags, |
||
3263 | - token); |
||
3264 | - |
||
3265 | - /* send command to mc*/ |
||
3266 | - err = mc_send_command(mc_io, &cmd); |
||
3267 | - if (err) |
||
3268 | - return err; |
||
3269 | - |
||
3270 | - /* retrieve response parameters */ |
||
3271 | - rsp_params = (struct dprc_rsp_get_attributes *)cmd.params; |
||
3272 | - attr->container_id = le32_to_cpu(rsp_params->container_id); |
||
3273 | - attr->icid = le16_to_cpu(rsp_params->icid); |
||
3274 | - attr->options = le32_to_cpu(rsp_params->options); |
||
3275 | - attr->portal_id = le32_to_cpu(rsp_params->portal_id); |
||
3276 | - |
||
3277 | - return 0; |
||
3278 | -} |
||
3279 | - |
||
3280 | -/** |
||
3281 | - * dprc_get_obj_count() - Obtains the number of objects in the DPRC |
||
3282 | - * @mc_io: Pointer to MC portal's I/O object |
||
3283 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3284 | - * @token: Token of DPRC object |
||
3285 | - * @obj_count: Number of objects assigned to the DPRC |
||
3286 | - * |
||
3287 | - * Return: '0' on Success; Error code otherwise. |
||
3288 | - */ |
||
3289 | -int dprc_get_obj_count(struct fsl_mc_io *mc_io, |
||
3290 | - u32 cmd_flags, |
||
3291 | - u16 token, |
||
3292 | - int *obj_count) |
||
3293 | -{ |
||
3294 | - struct mc_command cmd = { 0 }; |
||
3295 | - struct dprc_rsp_get_obj_count *rsp_params; |
||
3296 | - int err; |
||
3297 | - |
||
3298 | - /* prepare command */ |
||
3299 | - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_COUNT, |
||
3300 | - cmd_flags, token); |
||
3301 | - |
||
3302 | - /* send command to mc*/ |
||
3303 | - err = mc_send_command(mc_io, &cmd); |
||
3304 | - if (err) |
||
3305 | - return err; |
||
3306 | - |
||
3307 | - /* retrieve response parameters */ |
||
3308 | - rsp_params = (struct dprc_rsp_get_obj_count *)cmd.params; |
||
3309 | - *obj_count = le32_to_cpu(rsp_params->obj_count); |
||
3310 | - |
||
3311 | - return 0; |
||
3312 | -} |
||
3313 | -EXPORT_SYMBOL(dprc_get_obj_count); |
||
3314 | - |
||
3315 | -/** |
||
3316 | - * dprc_get_obj() - Get general information on an object |
||
3317 | - * @mc_io: Pointer to MC portal's I/O object |
||
3318 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3319 | - * @token: Token of DPRC object |
||
3320 | - * @obj_index: Index of the object to be queried (< obj_count) |
||
3321 | - * @obj_desc: Returns the requested object descriptor |
||
3322 | - * |
||
3323 | - * The object descriptors are retrieved one by one by incrementing |
||
3324 | - * obj_index up to (not including) the value of obj_count returned |
||
3325 | - * from dprc_get_obj_count(). dprc_get_obj_count() must |
||
3326 | - * be called prior to dprc_get_obj(). |
||
3327 | - * |
||
3328 | - * Return: '0' on Success; Error code otherwise. |
||
3329 | - */ |
||
3330 | -int dprc_get_obj(struct fsl_mc_io *mc_io, |
||
3331 | - u32 cmd_flags, |
||
3332 | - u16 token, |
||
3333 | - int obj_index, |
||
3334 | - struct fsl_mc_obj_desc *obj_desc) |
||
3335 | -{ |
||
3336 | - struct mc_command cmd = { 0 }; |
||
3337 | - struct dprc_cmd_get_obj *cmd_params; |
||
3338 | - struct dprc_rsp_get_obj *rsp_params; |
||
3339 | - int err; |
||
3340 | - |
||
3341 | - /* prepare command */ |
||
3342 | - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ, |
||
3343 | - cmd_flags, |
||
3344 | - token); |
||
3345 | - cmd_params = (struct dprc_cmd_get_obj *)cmd.params; |
||
3346 | - cmd_params->obj_index = cpu_to_le32(obj_index); |
||
3347 | - |
||
3348 | - /* send command to mc*/ |
||
3349 | - err = mc_send_command(mc_io, &cmd); |
||
3350 | - if (err) |
||
3351 | - return err; |
||
3352 | - |
||
3353 | - /* retrieve response parameters */ |
||
3354 | - rsp_params = (struct dprc_rsp_get_obj *)cmd.params; |
||
3355 | - obj_desc->id = le32_to_cpu(rsp_params->id); |
||
3356 | - obj_desc->vendor = le16_to_cpu(rsp_params->vendor); |
||
3357 | - obj_desc->irq_count = rsp_params->irq_count; |
||
3358 | - obj_desc->region_count = rsp_params->region_count; |
||
3359 | - obj_desc->state = le32_to_cpu(rsp_params->state); |
||
3360 | - obj_desc->ver_major = le16_to_cpu(rsp_params->version_major); |
||
3361 | - obj_desc->ver_minor = le16_to_cpu(rsp_params->version_minor); |
||
3362 | - obj_desc->flags = le16_to_cpu(rsp_params->flags); |
||
3363 | - strncpy(obj_desc->type, rsp_params->type, 16); |
||
3364 | - obj_desc->type[15] = '\0'; |
||
3365 | - strncpy(obj_desc->label, rsp_params->label, 16); |
||
3366 | - obj_desc->label[15] = '\0'; |
||
3367 | - return 0; |
||
3368 | -} |
||
3369 | -EXPORT_SYMBOL(dprc_get_obj); |
||
3370 | - |
||
3371 | -/** |
||
3372 | - * dprc_set_obj_irq() - Set IRQ information for object to trigger an interrupt. |
||
3373 | - * @mc_io: Pointer to MC portal's I/O object |
||
3374 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3375 | - * @token: Token of DPRC object |
||
3376 | - * @obj_type: Type of the object to set its IRQ |
||
3377 | - * @obj_id: ID of the object to set its IRQ |
||
3378 | - * @irq_index: The interrupt index to configure |
||
3379 | - * @irq_cfg: IRQ configuration |
||
3380 | - * |
||
3381 | - * Return: '0' on Success; Error code otherwise. |
||
3382 | - */ |
||
3383 | -int dprc_set_obj_irq(struct fsl_mc_io *mc_io, |
||
3384 | - u32 cmd_flags, |
||
3385 | - u16 token, |
||
3386 | - char *obj_type, |
||
3387 | - int obj_id, |
||
3388 | - u8 irq_index, |
||
3389 | - struct dprc_irq_cfg *irq_cfg) |
||
3390 | -{ |
||
3391 | - struct mc_command cmd = { 0 }; |
||
3392 | - struct dprc_cmd_set_obj_irq *cmd_params; |
||
3393 | - |
||
3394 | - /* prepare command */ |
||
3395 | - cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_OBJ_IRQ, |
||
3396 | - cmd_flags, |
||
3397 | - token); |
||
3398 | - cmd_params = (struct dprc_cmd_set_obj_irq *)cmd.params; |
||
3399 | - cmd_params->irq_val = cpu_to_le32(irq_cfg->val); |
||
3400 | - cmd_params->irq_index = irq_index; |
||
3401 | - cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr); |
||
3402 | - cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num); |
||
3403 | - cmd_params->obj_id = cpu_to_le32(obj_id); |
||
3404 | - strncpy(cmd_params->obj_type, obj_type, 16); |
||
3405 | - cmd_params->obj_type[15] = '\0'; |
||
3406 | - |
||
3407 | - /* send command to mc*/ |
||
3408 | - return mc_send_command(mc_io, &cmd); |
||
3409 | -} |
||
3410 | -EXPORT_SYMBOL(dprc_set_obj_irq); |
||
3411 | - |
||
3412 | -/** |
||
3413 | - * dprc_get_obj_irq() - Get IRQ information from object. |
||
3414 | - * @mc_io: Pointer to MC portal's I/O object |
||
3415 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3416 | - * @token: Token of DPRC object |
||
3417 | - * @obj_type: Type od the object to get its IRQ |
||
3418 | - * @obj_id: ID of the object to get its IRQ |
||
3419 | - * @irq_index: The interrupt index to configure |
||
3420 | - * @type: Interrupt type: 0 represents message interrupt |
||
3421 | - * type (both irq_addr and irq_val are valid) |
||
3422 | - * @irq_cfg: The returned IRQ attributes |
||
3423 | - * |
||
3424 | - * Return: '0' on Success; Error code otherwise. |
||
3425 | - */ |
||
3426 | -int dprc_get_obj_irq(struct fsl_mc_io *mc_io, |
||
3427 | - u32 cmd_flags, |
||
3428 | - u16 token, |
||
3429 | - char *obj_type, |
||
3430 | - int obj_id, |
||
3431 | - u8 irq_index, |
||
3432 | - int *type, |
||
3433 | - struct dprc_irq_cfg *irq_cfg) |
||
3434 | -{ |
||
3435 | - struct mc_command cmd = { 0 }; |
||
3436 | - struct dprc_cmd_get_obj_irq *cmd_params; |
||
3437 | - struct dprc_rsp_get_obj_irq *rsp_params; |
||
3438 | - int err; |
||
3439 | - |
||
3440 | - /* prepare command */ |
||
3441 | - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_IRQ, |
||
3442 | - cmd_flags, |
||
3443 | - token); |
||
3444 | - cmd_params = (struct dprc_cmd_get_obj_irq *)cmd.params; |
||
3445 | - cmd_params->obj_id = cpu_to_le32(obj_id); |
||
3446 | - cmd_params->irq_index = irq_index; |
||
3447 | - strncpy(cmd_params->obj_type, obj_type, 16); |
||
3448 | - cmd_params->obj_type[15] = '\0'; |
||
3449 | - |
||
3450 | - /* send command to mc*/ |
||
3451 | - err = mc_send_command(mc_io, &cmd); |
||
3452 | - if (err) |
||
3453 | - return err; |
||
3454 | - |
||
3455 | - /* retrieve response parameters */ |
||
3456 | - rsp_params = (struct dprc_rsp_get_obj_irq *)cmd.params; |
||
3457 | - irq_cfg->val = le32_to_cpu(rsp_params->irq_val); |
||
3458 | - irq_cfg->paddr = le64_to_cpu(rsp_params->irq_addr); |
||
3459 | - irq_cfg->irq_num = le32_to_cpu(rsp_params->irq_num); |
||
3460 | - *type = le32_to_cpu(rsp_params->type); |
||
3461 | - |
||
3462 | - return 0; |
||
3463 | -} |
||
3464 | -EXPORT_SYMBOL(dprc_get_obj_irq); |
||
3465 | - |
||
3466 | -/** |
||
3467 | - * dprc_get_res_count() - Obtains the number of free resources that are assigned |
||
3468 | - * to this container, by pool type |
||
3469 | - * @mc_io: Pointer to MC portal's I/O object |
||
3470 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3471 | - * @token: Token of DPRC object |
||
3472 | - * @type: pool type |
||
3473 | - * @res_count: Returned number of free resources of the given |
||
3474 | - * resource type that are assigned to this DPRC |
||
3475 | - * |
||
3476 | - * Return: '0' on Success; Error code otherwise. |
||
3477 | - */ |
||
3478 | -int dprc_get_res_count(struct fsl_mc_io *mc_io, |
||
3479 | - u32 cmd_flags, |
||
3480 | - u16 token, |
||
3481 | - char *type, |
||
3482 | - int *res_count) |
||
3483 | -{ |
||
3484 | - struct mc_command cmd = { 0 }; |
||
3485 | - struct dprc_cmd_get_res_count *cmd_params; |
||
3486 | - struct dprc_rsp_get_res_count *rsp_params; |
||
3487 | - int err; |
||
3488 | - |
||
3489 | - /* prepare command */ |
||
3490 | - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_COUNT, |
||
3491 | - cmd_flags, token); |
||
3492 | - cmd_params = (struct dprc_cmd_get_res_count *)cmd.params; |
||
3493 | - strncpy(cmd_params->type, type, 16); |
||
3494 | - cmd_params->type[15] = '\0'; |
||
3495 | - |
||
3496 | - /* send command to mc*/ |
||
3497 | - err = mc_send_command(mc_io, &cmd); |
||
3498 | - if (err) |
||
3499 | - return err; |
||
3500 | - |
||
3501 | - /* retrieve response parameters */ |
||
3502 | - rsp_params = (struct dprc_rsp_get_res_count *)cmd.params; |
||
3503 | - *res_count = le32_to_cpu(rsp_params->res_count); |
||
3504 | - |
||
3505 | - return 0; |
||
3506 | -} |
||
3507 | -EXPORT_SYMBOL(dprc_get_res_count); |
||
3508 | - |
||
3509 | -/** |
||
3510 | - * dprc_get_obj_region() - Get region information for a specified object. |
||
3511 | - * @mc_io: Pointer to MC portal's I/O object |
||
3512 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3513 | - * @token: Token of DPRC object |
||
3514 | - * @obj_type; Object type as returned in dprc_get_obj() |
||
3515 | - * @obj_id: Unique object instance as returned in dprc_get_obj() |
||
3516 | - * @region_index: The specific region to query |
||
3517 | - * @region_desc: Returns the requested region descriptor |
||
3518 | - * |
||
3519 | - * Return: '0' on Success; Error code otherwise. |
||
3520 | - */ |
||
3521 | -int dprc_get_obj_region(struct fsl_mc_io *mc_io, |
||
3522 | - u32 cmd_flags, |
||
3523 | - u16 token, |
||
3524 | - char *obj_type, |
||
3525 | - int obj_id, |
||
3526 | - u8 region_index, |
||
3527 | - struct dprc_region_desc *region_desc) |
||
3528 | -{ |
||
3529 | - struct mc_command cmd = { 0 }; |
||
3530 | - struct dprc_cmd_get_obj_region *cmd_params; |
||
3531 | - struct dprc_rsp_get_obj_region *rsp_params; |
||
3532 | - int err; |
||
3533 | - |
||
3534 | - /* prepare command */ |
||
3535 | - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG, |
||
3536 | - cmd_flags, token); |
||
3537 | - cmd_params = (struct dprc_cmd_get_obj_region *)cmd.params; |
||
3538 | - cmd_params->obj_id = cpu_to_le32(obj_id); |
||
3539 | - cmd_params->region_index = region_index; |
||
3540 | - strncpy(cmd_params->obj_type, obj_type, 16); |
||
3541 | - cmd_params->obj_type[15] = '\0'; |
||
3542 | - |
||
3543 | - /* send command to mc*/ |
||
3544 | - err = mc_send_command(mc_io, &cmd); |
||
3545 | - if (err) |
||
3546 | - return err; |
||
3547 | - |
||
3548 | - /* retrieve response parameters */ |
||
3549 | - rsp_params = (struct dprc_rsp_get_obj_region *)cmd.params; |
||
3550 | - region_desc->base_offset = le64_to_cpu(rsp_params->base_addr); |
||
3551 | - region_desc->size = le32_to_cpu(rsp_params->size); |
||
3552 | - |
||
3553 | - return 0; |
||
3554 | -} |
||
3555 | -EXPORT_SYMBOL(dprc_get_obj_region); |
||
3556 | - |
||
3557 | -/** |
||
3558 | - * dprc_get_api_version - Get Data Path Resource Container API version |
||
3559 | - * @mc_io: Pointer to Mc portal's I/O object |
||
3560 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3561 | - * @major_ver: Major version of Data Path Resource Container API |
||
3562 | - * @minor_ver: Minor version of Data Path Resource Container API |
||
3563 | - * |
||
3564 | - * Return: '0' on Success; Error code otherwise. |
||
3565 | - */ |
||
3566 | -int dprc_get_api_version(struct fsl_mc_io *mc_io, |
||
3567 | - u32 cmd_flags, |
||
3568 | - u16 *major_ver, |
||
3569 | - u16 *minor_ver) |
||
3570 | -{ |
||
3571 | - struct mc_command cmd = { 0 }; |
||
3572 | - int err; |
||
3573 | - |
||
3574 | - /* prepare command */ |
||
3575 | - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_API_VERSION, |
||
3576 | - cmd_flags, 0); |
||
3577 | - |
||
3578 | - /* send command to mc */ |
||
3579 | - err = mc_send_command(mc_io, &cmd); |
||
3580 | - if (err) |
||
3581 | - return err; |
||
3582 | - |
||
3583 | - /* retrieve response parameters */ |
||
3584 | - mc_cmd_read_api_version(&cmd, major_ver, minor_ver); |
||
3585 | - |
||
3586 | - return 0; |
||
3587 | -} |
||
3588 | - |
||
3589 | -/** |
||
3590 | - * dprc_get_container_id - Get container ID associated with a given portal. |
||
3591 | - * @mc_io: Pointer to Mc portal's I/O object |
||
3592 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3593 | - * @container_id: Requested container id |
||
3594 | - * |
||
3595 | - * Return: '0' on Success; Error code otherwise. |
||
3596 | - */ |
||
3597 | -int dprc_get_container_id(struct fsl_mc_io *mc_io, |
||
3598 | - u32 cmd_flags, |
||
3599 | - int *container_id) |
||
3600 | -{ |
||
3601 | - struct mc_command cmd = { 0 }; |
||
3602 | - int err; |
||
3603 | - |
||
3604 | - /* prepare command */ |
||
3605 | - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONT_ID, |
||
3606 | - cmd_flags, |
||
3607 | - 0); |
||
3608 | - |
||
3609 | - /* send command to mc*/ |
||
3610 | - err = mc_send_command(mc_io, &cmd); |
||
3611 | - if (err) |
||
3612 | - return err; |
||
3613 | - |
||
3614 | - /* retrieve response parameters */ |
||
3615 | - *container_id = (int)mc_cmd_read_object_id(&cmd); |
||
3616 | - |
||
3617 | - return 0; |
||
3618 | -} |
||
3619 | --- /dev/null |
||
3620 | +++ b/drivers/bus/fsl-mc/dprc.c |
||
3621 | @@ -0,0 +1,575 @@ |
||
3622 | +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) |
||
3623 | +/* |
||
3624 | + * Copyright 2013-2016 Freescale Semiconductor Inc. |
||
3625 | + * |
||
3626 | + */ |
||
3627 | +#include <linux/kernel.h> |
||
3628 | +#include <linux/fsl/mc.h> |
||
3629 | + |
||
3630 | +#include "fsl-mc-private.h" |
||
3631 | + |
||
3632 | +/** |
||
3633 | + * dprc_open() - Open DPRC object for use |
||
3634 | + * @mc_io: Pointer to MC portal's I/O object |
||
3635 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3636 | + * @container_id: Container ID to open |
||
3637 | + * @token: Returned token of DPRC object |
||
3638 | + * |
||
3639 | + * Return: '0' on Success; Error code otherwise. |
||
3640 | + * |
||
3641 | + * @warning Required before any operation on the object. |
||
3642 | + */ |
||
3643 | +int dprc_open(struct fsl_mc_io *mc_io, |
||
3644 | + u32 cmd_flags, |
||
3645 | + int container_id, |
||
3646 | + u16 *token) |
||
3647 | +{ |
||
3648 | + struct fsl_mc_command cmd = { 0 }; |
||
3649 | + struct dprc_cmd_open *cmd_params; |
||
3650 | + int err; |
||
3651 | + |
||
3652 | + /* prepare command */ |
||
3653 | + cmd.header = mc_encode_cmd_header(DPRC_CMDID_OPEN, cmd_flags, |
||
3654 | + 0); |
||
3655 | + cmd_params = (struct dprc_cmd_open *)cmd.params; |
||
3656 | + cmd_params->container_id = cpu_to_le32(container_id); |
||
3657 | + |
||
3658 | + /* send command to mc*/ |
||
3659 | + err = mc_send_command(mc_io, &cmd); |
||
3660 | + if (err) |
||
3661 | + return err; |
||
3662 | + |
||
3663 | + /* retrieve response parameters */ |
||
3664 | + *token = mc_cmd_hdr_read_token(&cmd); |
||
3665 | + |
||
3666 | + return 0; |
||
3667 | +} |
||
3668 | +EXPORT_SYMBOL_GPL(dprc_open); |
||
3669 | + |
||
3670 | +/** |
||
3671 | + * dprc_close() - Close the control session of the object |
||
3672 | + * @mc_io: Pointer to MC portal's I/O object |
||
3673 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3674 | + * @token: Token of DPRC object |
||
3675 | + * |
||
3676 | + * After this function is called, no further operations are |
||
3677 | + * allowed on the object without opening a new control session. |
||
3678 | + * |
||
3679 | + * Return: '0' on Success; Error code otherwise. |
||
3680 | + */ |
||
3681 | +int dprc_close(struct fsl_mc_io *mc_io, |
||
3682 | + u32 cmd_flags, |
||
3683 | + u16 token) |
||
3684 | +{ |
||
3685 | + struct fsl_mc_command cmd = { 0 }; |
||
3686 | + |
||
3687 | + /* prepare command */ |
||
3688 | + cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLOSE, cmd_flags, |
||
3689 | + token); |
||
3690 | + |
||
3691 | + /* send command to mc*/ |
||
3692 | + return mc_send_command(mc_io, &cmd); |
||
3693 | +} |
||
3694 | +EXPORT_SYMBOL_GPL(dprc_close); |
||
3695 | + |
||
3696 | +/** |
||
3697 | + * dprc_reset_container - Reset child container. |
||
3698 | + * @mc_io: Pointer to MC portal's I/O object |
||
3699 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3700 | + * @token: Token of DPRC object |
||
3701 | + * @child_container_id: ID of the container to reset |
||
3702 | + * |
||
3703 | + * In case a software context crashes or becomes non-responsive, the parent |
||
3704 | + * may wish to reset its resources container before the software context is |
||
3705 | + * restarted. |
||
3706 | + * |
||
3707 | + * This routine informs all objects assigned to the child container that the |
||
3708 | + * container is being reset, so they may perform any cleanup operations that are |
||
3709 | + * needed. All objects handles that were owned by the child container shall be |
||
3710 | + * closed. |
||
3711 | + * |
||
3712 | + * Note that such request may be submitted even if the child software context |
||
3713 | + * has not crashed, but the resulting object cleanup operations will not be |
||
3714 | + * aware of that. |
||
3715 | + * |
||
3716 | + * Return: '0' on Success; Error code otherwise. |
||
3717 | + */ |
||
3718 | +int dprc_reset_container(struct fsl_mc_io *mc_io, |
||
3719 | + u32 cmd_flags, |
||
3720 | + u16 token, |
||
3721 | + int child_container_id) |
||
3722 | +{ |
||
3723 | + struct fsl_mc_command cmd = { 0 }; |
||
3724 | + struct dprc_cmd_reset_container *cmd_params; |
||
3725 | + |
||
3726 | + /* prepare command */ |
||
3727 | + cmd.header = mc_encode_cmd_header(DPRC_CMDID_RESET_CONT, |
||
3728 | + cmd_flags, token); |
||
3729 | + cmd_params = (struct dprc_cmd_reset_container *)cmd.params; |
||
3730 | + cmd_params->child_container_id = cpu_to_le32(child_container_id); |
||
3731 | + |
||
3732 | + /* send command to mc*/ |
||
3733 | + return mc_send_command(mc_io, &cmd); |
||
3734 | +} |
||
3735 | +EXPORT_SYMBOL_GPL(dprc_reset_container); |
||
3736 | + |
||
3737 | +/** |
||
3738 | + * dprc_set_irq() - Set IRQ information for the DPRC to trigger an interrupt. |
||
3739 | + * @mc_io: Pointer to MC portal's I/O object |
||
3740 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3741 | + * @token: Token of DPRC object |
||
3742 | + * @irq_index: Identifies the interrupt index to configure |
||
3743 | + * @irq_cfg: IRQ configuration |
||
3744 | + * |
||
3745 | + * Return: '0' on Success; Error code otherwise. |
||
3746 | + */ |
||
3747 | +int dprc_set_irq(struct fsl_mc_io *mc_io, |
||
3748 | + u32 cmd_flags, |
||
3749 | + u16 token, |
||
3750 | + u8 irq_index, |
||
3751 | + struct dprc_irq_cfg *irq_cfg) |
||
3752 | +{ |
||
3753 | + struct fsl_mc_command cmd = { 0 }; |
||
3754 | + struct dprc_cmd_set_irq *cmd_params; |
||
3755 | + |
||
3756 | + /* prepare command */ |
||
3757 | + cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ, |
||
3758 | + cmd_flags, |
||
3759 | + token); |
||
3760 | + cmd_params = (struct dprc_cmd_set_irq *)cmd.params; |
||
3761 | + cmd_params->irq_val = cpu_to_le32(irq_cfg->val); |
||
3762 | + cmd_params->irq_index = irq_index; |
||
3763 | + cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr); |
||
3764 | + cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num); |
||
3765 | + |
||
3766 | + /* send command to mc*/ |
||
3767 | + return mc_send_command(mc_io, &cmd); |
||
3768 | +} |
||
3769 | + |
||
3770 | +/** |
||
3771 | + * dprc_set_irq_enable() - Set overall interrupt state. |
||
3772 | + * @mc_io: Pointer to MC portal's I/O object |
||
3773 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3774 | + * @token: Token of DPRC object |
||
3775 | + * @irq_index: The interrupt index to configure |
||
3776 | + * @en: Interrupt state - enable = 1, disable = 0 |
||
3777 | + * |
||
3778 | + * Allows GPP software to control when interrupts are generated. |
||
3779 | + * Each interrupt can have up to 32 causes. The enable/disable control's the |
||
3780 | + * overall interrupt state. if the interrupt is disabled no causes will cause |
||
3781 | + * an interrupt. |
||
3782 | + * |
||
3783 | + * Return: '0' on Success; Error code otherwise. |
||
3784 | + */ |
||
3785 | +int dprc_set_irq_enable(struct fsl_mc_io *mc_io, |
||
3786 | + u32 cmd_flags, |
||
3787 | + u16 token, |
||
3788 | + u8 irq_index, |
||
3789 | + u8 en) |
||
3790 | +{ |
||
3791 | + struct fsl_mc_command cmd = { 0 }; |
||
3792 | + struct dprc_cmd_set_irq_enable *cmd_params; |
||
3793 | + |
||
3794 | + /* prepare command */ |
||
3795 | + cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_ENABLE, |
||
3796 | + cmd_flags, token); |
||
3797 | + cmd_params = (struct dprc_cmd_set_irq_enable *)cmd.params; |
||
3798 | + cmd_params->enable = en & DPRC_ENABLE; |
||
3799 | + cmd_params->irq_index = irq_index; |
||
3800 | + |
||
3801 | + /* send command to mc*/ |
||
3802 | + return mc_send_command(mc_io, &cmd); |
||
3803 | +} |
||
3804 | + |
||
3805 | +/** |
||
3806 | + * dprc_set_irq_mask() - Set interrupt mask. |
||
3807 | + * @mc_io: Pointer to MC portal's I/O object |
||
3808 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3809 | + * @token: Token of DPRC object |
||
3810 | + * @irq_index: The interrupt index to configure |
||
3811 | + * @mask: event mask to trigger interrupt; |
||
3812 | + * each bit: |
||
3813 | + * 0 = ignore event |
||
3814 | + * 1 = consider event for asserting irq |
||
3815 | + * |
||
3816 | + * Every interrupt can have up to 32 causes and the interrupt model supports |
||
3817 | + * masking/unmasking each cause independently |
||
3818 | + * |
||
3819 | + * Return: '0' on Success; Error code otherwise. |
||
3820 | + */ |
||
3821 | +int dprc_set_irq_mask(struct fsl_mc_io *mc_io, |
||
3822 | + u32 cmd_flags, |
||
3823 | + u16 token, |
||
3824 | + u8 irq_index, |
||
3825 | + u32 mask) |
||
3826 | +{ |
||
3827 | + struct fsl_mc_command cmd = { 0 }; |
||
3828 | + struct dprc_cmd_set_irq_mask *cmd_params; |
||
3829 | + |
||
3830 | + /* prepare command */ |
||
3831 | + cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_MASK, |
||
3832 | + cmd_flags, token); |
||
3833 | + cmd_params = (struct dprc_cmd_set_irq_mask *)cmd.params; |
||
3834 | + cmd_params->mask = cpu_to_le32(mask); |
||
3835 | + cmd_params->irq_index = irq_index; |
||
3836 | + |
||
3837 | + /* send command to mc*/ |
||
3838 | + return mc_send_command(mc_io, &cmd); |
||
3839 | +} |
||
3840 | + |
||
3841 | +/** |
||
3842 | + * dprc_get_irq_status() - Get the current status of any pending interrupts. |
||
3843 | + * @mc_io: Pointer to MC portal's I/O object |
||
3844 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3845 | + * @token: Token of DPRC object |
||
3846 | + * @irq_index: The interrupt index to configure |
||
3847 | + * @status: Returned interrupts status - one bit per cause: |
||
3848 | + * 0 = no interrupt pending |
||
3849 | + * 1 = interrupt pending |
||
3850 | + * |
||
3851 | + * Return: '0' on Success; Error code otherwise. |
||
3852 | + */ |
||
3853 | +int dprc_get_irq_status(struct fsl_mc_io *mc_io, |
||
3854 | + u32 cmd_flags, |
||
3855 | + u16 token, |
||
3856 | + u8 irq_index, |
||
3857 | + u32 *status) |
||
3858 | +{ |
||
3859 | + struct fsl_mc_command cmd = { 0 }; |
||
3860 | + struct dprc_cmd_get_irq_status *cmd_params; |
||
3861 | + struct dprc_rsp_get_irq_status *rsp_params; |
||
3862 | + int err; |
||
3863 | + |
||
3864 | + /* prepare command */ |
||
3865 | + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_STATUS, |
||
3866 | + cmd_flags, token); |
||
3867 | + cmd_params = (struct dprc_cmd_get_irq_status *)cmd.params; |
||
3868 | + cmd_params->status = cpu_to_le32(*status); |
||
3869 | + cmd_params->irq_index = irq_index; |
||
3870 | + |
||
3871 | + /* send command to mc*/ |
||
3872 | + err = mc_send_command(mc_io, &cmd); |
||
3873 | + if (err) |
||
3874 | + return err; |
||
3875 | + |
||
3876 | + /* retrieve response parameters */ |
||
3877 | + rsp_params = (struct dprc_rsp_get_irq_status *)cmd.params; |
||
3878 | + *status = le32_to_cpu(rsp_params->status); |
||
3879 | + |
||
3880 | + return 0; |
||
3881 | +} |
||
3882 | + |
||
3883 | +/** |
||
3884 | + * dprc_clear_irq_status() - Clear a pending interrupt's status |
||
3885 | + * @mc_io: Pointer to MC portal's I/O object |
||
3886 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3887 | + * @token: Token of DPRC object |
||
3888 | + * @irq_index: The interrupt index to configure |
||
3889 | + * @status: bits to clear (W1C) - one bit per cause: |
||
3890 | + * 0 = don't change |
||
3891 | + * 1 = clear status bit |
||
3892 | + * |
||
3893 | + * Return: '0' on Success; Error code otherwise. |
||
3894 | + */ |
||
3895 | +int dprc_clear_irq_status(struct fsl_mc_io *mc_io, |
||
3896 | + u32 cmd_flags, |
||
3897 | + u16 token, |
||
3898 | + u8 irq_index, |
||
3899 | + u32 status) |
||
3900 | +{ |
||
3901 | + struct fsl_mc_command cmd = { 0 }; |
||
3902 | + struct dprc_cmd_clear_irq_status *cmd_params; |
||
3903 | + |
||
3904 | + /* prepare command */ |
||
3905 | + cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLEAR_IRQ_STATUS, |
||
3906 | + cmd_flags, token); |
||
3907 | + cmd_params = (struct dprc_cmd_clear_irq_status *)cmd.params; |
||
3908 | + cmd_params->status = cpu_to_le32(status); |
||
3909 | + cmd_params->irq_index = irq_index; |
||
3910 | + |
||
3911 | + /* send command to mc*/ |
||
3912 | + return mc_send_command(mc_io, &cmd); |
||
3913 | +} |
||
3914 | + |
||
3915 | +/** |
||
3916 | + * dprc_get_attributes() - Obtains container attributes |
||
3917 | + * @mc_io: Pointer to MC portal's I/O object |
||
3918 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3919 | + * @token: Token of DPRC object |
||
3920 | + * @attributes Returned container attributes |
||
3921 | + * |
||
3922 | + * Return: '0' on Success; Error code otherwise. |
||
3923 | + */ |
||
3924 | +int dprc_get_attributes(struct fsl_mc_io *mc_io, |
||
3925 | + u32 cmd_flags, |
||
3926 | + u16 token, |
||
3927 | + struct dprc_attributes *attr) |
||
3928 | +{ |
||
3929 | + struct fsl_mc_command cmd = { 0 }; |
||
3930 | + struct dprc_rsp_get_attributes *rsp_params; |
||
3931 | + int err; |
||
3932 | + |
||
3933 | + /* prepare command */ |
||
3934 | + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_ATTR, |
||
3935 | + cmd_flags, |
||
3936 | + token); |
||
3937 | + |
||
3938 | + /* send command to mc*/ |
||
3939 | + err = mc_send_command(mc_io, &cmd); |
||
3940 | + if (err) |
||
3941 | + return err; |
||
3942 | + |
||
3943 | + /* retrieve response parameters */ |
||
3944 | + rsp_params = (struct dprc_rsp_get_attributes *)cmd.params; |
||
3945 | + attr->container_id = le32_to_cpu(rsp_params->container_id); |
||
3946 | + attr->icid = le32_to_cpu(rsp_params->icid); |
||
3947 | + attr->options = le32_to_cpu(rsp_params->options); |
||
3948 | + attr->portal_id = le32_to_cpu(rsp_params->portal_id); |
||
3949 | + |
||
3950 | + return 0; |
||
3951 | +} |
||
3952 | + |
||
3953 | +/** |
||
3954 | + * dprc_get_obj_count() - Obtains the number of objects in the DPRC |
||
3955 | + * @mc_io: Pointer to MC portal's I/O object |
||
3956 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3957 | + * @token: Token of DPRC object |
||
3958 | + * @obj_count: Number of objects assigned to the DPRC |
||
3959 | + * |
||
3960 | + * Return: '0' on Success; Error code otherwise. |
||
3961 | + */ |
||
3962 | +int dprc_get_obj_count(struct fsl_mc_io *mc_io, |
||
3963 | + u32 cmd_flags, |
||
3964 | + u16 token, |
||
3965 | + int *obj_count) |
||
3966 | +{ |
||
3967 | + struct fsl_mc_command cmd = { 0 }; |
||
3968 | + struct dprc_rsp_get_obj_count *rsp_params; |
||
3969 | + int err; |
||
3970 | + |
||
3971 | + /* prepare command */ |
||
3972 | + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_COUNT, |
||
3973 | + cmd_flags, token); |
||
3974 | + |
||
3975 | + /* send command to mc*/ |
||
3976 | + err = mc_send_command(mc_io, &cmd); |
||
3977 | + if (err) |
||
3978 | + return err; |
||
3979 | + |
||
3980 | + /* retrieve response parameters */ |
||
3981 | + rsp_params = (struct dprc_rsp_get_obj_count *)cmd.params; |
||
3982 | + *obj_count = le32_to_cpu(rsp_params->obj_count); |
||
3983 | + |
||
3984 | + return 0; |
||
3985 | +} |
||
3986 | +EXPORT_SYMBOL_GPL(dprc_get_obj_count); |
||
3987 | + |
||
3988 | +/** |
||
3989 | + * dprc_get_obj() - Get general information on an object |
||
3990 | + * @mc_io: Pointer to MC portal's I/O object |
||
3991 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
3992 | + * @token: Token of DPRC object |
||
3993 | + * @obj_index: Index of the object to be queried (< obj_count) |
||
3994 | + * @obj_desc: Returns the requested object descriptor |
||
3995 | + * |
||
3996 | + * The object descriptors are retrieved one by one by incrementing |
||
3997 | + * obj_index up to (not including) the value of obj_count returned |
||
3998 | + * from dprc_get_obj_count(). dprc_get_obj_count() must |
||
3999 | + * be called prior to dprc_get_obj(). |
||
4000 | + * |
||
4001 | + * Return: '0' on Success; Error code otherwise. |
||
4002 | + */ |
||
4003 | +int dprc_get_obj(struct fsl_mc_io *mc_io, |
||
4004 | + u32 cmd_flags, |
||
4005 | + u16 token, |
||
4006 | + int obj_index, |
||
4007 | + struct fsl_mc_obj_desc *obj_desc) |
||
4008 | +{ |
||
4009 | + struct fsl_mc_command cmd = { 0 }; |
||
4010 | + struct dprc_cmd_get_obj *cmd_params; |
||
4011 | + struct dprc_rsp_get_obj *rsp_params; |
||
4012 | + int err; |
||
4013 | + |
||
4014 | + /* prepare command */ |
||
4015 | + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ, |
||
4016 | + cmd_flags, |
||
4017 | + token); |
||
4018 | + cmd_params = (struct dprc_cmd_get_obj *)cmd.params; |
||
4019 | + cmd_params->obj_index = cpu_to_le32(obj_index); |
||
4020 | + |
||
4021 | + /* send command to mc*/ |
||
4022 | + err = mc_send_command(mc_io, &cmd); |
||
4023 | + if (err) |
||
4024 | + return err; |
||
4025 | + |
||
4026 | + /* retrieve response parameters */ |
||
4027 | + rsp_params = (struct dprc_rsp_get_obj *)cmd.params; |
||
4028 | + obj_desc->id = le32_to_cpu(rsp_params->id); |
||
4029 | + obj_desc->vendor = le16_to_cpu(rsp_params->vendor); |
||
4030 | + obj_desc->irq_count = rsp_params->irq_count; |
||
4031 | + obj_desc->region_count = rsp_params->region_count; |
||
4032 | + obj_desc->state = le32_to_cpu(rsp_params->state); |
||
4033 | + obj_desc->ver_major = le16_to_cpu(rsp_params->version_major); |
||
4034 | + obj_desc->ver_minor = le16_to_cpu(rsp_params->version_minor); |
||
4035 | + obj_desc->flags = le16_to_cpu(rsp_params->flags); |
||
4036 | + strncpy(obj_desc->type, rsp_params->type, 16); |
||
4037 | + obj_desc->type[15] = '\0'; |
||
4038 | + strncpy(obj_desc->label, rsp_params->label, 16); |
||
4039 | + obj_desc->label[15] = '\0'; |
||
4040 | + return 0; |
||
4041 | +} |
||
4042 | +EXPORT_SYMBOL_GPL(dprc_get_obj); |
||
4043 | + |
||
4044 | +/** |
||
4045 | + * dprc_set_obj_irq() - Set IRQ information for object to trigger an interrupt. |
||
4046 | + * @mc_io: Pointer to MC portal's I/O object |
||
4047 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
4048 | + * @token: Token of DPRC object |
||
4049 | + * @obj_type: Type of the object to set its IRQ |
||
4050 | + * @obj_id: ID of the object to set its IRQ |
||
4051 | + * @irq_index: The interrupt index to configure |
||
4052 | + * @irq_cfg: IRQ configuration |
||
4053 | + * |
||
4054 | + * Return: '0' on Success; Error code otherwise. |
||
4055 | + */ |
||
4056 | +int dprc_set_obj_irq(struct fsl_mc_io *mc_io, |
||
4057 | + u32 cmd_flags, |
||
4058 | + u16 token, |
||
4059 | + char *obj_type, |
||
4060 | + int obj_id, |
||
4061 | + u8 irq_index, |
||
4062 | + struct dprc_irq_cfg *irq_cfg) |
||
4063 | +{ |
||
4064 | + struct fsl_mc_command cmd = { 0 }; |
||
4065 | + struct dprc_cmd_set_obj_irq *cmd_params; |
||
4066 | + |
||
4067 | + /* prepare command */ |
||
4068 | + cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_OBJ_IRQ, |
||
4069 | + cmd_flags, |
||
4070 | + token); |
||
4071 | + cmd_params = (struct dprc_cmd_set_obj_irq *)cmd.params; |
||
4072 | + cmd_params->irq_val = cpu_to_le32(irq_cfg->val); |
||
4073 | + cmd_params->irq_index = irq_index; |
||
4074 | + cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr); |
||
4075 | + cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num); |
||
4076 | + cmd_params->obj_id = cpu_to_le32(obj_id); |
||
4077 | + strncpy(cmd_params->obj_type, obj_type, 16); |
||
4078 | + cmd_params->obj_type[15] = '\0'; |
||
4079 | + |
||
4080 | + /* send command to mc*/ |
||
4081 | + return mc_send_command(mc_io, &cmd); |
||
4082 | +} |
||
4083 | +EXPORT_SYMBOL_GPL(dprc_set_obj_irq); |
||
4084 | + |
||
4085 | +/** |
||
4086 | + * dprc_get_obj_region() - Get region information for a specified object. |
||
4087 | + * @mc_io: Pointer to MC portal's I/O object |
||
4088 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
4089 | + * @token: Token of DPRC object |
||
4090 | + * @obj_type; Object type as returned in dprc_get_obj() |
||
4091 | + * @obj_id: Unique object instance as returned in dprc_get_obj() |
||
4092 | + * @region_index: The specific region to query |
||
4093 | + * @region_desc: Returns the requested region descriptor |
||
4094 | + * |
||
4095 | + * Return: '0' on Success; Error code otherwise. |
||
4096 | + */ |
||
4097 | +int dprc_get_obj_region(struct fsl_mc_io *mc_io, |
||
4098 | + u32 cmd_flags, |
||
4099 | + u16 token, |
||
4100 | + char *obj_type, |
||
4101 | + int obj_id, |
||
4102 | + u8 region_index, |
||
4103 | + struct dprc_region_desc *region_desc) |
||
4104 | +{ |
||
4105 | + struct fsl_mc_command cmd = { 0 }; |
||
4106 | + struct dprc_cmd_get_obj_region *cmd_params; |
||
4107 | + struct dprc_rsp_get_obj_region *rsp_params; |
||
4108 | + int err; |
||
4109 | + |
||
4110 | + /* prepare command */ |
||
4111 | + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG, |
||
4112 | + cmd_flags, token); |
||
4113 | + cmd_params = (struct dprc_cmd_get_obj_region *)cmd.params; |
||
4114 | + cmd_params->obj_id = cpu_to_le32(obj_id); |
||
4115 | + cmd_params->region_index = region_index; |
||
4116 | + strncpy(cmd_params->obj_type, obj_type, 16); |
||
4117 | + cmd_params->obj_type[15] = '\0'; |
||
4118 | + |
||
4119 | + /* send command to mc*/ |
||
4120 | + err = mc_send_command(mc_io, &cmd); |
||
4121 | + if (err) |
||
4122 | + return err; |
||
4123 | + |
||
4124 | + /* retrieve response parameters */ |
||
4125 | + rsp_params = (struct dprc_rsp_get_obj_region *)cmd.params; |
||
4126 | + region_desc->base_offset = le32_to_cpu(rsp_params->base_addr); |
||
4127 | + region_desc->size = le32_to_cpu(rsp_params->size); |
||
4128 | + region_desc->type = rsp_params->type; |
||
4129 | + region_desc->flags = le32_to_cpu(rsp_params->flags); |
||
4130 | + |
||
4131 | + return 0; |
||
4132 | +} |
||
4133 | +EXPORT_SYMBOL_GPL(dprc_get_obj_region); |
||
4134 | + |
||
4135 | +/** |
||
4136 | + * dprc_get_api_version - Get Data Path Resource Container API version |
||
4137 | + * @mc_io: Pointer to Mc portal's I/O object |
||
4138 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
4139 | + * @major_ver: Major version of Data Path Resource Container API |
||
4140 | + * @minor_ver: Minor version of Data Path Resource Container API |
||
4141 | + * |
||
4142 | + * Return: '0' on Success; Error code otherwise. |
||
4143 | + */ |
||
4144 | +int dprc_get_api_version(struct fsl_mc_io *mc_io, |
||
4145 | + u32 cmd_flags, |
||
4146 | + u16 *major_ver, |
||
4147 | + u16 *minor_ver) |
||
4148 | +{ |
||
4149 | + struct fsl_mc_command cmd = { 0 }; |
||
4150 | + int err; |
||
4151 | + |
||
4152 | + /* prepare command */ |
||
4153 | + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_API_VERSION, |
||
4154 | + cmd_flags, 0); |
||
4155 | + |
||
4156 | + /* send command to mc */ |
||
4157 | + err = mc_send_command(mc_io, &cmd); |
||
4158 | + if (err) |
||
4159 | + return err; |
||
4160 | + |
||
4161 | + /* retrieve response parameters */ |
||
4162 | + mc_cmd_read_api_version(&cmd, major_ver, minor_ver); |
||
4163 | + |
||
4164 | + return 0; |
||
4165 | +} |
||
4166 | + |
||
4167 | +/** |
||
4168 | + * dprc_get_container_id - Get container ID associated with a given portal. |
||
4169 | + * @mc_io: Pointer to Mc portal's I/O object |
||
4170 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
4171 | + * @container_id: Requested container id |
||
4172 | + * |
||
4173 | + * Return: '0' on Success; Error code otherwise. |
||
4174 | + */ |
||
4175 | +int dprc_get_container_id(struct fsl_mc_io *mc_io, |
||
4176 | + u32 cmd_flags, |
||
4177 | + int *container_id) |
||
4178 | +{ |
||
4179 | + struct fsl_mc_command cmd = { 0 }; |
||
4180 | + int err; |
||
4181 | + |
||
4182 | + /* prepare command */ |
||
4183 | + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONT_ID, |
||
4184 | + cmd_flags, |
||
4185 | + 0); |
||
4186 | + |
||
4187 | + /* send command to mc*/ |
||
4188 | + err = mc_send_command(mc_io, &cmd); |
||
4189 | + if (err) |
||
4190 | + return err; |
||
4191 | + |
||
4192 | + /* retrieve response parameters */ |
||
4193 | + *container_id = (int)mc_cmd_read_object_id(&cmd); |
||
4194 | + |
||
4195 | + return 0; |
||
4196 | +} |
||
4197 | --- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c |
||
4198 | +++ /dev/null |
||
4199 | @@ -1,663 +0,0 @@ |
||
4200 | -// SPDX-License-Identifier: GPL-2.0 |
||
4201 | -/* |
||
4202 | - * fsl-mc object allocator driver |
||
4203 | - * |
||
4204 | - * Copyright (C) 2013-2016 Freescale Semiconductor, Inc. |
||
4205 | - * |
||
4206 | - */ |
||
4207 | - |
||
4208 | -#include <linux/module.h> |
||
4209 | -#include <linux/msi.h> |
||
4210 | -#include "../include/mc.h" |
||
4211 | - |
||
4212 | -#include "fsl-mc-private.h" |
||
4213 | - |
||
4214 | -static bool __must_check fsl_mc_is_allocatable(const char *obj_type) |
||
4215 | -{ |
||
4216 | - return strcmp(obj_type, "dpbp") == 0 || |
||
4217 | - strcmp(obj_type, "dpmcp") == 0 || |
||
4218 | - strcmp(obj_type, "dpcon") == 0; |
||
4219 | -} |
||
4220 | - |
||
4221 | -/** |
||
4222 | - * fsl_mc_resource_pool_add_device - add allocatable object to a resource |
||
4223 | - * pool of a given fsl-mc bus |
||
4224 | - * |
||
4225 | - * @mc_bus: pointer to the fsl-mc bus |
||
4226 | - * @pool_type: pool type |
||
4227 | - * @mc_dev: pointer to allocatable fsl-mc device |
||
4228 | - */ |
||
4229 | -static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus |
||
4230 | - *mc_bus, |
||
4231 | - enum fsl_mc_pool_type |
||
4232 | - pool_type, |
||
4233 | - struct fsl_mc_device |
||
4234 | - *mc_dev) |
||
4235 | -{ |
||
4236 | - struct fsl_mc_resource_pool *res_pool; |
||
4237 | - struct fsl_mc_resource *resource; |
||
4238 | - struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; |
||
4239 | - int error = -EINVAL; |
||
4240 | - |
||
4241 | - if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)) |
||
4242 | - goto out; |
||
4243 | - if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type))) |
||
4244 | - goto out; |
||
4245 | - if (WARN_ON(mc_dev->resource)) |
||
4246 | - goto out; |
||
4247 | - |
||
4248 | - res_pool = &mc_bus->resource_pools[pool_type]; |
||
4249 | - if (WARN_ON(res_pool->type != pool_type)) |
||
4250 | - goto out; |
||
4251 | - if (WARN_ON(res_pool->mc_bus != mc_bus)) |
||
4252 | - goto out; |
||
4253 | - |
||
4254 | - mutex_lock(&res_pool->mutex); |
||
4255 | - |
||
4256 | - if (WARN_ON(res_pool->max_count < 0)) |
||
4257 | - goto out_unlock; |
||
4258 | - if (WARN_ON(res_pool->free_count < 0 || |
||
4259 | - res_pool->free_count > res_pool->max_count)) |
||
4260 | - goto out_unlock; |
||
4261 | - |
||
4262 | - resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource), |
||
4263 | - GFP_KERNEL); |
||
4264 | - if (!resource) { |
||
4265 | - error = -ENOMEM; |
||
4266 | - dev_err(&mc_bus_dev->dev, |
||
4267 | - "Failed to allocate memory for fsl_mc_resource\n"); |
||
4268 | - goto out_unlock; |
||
4269 | - } |
||
4270 | - |
||
4271 | - resource->type = pool_type; |
||
4272 | - resource->id = mc_dev->obj_desc.id; |
||
4273 | - resource->data = mc_dev; |
||
4274 | - resource->parent_pool = res_pool; |
||
4275 | - INIT_LIST_HEAD(&resource->node); |
||
4276 | - list_add_tail(&resource->node, &res_pool->free_list); |
||
4277 | - mc_dev->resource = resource; |
||
4278 | - res_pool->free_count++; |
||
4279 | - res_pool->max_count++; |
||
4280 | - error = 0; |
||
4281 | -out_unlock: |
||
4282 | - mutex_unlock(&res_pool->mutex); |
||
4283 | -out: |
||
4284 | - return error; |
||
4285 | -} |
||
4286 | - |
||
4287 | -/** |
||
4288 | - * fsl_mc_resource_pool_remove_device - remove an allocatable device from a |
||
4289 | - * resource pool |
||
4290 | - * |
||
4291 | - * @mc_dev: pointer to allocatable fsl-mc device |
||
4292 | - * |
||
4293 | - * It permanently removes an allocatable fsl-mc device from the resource |
||
4294 | - * pool. It's an error if the device is in use. |
||
4295 | - */ |
||
4296 | -static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device |
||
4297 | - *mc_dev) |
||
4298 | -{ |
||
4299 | - struct fsl_mc_device *mc_bus_dev; |
||
4300 | - struct fsl_mc_bus *mc_bus; |
||
4301 | - struct fsl_mc_resource_pool *res_pool; |
||
4302 | - struct fsl_mc_resource *resource; |
||
4303 | - int error = -EINVAL; |
||
4304 | - |
||
4305 | - if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type))) |
||
4306 | - goto out; |
||
4307 | - |
||
4308 | - resource = mc_dev->resource; |
||
4309 | - if (WARN_ON(!resource || resource->data != mc_dev)) |
||
4310 | - goto out; |
||
4311 | - |
||
4312 | - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); |
||
4313 | - mc_bus = to_fsl_mc_bus(mc_bus_dev); |
||
4314 | - res_pool = resource->parent_pool; |
||
4315 | - if (WARN_ON(res_pool != &mc_bus->resource_pools[resource->type])) |
||
4316 | - goto out; |
||
4317 | - |
||
4318 | - mutex_lock(&res_pool->mutex); |
||
4319 | - |
||
4320 | - if (WARN_ON(res_pool->max_count <= 0)) |
||
4321 | - goto out_unlock; |
||
4322 | - if (WARN_ON(res_pool->free_count <= 0 || |
||
4323 | - res_pool->free_count > res_pool->max_count)) |
||
4324 | - goto out_unlock; |
||
4325 | - |
||
4326 | - /* |
||
4327 | - * If the device is currently allocated, its resource is not |
||
4328 | - * in the free list and thus, the device cannot be removed. |
||
4329 | - */ |
||
4330 | - if (list_empty(&resource->node)) { |
||
4331 | - error = -EBUSY; |
||
4332 | - dev_err(&mc_bus_dev->dev, |
||
4333 | - "Device %s cannot be removed from resource pool\n", |
||
4334 | - dev_name(&mc_dev->dev)); |
||
4335 | - goto out_unlock; |
||
4336 | - } |
||
4337 | - |
||
4338 | - list_del_init(&resource->node); |
||
4339 | - res_pool->free_count--; |
||
4340 | - res_pool->max_count--; |
||
4341 | - |
||
4342 | - devm_kfree(&mc_bus_dev->dev, resource); |
||
4343 | - mc_dev->resource = NULL; |
||
4344 | - error = 0; |
||
4345 | -out_unlock: |
||
4346 | - mutex_unlock(&res_pool->mutex); |
||
4347 | -out: |
||
4348 | - return error; |
||
4349 | -} |
||
4350 | - |
||
4351 | -static const char *const fsl_mc_pool_type_strings[] = { |
||
4352 | - [FSL_MC_POOL_DPMCP] = "dpmcp", |
||
4353 | - [FSL_MC_POOL_DPBP] = "dpbp", |
||
4354 | - [FSL_MC_POOL_DPCON] = "dpcon", |
||
4355 | - [FSL_MC_POOL_IRQ] = "irq", |
||
4356 | -}; |
||
4357 | - |
||
4358 | -static int __must_check object_type_to_pool_type(const char *object_type, |
||
4359 | - enum fsl_mc_pool_type |
||
4360 | - *pool_type) |
||
4361 | -{ |
||
4362 | - unsigned int i; |
||
4363 | - |
||
4364 | - for (i = 0; i < ARRAY_SIZE(fsl_mc_pool_type_strings); i++) { |
||
4365 | - if (strcmp(object_type, fsl_mc_pool_type_strings[i]) == 0) { |
||
4366 | - *pool_type = i; |
||
4367 | - return 0; |
||
4368 | - } |
||
4369 | - } |
||
4370 | - |
||
4371 | - return -EINVAL; |
||
4372 | -} |
||
4373 | - |
||
4374 | -int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, |
||
4375 | - enum fsl_mc_pool_type pool_type, |
||
4376 | - struct fsl_mc_resource **new_resource) |
||
4377 | -{ |
||
4378 | - struct fsl_mc_resource_pool *res_pool; |
||
4379 | - struct fsl_mc_resource *resource; |
||
4380 | - struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; |
||
4381 | - int error = -EINVAL; |
||
4382 | - |
||
4383 | - BUILD_BUG_ON(ARRAY_SIZE(fsl_mc_pool_type_strings) != |
||
4384 | - FSL_MC_NUM_POOL_TYPES); |
||
4385 | - |
||
4386 | - *new_resource = NULL; |
||
4387 | - if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)) |
||
4388 | - goto out; |
||
4389 | - |
||
4390 | - res_pool = &mc_bus->resource_pools[pool_type]; |
||
4391 | - if (WARN_ON(res_pool->mc_bus != mc_bus)) |
||
4392 | - goto out; |
||
4393 | - |
||
4394 | - mutex_lock(&res_pool->mutex); |
||
4395 | - resource = list_first_entry_or_null(&res_pool->free_list, |
||
4396 | - struct fsl_mc_resource, node); |
||
4397 | - |
||
4398 | - if (!resource) { |
||
4399 | - WARN_ON(res_pool->free_count != 0); |
||
4400 | - error = -ENXIO; |
||
4401 | - dev_err(&mc_bus_dev->dev, |
||
4402 | - "No more resources of type %s left\n", |
||
4403 | - fsl_mc_pool_type_strings[pool_type]); |
||
4404 | - goto out_unlock; |
||
4405 | - } |
||
4406 | - |
||
4407 | - if (WARN_ON(resource->type != pool_type)) |
||
4408 | - goto out_unlock; |
||
4409 | - if (WARN_ON(resource->parent_pool != res_pool)) |
||
4410 | - goto out_unlock; |
||
4411 | - if (WARN_ON(res_pool->free_count <= 0 || |
||
4412 | - res_pool->free_count > res_pool->max_count)) |
||
4413 | - goto out_unlock; |
||
4414 | - |
||
4415 | - list_del_init(&resource->node); |
||
4416 | - |
||
4417 | - res_pool->free_count--; |
||
4418 | - error = 0; |
||
4419 | -out_unlock: |
||
4420 | - mutex_unlock(&res_pool->mutex); |
||
4421 | - *new_resource = resource; |
||
4422 | -out: |
||
4423 | - return error; |
||
4424 | -} |
||
4425 | -EXPORT_SYMBOL_GPL(fsl_mc_resource_allocate); |
||
4426 | - |
||
4427 | -void fsl_mc_resource_free(struct fsl_mc_resource *resource) |
||
4428 | -{ |
||
4429 | - struct fsl_mc_resource_pool *res_pool; |
||
4430 | - |
||
4431 | - res_pool = resource->parent_pool; |
||
4432 | - if (WARN_ON(resource->type != res_pool->type)) |
||
4433 | - return; |
||
4434 | - |
||
4435 | - mutex_lock(&res_pool->mutex); |
||
4436 | - if (WARN_ON(res_pool->free_count < 0 || |
||
4437 | - res_pool->free_count >= res_pool->max_count)) |
||
4438 | - goto out_unlock; |
||
4439 | - |
||
4440 | - if (WARN_ON(!list_empty(&resource->node))) |
||
4441 | - goto out_unlock; |
||
4442 | - |
||
4443 | - list_add_tail(&resource->node, &res_pool->free_list); |
||
4444 | - res_pool->free_count++; |
||
4445 | -out_unlock: |
||
4446 | - mutex_unlock(&res_pool->mutex); |
||
4447 | -} |
||
4448 | -EXPORT_SYMBOL_GPL(fsl_mc_resource_free); |
||
4449 | - |
||
4450 | -/** |
||
4451 | - * fsl_mc_object_allocate - Allocates an fsl-mc object of the given |
||
4452 | - * pool type from a given fsl-mc bus instance |
||
4453 | - * |
||
4454 | - * @mc_dev: fsl-mc device which is used in conjunction with the |
||
4455 | - * allocated object |
||
4456 | - * @pool_type: pool type |
||
4457 | - * @new_mc_dev: pointer to area where the pointer to the allocated device |
||
4458 | - * is to be returned |
||
4459 | - * |
||
4460 | - * Allocatable objects are always used in conjunction with some functional |
||
4461 | - * device. This function allocates an object of the specified type from |
||
4462 | - * the DPRC containing the functional device. |
||
4463 | - * |
||
4464 | - * NOTE: pool_type must be different from FSL_MC_POOL_MCP, since MC |
||
4465 | - * portals are allocated using fsl_mc_portal_allocate(), instead of |
||
4466 | - * this function. |
||
4467 | - */ |
||
4468 | -int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev, |
||
4469 | - enum fsl_mc_pool_type pool_type, |
||
4470 | - struct fsl_mc_device **new_mc_adev) |
||
4471 | -{ |
||
4472 | - struct fsl_mc_device *mc_bus_dev; |
||
4473 | - struct fsl_mc_bus *mc_bus; |
||
4474 | - struct fsl_mc_device *mc_adev; |
||
4475 | - int error = -EINVAL; |
||
4476 | - struct fsl_mc_resource *resource = NULL; |
||
4477 | - |
||
4478 | - *new_mc_adev = NULL; |
||
4479 | - if (WARN_ON(mc_dev->flags & FSL_MC_IS_DPRC)) |
||
4480 | - goto error; |
||
4481 | - |
||
4482 | - if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent))) |
||
4483 | - goto error; |
||
4484 | - |
||
4485 | - if (WARN_ON(pool_type == FSL_MC_POOL_DPMCP)) |
||
4486 | - goto error; |
||
4487 | - |
||
4488 | - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); |
||
4489 | - mc_bus = to_fsl_mc_bus(mc_bus_dev); |
||
4490 | - error = fsl_mc_resource_allocate(mc_bus, pool_type, &resource); |
||
4491 | - if (error < 0) |
||
4492 | - goto error; |
||
4493 | - |
||
4494 | - mc_adev = resource->data; |
||
4495 | - if (WARN_ON(!mc_adev)) |
||
4496 | - goto error; |
||
4497 | - |
||
4498 | - *new_mc_adev = mc_adev; |
||
4499 | - return 0; |
||
4500 | -error: |
||
4501 | - if (resource) |
||
4502 | - fsl_mc_resource_free(resource); |
||
4503 | - |
||
4504 | - return error; |
||
4505 | -} |
||
4506 | -EXPORT_SYMBOL_GPL(fsl_mc_object_allocate); |
||
4507 | - |
||
4508 | -/** |
||
4509 | - * fsl_mc_object_free - Returns an fsl-mc object to the resource |
||
4510 | - * pool where it came from. |
||
4511 | - * @mc_adev: Pointer to the fsl-mc device |
||
4512 | - */ |
||
4513 | -void fsl_mc_object_free(struct fsl_mc_device *mc_adev) |
||
4514 | -{ |
||
4515 | - struct fsl_mc_resource *resource; |
||
4516 | - |
||
4517 | - resource = mc_adev->resource; |
||
4518 | - if (WARN_ON(resource->type == FSL_MC_POOL_DPMCP)) |
||
4519 | - return; |
||
4520 | - if (WARN_ON(resource->data != mc_adev)) |
||
4521 | - return; |
||
4522 | - |
||
4523 | - fsl_mc_resource_free(resource); |
||
4524 | -} |
||
4525 | -EXPORT_SYMBOL_GPL(fsl_mc_object_free); |
||
4526 | - |
||
4527 | -/* |
||
4528 | - * A DPRC and the devices in the DPRC all share the same GIC-ITS device |
||
4529 | - * ID. A block of IRQs is pre-allocated and maintained in a pool |
||
4530 | - * from which devices can allocate them when needed. |
||
4531 | - */ |
||
4532 | - |
||
4533 | -/* |
||
4534 | - * Initialize the interrupt pool associated with an fsl-mc bus. |
||
4535 | - * It allocates a block of IRQs from the GIC-ITS. |
||
4536 | - */ |
||
4537 | -int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, |
||
4538 | - unsigned int irq_count) |
||
4539 | -{ |
||
4540 | - unsigned int i; |
||
4541 | - struct msi_desc *msi_desc; |
||
4542 | - struct fsl_mc_device_irq *irq_resources; |
||
4543 | - struct fsl_mc_device_irq *mc_dev_irq; |
||
4544 | - int error; |
||
4545 | - struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; |
||
4546 | - struct fsl_mc_resource_pool *res_pool = |
||
4547 | - &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; |
||
4548 | - |
||
4549 | - if (WARN_ON(irq_count == 0 || |
||
4550 | - irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS)) |
||
4551 | - return -EINVAL; |
||
4552 | - |
||
4553 | - error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count); |
||
4554 | - if (error < 0) |
||
4555 | - return error; |
||
4556 | - |
||
4557 | - irq_resources = devm_kzalloc(&mc_bus_dev->dev, |
||
4558 | - sizeof(*irq_resources) * irq_count, |
||
4559 | - GFP_KERNEL); |
||
4560 | - if (!irq_resources) { |
||
4561 | - error = -ENOMEM; |
||
4562 | - goto cleanup_msi_irqs; |
||
4563 | - } |
||
4564 | - |
||
4565 | - for (i = 0; i < irq_count; i++) { |
||
4566 | - mc_dev_irq = &irq_resources[i]; |
||
4567 | - |
||
4568 | - /* |
||
4569 | - * NOTE: This mc_dev_irq's MSI addr/value pair will be set |
||
4570 | - * by the fsl_mc_msi_write_msg() callback |
||
4571 | - */ |
||
4572 | - mc_dev_irq->resource.type = res_pool->type; |
||
4573 | - mc_dev_irq->resource.data = mc_dev_irq; |
||
4574 | - mc_dev_irq->resource.parent_pool = res_pool; |
||
4575 | - INIT_LIST_HEAD(&mc_dev_irq->resource.node); |
||
4576 | - list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list); |
||
4577 | - } |
||
4578 | - |
||
4579 | - for_each_msi_entry(msi_desc, &mc_bus_dev->dev) { |
||
4580 | - mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index]; |
||
4581 | - mc_dev_irq->msi_desc = msi_desc; |
||
4582 | - mc_dev_irq->resource.id = msi_desc->irq; |
||
4583 | - } |
||
4584 | - |
||
4585 | - res_pool->max_count = irq_count; |
||
4586 | - res_pool->free_count = irq_count; |
||
4587 | - mc_bus->irq_resources = irq_resources; |
||
4588 | - return 0; |
||
4589 | - |
||
4590 | -cleanup_msi_irqs: |
||
4591 | - fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); |
||
4592 | - return error; |
||
4593 | -} |
||
4594 | -EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool); |
||
4595 | - |
||
4596 | -/** |
||
4597 | - * Teardown the interrupt pool associated with an fsl-mc bus. |
||
4598 | - * It frees the IRQs that were allocated to the pool, back to the GIC-ITS. |
||
4599 | - */ |
||
4600 | -void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus) |
||
4601 | -{ |
||
4602 | - struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; |
||
4603 | - struct fsl_mc_resource_pool *res_pool = |
||
4604 | - &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; |
||
4605 | - |
||
4606 | - if (WARN_ON(!mc_bus->irq_resources)) |
||
4607 | - return; |
||
4608 | - |
||
4609 | - if (WARN_ON(res_pool->max_count == 0)) |
||
4610 | - return; |
||
4611 | - |
||
4612 | - if (WARN_ON(res_pool->free_count != res_pool->max_count)) |
||
4613 | - return; |
||
4614 | - |
||
4615 | - INIT_LIST_HEAD(&res_pool->free_list); |
||
4616 | - res_pool->max_count = 0; |
||
4617 | - res_pool->free_count = 0; |
||
4618 | - mc_bus->irq_resources = NULL; |
||
4619 | - fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); |
||
4620 | -} |
||
4621 | -EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool); |
||
4622 | - |
||
4623 | -/** |
||
4624 | - * Allocate the IRQs required by a given fsl-mc device. |
||
4625 | - */ |
||
4626 | -int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev) |
||
4627 | -{ |
||
4628 | - int i; |
||
4629 | - int irq_count; |
||
4630 | - int res_allocated_count = 0; |
||
4631 | - int error = -EINVAL; |
||
4632 | - struct fsl_mc_device_irq **irqs = NULL; |
||
4633 | - struct fsl_mc_bus *mc_bus; |
||
4634 | - struct fsl_mc_resource_pool *res_pool; |
||
4635 | - |
||
4636 | - if (WARN_ON(mc_dev->irqs)) |
||
4637 | - return -EINVAL; |
||
4638 | - |
||
4639 | - irq_count = mc_dev->obj_desc.irq_count; |
||
4640 | - if (WARN_ON(irq_count == 0)) |
||
4641 | - return -EINVAL; |
||
4642 | - |
||
4643 | - if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) |
||
4644 | - mc_bus = to_fsl_mc_bus(mc_dev); |
||
4645 | - else |
||
4646 | - mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); |
||
4647 | - |
||
4648 | - if (WARN_ON(!mc_bus->irq_resources)) |
||
4649 | - return -EINVAL; |
||
4650 | - |
||
4651 | - res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; |
||
4652 | - if (res_pool->free_count < irq_count) { |
||
4653 | - dev_err(&mc_dev->dev, |
||
4654 | - "Not able to allocate %u irqs for device\n", irq_count); |
||
4655 | - return -ENOSPC; |
||
4656 | - } |
||
4657 | - |
||
4658 | - irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]), |
||
4659 | - GFP_KERNEL); |
||
4660 | - if (!irqs) |
||
4661 | - return -ENOMEM; |
||
4662 | - |
||
4663 | - for (i = 0; i < irq_count; i++) { |
||
4664 | - struct fsl_mc_resource *resource; |
||
4665 | - |
||
4666 | - error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ, |
||
4667 | - &resource); |
||
4668 | - if (error < 0) |
||
4669 | - goto error_resource_alloc; |
||
4670 | - |
||
4671 | - irqs[i] = to_fsl_mc_irq(resource); |
||
4672 | - res_allocated_count++; |
||
4673 | - |
||
4674 | - WARN_ON(irqs[i]->mc_dev); |
||
4675 | - irqs[i]->mc_dev = mc_dev; |
||
4676 | - irqs[i]->dev_irq_index = i; |
||
4677 | - } |
||
4678 | - |
||
4679 | - mc_dev->irqs = irqs; |
||
4680 | - return 0; |
||
4681 | - |
||
4682 | -error_resource_alloc: |
||
4683 | - for (i = 0; i < res_allocated_count; i++) { |
||
4684 | - irqs[i]->mc_dev = NULL; |
||
4685 | - fsl_mc_resource_free(&irqs[i]->resource); |
||
4686 | - } |
||
4687 | - |
||
4688 | - return error; |
||
4689 | -} |
||
4690 | -EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs); |
||
4691 | - |
||
4692 | -/* |
||
4693 | - * Frees the IRQs that were allocated for an fsl-mc device. |
||
4694 | - */ |
||
4695 | -void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev) |
||
4696 | -{ |
||
4697 | - int i; |
||
4698 | - int irq_count; |
||
4699 | - struct fsl_mc_bus *mc_bus; |
||
4700 | - struct fsl_mc_device_irq **irqs = mc_dev->irqs; |
||
4701 | - |
||
4702 | - if (WARN_ON(!irqs)) |
||
4703 | - return; |
||
4704 | - |
||
4705 | - irq_count = mc_dev->obj_desc.irq_count; |
||
4706 | - |
||
4707 | - if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) |
||
4708 | - mc_bus = to_fsl_mc_bus(mc_dev); |
||
4709 | - else |
||
4710 | - mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); |
||
4711 | - |
||
4712 | - if (WARN_ON(!mc_bus->irq_resources)) |
||
4713 | - return; |
||
4714 | - |
||
4715 | - for (i = 0; i < irq_count; i++) { |
||
4716 | - WARN_ON(!irqs[i]->mc_dev); |
||
4717 | - irqs[i]->mc_dev = NULL; |
||
4718 | - fsl_mc_resource_free(&irqs[i]->resource); |
||
4719 | - } |
||
4720 | - |
||
4721 | - mc_dev->irqs = NULL; |
||
4722 | -} |
||
4723 | -EXPORT_SYMBOL_GPL(fsl_mc_free_irqs); |
||
4724 | - |
||
4725 | -void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev) |
||
4726 | -{ |
||
4727 | - int pool_type; |
||
4728 | - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); |
||
4729 | - |
||
4730 | - for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) { |
||
4731 | - struct fsl_mc_resource_pool *res_pool = |
||
4732 | - &mc_bus->resource_pools[pool_type]; |
||
4733 | - |
||
4734 | - res_pool->type = pool_type; |
||
4735 | - res_pool->max_count = 0; |
||
4736 | - res_pool->free_count = 0; |
||
4737 | - res_pool->mc_bus = mc_bus; |
||
4738 | - INIT_LIST_HEAD(&res_pool->free_list); |
||
4739 | - mutex_init(&res_pool->mutex); |
||
4740 | - } |
||
4741 | -} |
||
4742 | - |
||
4743 | -static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev, |
||
4744 | - enum fsl_mc_pool_type pool_type) |
||
4745 | -{ |
||
4746 | - struct fsl_mc_resource *resource; |
||
4747 | - struct fsl_mc_resource *next; |
||
4748 | - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); |
||
4749 | - struct fsl_mc_resource_pool *res_pool = |
||
4750 | - &mc_bus->resource_pools[pool_type]; |
||
4751 | - int free_count = 0; |
||
4752 | - |
||
4753 | - WARN_ON(res_pool->type != pool_type); |
||
4754 | - WARN_ON(res_pool->free_count != res_pool->max_count); |
||
4755 | - |
||
4756 | - list_for_each_entry_safe(resource, next, &res_pool->free_list, node) { |
||
4757 | - free_count++; |
||
4758 | - WARN_ON(resource->type != res_pool->type); |
||
4759 | - WARN_ON(resource->parent_pool != res_pool); |
||
4760 | - devm_kfree(&mc_bus_dev->dev, resource); |
||
4761 | - } |
||
4762 | - |
||
4763 | - WARN_ON(free_count != res_pool->free_count); |
||
4764 | -} |
||
4765 | - |
||
4766 | -void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev) |
||
4767 | -{ |
||
4768 | - int pool_type; |
||
4769 | - |
||
4770 | - for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) |
||
4771 | - fsl_mc_cleanup_resource_pool(mc_bus_dev, pool_type); |
||
4772 | -} |
||
4773 | - |
||
4774 | -/** |
||
4775 | - * fsl_mc_allocator_probe - callback invoked when an allocatable device is |
||
4776 | - * being added to the system |
||
4777 | - */ |
||
4778 | -static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev) |
||
4779 | -{ |
||
4780 | - enum fsl_mc_pool_type pool_type; |
||
4781 | - struct fsl_mc_device *mc_bus_dev; |
||
4782 | - struct fsl_mc_bus *mc_bus; |
||
4783 | - int error; |
||
4784 | - |
||
4785 | - if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type))) |
||
4786 | - return -EINVAL; |
||
4787 | - |
||
4788 | - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); |
||
4789 | - if (WARN_ON(!dev_is_fsl_mc(&mc_bus_dev->dev))) |
||
4790 | - return -EINVAL; |
||
4791 | - |
||
4792 | - mc_bus = to_fsl_mc_bus(mc_bus_dev); |
||
4793 | - error = object_type_to_pool_type(mc_dev->obj_desc.type, &pool_type); |
||
4794 | - if (error < 0) |
||
4795 | - return error; |
||
4796 | - |
||
4797 | - error = fsl_mc_resource_pool_add_device(mc_bus, pool_type, mc_dev); |
||
4798 | - if (error < 0) |
||
4799 | - return error; |
||
4800 | - |
||
4801 | - dev_dbg(&mc_dev->dev, |
||
4802 | - "Allocatable fsl-mc device bound to fsl_mc_allocator driver"); |
||
4803 | - return 0; |
||
4804 | -} |
||
4805 | - |
||
4806 | -/** |
||
4807 | - * fsl_mc_allocator_remove - callback invoked when an allocatable device is |
||
4808 | - * being removed from the system |
||
4809 | - */ |
||
4810 | -static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev) |
||
4811 | -{ |
||
4812 | - int error; |
||
4813 | - |
||
4814 | - if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type))) |
||
4815 | - return -EINVAL; |
||
4816 | - |
||
4817 | - if (mc_dev->resource) { |
||
4818 | - error = fsl_mc_resource_pool_remove_device(mc_dev); |
||
4819 | - if (error < 0) |
||
4820 | - return error; |
||
4821 | - } |
||
4822 | - |
||
4823 | - dev_dbg(&mc_dev->dev, |
||
4824 | - "Allocatable fsl-mc device unbound from fsl_mc_allocator driver"); |
||
4825 | - return 0; |
||
4826 | -} |
||
4827 | - |
||
4828 | -static const struct fsl_mc_device_id match_id_table[] = { |
||
4829 | - { |
||
4830 | - .vendor = FSL_MC_VENDOR_FREESCALE, |
||
4831 | - .obj_type = "dpbp", |
||
4832 | - }, |
||
4833 | - { |
||
4834 | - .vendor = FSL_MC_VENDOR_FREESCALE, |
||
4835 | - .obj_type = "dpmcp", |
||
4836 | - }, |
||
4837 | - { |
||
4838 | - .vendor = FSL_MC_VENDOR_FREESCALE, |
||
4839 | - .obj_type = "dpcon", |
||
4840 | - }, |
||
4841 | - {.vendor = 0x0}, |
||
4842 | -}; |
||
4843 | - |
||
4844 | -static struct fsl_mc_driver fsl_mc_allocator_driver = { |
||
4845 | - .driver = { |
||
4846 | - .name = "fsl_mc_allocator", |
||
4847 | - .pm = NULL, |
||
4848 | - }, |
||
4849 | - .match_id_table = match_id_table, |
||
4850 | - .probe = fsl_mc_allocator_probe, |
||
4851 | - .remove = fsl_mc_allocator_remove, |
||
4852 | -}; |
||
4853 | - |
||
4854 | -int __init fsl_mc_allocator_driver_init(void) |
||
4855 | -{ |
||
4856 | - return fsl_mc_driver_register(&fsl_mc_allocator_driver); |
||
4857 | -} |
||
4858 | - |
||
4859 | -void fsl_mc_allocator_driver_exit(void) |
||
4860 | -{ |
||
4861 | - fsl_mc_driver_unregister(&fsl_mc_allocator_driver); |
||
4862 | -} |
||
4863 | --- /dev/null |
||
4864 | +++ b/drivers/bus/fsl-mc/fsl-mc-allocator.c |
||
4865 | @@ -0,0 +1,655 @@ |
||
4866 | +// SPDX-License-Identifier: GPL-2.0 |
||
4867 | +/* |
||
4868 | + * fsl-mc object allocator driver |
||
4869 | + * |
||
4870 | + * Copyright (C) 2013-2016 Freescale Semiconductor, Inc. |
||
4871 | + * |
||
4872 | + */ |
||
4873 | + |
||
4874 | +#include <linux/module.h> |
||
4875 | +#include <linux/msi.h> |
||
4876 | +#include <linux/fsl/mc.h> |
||
4877 | + |
||
4878 | +#include "fsl-mc-private.h" |
||
4879 | + |
||
4880 | +static bool __must_check fsl_mc_is_allocatable(struct fsl_mc_device *mc_dev) |
||
4881 | +{ |
||
4882 | + return is_fsl_mc_bus_dpbp(mc_dev) || |
||
4883 | + is_fsl_mc_bus_dpmcp(mc_dev) || |
||
4884 | + is_fsl_mc_bus_dpcon(mc_dev); |
||
4885 | +} |
||
4886 | + |
||
4887 | +/** |
||
4888 | + * fsl_mc_resource_pool_add_device - add allocatable object to a resource |
||
4889 | + * pool of a given fsl-mc bus |
||
4890 | + * |
||
4891 | + * @mc_bus: pointer to the fsl-mc bus |
||
4892 | + * @pool_type: pool type |
||
4893 | + * @mc_dev: pointer to allocatable fsl-mc device |
||
4894 | + */ |
||
4895 | +static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus |
||
4896 | + *mc_bus, |
||
4897 | + enum fsl_mc_pool_type |
||
4898 | + pool_type, |
||
4899 | + struct fsl_mc_device |
||
4900 | + *mc_dev) |
||
4901 | +{ |
||
4902 | + struct fsl_mc_resource_pool *res_pool; |
||
4903 | + struct fsl_mc_resource *resource; |
||
4904 | + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; |
||
4905 | + int error = -EINVAL; |
||
4906 | + |
||
4907 | + if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES) |
||
4908 | + goto out; |
||
4909 | + if (!fsl_mc_is_allocatable(mc_dev)) |
||
4910 | + goto out; |
||
4911 | + if (mc_dev->resource) |
||
4912 | + goto out; |
||
4913 | + |
||
4914 | + res_pool = &mc_bus->resource_pools[pool_type]; |
||
4915 | + if (res_pool->type != pool_type) |
||
4916 | + goto out; |
||
4917 | + if (res_pool->mc_bus != mc_bus) |
||
4918 | + goto out; |
||
4919 | + |
||
4920 | + mutex_lock(&res_pool->mutex); |
||
4921 | + |
||
4922 | + if (res_pool->max_count < 0) |
||
4923 | + goto out_unlock; |
||
4924 | + if (res_pool->free_count < 0 || |
||
4925 | + res_pool->free_count > res_pool->max_count) |
||
4926 | + goto out_unlock; |
||
4927 | + |
||
4928 | + resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource), |
||
4929 | + GFP_KERNEL); |
||
4930 | + if (!resource) { |
||
4931 | + error = -ENOMEM; |
||
4932 | + dev_err(&mc_bus_dev->dev, |
||
4933 | + "Failed to allocate memory for fsl_mc_resource\n"); |
||
4934 | + goto out_unlock; |
||
4935 | + } |
||
4936 | + |
||
4937 | + resource->type = pool_type; |
||
4938 | + resource->id = mc_dev->obj_desc.id; |
||
4939 | + resource->data = mc_dev; |
||
4940 | + resource->parent_pool = res_pool; |
||
4941 | + INIT_LIST_HEAD(&resource->node); |
||
4942 | + list_add_tail(&resource->node, &res_pool->free_list); |
||
4943 | + mc_dev->resource = resource; |
||
4944 | + res_pool->free_count++; |
||
4945 | + res_pool->max_count++; |
||
4946 | + error = 0; |
||
4947 | +out_unlock: |
||
4948 | + mutex_unlock(&res_pool->mutex); |
||
4949 | +out: |
||
4950 | + return error; |
||
4951 | +} |
||
4952 | + |
||
4953 | +/** |
||
4954 | + * fsl_mc_resource_pool_remove_device - remove an allocatable device from a |
||
4955 | + * resource pool |
||
4956 | + * |
||
4957 | + * @mc_dev: pointer to allocatable fsl-mc device |
||
4958 | + * |
||
4959 | + * It permanently removes an allocatable fsl-mc device from the resource |
||
4960 | + * pool. It's an error if the device is in use. |
||
4961 | + */ |
||
4962 | +static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device |
||
4963 | + *mc_dev) |
||
4964 | +{ |
||
4965 | + struct fsl_mc_device *mc_bus_dev; |
||
4966 | + struct fsl_mc_bus *mc_bus; |
||
4967 | + struct fsl_mc_resource_pool *res_pool; |
||
4968 | + struct fsl_mc_resource *resource; |
||
4969 | + int error = -EINVAL; |
||
4970 | + |
||
4971 | + if (!fsl_mc_is_allocatable(mc_dev)) |
||
4972 | + goto out; |
||
4973 | + |
||
4974 | + resource = mc_dev->resource; |
||
4975 | + if (!resource || resource->data != mc_dev) |
||
4976 | + goto out; |
||
4977 | + |
||
4978 | + mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); |
||
4979 | + mc_bus = to_fsl_mc_bus(mc_bus_dev); |
||
4980 | + res_pool = resource->parent_pool; |
||
4981 | + if (res_pool != &mc_bus->resource_pools[resource->type]) |
||
4982 | + goto out; |
||
4983 | + |
||
4984 | + mutex_lock(&res_pool->mutex); |
||
4985 | + |
||
4986 | + if (res_pool->max_count <= 0) |
||
4987 | + goto out_unlock; |
||
4988 | + if (res_pool->free_count <= 0 || |
||
4989 | + res_pool->free_count > res_pool->max_count) |
||
4990 | + goto out_unlock; |
||
4991 | + |
||
4992 | + /* |
||
4993 | + * If the device is currently allocated, its resource is not |
||
4994 | + * in the free list and thus, the device cannot be removed. |
||
4995 | + */ |
||
4996 | + if (list_empty(&resource->node)) { |
||
4997 | + error = -EBUSY; |
||
4998 | + dev_err(&mc_bus_dev->dev, |
||
4999 | + "Device %s cannot be removed from resource pool\n", |
||
5000 | + dev_name(&mc_dev->dev)); |
||
5001 | + goto out_unlock; |
||
5002 | + } |
||
5003 | + |
||
5004 | + list_del_init(&resource->node); |
||
5005 | + res_pool->free_count--; |
||
5006 | + res_pool->max_count--; |
||
5007 | + |
||
5008 | + devm_kfree(&mc_bus_dev->dev, resource); |
||
5009 | + mc_dev->resource = NULL; |
||
5010 | + error = 0; |
||
5011 | +out_unlock: |
||
5012 | + mutex_unlock(&res_pool->mutex); |
||
5013 | +out: |
||
5014 | + return error; |
||
5015 | +} |
||
5016 | + |
||
5017 | +static const char *const fsl_mc_pool_type_strings[] = { |
||
5018 | + [FSL_MC_POOL_DPMCP] = "dpmcp", |
||
5019 | + [FSL_MC_POOL_DPBP] = "dpbp", |
||
5020 | + [FSL_MC_POOL_DPCON] = "dpcon", |
||
5021 | + [FSL_MC_POOL_IRQ] = "irq", |
||
5022 | +}; |
||
5023 | + |
||
5024 | +static int __must_check object_type_to_pool_type(const char *object_type, |
||
5025 | + enum fsl_mc_pool_type |
||
5026 | + *pool_type) |
||
5027 | +{ |
||
5028 | + unsigned int i; |
||
5029 | + |
||
5030 | + for (i = 0; i < ARRAY_SIZE(fsl_mc_pool_type_strings); i++) { |
||
5031 | + if (strcmp(object_type, fsl_mc_pool_type_strings[i]) == 0) { |
||
5032 | + *pool_type = i; |
||
5033 | + return 0; |
||
5034 | + } |
||
5035 | + } |
||
5036 | + |
||
5037 | + return -EINVAL; |
||
5038 | +} |
||
5039 | + |
||
5040 | +int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, |
||
5041 | + enum fsl_mc_pool_type pool_type, |
||
5042 | + struct fsl_mc_resource **new_resource) |
||
5043 | +{ |
||
5044 | + struct fsl_mc_resource_pool *res_pool; |
||
5045 | + struct fsl_mc_resource *resource; |
||
5046 | + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; |
||
5047 | + int error = -EINVAL; |
||
5048 | + |
||
5049 | + BUILD_BUG_ON(ARRAY_SIZE(fsl_mc_pool_type_strings) != |
||
5050 | + FSL_MC_NUM_POOL_TYPES); |
||
5051 | + |
||
5052 | + *new_resource = NULL; |
||
5053 | + if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES) |
||
5054 | + goto out; |
||
5055 | + |
||
5056 | + res_pool = &mc_bus->resource_pools[pool_type]; |
||
5057 | + if (res_pool->mc_bus != mc_bus) |
||
5058 | + goto out; |
||
5059 | + |
||
5060 | + mutex_lock(&res_pool->mutex); |
||
5061 | + resource = list_first_entry_or_null(&res_pool->free_list, |
||
5062 | + struct fsl_mc_resource, node); |
||
5063 | + |
||
5064 | + if (!resource) { |
||
5065 | + error = -ENXIO; |
||
5066 | + dev_err(&mc_bus_dev->dev, |
||
5067 | + "No more resources of type %s left\n", |
||
5068 | + fsl_mc_pool_type_strings[pool_type]); |
||
5069 | + goto out_unlock; |
||
5070 | + } |
||
5071 | + |
||
5072 | + if (resource->type != pool_type) |
||
5073 | + goto out_unlock; |
||
5074 | + if (resource->parent_pool != res_pool) |
||
5075 | + goto out_unlock; |
||
5076 | + if (res_pool->free_count <= 0 || |
||
5077 | + res_pool->free_count > res_pool->max_count) |
||
5078 | + goto out_unlock; |
||
5079 | + |
||
5080 | + list_del_init(&resource->node); |
||
5081 | + |
||
5082 | + res_pool->free_count--; |
||
5083 | + error = 0; |
||
5084 | +out_unlock: |
||
5085 | + mutex_unlock(&res_pool->mutex); |
||
5086 | + *new_resource = resource; |
||
5087 | +out: |
||
5088 | + return error; |
||
5089 | +} |
||
5090 | +EXPORT_SYMBOL_GPL(fsl_mc_resource_allocate); |
||
5091 | + |
||
5092 | +void fsl_mc_resource_free(struct fsl_mc_resource *resource) |
||
5093 | +{ |
||
5094 | + struct fsl_mc_resource_pool *res_pool; |
||
5095 | + |
||
5096 | + res_pool = resource->parent_pool; |
||
5097 | + if (resource->type != res_pool->type) |
||
5098 | + return; |
||
5099 | + |
||
5100 | + mutex_lock(&res_pool->mutex); |
||
5101 | + if (res_pool->free_count < 0 || |
||
5102 | + res_pool->free_count >= res_pool->max_count) |
||
5103 | + goto out_unlock; |
||
5104 | + |
||
5105 | + if (!list_empty(&resource->node)) |
||
5106 | + goto out_unlock; |
||
5107 | + |
||
5108 | + list_add_tail(&resource->node, &res_pool->free_list); |
||
5109 | + res_pool->free_count++; |
||
5110 | +out_unlock: |
||
5111 | + mutex_unlock(&res_pool->mutex); |
||
5112 | +} |
||
5113 | +EXPORT_SYMBOL_GPL(fsl_mc_resource_free); |
||
5114 | + |
||
5115 | +/** |
||
5116 | + * fsl_mc_object_allocate - Allocates an fsl-mc object of the given |
||
5117 | + * pool type from a given fsl-mc bus instance |
||
5118 | + * |
||
5119 | + * @mc_dev: fsl-mc device which is used in conjunction with the |
||
5120 | + * allocated object |
||
5121 | + * @pool_type: pool type |
||
5122 | + * @new_mc_dev: pointer to area where the pointer to the allocated device |
||
5123 | + * is to be returned |
||
5124 | + * |
||
5125 | + * Allocatable objects are always used in conjunction with some functional |
||
5126 | + * device. This function allocates an object of the specified type from |
||
5127 | + * the DPRC containing the functional device. |
||
5128 | + * |
||
5129 | + * NOTE: pool_type must be different from FSL_MC_POOL_MCP, since MC |
||
5130 | + * portals are allocated using fsl_mc_portal_allocate(), instead of |
||
5131 | + * this function. |
||
5132 | + */ |
||
5133 | +int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev, |
||
5134 | + enum fsl_mc_pool_type pool_type, |
||
5135 | + struct fsl_mc_device **new_mc_adev) |
||
5136 | +{ |
||
5137 | + struct fsl_mc_device *mc_bus_dev; |
||
5138 | + struct fsl_mc_bus *mc_bus; |
||
5139 | + struct fsl_mc_device *mc_adev; |
||
5140 | + int error = -EINVAL; |
||
5141 | + struct fsl_mc_resource *resource = NULL; |
||
5142 | + |
||
5143 | + *new_mc_adev = NULL; |
||
5144 | + if (mc_dev->flags & FSL_MC_IS_DPRC) |
||
5145 | + goto error; |
||
5146 | + |
||
5147 | + if (!dev_is_fsl_mc(mc_dev->dev.parent)) |
||
5148 | + goto error; |
||
5149 | + |
||
5150 | + if (pool_type == FSL_MC_POOL_DPMCP) |
||
5151 | + goto error; |
||
5152 | + |
||
5153 | + mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); |
||
5154 | + mc_bus = to_fsl_mc_bus(mc_bus_dev); |
||
5155 | + error = fsl_mc_resource_allocate(mc_bus, pool_type, &resource); |
||
5156 | + if (error < 0) |
||
5157 | + goto error; |
||
5158 | + |
||
5159 | + mc_adev = resource->data; |
||
5160 | + if (!mc_adev) |
||
5161 | + goto error; |
||
5162 | + |
||
5163 | + *new_mc_adev = mc_adev; |
||
5164 | + return 0; |
||
5165 | +error: |
||
5166 | + if (resource) |
||
5167 | + fsl_mc_resource_free(resource); |
||
5168 | + |
||
5169 | + return error; |
||
5170 | +} |
||
5171 | +EXPORT_SYMBOL_GPL(fsl_mc_object_allocate); |
||
5172 | + |
||
5173 | +/** |
||
5174 | + * fsl_mc_object_free - Returns an fsl-mc object to the resource |
||
5175 | + * pool where it came from. |
||
5176 | + * @mc_adev: Pointer to the fsl-mc device |
||
5177 | + */ |
||
5178 | +void fsl_mc_object_free(struct fsl_mc_device *mc_adev) |
||
5179 | +{ |
||
5180 | + struct fsl_mc_resource *resource; |
||
5181 | + |
||
5182 | + resource = mc_adev->resource; |
||
5183 | + if (resource->type == FSL_MC_POOL_DPMCP) |
||
5184 | + return; |
||
5185 | + if (resource->data != mc_adev) |
||
5186 | + return; |
||
5187 | + |
||
5188 | + fsl_mc_resource_free(resource); |
||
5189 | +} |
||
5190 | +EXPORT_SYMBOL_GPL(fsl_mc_object_free); |
||
5191 | + |
||
5192 | +/* |
||
5193 | + * A DPRC and the devices in the DPRC all share the same GIC-ITS device |
||
5194 | + * ID. A block of IRQs is pre-allocated and maintained in a pool |
||
5195 | + * from which devices can allocate them when needed. |
||
5196 | + */ |
||
5197 | + |
||
5198 | +/* |
||
5199 | + * Initialize the interrupt pool associated with an fsl-mc bus. |
||
5200 | + * It allocates a block of IRQs from the GIC-ITS. |
||
5201 | + */ |
||
5202 | +int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, |
||
5203 | + unsigned int irq_count) |
||
5204 | +{ |
||
5205 | + unsigned int i; |
||
5206 | + struct msi_desc *msi_desc; |
||
5207 | + struct fsl_mc_device_irq *irq_resources; |
||
5208 | + struct fsl_mc_device_irq *mc_dev_irq; |
||
5209 | + int error; |
||
5210 | + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; |
||
5211 | + struct fsl_mc_resource_pool *res_pool = |
||
5212 | + &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; |
||
5213 | + |
||
5214 | + if (irq_count == 0 || |
||
5215 | + irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) |
||
5216 | + return -EINVAL; |
||
5217 | + |
||
5218 | + error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count); |
||
5219 | + if (error < 0) |
||
5220 | + return error; |
||
5221 | + |
||
5222 | + irq_resources = devm_kzalloc(&mc_bus_dev->dev, |
||
5223 | + sizeof(*irq_resources) * irq_count, |
||
5224 | + GFP_KERNEL); |
||
5225 | + if (!irq_resources) { |
||
5226 | + error = -ENOMEM; |
||
5227 | + goto cleanup_msi_irqs; |
||
5228 | + } |
||
5229 | + |
||
5230 | + for (i = 0; i < irq_count; i++) { |
||
5231 | + mc_dev_irq = &irq_resources[i]; |
||
5232 | + |
||
5233 | + /* |
||
5234 | + * NOTE: This mc_dev_irq's MSI addr/value pair will be set |
||
5235 | + * by the fsl_mc_msi_write_msg() callback |
||
5236 | + */ |
||
5237 | + mc_dev_irq->resource.type = res_pool->type; |
||
5238 | + mc_dev_irq->resource.data = mc_dev_irq; |
||
5239 | + mc_dev_irq->resource.parent_pool = res_pool; |
||
5240 | + INIT_LIST_HEAD(&mc_dev_irq->resource.node); |
||
5241 | + list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list); |
||
5242 | + } |
||
5243 | + |
||
5244 | + for_each_msi_entry(msi_desc, &mc_bus_dev->dev) { |
||
5245 | + mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index]; |
||
5246 | + mc_dev_irq->msi_desc = msi_desc; |
||
5247 | + mc_dev_irq->resource.id = msi_desc->irq; |
||
5248 | + } |
||
5249 | + |
||
5250 | + res_pool->max_count = irq_count; |
||
5251 | + res_pool->free_count = irq_count; |
||
5252 | + mc_bus->irq_resources = irq_resources; |
||
5253 | + return 0; |
||
5254 | + |
||
5255 | +cleanup_msi_irqs: |
||
5256 | + fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); |
||
5257 | + return error; |
||
5258 | +} |
||
5259 | +EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool); |
||
5260 | + |
||
5261 | +/** |
||
5262 | + * Teardown the interrupt pool associated with an fsl-mc bus. |
||
5263 | + * It frees the IRQs that were allocated to the pool, back to the GIC-ITS. |
||
5264 | + */ |
||
5265 | +void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus) |
||
5266 | +{ |
||
5267 | + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; |
||
5268 | + struct fsl_mc_resource_pool *res_pool = |
||
5269 | + &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; |
||
5270 | + |
||
5271 | + if (!mc_bus->irq_resources) |
||
5272 | + return; |
||
5273 | + |
||
5274 | + if (res_pool->max_count == 0) |
||
5275 | + return; |
||
5276 | + |
||
5277 | + if (res_pool->free_count != res_pool->max_count) |
||
5278 | + return; |
||
5279 | + |
||
5280 | + INIT_LIST_HEAD(&res_pool->free_list); |
||
5281 | + res_pool->max_count = 0; |
||
5282 | + res_pool->free_count = 0; |
||
5283 | + mc_bus->irq_resources = NULL; |
||
5284 | + fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); |
||
5285 | +} |
||
5286 | +EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool); |
||
5287 | + |
||
5288 | +/** |
||
5289 | + * Allocate the IRQs required by a given fsl-mc device. |
||
5290 | + */ |
||
5291 | +int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev) |
||
5292 | +{ |
||
5293 | + int i; |
||
5294 | + int irq_count; |
||
5295 | + int res_allocated_count = 0; |
||
5296 | + int error = -EINVAL; |
||
5297 | + struct fsl_mc_device_irq **irqs = NULL; |
||
5298 | + struct fsl_mc_bus *mc_bus; |
||
5299 | + struct fsl_mc_resource_pool *res_pool; |
||
5300 | + |
||
5301 | + if (mc_dev->irqs) |
||
5302 | + return -EINVAL; |
||
5303 | + |
||
5304 | + irq_count = mc_dev->obj_desc.irq_count; |
||
5305 | + if (irq_count == 0) |
||
5306 | + return -EINVAL; |
||
5307 | + |
||
5308 | + if (is_fsl_mc_bus_dprc(mc_dev)) |
||
5309 | + mc_bus = to_fsl_mc_bus(mc_dev); |
||
5310 | + else |
||
5311 | + mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); |
||
5312 | + |
||
5313 | + if (!mc_bus->irq_resources) |
||
5314 | + return -EINVAL; |
||
5315 | + |
||
5316 | + res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; |
||
5317 | + if (res_pool->free_count < irq_count) { |
||
5318 | + dev_err(&mc_dev->dev, |
||
5319 | + "Not able to allocate %u irqs for device\n", irq_count); |
||
5320 | + return -ENOSPC; |
||
5321 | + } |
||
5322 | + |
||
5323 | + irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]), |
||
5324 | + GFP_KERNEL); |
||
5325 | + if (!irqs) |
||
5326 | + return -ENOMEM; |
||
5327 | + |
||
5328 | + for (i = 0; i < irq_count; i++) { |
||
5329 | + struct fsl_mc_resource *resource; |
||
5330 | + |
||
5331 | + error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ, |
||
5332 | + &resource); |
||
5333 | + if (error < 0) |
||
5334 | + goto error_resource_alloc; |
||
5335 | + |
||
5336 | + irqs[i] = to_fsl_mc_irq(resource); |
||
5337 | + res_allocated_count++; |
||
5338 | + |
||
5339 | + irqs[i]->mc_dev = mc_dev; |
||
5340 | + irqs[i]->dev_irq_index = i; |
||
5341 | + } |
||
5342 | + |
||
5343 | + mc_dev->irqs = irqs; |
||
5344 | + return 0; |
||
5345 | + |
||
5346 | +error_resource_alloc: |
||
5347 | + for (i = 0; i < res_allocated_count; i++) { |
||
5348 | + irqs[i]->mc_dev = NULL; |
||
5349 | + fsl_mc_resource_free(&irqs[i]->resource); |
||
5350 | + } |
||
5351 | + |
||
5352 | + return error; |
||
5353 | +} |
||
5354 | +EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs); |
||
5355 | + |
||
5356 | +/* |
||
5357 | + * Frees the IRQs that were allocated for an fsl-mc device. |
||
5358 | + */ |
||
5359 | +void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev) |
||
5360 | +{ |
||
5361 | + int i; |
||
5362 | + int irq_count; |
||
5363 | + struct fsl_mc_bus *mc_bus; |
||
5364 | + struct fsl_mc_device_irq **irqs = mc_dev->irqs; |
||
5365 | + |
||
5366 | + if (!irqs) |
||
5367 | + return; |
||
5368 | + |
||
5369 | + irq_count = mc_dev->obj_desc.irq_count; |
||
5370 | + |
||
5371 | + if (is_fsl_mc_bus_dprc(mc_dev)) |
||
5372 | + mc_bus = to_fsl_mc_bus(mc_dev); |
||
5373 | + else |
||
5374 | + mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); |
||
5375 | + |
||
5376 | + if (!mc_bus->irq_resources) |
||
5377 | + return; |
||
5378 | + |
||
5379 | + for (i = 0; i < irq_count; i++) { |
||
5380 | + irqs[i]->mc_dev = NULL; |
||
5381 | + fsl_mc_resource_free(&irqs[i]->resource); |
||
5382 | + } |
||
5383 | + |
||
5384 | + mc_dev->irqs = NULL; |
||
5385 | +} |
||
5386 | +EXPORT_SYMBOL_GPL(fsl_mc_free_irqs); |
||
5387 | + |
||
5388 | +void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev) |
||
5389 | +{ |
||
5390 | + int pool_type; |
||
5391 | + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); |
||
5392 | + |
||
5393 | + for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) { |
||
5394 | + struct fsl_mc_resource_pool *res_pool = |
||
5395 | + &mc_bus->resource_pools[pool_type]; |
||
5396 | + |
||
5397 | + res_pool->type = pool_type; |
||
5398 | + res_pool->max_count = 0; |
||
5399 | + res_pool->free_count = 0; |
||
5400 | + res_pool->mc_bus = mc_bus; |
||
5401 | + INIT_LIST_HEAD(&res_pool->free_list); |
||
5402 | + mutex_init(&res_pool->mutex); |
||
5403 | + } |
||
5404 | +} |
||
5405 | +EXPORT_SYMBOL_GPL(fsl_mc_init_all_resource_pools); |
||
5406 | + |
||
5407 | +static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev, |
||
5408 | + enum fsl_mc_pool_type pool_type) |
||
5409 | +{ |
||
5410 | + struct fsl_mc_resource *resource; |
||
5411 | + struct fsl_mc_resource *next; |
||
5412 | + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); |
||
5413 | + struct fsl_mc_resource_pool *res_pool = |
||
5414 | + &mc_bus->resource_pools[pool_type]; |
||
5415 | + int free_count = 0; |
||
5416 | + |
||
5417 | + list_for_each_entry_safe(resource, next, &res_pool->free_list, node) { |
||
5418 | + free_count++; |
||
5419 | + devm_kfree(&mc_bus_dev->dev, resource); |
||
5420 | + } |
||
5421 | +} |
||
5422 | + |
||
5423 | +void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev) |
||
5424 | +{ |
||
5425 | + int pool_type; |
||
5426 | + |
||
5427 | + for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) |
||
5428 | + fsl_mc_cleanup_resource_pool(mc_bus_dev, pool_type); |
||
5429 | +} |
||
5430 | +EXPORT_SYMBOL_GPL(fsl_mc_cleanup_all_resource_pools); |
||
5431 | + |
||
5432 | +/** |
||
5433 | + * fsl_mc_allocator_probe - callback invoked when an allocatable device is |
||
5434 | + * being added to the system |
||
5435 | + */ |
||
5436 | +static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev) |
||
5437 | +{ |
||
5438 | + enum fsl_mc_pool_type pool_type; |
||
5439 | + struct fsl_mc_device *mc_bus_dev; |
||
5440 | + struct fsl_mc_bus *mc_bus; |
||
5441 | + int error; |
||
5442 | + |
||
5443 | + if (!fsl_mc_is_allocatable(mc_dev)) |
||
5444 | + return -EINVAL; |
||
5445 | + |
||
5446 | + mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); |
||
5447 | + if (!dev_is_fsl_mc(&mc_bus_dev->dev)) |
||
5448 | + return -EINVAL; |
||
5449 | + |
||
5450 | + mc_bus = to_fsl_mc_bus(mc_bus_dev); |
||
5451 | + error = object_type_to_pool_type(mc_dev->obj_desc.type, &pool_type); |
||
5452 | + if (error < 0) |
||
5453 | + return error; |
||
5454 | + |
||
5455 | + error = fsl_mc_resource_pool_add_device(mc_bus, pool_type, mc_dev); |
||
5456 | + if (error < 0) |
||
5457 | + return error; |
||
5458 | + |
||
5459 | + dev_dbg(&mc_dev->dev, |
||
5460 | + "Allocatable fsl-mc device bound to fsl_mc_allocator driver"); |
||
5461 | + return 0; |
||
5462 | +} |
||
5463 | + |
||
5464 | +/** |
||
5465 | + * fsl_mc_allocator_remove - callback invoked when an allocatable device is |
||
5466 | + * being removed from the system |
||
5467 | + */ |
||
5468 | +static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev) |
||
5469 | +{ |
||
5470 | + int error; |
||
5471 | + |
||
5472 | + if (!fsl_mc_is_allocatable(mc_dev)) |
||
5473 | + return -EINVAL; |
||
5474 | + |
||
5475 | + if (mc_dev->resource) { |
||
5476 | + error = fsl_mc_resource_pool_remove_device(mc_dev); |
||
5477 | + if (error < 0) |
||
5478 | + return error; |
||
5479 | + } |
||
5480 | + |
||
5481 | + dev_dbg(&mc_dev->dev, |
||
5482 | + "Allocatable fsl-mc device unbound from fsl_mc_allocator driver"); |
||
5483 | + return 0; |
||
5484 | +} |
||
5485 | + |
||
5486 | +static const struct fsl_mc_device_id match_id_table[] = { |
||
5487 | + { |
||
5488 | + .vendor = FSL_MC_VENDOR_FREESCALE, |
||
5489 | + .obj_type = "dpbp", |
||
5490 | + }, |
||
5491 | + { |
||
5492 | + .vendor = FSL_MC_VENDOR_FREESCALE, |
||
5493 | + .obj_type = "dpmcp", |
||
5494 | + }, |
||
5495 | + { |
||
5496 | + .vendor = FSL_MC_VENDOR_FREESCALE, |
||
5497 | + .obj_type = "dpcon", |
||
5498 | + }, |
||
5499 | + {.vendor = 0x0}, |
||
5500 | +}; |
||
5501 | + |
||
5502 | +static struct fsl_mc_driver fsl_mc_allocator_driver = { |
||
5503 | + .driver = { |
||
5504 | + .name = "fsl_mc_allocator", |
||
5505 | + .pm = NULL, |
||
5506 | + }, |
||
5507 | + .match_id_table = match_id_table, |
||
5508 | + .probe = fsl_mc_allocator_probe, |
||
5509 | + .remove = fsl_mc_allocator_remove, |
||
5510 | +}; |
||
5511 | + |
||
5512 | +int __init fsl_mc_allocator_driver_init(void) |
||
5513 | +{ |
||
5514 | + return fsl_mc_driver_register(&fsl_mc_allocator_driver); |
||
5515 | +} |
||
5516 | + |
||
5517 | +void fsl_mc_allocator_driver_exit(void) |
||
5518 | +{ |
||
5519 | + fsl_mc_driver_unregister(&fsl_mc_allocator_driver); |
||
5520 | +} |
||
5521 | --- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c |
||
5522 | +++ /dev/null |
||
5523 | @@ -1,900 +0,0 @@ |
||
5524 | -// SPDX-License-Identifier: GPL-2.0 |
||
5525 | -/* |
||
5526 | - * Freescale Management Complex (MC) bus driver |
||
5527 | - * |
||
5528 | - * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. |
||
5529 | - * Author: German Rivera <German.Rivera@freescale.com> |
||
5530 | - * |
||
5531 | - */ |
||
5532 | - |
||
5533 | -#define pr_fmt(fmt) "fsl-mc: " fmt |
||
5534 | - |
||
5535 | -#include <linux/module.h> |
||
5536 | -#include <linux/of_device.h> |
||
5537 | -#include <linux/of_address.h> |
||
5538 | -#include <linux/ioport.h> |
||
5539 | -#include <linux/slab.h> |
||
5540 | -#include <linux/limits.h> |
||
5541 | -#include <linux/bitops.h> |
||
5542 | -#include <linux/msi.h> |
||
5543 | -#include <linux/dma-mapping.h> |
||
5544 | - |
||
5545 | -#include "fsl-mc-private.h" |
||
5546 | -#include "dprc-cmd.h" |
||
5547 | -#include "dpmng-cmd.h" |
||
5548 | - |
||
5549 | -/** |
||
5550 | - * Default DMA mask for devices on a fsl-mc bus |
||
5551 | - */ |
||
5552 | -#define FSL_MC_DEFAULT_DMA_MASK (~0ULL) |
||
5553 | - |
||
5554 | -/** |
||
5555 | - * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device |
||
5556 | - * @root_mc_bus_dev: fsl-mc device representing the root DPRC |
||
5557 | - * @num_translation_ranges: number of entries in addr_translation_ranges |
||
5558 | - * @translation_ranges: array of bus to system address translation ranges |
||
5559 | - */ |
||
5560 | -struct fsl_mc { |
||
5561 | - struct fsl_mc_device *root_mc_bus_dev; |
||
5562 | - u8 num_translation_ranges; |
||
5563 | - struct fsl_mc_addr_translation_range *translation_ranges; |
||
5564 | -}; |
||
5565 | - |
||
5566 | -/** |
||
5567 | - * struct fsl_mc_addr_translation_range - bus to system address translation |
||
5568 | - * range |
||
5569 | - * @mc_region_type: Type of MC region for the range being translated |
||
5570 | - * @start_mc_offset: Start MC offset of the range being translated |
||
5571 | - * @end_mc_offset: MC offset of the first byte after the range (last MC |
||
5572 | - * offset of the range is end_mc_offset - 1) |
||
5573 | - * @start_phys_addr: system physical address corresponding to start_mc_addr |
||
5574 | - */ |
||
5575 | -struct fsl_mc_addr_translation_range { |
||
5576 | - enum dprc_region_type mc_region_type; |
||
5577 | - u64 start_mc_offset; |
||
5578 | - u64 end_mc_offset; |
||
5579 | - phys_addr_t start_phys_addr; |
||
5580 | -}; |
||
5581 | - |
||
5582 | -/** |
||
5583 | - * struct mc_version |
||
5584 | - * @major: Major version number: incremented on API compatibility changes |
||
5585 | - * @minor: Minor version number: incremented on API additions (that are |
||
5586 | - * backward compatible); reset when major version is incremented |
||
5587 | - * @revision: Internal revision number: incremented on implementation changes |
||
5588 | - * and/or bug fixes that have no impact on API |
||
5589 | - */ |
||
5590 | -struct mc_version { |
||
5591 | - u32 major; |
||
5592 | - u32 minor; |
||
5593 | - u32 revision; |
||
5594 | -}; |
||
5595 | - |
||
5596 | -/** |
||
5597 | - * fsl_mc_bus_match - device to driver matching callback |
||
5598 | - * @dev: the fsl-mc device to match against |
||
5599 | - * @drv: the device driver to search for matching fsl-mc object type |
||
5600 | - * structures |
||
5601 | - * |
||
5602 | - * Returns 1 on success, 0 otherwise. |
||
5603 | - */ |
||
5604 | -static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv) |
||
5605 | -{ |
||
5606 | - const struct fsl_mc_device_id *id; |
||
5607 | - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); |
||
5608 | - struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv); |
||
5609 | - bool found = false; |
||
5610 | - |
||
5611 | - if (!mc_drv->match_id_table) |
||
5612 | - goto out; |
||
5613 | - |
||
5614 | - /* |
||
5615 | - * If the object is not 'plugged' don't match. |
||
5616 | - * Only exception is the root DPRC, which is a special case. |
||
5617 | - */ |
||
5618 | - if ((mc_dev->obj_desc.state & FSL_MC_OBJ_STATE_PLUGGED) == 0 && |
||
5619 | - !fsl_mc_is_root_dprc(&mc_dev->dev)) |
||
5620 | - goto out; |
||
5621 | - |
||
5622 | - /* |
||
5623 | - * Traverse the match_id table of the given driver, trying to find |
||
5624 | - * a matching for the given device. |
||
5625 | - */ |
||
5626 | - for (id = mc_drv->match_id_table; id->vendor != 0x0; id++) { |
||
5627 | - if (id->vendor == mc_dev->obj_desc.vendor && |
||
5628 | - strcmp(id->obj_type, mc_dev->obj_desc.type) == 0) { |
||
5629 | - found = true; |
||
5630 | - |
||
5631 | - break; |
||
5632 | - } |
||
5633 | - } |
||
5634 | - |
||
5635 | -out: |
||
5636 | - dev_dbg(dev, "%smatched\n", found ? "" : "not "); |
||
5637 | - return found; |
||
5638 | -} |
||
5639 | - |
||
5640 | -/** |
||
5641 | - * fsl_mc_bus_uevent - callback invoked when a device is added |
||
5642 | - */ |
||
5643 | -static int fsl_mc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) |
||
5644 | -{ |
||
5645 | - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); |
||
5646 | - |
||
5647 | - if (add_uevent_var(env, "MODALIAS=fsl-mc:v%08Xd%s", |
||
5648 | - mc_dev->obj_desc.vendor, |
||
5649 | - mc_dev->obj_desc.type)) |
||
5650 | - return -ENOMEM; |
||
5651 | - |
||
5652 | - return 0; |
||
5653 | -} |
||
5654 | - |
||
5655 | -static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, |
||
5656 | - char *buf) |
||
5657 | -{ |
||
5658 | - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); |
||
5659 | - |
||
5660 | - return sprintf(buf, "fsl-mc:v%08Xd%s\n", mc_dev->obj_desc.vendor, |
||
5661 | - mc_dev->obj_desc.type); |
||
5662 | -} |
||
5663 | -static DEVICE_ATTR_RO(modalias); |
||
5664 | - |
||
5665 | -static struct attribute *fsl_mc_dev_attrs[] = { |
||
5666 | - &dev_attr_modalias.attr, |
||
5667 | - NULL, |
||
5668 | -}; |
||
5669 | - |
||
5670 | -ATTRIBUTE_GROUPS(fsl_mc_dev); |
||
5671 | - |
||
5672 | -struct bus_type fsl_mc_bus_type = { |
||
5673 | - .name = "fsl-mc", |
||
5674 | - .match = fsl_mc_bus_match, |
||
5675 | - .uevent = fsl_mc_bus_uevent, |
||
5676 | - .dev_groups = fsl_mc_dev_groups, |
||
5677 | -}; |
||
5678 | -EXPORT_SYMBOL_GPL(fsl_mc_bus_type); |
||
5679 | - |
||
5680 | -static int fsl_mc_driver_probe(struct device *dev) |
||
5681 | -{ |
||
5682 | - struct fsl_mc_driver *mc_drv; |
||
5683 | - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); |
||
5684 | - int error; |
||
5685 | - |
||
5686 | - if (WARN_ON(!dev->driver)) |
||
5687 | - return -EINVAL; |
||
5688 | - |
||
5689 | - mc_drv = to_fsl_mc_driver(dev->driver); |
||
5690 | - if (WARN_ON(!mc_drv->probe)) |
||
5691 | - return -EINVAL; |
||
5692 | - |
||
5693 | - error = mc_drv->probe(mc_dev); |
||
5694 | - if (error < 0) { |
||
5695 | - dev_err(dev, "%s failed: %d\n", __func__, error); |
||
5696 | - return error; |
||
5697 | - } |
||
5698 | - |
||
5699 | - return 0; |
||
5700 | -} |
||
5701 | - |
||
5702 | -static int fsl_mc_driver_remove(struct device *dev) |
||
5703 | -{ |
||
5704 | - struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); |
||
5705 | - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); |
||
5706 | - int error; |
||
5707 | - |
||
5708 | - if (WARN_ON(!dev->driver)) |
||
5709 | - return -EINVAL; |
||
5710 | - |
||
5711 | - error = mc_drv->remove(mc_dev); |
||
5712 | - if (error < 0) { |
||
5713 | - dev_err(dev, "%s failed: %d\n", __func__, error); |
||
5714 | - return error; |
||
5715 | - } |
||
5716 | - |
||
5717 | - return 0; |
||
5718 | -} |
||
5719 | - |
||
5720 | -static void fsl_mc_driver_shutdown(struct device *dev) |
||
5721 | -{ |
||
5722 | - struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); |
||
5723 | - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); |
||
5724 | - |
||
5725 | - mc_drv->shutdown(mc_dev); |
||
5726 | -} |
||
5727 | - |
||
5728 | -/** |
||
5729 | - * __fsl_mc_driver_register - registers a child device driver with the |
||
5730 | - * MC bus |
||
5731 | - * |
||
5732 | - * This function is implicitly invoked from the registration function of |
||
5733 | - * fsl_mc device drivers, which is generated by the |
||
5734 | - * module_fsl_mc_driver() macro. |
||
5735 | - */ |
||
5736 | -int __fsl_mc_driver_register(struct fsl_mc_driver *mc_driver, |
||
5737 | - struct module *owner) |
||
5738 | -{ |
||
5739 | - int error; |
||
5740 | - |
||
5741 | - mc_driver->driver.owner = owner; |
||
5742 | - mc_driver->driver.bus = &fsl_mc_bus_type; |
||
5743 | - |
||
5744 | - if (mc_driver->probe) |
||
5745 | - mc_driver->driver.probe = fsl_mc_driver_probe; |
||
5746 | - |
||
5747 | - if (mc_driver->remove) |
||
5748 | - mc_driver->driver.remove = fsl_mc_driver_remove; |
||
5749 | - |
||
5750 | - if (mc_driver->shutdown) |
||
5751 | - mc_driver->driver.shutdown = fsl_mc_driver_shutdown; |
||
5752 | - |
||
5753 | - error = driver_register(&mc_driver->driver); |
||
5754 | - if (error < 0) { |
||
5755 | - pr_err("driver_register() failed for %s: %d\n", |
||
5756 | - mc_driver->driver.name, error); |
||
5757 | - return error; |
||
5758 | - } |
||
5759 | - |
||
5760 | - return 0; |
||
5761 | -} |
||
5762 | -EXPORT_SYMBOL_GPL(__fsl_mc_driver_register); |
||
5763 | - |
||
5764 | -/** |
||
5765 | - * fsl_mc_driver_unregister - unregisters a device driver from the |
||
5766 | - * MC bus |
||
5767 | - */ |
||
5768 | -void fsl_mc_driver_unregister(struct fsl_mc_driver *mc_driver) |
||
5769 | -{ |
||
5770 | - driver_unregister(&mc_driver->driver); |
||
5771 | -} |
||
5772 | -EXPORT_SYMBOL_GPL(fsl_mc_driver_unregister); |
||
5773 | - |
||
5774 | -/** |
||
5775 | - * mc_get_version() - Retrieves the Management Complex firmware |
||
5776 | - * version information |
||
5777 | - * @mc_io: Pointer to opaque I/O object |
||
5778 | - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
5779 | - * @mc_ver_info: Returned version information structure |
||
5780 | - * |
||
5781 | - * Return: '0' on Success; Error code otherwise. |
||
5782 | - */ |
||
5783 | -static int mc_get_version(struct fsl_mc_io *mc_io, |
||
5784 | - u32 cmd_flags, |
||
5785 | - struct mc_version *mc_ver_info) |
||
5786 | -{ |
||
5787 | - struct mc_command cmd = { 0 }; |
||
5788 | - struct dpmng_rsp_get_version *rsp_params; |
||
5789 | - int err; |
||
5790 | - |
||
5791 | - /* prepare command */ |
||
5792 | - cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_VERSION, |
||
5793 | - cmd_flags, |
||
5794 | - 0); |
||
5795 | - |
||
5796 | - /* send command to mc*/ |
||
5797 | - err = mc_send_command(mc_io, &cmd); |
||
5798 | - if (err) |
||
5799 | - return err; |
||
5800 | - |
||
5801 | - /* retrieve response parameters */ |
||
5802 | - rsp_params = (struct dpmng_rsp_get_version *)cmd.params; |
||
5803 | - mc_ver_info->revision = le32_to_cpu(rsp_params->revision); |
||
5804 | - mc_ver_info->major = le32_to_cpu(rsp_params->version_major); |
||
5805 | - mc_ver_info->minor = le32_to_cpu(rsp_params->version_minor); |
||
5806 | - |
||
5807 | - return 0; |
||
5808 | -} |
||
5809 | - |
||
5810 | -/** |
||
5811 | - * fsl_mc_get_root_dprc - function to traverse to the root dprc |
||
5812 | - */ |
||
5813 | -static void fsl_mc_get_root_dprc(struct device *dev, |
||
5814 | - struct device **root_dprc_dev) |
||
5815 | -{ |
||
5816 | - if (WARN_ON(!dev)) { |
||
5817 | - *root_dprc_dev = NULL; |
||
5818 | - } else if (WARN_ON(!dev_is_fsl_mc(dev))) { |
||
5819 | - *root_dprc_dev = NULL; |
||
5820 | - } else { |
||
5821 | - *root_dprc_dev = dev; |
||
5822 | - while (dev_is_fsl_mc((*root_dprc_dev)->parent)) |
||
5823 | - *root_dprc_dev = (*root_dprc_dev)->parent; |
||
5824 | - } |
||
5825 | -} |
||
5826 | - |
||
5827 | -static int get_dprc_attr(struct fsl_mc_io *mc_io, |
||
5828 | - int container_id, struct dprc_attributes *attr) |
||
5829 | -{ |
||
5830 | - u16 dprc_handle; |
||
5831 | - int error; |
||
5832 | - |
||
5833 | - error = dprc_open(mc_io, 0, container_id, &dprc_handle); |
||
5834 | - if (error < 0) { |
||
5835 | - dev_err(mc_io->dev, "dprc_open() failed: %d\n", error); |
||
5836 | - return error; |
||
5837 | - } |
||
5838 | - |
||
5839 | - memset(attr, 0, sizeof(struct dprc_attributes)); |
||
5840 | - error = dprc_get_attributes(mc_io, 0, dprc_handle, attr); |
||
5841 | - if (error < 0) { |
||
5842 | - dev_err(mc_io->dev, "dprc_get_attributes() failed: %d\n", |
||
5843 | - error); |
||
5844 | - goto common_cleanup; |
||
5845 | - } |
||
5846 | - |
||
5847 | - error = 0; |
||
5848 | - |
||
5849 | -common_cleanup: |
||
5850 | - (void)dprc_close(mc_io, 0, dprc_handle); |
||
5851 | - return error; |
||
5852 | -} |
||
5853 | - |
||
5854 | -static int get_dprc_icid(struct fsl_mc_io *mc_io, |
||
5855 | - int container_id, u16 *icid) |
||
5856 | -{ |
||
5857 | - struct dprc_attributes attr; |
||
5858 | - int error; |
||
5859 | - |
||
5860 | - error = get_dprc_attr(mc_io, container_id, &attr); |
||
5861 | - if (error == 0) |
||
5862 | - *icid = attr.icid; |
||
5863 | - |
||
5864 | - return error; |
||
5865 | -} |
||
5866 | - |
||
5867 | -static int translate_mc_addr(struct fsl_mc_device *mc_dev, |
||
5868 | - enum dprc_region_type mc_region_type, |
||
5869 | - u64 mc_offset, phys_addr_t *phys_addr) |
||
5870 | -{ |
||
5871 | - int i; |
||
5872 | - struct device *root_dprc_dev; |
||
5873 | - struct fsl_mc *mc; |
||
5874 | - |
||
5875 | - fsl_mc_get_root_dprc(&mc_dev->dev, &root_dprc_dev); |
||
5876 | - if (WARN_ON(!root_dprc_dev)) |
||
5877 | - return -EINVAL; |
||
5878 | - mc = dev_get_drvdata(root_dprc_dev->parent); |
||
5879 | - |
||
5880 | - if (mc->num_translation_ranges == 0) { |
||
5881 | - /* |
||
5882 | - * Do identity mapping: |
||
5883 | - */ |
||
5884 | - *phys_addr = mc_offset; |
||
5885 | - return 0; |
||
5886 | - } |
||
5887 | - |
||
5888 | - for (i = 0; i < mc->num_translation_ranges; i++) { |
||
5889 | - struct fsl_mc_addr_translation_range *range = |
||
5890 | - &mc->translation_ranges[i]; |
||
5891 | - |
||
5892 | - if (mc_region_type == range->mc_region_type && |
||
5893 | - mc_offset >= range->start_mc_offset && |
||
5894 | - mc_offset < range->end_mc_offset) { |
||
5895 | - *phys_addr = range->start_phys_addr + |
||
5896 | - (mc_offset - range->start_mc_offset); |
||
5897 | - return 0; |
||
5898 | - } |
||
5899 | - } |
||
5900 | - |
||
5901 | - return -EFAULT; |
||
5902 | -} |
||
5903 | - |
||
5904 | -static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev, |
||
5905 | - struct fsl_mc_device *mc_bus_dev) |
||
5906 | -{ |
||
5907 | - int i; |
||
5908 | - int error; |
||
5909 | - struct resource *regions; |
||
5910 | - struct fsl_mc_obj_desc *obj_desc = &mc_dev->obj_desc; |
||
5911 | - struct device *parent_dev = mc_dev->dev.parent; |
||
5912 | - enum dprc_region_type mc_region_type; |
||
5913 | - |
||
5914 | - if (strcmp(obj_desc->type, "dprc") == 0 || |
||
5915 | - strcmp(obj_desc->type, "dpmcp") == 0) { |
||
5916 | - mc_region_type = DPRC_REGION_TYPE_MC_PORTAL; |
||
5917 | - } else if (strcmp(obj_desc->type, "dpio") == 0) { |
||
5918 | - mc_region_type = DPRC_REGION_TYPE_QBMAN_PORTAL; |
||
5919 | - } else { |
||
5920 | - /* |
||
5921 | - * This function should not have been called for this MC object |
||
5922 | - * type, as this object type is not supposed to have MMIO |
||
5923 | - * regions |
||
5924 | - */ |
||
5925 | - WARN_ON(true); |
||
5926 | - return -EINVAL; |
||
5927 | - } |
||
5928 | - |
||
5929 | - regions = kmalloc_array(obj_desc->region_count, |
||
5930 | - sizeof(regions[0]), GFP_KERNEL); |
||
5931 | - if (!regions) |
||
5932 | - return -ENOMEM; |
||
5933 | - |
||
5934 | - for (i = 0; i < obj_desc->region_count; i++) { |
||
5935 | - struct dprc_region_desc region_desc; |
||
5936 | - |
||
5937 | - error = dprc_get_obj_region(mc_bus_dev->mc_io, |
||
5938 | - 0, |
||
5939 | - mc_bus_dev->mc_handle, |
||
5940 | - obj_desc->type, |
||
5941 | - obj_desc->id, i, ®ion_desc); |
||
5942 | - if (error < 0) { |
||
5943 | - dev_err(parent_dev, |
||
5944 | - "dprc_get_obj_region() failed: %d\n", error); |
||
5945 | - goto error_cleanup_regions; |
||
5946 | - } |
||
5947 | - |
||
5948 | - WARN_ON(region_desc.size == 0); |
||
5949 | - error = translate_mc_addr(mc_dev, mc_region_type, |
||
5950 | - region_desc.base_offset, |
||
5951 | - ®ions[i].start); |
||
5952 | - if (error < 0) { |
||
5953 | - dev_err(parent_dev, |
||
5954 | - "Invalid MC offset: %#x (for %s.%d\'s region %d)\n", |
||
5955 | - region_desc.base_offset, |
||
5956 | - obj_desc->type, obj_desc->id, i); |
||
5957 | - goto error_cleanup_regions; |
||
5958 | - } |
||
5959 | - |
||
5960 | - regions[i].end = regions[i].start + region_desc.size - 1; |
||
5961 | - regions[i].name = "fsl-mc object MMIO region"; |
||
5962 | - regions[i].flags = IORESOURCE_IO; |
||
5963 | - if (region_desc.flags & DPRC_REGION_CACHEABLE) |
||
5964 | - regions[i].flags |= IORESOURCE_CACHEABLE; |
||
5965 | - } |
||
5966 | - |
||
5967 | - mc_dev->regions = regions; |
||
5968 | - return 0; |
||
5969 | - |
||
5970 | -error_cleanup_regions: |
||
5971 | - kfree(regions); |
||
5972 | - return error; |
||
5973 | -} |
||
5974 | - |
||
5975 | -/** |
||
5976 | - * fsl_mc_is_root_dprc - function to check if a given device is a root dprc |
||
5977 | - */ |
||
5978 | -bool fsl_mc_is_root_dprc(struct device *dev) |
||
5979 | -{ |
||
5980 | - struct device *root_dprc_dev; |
||
5981 | - |
||
5982 | - fsl_mc_get_root_dprc(dev, &root_dprc_dev); |
||
5983 | - if (!root_dprc_dev) |
||
5984 | - return false; |
||
5985 | - return dev == root_dprc_dev; |
||
5986 | -} |
||
5987 | - |
||
5988 | -static void fsl_mc_device_release(struct device *dev) |
||
5989 | -{ |
||
5990 | - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); |
||
5991 | - |
||
5992 | - kfree(mc_dev->regions); |
||
5993 | - |
||
5994 | - if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) |
||
5995 | - kfree(to_fsl_mc_bus(mc_dev)); |
||
5996 | - else |
||
5997 | - kfree(mc_dev); |
||
5998 | -} |
||
5999 | - |
||
6000 | -/** |
||
6001 | - * Add a newly discovered fsl-mc device to be visible in Linux |
||
6002 | - */ |
||
6003 | -int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc, |
||
6004 | - struct fsl_mc_io *mc_io, |
||
6005 | - struct device *parent_dev, |
||
6006 | - struct fsl_mc_device **new_mc_dev) |
||
6007 | -{ |
||
6008 | - int error; |
||
6009 | - struct fsl_mc_device *mc_dev = NULL; |
||
6010 | - struct fsl_mc_bus *mc_bus = NULL; |
||
6011 | - struct fsl_mc_device *parent_mc_dev; |
||
6012 | - |
||
6013 | - if (dev_is_fsl_mc(parent_dev)) |
||
6014 | - parent_mc_dev = to_fsl_mc_device(parent_dev); |
||
6015 | - else |
||
6016 | - parent_mc_dev = NULL; |
||
6017 | - |
||
6018 | - if (strcmp(obj_desc->type, "dprc") == 0) { |
||
6019 | - /* |
||
6020 | - * Allocate an MC bus device object: |
||
6021 | - */ |
||
6022 | - mc_bus = kzalloc(sizeof(*mc_bus), GFP_KERNEL); |
||
6023 | - if (!mc_bus) |
||
6024 | - return -ENOMEM; |
||
6025 | - |
||
6026 | - mc_dev = &mc_bus->mc_dev; |
||
6027 | - } else { |
||
6028 | - /* |
||
6029 | - * Allocate a regular fsl_mc_device object: |
||
6030 | - */ |
||
6031 | - mc_dev = kzalloc(sizeof(*mc_dev), GFP_KERNEL); |
||
6032 | - if (!mc_dev) |
||
6033 | - return -ENOMEM; |
||
6034 | - } |
||
6035 | - |
||
6036 | - mc_dev->obj_desc = *obj_desc; |
||
6037 | - mc_dev->mc_io = mc_io; |
||
6038 | - device_initialize(&mc_dev->dev); |
||
6039 | - mc_dev->dev.parent = parent_dev; |
||
6040 | - mc_dev->dev.bus = &fsl_mc_bus_type; |
||
6041 | - mc_dev->dev.release = fsl_mc_device_release; |
||
6042 | - dev_set_name(&mc_dev->dev, "%s.%d", obj_desc->type, obj_desc->id); |
||
6043 | - |
||
6044 | - if (strcmp(obj_desc->type, "dprc") == 0) { |
||
6045 | - struct fsl_mc_io *mc_io2; |
||
6046 | - |
||
6047 | - mc_dev->flags |= FSL_MC_IS_DPRC; |
||
6048 | - |
||
6049 | - /* |
||
6050 | - * To get the DPRC's ICID, we need to open the DPRC |
||
6051 | - * in get_dprc_icid(). For child DPRCs, we do so using the |
||
6052 | - * parent DPRC's MC portal instead of the child DPRC's MC |
||
6053 | - * portal, in case the child DPRC is already opened with |
||
6054 | - * its own portal (e.g., the DPRC used by AIOP). |
||
6055 | - * |
||
6056 | - * NOTE: There cannot be more than one active open for a |
||
6057 | - * given MC object, using the same MC portal. |
||
6058 | - */ |
||
6059 | - if (parent_mc_dev) { |
||
6060 | - /* |
||
6061 | - * device being added is a child DPRC device |
||
6062 | - */ |
||
6063 | - mc_io2 = parent_mc_dev->mc_io; |
||
6064 | - } else { |
||
6065 | - /* |
||
6066 | - * device being added is the root DPRC device |
||
6067 | - */ |
||
6068 | - if (WARN_ON(!mc_io)) { |
||
6069 | - error = -EINVAL; |
||
6070 | - goto error_cleanup_dev; |
||
6071 | - } |
||
6072 | - |
||
6073 | - mc_io2 = mc_io; |
||
6074 | - } |
||
6075 | - |
||
6076 | - error = get_dprc_icid(mc_io2, obj_desc->id, &mc_dev->icid); |
||
6077 | - if (error < 0) |
||
6078 | - goto error_cleanup_dev; |
||
6079 | - } else { |
||
6080 | - /* |
||
6081 | - * A non-DPRC object has to be a child of a DPRC, use the |
||
6082 | - * parent's ICID and interrupt domain. |
||
6083 | - */ |
||
6084 | - mc_dev->icid = parent_mc_dev->icid; |
||
6085 | - mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK; |
||
6086 | - mc_dev->dev.dma_mask = &mc_dev->dma_mask; |
||
6087 | - dev_set_msi_domain(&mc_dev->dev, |
||
6088 | - dev_get_msi_domain(&parent_mc_dev->dev)); |
||
6089 | - } |
||
6090 | - |
||
6091 | - /* |
||
6092 | - * Get MMIO regions for the device from the MC: |
||
6093 | - * |
||
6094 | - * NOTE: the root DPRC is a special case as its MMIO region is |
||
6095 | - * obtained from the device tree |
||
6096 | - */ |
||
6097 | - if (parent_mc_dev && obj_desc->region_count != 0) { |
||
6098 | - error = fsl_mc_device_get_mmio_regions(mc_dev, |
||
6099 | - parent_mc_dev); |
||
6100 | - if (error < 0) |
||
6101 | - goto error_cleanup_dev; |
||
6102 | - } |
||
6103 | - |
||
6104 | - /* Objects are coherent, unless 'no shareability' flag set. */ |
||
6105 | - if (!(obj_desc->flags & FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY)) |
||
6106 | - arch_setup_dma_ops(&mc_dev->dev, 0, 0, NULL, true); |
||
6107 | - |
||
6108 | - /* |
||
6109 | - * The device-specific probe callback will get invoked by device_add() |
||
6110 | - */ |
||
6111 | - error = device_add(&mc_dev->dev); |
||
6112 | - if (error < 0) { |
||
6113 | - dev_err(parent_dev, |
||
6114 | - "device_add() failed for device %s: %d\n", |
||
6115 | - dev_name(&mc_dev->dev), error); |
||
6116 | - goto error_cleanup_dev; |
||
6117 | - } |
||
6118 | - |
||
6119 | - dev_dbg(parent_dev, "added %s\n", dev_name(&mc_dev->dev)); |
||
6120 | - |
||
6121 | - *new_mc_dev = mc_dev; |
||
6122 | - return 0; |
||
6123 | - |
||
6124 | -error_cleanup_dev: |
||
6125 | - kfree(mc_dev->regions); |
||
6126 | - kfree(mc_bus); |
||
6127 | - kfree(mc_dev); |
||
6128 | - |
||
6129 | - return error; |
||
6130 | -} |
||
6131 | -EXPORT_SYMBOL_GPL(fsl_mc_device_add); |
||
6132 | - |
||
6133 | -/** |
||
6134 | - * fsl_mc_device_remove - Remove an fsl-mc device from being visible to |
||
6135 | - * Linux |
||
6136 | - * |
||
6137 | - * @mc_dev: Pointer to an fsl-mc device |
||
6138 | - */ |
||
6139 | -void fsl_mc_device_remove(struct fsl_mc_device *mc_dev) |
||
6140 | -{ |
||
6141 | - /* |
||
6142 | - * The device-specific remove callback will get invoked by device_del() |
||
6143 | - */ |
||
6144 | - device_del(&mc_dev->dev); |
||
6145 | - put_device(&mc_dev->dev); |
||
6146 | -} |
||
6147 | -EXPORT_SYMBOL_GPL(fsl_mc_device_remove); |
||
6148 | - |
||
6149 | -static int parse_mc_ranges(struct device *dev, |
||
6150 | - int *paddr_cells, |
||
6151 | - int *mc_addr_cells, |
||
6152 | - int *mc_size_cells, |
||
6153 | - const __be32 **ranges_start) |
||
6154 | -{ |
||
6155 | - const __be32 *prop; |
||
6156 | - int range_tuple_cell_count; |
||
6157 | - int ranges_len; |
||
6158 | - int tuple_len; |
||
6159 | - struct device_node *mc_node = dev->of_node; |
||
6160 | - |
||
6161 | - *ranges_start = of_get_property(mc_node, "ranges", &ranges_len); |
||
6162 | - if (!(*ranges_start) || !ranges_len) { |
||
6163 | - dev_warn(dev, |
||
6164 | - "missing or empty ranges property for device tree node '%s'\n", |
||
6165 | - mc_node->name); |
||
6166 | - return 0; |
||
6167 | - } |
||
6168 | - |
||
6169 | - *paddr_cells = of_n_addr_cells(mc_node); |
||
6170 | - |
||
6171 | - prop = of_get_property(mc_node, "#address-cells", NULL); |
||
6172 | - if (prop) |
||
6173 | - *mc_addr_cells = be32_to_cpup(prop); |
||
6174 | - else |
||
6175 | - *mc_addr_cells = *paddr_cells; |
||
6176 | - |
||
6177 | - prop = of_get_property(mc_node, "#size-cells", NULL); |
||
6178 | - if (prop) |
||
6179 | - *mc_size_cells = be32_to_cpup(prop); |
||
6180 | - else |
||
6181 | - *mc_size_cells = of_n_size_cells(mc_node); |
||
6182 | - |
||
6183 | - range_tuple_cell_count = *paddr_cells + *mc_addr_cells + |
||
6184 | - *mc_size_cells; |
||
6185 | - |
||
6186 | - tuple_len = range_tuple_cell_count * sizeof(__be32); |
||
6187 | - if (ranges_len % tuple_len != 0) { |
||
6188 | - dev_err(dev, "malformed ranges property '%s'\n", mc_node->name); |
||
6189 | - return -EINVAL; |
||
6190 | - } |
||
6191 | - |
||
6192 | - return ranges_len / tuple_len; |
||
6193 | -} |
||
6194 | - |
||
6195 | -static int get_mc_addr_translation_ranges(struct device *dev, |
||
6196 | - struct fsl_mc_addr_translation_range |
||
6197 | - **ranges, |
||
6198 | - u8 *num_ranges) |
||
6199 | -{ |
||
6200 | - int ret; |
||
6201 | - int paddr_cells; |
||
6202 | - int mc_addr_cells; |
||
6203 | - int mc_size_cells; |
||
6204 | - int i; |
||
6205 | - const __be32 *ranges_start; |
||
6206 | - const __be32 *cell; |
||
6207 | - |
||
6208 | - ret = parse_mc_ranges(dev, |
||
6209 | - &paddr_cells, |
||
6210 | - &mc_addr_cells, |
||
6211 | - &mc_size_cells, |
||
6212 | - &ranges_start); |
||
6213 | - if (ret < 0) |
||
6214 | - return ret; |
||
6215 | - |
||
6216 | - *num_ranges = ret; |
||
6217 | - if (!ret) { |
||
6218 | - /* |
||
6219 | - * Missing or empty ranges property ("ranges;") for the |
||
6220 | - * 'fsl,qoriq-mc' node. In this case, identity mapping |
||
6221 | - * will be used. |
||
6222 | - */ |
||
6223 | - *ranges = NULL; |
||
6224 | - return 0; |
||
6225 | - } |
||
6226 | - |
||
6227 | - *ranges = devm_kcalloc(dev, *num_ranges, |
||
6228 | - sizeof(struct fsl_mc_addr_translation_range), |
||
6229 | - GFP_KERNEL); |
||
6230 | - if (!(*ranges)) |
||
6231 | - return -ENOMEM; |
||
6232 | - |
||
6233 | - cell = ranges_start; |
||
6234 | - for (i = 0; i < *num_ranges; ++i) { |
||
6235 | - struct fsl_mc_addr_translation_range *range = &(*ranges)[i]; |
||
6236 | - |
||
6237 | - range->mc_region_type = of_read_number(cell, 1); |
||
6238 | - range->start_mc_offset = of_read_number(cell + 1, |
||
6239 | - mc_addr_cells - 1); |
||
6240 | - cell += mc_addr_cells; |
||
6241 | - range->start_phys_addr = of_read_number(cell, paddr_cells); |
||
6242 | - cell += paddr_cells; |
||
6243 | - range->end_mc_offset = range->start_mc_offset + |
||
6244 | - of_read_number(cell, mc_size_cells); |
||
6245 | - |
||
6246 | - cell += mc_size_cells; |
||
6247 | - } |
||
6248 | - |
||
6249 | - return 0; |
||
6250 | -} |
||
6251 | - |
||
6252 | -/** |
||
6253 | - * fsl_mc_bus_probe - callback invoked when the root MC bus is being |
||
6254 | - * added |
||
6255 | - */ |
||
6256 | -static int fsl_mc_bus_probe(struct platform_device *pdev) |
||
6257 | -{ |
||
6258 | - struct fsl_mc_obj_desc obj_desc; |
||
6259 | - int error; |
||
6260 | - struct fsl_mc *mc; |
||
6261 | - struct fsl_mc_device *mc_bus_dev = NULL; |
||
6262 | - struct fsl_mc_io *mc_io = NULL; |
||
6263 | - int container_id; |
||
6264 | - phys_addr_t mc_portal_phys_addr; |
||
6265 | - u32 mc_portal_size; |
||
6266 | - struct mc_version mc_version; |
||
6267 | - struct resource res; |
||
6268 | - |
||
6269 | - mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL); |
||
6270 | - if (!mc) |
||
6271 | - return -ENOMEM; |
||
6272 | - |
||
6273 | - platform_set_drvdata(pdev, mc); |
||
6274 | - |
||
6275 | - /* |
||
6276 | - * Get physical address of MC portal for the root DPRC: |
||
6277 | - */ |
||
6278 | - error = of_address_to_resource(pdev->dev.of_node, 0, &res); |
||
6279 | - if (error < 0) { |
||
6280 | - dev_err(&pdev->dev, |
||
6281 | - "of_address_to_resource() failed for %pOF\n", |
||
6282 | - pdev->dev.of_node); |
||
6283 | - return error; |
||
6284 | - } |
||
6285 | - |
||
6286 | - mc_portal_phys_addr = res.start; |
||
6287 | - mc_portal_size = resource_size(&res); |
||
6288 | - error = fsl_create_mc_io(&pdev->dev, mc_portal_phys_addr, |
||
6289 | - mc_portal_size, NULL, |
||
6290 | - FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, &mc_io); |
||
6291 | - if (error < 0) |
||
6292 | - return error; |
||
6293 | - |
||
6294 | - error = mc_get_version(mc_io, 0, &mc_version); |
||
6295 | - if (error != 0) { |
||
6296 | - dev_err(&pdev->dev, |
||
6297 | - "mc_get_version() failed with error %d\n", error); |
||
6298 | - goto error_cleanup_mc_io; |
||
6299 | - } |
||
6300 | - |
||
6301 | - dev_info(&pdev->dev, "MC firmware version: %u.%u.%u\n", |
||
6302 | - mc_version.major, mc_version.minor, mc_version.revision); |
||
6303 | - |
||
6304 | - error = get_mc_addr_translation_ranges(&pdev->dev, |
||
6305 | - &mc->translation_ranges, |
||
6306 | - &mc->num_translation_ranges); |
||
6307 | - if (error < 0) |
||
6308 | - goto error_cleanup_mc_io; |
||
6309 | - |
||
6310 | - error = dprc_get_container_id(mc_io, 0, &container_id); |
||
6311 | - if (error < 0) { |
||
6312 | - dev_err(&pdev->dev, |
||
6313 | - "dprc_get_container_id() failed: %d\n", error); |
||
6314 | - goto error_cleanup_mc_io; |
||
6315 | - } |
||
6316 | - |
||
6317 | - memset(&obj_desc, 0, sizeof(struct fsl_mc_obj_desc)); |
||
6318 | - error = dprc_get_api_version(mc_io, 0, |
||
6319 | - &obj_desc.ver_major, |
||
6320 | - &obj_desc.ver_minor); |
||
6321 | - if (error < 0) |
||
6322 | - goto error_cleanup_mc_io; |
||
6323 | - |
||
6324 | - obj_desc.vendor = FSL_MC_VENDOR_FREESCALE; |
||
6325 | - strcpy(obj_desc.type, "dprc"); |
||
6326 | - obj_desc.id = container_id; |
||
6327 | - obj_desc.irq_count = 1; |
||
6328 | - obj_desc.region_count = 0; |
||
6329 | - |
||
6330 | - error = fsl_mc_device_add(&obj_desc, mc_io, &pdev->dev, &mc_bus_dev); |
||
6331 | - if (error < 0) |
||
6332 | - goto error_cleanup_mc_io; |
||
6333 | - |
||
6334 | - mc->root_mc_bus_dev = mc_bus_dev; |
||
6335 | - return 0; |
||
6336 | - |
||
6337 | -error_cleanup_mc_io: |
||
6338 | - fsl_destroy_mc_io(mc_io); |
||
6339 | - return error; |
||
6340 | -} |
||
6341 | - |
||
6342 | -/** |
||
6343 | - * fsl_mc_bus_remove - callback invoked when the root MC bus is being |
||
6344 | - * removed |
||
6345 | - */ |
||
6346 | -static int fsl_mc_bus_remove(struct platform_device *pdev) |
||
6347 | -{ |
||
6348 | - struct fsl_mc *mc = platform_get_drvdata(pdev); |
||
6349 | - |
||
6350 | - if (WARN_ON(!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev))) |
||
6351 | - return -EINVAL; |
||
6352 | - |
||
6353 | - fsl_mc_device_remove(mc->root_mc_bus_dev); |
||
6354 | - |
||
6355 | - fsl_destroy_mc_io(mc->root_mc_bus_dev->mc_io); |
||
6356 | - mc->root_mc_bus_dev->mc_io = NULL; |
||
6357 | - |
||
6358 | - return 0; |
||
6359 | -} |
||
6360 | - |
||
6361 | -static const struct of_device_id fsl_mc_bus_match_table[] = { |
||
6362 | - {.compatible = "fsl,qoriq-mc",}, |
||
6363 | - {}, |
||
6364 | -}; |
||
6365 | - |
||
6366 | -MODULE_DEVICE_TABLE(of, fsl_mc_bus_match_table); |
||
6367 | - |
||
6368 | -static struct platform_driver fsl_mc_bus_driver = { |
||
6369 | - .driver = { |
||
6370 | - .name = "fsl_mc_bus", |
||
6371 | - .pm = NULL, |
||
6372 | - .of_match_table = fsl_mc_bus_match_table, |
||
6373 | - }, |
||
6374 | - .probe = fsl_mc_bus_probe, |
||
6375 | - .remove = fsl_mc_bus_remove, |
||
6376 | -}; |
||
6377 | - |
||
6378 | -static int __init fsl_mc_bus_driver_init(void) |
||
6379 | -{ |
||
6380 | - int error; |
||
6381 | - |
||
6382 | - error = bus_register(&fsl_mc_bus_type); |
||
6383 | - if (error < 0) { |
||
6384 | - pr_err("bus type registration failed: %d\n", error); |
||
6385 | - goto error_cleanup_cache; |
||
6386 | - } |
||
6387 | - |
||
6388 | - error = platform_driver_register(&fsl_mc_bus_driver); |
||
6389 | - if (error < 0) { |
||
6390 | - pr_err("platform_driver_register() failed: %d\n", error); |
||
6391 | - goto error_cleanup_bus; |
||
6392 | - } |
||
6393 | - |
||
6394 | - error = dprc_driver_init(); |
||
6395 | - if (error < 0) |
||
6396 | - goto error_cleanup_driver; |
||
6397 | - |
||
6398 | - error = fsl_mc_allocator_driver_init(); |
||
6399 | - if (error < 0) |
||
6400 | - goto error_cleanup_dprc_driver; |
||
6401 | - |
||
6402 | - error = its_fsl_mc_msi_init(); |
||
6403 | - if (error < 0) |
||
6404 | - goto error_cleanup_mc_allocator; |
||
6405 | - |
||
6406 | - return 0; |
||
6407 | - |
||
6408 | -error_cleanup_mc_allocator: |
||
6409 | - fsl_mc_allocator_driver_exit(); |
||
6410 | - |
||
6411 | -error_cleanup_dprc_driver: |
||
6412 | - dprc_driver_exit(); |
||
6413 | - |
||
6414 | -error_cleanup_driver: |
||
6415 | - platform_driver_unregister(&fsl_mc_bus_driver); |
||
6416 | - |
||
6417 | -error_cleanup_bus: |
||
6418 | - bus_unregister(&fsl_mc_bus_type); |
||
6419 | - |
||
6420 | -error_cleanup_cache: |
||
6421 | - return error; |
||
6422 | -} |
||
6423 | -postcore_initcall(fsl_mc_bus_driver_init); |
||
6424 | --- /dev/null |
||
6425 | +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c |
||
6426 | @@ -0,0 +1,1139 @@ |
||
6427 | +// SPDX-License-Identifier: GPL-2.0 |
||
6428 | +/* |
||
6429 | + * Freescale Management Complex (MC) bus driver |
||
6430 | + * |
||
6431 | + * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. |
||
6432 | + * Author: German Rivera <German.Rivera@freescale.com> |
||
6433 | + * |
||
6434 | + */ |
||
6435 | + |
||
6436 | +#define pr_fmt(fmt) "fsl-mc: " fmt |
||
6437 | + |
||
6438 | +#include <linux/module.h> |
||
6439 | +#include <linux/of_device.h> |
||
6440 | +#include <linux/of_address.h> |
||
6441 | +#include <linux/ioport.h> |
||
6442 | +#include <linux/slab.h> |
||
6443 | +#include <linux/limits.h> |
||
6444 | +#include <linux/bitops.h> |
||
6445 | +#include <linux/msi.h> |
||
6446 | +#include <linux/dma-mapping.h> |
||
6447 | + |
||
6448 | +#include "fsl-mc-private.h" |
||
6449 | + |
||
6450 | +/** |
||
6451 | + * Default DMA mask for devices on a fsl-mc bus |
||
6452 | + */ |
||
6453 | +#define FSL_MC_DEFAULT_DMA_MASK (~0ULL) |
||
6454 | + |
||
6455 | +/** |
||
6456 | + * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device |
||
6457 | + * @root_mc_bus_dev: fsl-mc device representing the root DPRC |
||
6458 | + * @num_translation_ranges: number of entries in addr_translation_ranges |
||
6459 | + * @translation_ranges: array of bus to system address translation ranges |
||
6460 | + */ |
||
6461 | +struct fsl_mc { |
||
6462 | + struct fsl_mc_device *root_mc_bus_dev; |
||
6463 | + u8 num_translation_ranges; |
||
6464 | + struct fsl_mc_addr_translation_range *translation_ranges; |
||
6465 | +}; |
||
6466 | + |
||
6467 | +/** |
||
6468 | + * struct fsl_mc_addr_translation_range - bus to system address translation |
||
6469 | + * range |
||
6470 | + * @mc_region_type: Type of MC region for the range being translated |
||
6471 | + * @start_mc_offset: Start MC offset of the range being translated |
||
6472 | + * @end_mc_offset: MC offset of the first byte after the range (last MC |
||
6473 | + * offset of the range is end_mc_offset - 1) |
||
6474 | + * @start_phys_addr: system physical address corresponding to start_mc_addr |
||
6475 | + */ |
||
6476 | +struct fsl_mc_addr_translation_range { |
||
6477 | + enum dprc_region_type mc_region_type; |
||
6478 | + u64 start_mc_offset; |
||
6479 | + u64 end_mc_offset; |
||
6480 | + phys_addr_t start_phys_addr; |
||
6481 | +}; |
||
6482 | + |
||
6483 | +/** |
||
6484 | + * struct mc_version |
||
6485 | + * @major: Major version number: incremented on API compatibility changes |
||
6486 | + * @minor: Minor version number: incremented on API additions (that are |
||
6487 | + * backward compatible); reset when major version is incremented |
||
6488 | + * @revision: Internal revision number: incremented on implementation changes |
||
6489 | + * and/or bug fixes that have no impact on API |
||
6490 | + */ |
||
6491 | +struct mc_version { |
||
6492 | + u32 major; |
||
6493 | + u32 minor; |
||
6494 | + u32 revision; |
||
6495 | +}; |
||
6496 | + |
||
6497 | +/** |
||
6498 | + * fsl_mc_bus_match - device to driver matching callback |
||
6499 | + * @dev: the fsl-mc device to match against |
||
6500 | + * @drv: the device driver to search for matching fsl-mc object type |
||
6501 | + * structures |
||
6502 | + * |
||
6503 | + * Returns 1 on success, 0 otherwise. |
||
6504 | + */ |
||
6505 | +static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv) |
||
6506 | +{ |
||
6507 | + const struct fsl_mc_device_id *id; |
||
6508 | + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); |
||
6509 | + struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv); |
||
6510 | + bool found = false; |
||
6511 | + |
||
6512 | + /* When driver_override is set, only bind to the matching driver */ |
||
6513 | + if (mc_dev->driver_override) { |
||
6514 | + found = !strcmp(mc_dev->driver_override, mc_drv->driver.name); |
||
6515 | + goto out; |
||
6516 | + } |
||
6517 | + |
||
6518 | + if (!mc_drv->match_id_table) |
||
6519 | + goto out; |
||
6520 | + |
||
6521 | + /* |
||
6522 | + * If the object is not 'plugged' don't match. |
||
6523 | + * Only exception is the root DPRC, which is a special case. |
||
6524 | + */ |
||
6525 | + if ((mc_dev->obj_desc.state & FSL_MC_OBJ_STATE_PLUGGED) == 0 && |
||
6526 | + !fsl_mc_is_root_dprc(&mc_dev->dev)) |
||
6527 | + goto out; |
||
6528 | + |
||
6529 | + /* |
||
6530 | + * Traverse the match_id table of the given driver, trying to find |
||
6531 | + * a matching for the given device. |
||
6532 | + */ |
||
6533 | + for (id = mc_drv->match_id_table; id->vendor != 0x0; id++) { |
||
6534 | + if (id->vendor == mc_dev->obj_desc.vendor && |
||
6535 | + strcmp(id->obj_type, mc_dev->obj_desc.type) == 0) { |
||
6536 | + found = true; |
||
6537 | + |
||
6538 | + break; |
||
6539 | + } |
||
6540 | + } |
||
6541 | + |
||
6542 | +out: |
||
6543 | + dev_dbg(dev, "%smatched\n", found ? "" : "not "); |
||
6544 | + return found; |
||
6545 | +} |
||
6546 | + |
||
6547 | +/** |
||
6548 | + * fsl_mc_bus_uevent - callback invoked when a device is added |
||
6549 | + */ |
||
6550 | +static int fsl_mc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) |
||
6551 | +{ |
||
6552 | + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); |
||
6553 | + |
||
6554 | + if (add_uevent_var(env, "MODALIAS=fsl-mc:v%08Xd%s", |
||
6555 | + mc_dev->obj_desc.vendor, |
||
6556 | + mc_dev->obj_desc.type)) |
||
6557 | + return -ENOMEM; |
||
6558 | + |
||
6559 | + return 0; |
||
6560 | +} |
||
6561 | + |
||
6562 | +static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, |
||
6563 | + char *buf) |
||
6564 | +{ |
||
6565 | + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); |
||
6566 | + |
||
6567 | + return sprintf(buf, "fsl-mc:v%08Xd%s\n", mc_dev->obj_desc.vendor, |
||
6568 | + mc_dev->obj_desc.type); |
||
6569 | +} |
||
6570 | +static DEVICE_ATTR_RO(modalias); |
||
6571 | + |
||
6572 | +static ssize_t rescan_store(struct device *dev, |
||
6573 | + struct device_attribute *attr, |
||
6574 | + const char *buf, size_t count) |
||
6575 | +{ |
||
6576 | + struct fsl_mc_device *root_mc_dev; |
||
6577 | + struct fsl_mc_bus *root_mc_bus; |
||
6578 | + unsigned long val; |
||
6579 | + |
||
6580 | + if (!fsl_mc_is_root_dprc(dev)) |
||
6581 | + return -EINVAL; |
||
6582 | + |
||
6583 | + root_mc_dev = to_fsl_mc_device(dev); |
||
6584 | + root_mc_bus = to_fsl_mc_bus(root_mc_dev); |
||
6585 | + |
||
6586 | + if (kstrtoul(buf, 0, &val) < 0) |
||
6587 | + return -EINVAL; |
||
6588 | + |
||
6589 | + if (val) { |
||
6590 | + mutex_lock(&root_mc_bus->scan_mutex); |
||
6591 | + dprc_scan_objects(root_mc_dev, NULL, NULL); |
||
6592 | + mutex_unlock(&root_mc_bus->scan_mutex); |
||
6593 | + } |
||
6594 | + |
||
6595 | + return count; |
||
6596 | +} |
||
6597 | +static DEVICE_ATTR_WO(rescan); |
||
6598 | + |
||
6599 | +static ssize_t driver_override_store(struct device *dev, |
||
6600 | + struct device_attribute *attr, |
||
6601 | + const char *buf, size_t count) |
||
6602 | +{ |
||
6603 | + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); |
||
6604 | + const char *driver_override, *old = mc_dev->driver_override; |
||
6605 | + char *cp; |
||
6606 | + |
||
6607 | + if (WARN_ON(dev->bus != &fsl_mc_bus_type)) |
||
6608 | + return -EINVAL; |
||
6609 | + |
||
6610 | + if (count >= (PAGE_SIZE - 1)) |
||
6611 | + return -EINVAL; |
||
6612 | + |
||
6613 | + driver_override = kstrndup(buf, count, GFP_KERNEL); |
||
6614 | + if (!driver_override) |
||
6615 | + return -ENOMEM; |
||
6616 | + |
||
6617 | + cp = strchr(driver_override, '\n'); |
||
6618 | + if (cp) |
||
6619 | + *cp = '\0'; |
||
6620 | + |
||
6621 | + if (strlen(driver_override)) { |
||
6622 | + mc_dev->driver_override = driver_override; |
||
6623 | + } else { |
||
6624 | + kfree(driver_override); |
||
6625 | + mc_dev->driver_override = NULL; |
||
6626 | + } |
||
6627 | + |
||
6628 | + kfree(old); |
||
6629 | + |
||
6630 | + return count; |
||
6631 | +} |
||
6632 | + |
||
6633 | +static ssize_t driver_override_show(struct device *dev, |
||
6634 | + struct device_attribute *attr, char *buf) |
||
6635 | +{ |
||
6636 | + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); |
||
6637 | + |
||
6638 | + return snprintf(buf, PAGE_SIZE, "%s\n", mc_dev->driver_override); |
||
6639 | +} |
||
6640 | +static DEVICE_ATTR_RW(driver_override); |
||
6641 | + |
||
6642 | +static struct attribute *fsl_mc_dev_attrs[] = { |
||
6643 | + &dev_attr_modalias.attr, |
||
6644 | + &dev_attr_rescan.attr, |
||
6645 | + &dev_attr_driver_override.attr, |
||
6646 | + NULL, |
||
6647 | +}; |
||
6648 | + |
||
6649 | +ATTRIBUTE_GROUPS(fsl_mc_dev); |
||
6650 | + |
||
6651 | +static int scan_fsl_mc_bus(struct device *dev, void *data) |
||
6652 | +{ |
||
6653 | + struct fsl_mc_device *root_mc_dev; |
||
6654 | + struct fsl_mc_bus *root_mc_bus; |
||
6655 | + |
||
6656 | + if (!fsl_mc_is_root_dprc(dev)) |
||
6657 | + goto exit; |
||
6658 | + |
||
6659 | + root_mc_dev = to_fsl_mc_device(dev); |
||
6660 | + root_mc_bus = to_fsl_mc_bus(root_mc_dev); |
||
6661 | + mutex_lock(&root_mc_bus->scan_mutex); |
||
6662 | + dprc_scan_objects(root_mc_dev, NULL, NULL); |
||
6663 | + mutex_unlock(&root_mc_bus->scan_mutex); |
||
6664 | + |
||
6665 | +exit: |
||
6666 | + return 0; |
||
6667 | +} |
||
6668 | + |
||
6669 | +static ssize_t bus_rescan_store(struct bus_type *bus, |
||
6670 | + const char *buf, size_t count) |
||
6671 | +{ |
||
6672 | + unsigned long val; |
||
6673 | + |
||
6674 | + if (kstrtoul(buf, 0, &val) < 0) |
||
6675 | + return -EINVAL; |
||
6676 | + |
||
6677 | + if (val) |
||
6678 | + bus_for_each_dev(bus, NULL, NULL, scan_fsl_mc_bus); |
||
6679 | + |
||
6680 | + return count; |
||
6681 | +} |
||
6682 | +static BUS_ATTR(rescan, 0220, NULL, bus_rescan_store); |
||
6683 | + |
||
6684 | +static struct attribute *fsl_mc_bus_attrs[] = { |
||
6685 | + &bus_attr_rescan.attr, |
||
6686 | + NULL, |
||
6687 | +}; |
||
6688 | + |
||
6689 | +static const struct attribute_group fsl_mc_bus_group = { |
||
6690 | + .attrs = fsl_mc_bus_attrs, |
||
6691 | +}; |
||
6692 | + |
||
6693 | +static const struct attribute_group *fsl_mc_bus_groups[] = { |
||
6694 | + &fsl_mc_bus_group, |
||
6695 | + NULL, |
||
6696 | +}; |
||
6697 | + |
||
6698 | +struct bus_type fsl_mc_bus_type = { |
||
6699 | + .name = "fsl-mc", |
||
6700 | + .match = fsl_mc_bus_match, |
||
6701 | + .uevent = fsl_mc_bus_uevent, |
||
6702 | + .dev_groups = fsl_mc_dev_groups, |
||
6703 | + .bus_groups = fsl_mc_bus_groups, |
||
6704 | +}; |
||
6705 | +EXPORT_SYMBOL_GPL(fsl_mc_bus_type); |
||
6706 | + |
||
6707 | +struct device_type fsl_mc_bus_dprc_type = { |
||
6708 | + .name = "fsl_mc_bus_dprc" |
||
6709 | +}; |
||
6710 | + |
||
6711 | +struct device_type fsl_mc_bus_dpni_type = { |
||
6712 | + .name = "fsl_mc_bus_dpni" |
||
6713 | +}; |
||
6714 | + |
||
6715 | +struct device_type fsl_mc_bus_dpio_type = { |
||
6716 | + .name = "fsl_mc_bus_dpio" |
||
6717 | +}; |
||
6718 | + |
||
6719 | +struct device_type fsl_mc_bus_dpsw_type = { |
||
6720 | + .name = "fsl_mc_bus_dpsw" |
||
6721 | +}; |
||
6722 | + |
||
6723 | +struct device_type fsl_mc_bus_dpdmux_type = { |
||
6724 | + .name = "fsl_mc_bus_dpdmux" |
||
6725 | +}; |
||
6726 | + |
||
6727 | +struct device_type fsl_mc_bus_dpbp_type = { |
||
6728 | + .name = "fsl_mc_bus_dpbp" |
||
6729 | +}; |
||
6730 | + |
||
6731 | +struct device_type fsl_mc_bus_dpcon_type = { |
||
6732 | + .name = "fsl_mc_bus_dpcon" |
||
6733 | +}; |
||
6734 | + |
||
6735 | +struct device_type fsl_mc_bus_dpmcp_type = { |
||
6736 | + .name = "fsl_mc_bus_dpmcp" |
||
6737 | +}; |
||
6738 | + |
||
6739 | +struct device_type fsl_mc_bus_dpmac_type = { |
||
6740 | + .name = "fsl_mc_bus_dpmac" |
||
6741 | +}; |
||
6742 | + |
||
6743 | +struct device_type fsl_mc_bus_dprtc_type = { |
||
6744 | + .name = "fsl_mc_bus_dprtc" |
||
6745 | +}; |
||
6746 | + |
||
6747 | +struct device_type fsl_mc_bus_dpseci_type = { |
||
6748 | + .name = "fsl_mc_bus_dpseci" |
||
6749 | +}; |
||
6750 | + |
||
6751 | +struct device_type fsl_mc_bus_dpdcei_type = { |
||
6752 | + .name = "fsl_mc_bus_dpdcei" |
||
6753 | +}; |
||
6754 | + |
||
6755 | +struct device_type fsl_mc_bus_dpaiop_type = { |
||
6756 | + .name = "fsl_mc_bus_dpaiop" |
||
6757 | +}; |
||
6758 | + |
||
6759 | +struct device_type fsl_mc_bus_dpci_type = { |
||
6760 | + .name = "fsl_mc_bus_dpci" |
||
6761 | +}; |
||
6762 | + |
||
6763 | +struct device_type fsl_mc_bus_dpdmai_type = { |
||
6764 | + .name = "fsl_mc_bus_dpdmai" |
||
6765 | +}; |
||
6766 | + |
||
6767 | +static struct device_type *fsl_mc_get_device_type(const char *type) |
||
6768 | +{ |
||
6769 | + static const struct { |
||
6770 | + struct device_type *dev_type; |
||
6771 | + const char *type; |
||
6772 | + } dev_types[] = { |
||
6773 | + { &fsl_mc_bus_dprc_type, "dprc" }, |
||
6774 | + { &fsl_mc_bus_dpni_type, "dpni" }, |
||
6775 | + { &fsl_mc_bus_dpio_type, "dpio" }, |
||
6776 | + { &fsl_mc_bus_dpsw_type, "dpsw" }, |
||
6777 | + { &fsl_mc_bus_dpdmux_type, "dpdmux" }, |
||
6778 | + { &fsl_mc_bus_dpbp_type, "dpbp" }, |
||
6779 | + { &fsl_mc_bus_dpcon_type, "dpcon" }, |
||
6780 | + { &fsl_mc_bus_dpmcp_type, "dpmcp" }, |
||
6781 | + { &fsl_mc_bus_dpmac_type, "dpmac" }, |
||
6782 | + { &fsl_mc_bus_dprtc_type, "dprtc" }, |
||
6783 | + { &fsl_mc_bus_dpseci_type, "dpseci" }, |
||
6784 | + { &fsl_mc_bus_dpdcei_type, "dpdcei" }, |
||
6785 | + { &fsl_mc_bus_dpaiop_type, "dpaiop" }, |
||
6786 | + { &fsl_mc_bus_dpci_type, "dpci" }, |
||
6787 | + { &fsl_mc_bus_dpdmai_type, "dpdmai" }, |
||
6788 | + { NULL, NULL } |
||
6789 | + }; |
||
6790 | + int i; |
||
6791 | + |
||
6792 | + for (i = 0; dev_types[i].dev_type; i++) |
||
6793 | + if (!strcmp(dev_types[i].type, type)) |
||
6794 | + return dev_types[i].dev_type; |
||
6795 | + |
||
6796 | + return NULL; |
||
6797 | +} |
||
6798 | + |
||
6799 | +static int fsl_mc_driver_probe(struct device *dev) |
||
6800 | +{ |
||
6801 | + struct fsl_mc_driver *mc_drv; |
||
6802 | + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); |
||
6803 | + int error; |
||
6804 | + |
||
6805 | + mc_drv = to_fsl_mc_driver(dev->driver); |
||
6806 | + |
||
6807 | + error = mc_drv->probe(mc_dev); |
||
6808 | + if (error < 0) { |
||
6809 | + if (error != -EPROBE_DEFER) |
||
6810 | + dev_err(dev, "%s failed: %d\n", __func__, error); |
||
6811 | + return error; |
||
6812 | + } |
||
6813 | + |
||
6814 | + return 0; |
||
6815 | +} |
||
6816 | + |
||
6817 | +static int fsl_mc_driver_remove(struct device *dev) |
||
6818 | +{ |
||
6819 | + struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); |
||
6820 | + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); |
||
6821 | + int error; |
||
6822 | + |
||
6823 | + error = mc_drv->remove(mc_dev); |
||
6824 | + if (error < 0) { |
||
6825 | + dev_err(dev, "%s failed: %d\n", __func__, error); |
||
6826 | + return error; |
||
6827 | + } |
||
6828 | + |
||
6829 | + return 0; |
||
6830 | +} |
||
6831 | + |
||
6832 | +static void fsl_mc_driver_shutdown(struct device *dev) |
||
6833 | +{ |
||
6834 | + struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); |
||
6835 | + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); |
||
6836 | + |
||
6837 | + mc_drv->shutdown(mc_dev); |
||
6838 | +} |
||
6839 | + |
||
6840 | +/** |
||
6841 | + * __fsl_mc_driver_register - registers a child device driver with the |
||
6842 | + * MC bus |
||
6843 | + * |
||
6844 | + * This function is implicitly invoked from the registration function of |
||
6845 | + * fsl_mc device drivers, which is generated by the |
||
6846 | + * module_fsl_mc_driver() macro. |
||
6847 | + */ |
||
6848 | +int __fsl_mc_driver_register(struct fsl_mc_driver *mc_driver, |
||
6849 | + struct module *owner) |
||
6850 | +{ |
||
6851 | + int error; |
||
6852 | + |
||
6853 | + mc_driver->driver.owner = owner; |
||
6854 | + mc_driver->driver.bus = &fsl_mc_bus_type; |
||
6855 | + |
||
6856 | + if (mc_driver->probe) |
||
6857 | + mc_driver->driver.probe = fsl_mc_driver_probe; |
||
6858 | + |
||
6859 | + if (mc_driver->remove) |
||
6860 | + mc_driver->driver.remove = fsl_mc_driver_remove; |
||
6861 | + |
||
6862 | + if (mc_driver->shutdown) |
||
6863 | + mc_driver->driver.shutdown = fsl_mc_driver_shutdown; |
||
6864 | + |
||
6865 | + error = driver_register(&mc_driver->driver); |
||
6866 | + if (error < 0) { |
||
6867 | + pr_err("driver_register() failed for %s: %d\n", |
||
6868 | + mc_driver->driver.name, error); |
||
6869 | + return error; |
||
6870 | + } |
||
6871 | + |
||
6872 | + return 0; |
||
6873 | +} |
||
6874 | +EXPORT_SYMBOL_GPL(__fsl_mc_driver_register); |
||
6875 | + |
||
6876 | +/** |
||
6877 | + * fsl_mc_driver_unregister - unregisters a device driver from the |
||
6878 | + * MC bus |
||
6879 | + */ |
||
6880 | +void fsl_mc_driver_unregister(struct fsl_mc_driver *mc_driver) |
||
6881 | +{ |
||
6882 | + driver_unregister(&mc_driver->driver); |
||
6883 | +} |
||
6884 | +EXPORT_SYMBOL_GPL(fsl_mc_driver_unregister); |
||
6885 | + |
||
6886 | +/** |
||
6887 | + * mc_get_version() - Retrieves the Management Complex firmware |
||
6888 | + * version information |
||
6889 | + * @mc_io: Pointer to opaque I/O object |
||
6890 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
6891 | + * @mc_ver_info: Returned version information structure |
||
6892 | + * |
||
6893 | + * Return: '0' on Success; Error code otherwise. |
||
6894 | + */ |
||
6895 | +static int mc_get_version(struct fsl_mc_io *mc_io, |
||
6896 | + u32 cmd_flags, |
||
6897 | + struct mc_version *mc_ver_info) |
||
6898 | +{ |
||
6899 | + struct fsl_mc_command cmd = { 0 }; |
||
6900 | + struct dpmng_rsp_get_version *rsp_params; |
||
6901 | + int err; |
||
6902 | + |
||
6903 | + /* prepare command */ |
||
6904 | + cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_VERSION, |
||
6905 | + cmd_flags, |
||
6906 | + 0); |
||
6907 | + |
||
6908 | + /* send command to mc*/ |
||
6909 | + err = mc_send_command(mc_io, &cmd); |
||
6910 | + if (err) |
||
6911 | + return err; |
||
6912 | + |
||
6913 | + /* retrieve response parameters */ |
||
6914 | + rsp_params = (struct dpmng_rsp_get_version *)cmd.params; |
||
6915 | + mc_ver_info->revision = le32_to_cpu(rsp_params->revision); |
||
6916 | + mc_ver_info->major = le32_to_cpu(rsp_params->version_major); |
||
6917 | + mc_ver_info->minor = le32_to_cpu(rsp_params->version_minor); |
||
6918 | + |
||
6919 | + return 0; |
||
6920 | +} |
||
6921 | + |
||
6922 | +/** |
||
6923 | + * fsl_mc_get_root_dprc - function to traverse to the root dprc |
||
6924 | + */ |
||
6925 | +void fsl_mc_get_root_dprc(struct device *dev, |
||
6926 | + struct device **root_dprc_dev) |
||
6927 | +{ |
||
6928 | + if (!dev) { |
||
6929 | + *root_dprc_dev = NULL; |
||
6930 | + } else if (!dev_is_fsl_mc(dev)) { |
||
6931 | + *root_dprc_dev = NULL; |
||
6932 | + } else { |
||
6933 | + *root_dprc_dev = dev; |
||
6934 | + while (dev_is_fsl_mc((*root_dprc_dev)->parent)) |
||
6935 | + *root_dprc_dev = (*root_dprc_dev)->parent; |
||
6936 | + } |
||
6937 | +} |
||
6938 | +EXPORT_SYMBOL_GPL(fsl_mc_get_root_dprc); |
||
6939 | + |
||
6940 | +static int get_dprc_attr(struct fsl_mc_io *mc_io, |
||
6941 | + int container_id, struct dprc_attributes *attr) |
||
6942 | +{ |
||
6943 | + u16 dprc_handle; |
||
6944 | + int error; |
||
6945 | + |
||
6946 | + error = dprc_open(mc_io, 0, container_id, &dprc_handle); |
||
6947 | + if (error < 0) { |
||
6948 | + dev_err(mc_io->dev, "dprc_open() failed: %d\n", error); |
||
6949 | + return error; |
||
6950 | + } |
||
6951 | + |
||
6952 | + memset(attr, 0, sizeof(struct dprc_attributes)); |
||
6953 | + error = dprc_get_attributes(mc_io, 0, dprc_handle, attr); |
||
6954 | + if (error < 0) { |
||
6955 | + dev_err(mc_io->dev, "dprc_get_attributes() failed: %d\n", |
||
6956 | + error); |
||
6957 | + goto common_cleanup; |
||
6958 | + } |
||
6959 | + |
||
6960 | + error = 0; |
||
6961 | + |
||
6962 | +common_cleanup: |
||
6963 | + (void)dprc_close(mc_io, 0, dprc_handle); |
||
6964 | + return error; |
||
6965 | +} |
||
6966 | + |
||
6967 | +static int get_dprc_icid(struct fsl_mc_io *mc_io, |
||
6968 | + int container_id, u32 *icid) |
||
6969 | +{ |
||
6970 | + struct dprc_attributes attr; |
||
6971 | + int error; |
||
6972 | + |
||
6973 | + error = get_dprc_attr(mc_io, container_id, &attr); |
||
6974 | + if (error == 0) |
||
6975 | + *icid = attr.icid; |
||
6976 | + |
||
6977 | + return error; |
||
6978 | +} |
||
6979 | + |
||
6980 | +static int translate_mc_addr(struct fsl_mc_device *mc_dev, |
||
6981 | + enum dprc_region_type mc_region_type, |
||
6982 | + u64 mc_offset, phys_addr_t *phys_addr) |
||
6983 | +{ |
||
6984 | + int i; |
||
6985 | + struct device *root_dprc_dev; |
||
6986 | + struct fsl_mc *mc; |
||
6987 | + |
||
6988 | + fsl_mc_get_root_dprc(&mc_dev->dev, &root_dprc_dev); |
||
6989 | + mc = dev_get_drvdata(root_dprc_dev->parent); |
||
6990 | + |
||
6991 | + if (mc->num_translation_ranges == 0) { |
||
6992 | + /* |
||
6993 | + * Do identity mapping: |
||
6994 | + */ |
||
6995 | + *phys_addr = mc_offset; |
||
6996 | + return 0; |
||
6997 | + } |
||
6998 | + |
||
6999 | + for (i = 0; i < mc->num_translation_ranges; i++) { |
||
7000 | + struct fsl_mc_addr_translation_range *range = |
||
7001 | + &mc->translation_ranges[i]; |
||
7002 | + |
||
7003 | + if (mc_region_type == range->mc_region_type && |
||
7004 | + mc_offset >= range->start_mc_offset && |
||
7005 | + mc_offset < range->end_mc_offset) { |
||
7006 | + *phys_addr = range->start_phys_addr + |
||
7007 | + (mc_offset - range->start_mc_offset); |
||
7008 | + return 0; |
||
7009 | + } |
||
7010 | + } |
||
7011 | + |
||
7012 | + return -EFAULT; |
||
7013 | +} |
||
7014 | + |
||
7015 | +static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev, |
||
7016 | + struct fsl_mc_device *mc_bus_dev) |
||
7017 | +{ |
||
7018 | + int i; |
||
7019 | + int error; |
||
7020 | + struct resource *regions; |
||
7021 | + struct fsl_mc_obj_desc *obj_desc = &mc_dev->obj_desc; |
||
7022 | + struct device *parent_dev = mc_dev->dev.parent; |
||
7023 | + enum dprc_region_type mc_region_type; |
||
7024 | + |
||
7025 | + if (is_fsl_mc_bus_dprc(mc_dev) || |
||
7026 | + is_fsl_mc_bus_dpmcp(mc_dev)) { |
||
7027 | + mc_region_type = DPRC_REGION_TYPE_MC_PORTAL; |
||
7028 | + } else if (is_fsl_mc_bus_dpio(mc_dev)) { |
||
7029 | + mc_region_type = DPRC_REGION_TYPE_QBMAN_PORTAL; |
||
7030 | + } else { |
||
7031 | + /* |
||
7032 | + * This function should not have been called for this MC object |
||
7033 | + * type, as this object type is not supposed to have MMIO |
||
7034 | + * regions |
||
7035 | + */ |
||
7036 | + return -EINVAL; |
||
7037 | + } |
||
7038 | + |
||
7039 | + regions = kmalloc_array(obj_desc->region_count, |
||
7040 | + sizeof(regions[0]), GFP_KERNEL); |
||
7041 | + if (!regions) |
||
7042 | + return -ENOMEM; |
||
7043 | + |
||
7044 | + for (i = 0; i < obj_desc->region_count; i++) { |
||
7045 | + struct dprc_region_desc region_desc; |
||
7046 | + |
||
7047 | + error = dprc_get_obj_region(mc_bus_dev->mc_io, |
||
7048 | + 0, |
||
7049 | + mc_bus_dev->mc_handle, |
||
7050 | + obj_desc->type, |
||
7051 | + obj_desc->id, i, ®ion_desc); |
||
7052 | + if (error < 0) { |
||
7053 | + dev_err(parent_dev, |
||
7054 | + "dprc_get_obj_region() failed: %d\n", error); |
||
7055 | + goto error_cleanup_regions; |
||
7056 | + } |
||
7057 | + |
||
7058 | + error = translate_mc_addr(mc_dev, mc_region_type, |
||
7059 | + region_desc.base_offset, |
||
7060 | + ®ions[i].start); |
||
7061 | + if (error < 0) { |
||
7062 | + dev_err(parent_dev, |
||
7063 | + "Invalid MC offset: %#x (for %s.%d\'s region %d)\n", |
||
7064 | + region_desc.base_offset, |
||
7065 | + obj_desc->type, obj_desc->id, i); |
||
7066 | + goto error_cleanup_regions; |
||
7067 | + } |
||
7068 | + |
||
7069 | + regions[i].end = regions[i].start + region_desc.size - 1; |
||
7070 | + regions[i].name = "fsl-mc object MMIO region"; |
||
7071 | + regions[i].flags = IORESOURCE_IO; |
||
7072 | + if (region_desc.flags & DPRC_REGION_CACHEABLE) |
||
7073 | + regions[i].flags |= IORESOURCE_CACHEABLE; |
||
7074 | + } |
||
7075 | + |
||
7076 | + mc_dev->regions = regions; |
||
7077 | + return 0; |
||
7078 | + |
||
7079 | +error_cleanup_regions: |
||
7080 | + kfree(regions); |
||
7081 | + return error; |
||
7082 | +} |
||
7083 | + |
||
7084 | +/** |
||
7085 | + * fsl_mc_is_root_dprc - function to check if a given device is a root dprc |
||
7086 | + */ |
||
7087 | +bool fsl_mc_is_root_dprc(struct device *dev) |
||
7088 | +{ |
||
7089 | + struct device *root_dprc_dev; |
||
7090 | + |
||
7091 | + fsl_mc_get_root_dprc(dev, &root_dprc_dev); |
||
7092 | + if (!root_dprc_dev) |
||
7093 | + return false; |
||
7094 | + return dev == root_dprc_dev; |
||
7095 | +} |
||
7096 | + |
||
7097 | +static void fsl_mc_device_release(struct device *dev) |
||
7098 | +{ |
||
7099 | + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); |
||
7100 | + |
||
7101 | + kfree(mc_dev->regions); |
||
7102 | + |
||
7103 | + if (is_fsl_mc_bus_dprc(mc_dev)) |
||
7104 | + kfree(to_fsl_mc_bus(mc_dev)); |
||
7105 | + else |
||
7106 | + kfree(mc_dev); |
||
7107 | +} |
||
7108 | + |
||
7109 | +/** |
||
7110 | + * Add a newly discovered fsl-mc device to be visible in Linux |
||
7111 | + */ |
||
7112 | +int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc, |
||
7113 | + struct fsl_mc_io *mc_io, |
||
7114 | + struct device *parent_dev, |
||
7115 | + const char *driver_override, |
||
7116 | + struct fsl_mc_device **new_mc_dev) |
||
7117 | +{ |
||
7118 | + int error; |
||
7119 | + struct fsl_mc_device *mc_dev = NULL; |
||
7120 | + struct fsl_mc_bus *mc_bus = NULL; |
||
7121 | + struct fsl_mc_device *parent_mc_dev; |
||
7122 | + |
||
7123 | + if (dev_is_fsl_mc(parent_dev)) |
||
7124 | + parent_mc_dev = to_fsl_mc_device(parent_dev); |
||
7125 | + else |
||
7126 | + parent_mc_dev = NULL; |
||
7127 | + |
||
7128 | + if (strcmp(obj_desc->type, "dprc") == 0) { |
||
7129 | + /* |
||
7130 | + * Allocate an MC bus device object: |
||
7131 | + */ |
||
7132 | + mc_bus = kzalloc(sizeof(*mc_bus), GFP_KERNEL); |
||
7133 | + if (!mc_bus) |
||
7134 | + return -ENOMEM; |
||
7135 | + |
||
7136 | + mc_dev = &mc_bus->mc_dev; |
||
7137 | + } else { |
||
7138 | + /* |
||
7139 | + * Allocate a regular fsl_mc_device object: |
||
7140 | + */ |
||
7141 | + mc_dev = kzalloc(sizeof(*mc_dev), GFP_KERNEL); |
||
7142 | + if (!mc_dev) |
||
7143 | + return -ENOMEM; |
||
7144 | + } |
||
7145 | + |
||
7146 | + mc_dev->obj_desc = *obj_desc; |
||
7147 | + mc_dev->mc_io = mc_io; |
||
7148 | + |
||
7149 | + if (driver_override) { |
||
7150 | + /* |
||
7151 | + * We trust driver_override, so we don't need to use |
||
7152 | + * kstrndup() here |
||
7153 | + */ |
||
7154 | + mc_dev->driver_override = kstrdup(driver_override, GFP_KERNEL); |
||
7155 | + if (!mc_dev->driver_override) { |
||
7156 | + error = -ENOMEM; |
||
7157 | + goto error_cleanup_dev; |
||
7158 | + } |
||
7159 | + } |
||
7160 | + |
||
7161 | + device_initialize(&mc_dev->dev); |
||
7162 | + mc_dev->dev.parent = parent_dev; |
||
7163 | + mc_dev->dev.bus = &fsl_mc_bus_type; |
||
7164 | + mc_dev->dev.release = fsl_mc_device_release; |
||
7165 | + mc_dev->dev.type = fsl_mc_get_device_type(obj_desc->type); |
||
7166 | + if (!mc_dev->dev.type) { |
||
7167 | + error = -ENODEV; |
||
7168 | + dev_err(parent_dev, "unknown device type %s\n", obj_desc->type); |
||
7169 | + goto error_cleanup_dev; |
||
7170 | + } |
||
7171 | + dev_set_name(&mc_dev->dev, "%s.%d", obj_desc->type, obj_desc->id); |
||
7172 | + |
||
7173 | + if (strcmp(obj_desc->type, "dprc") == 0) { |
||
7174 | + struct fsl_mc_io *mc_io2; |
||
7175 | + |
||
7176 | + mc_dev->flags |= FSL_MC_IS_DPRC; |
||
7177 | + |
||
7178 | + /* |
||
7179 | + * To get the DPRC's ICID, we need to open the DPRC |
||
7180 | + * in get_dprc_icid(). For child DPRCs, we do so using the |
||
7181 | + * parent DPRC's MC portal instead of the child DPRC's MC |
||
7182 | + * portal, in case the child DPRC is already opened with |
||
7183 | + * its own portal (e.g., the DPRC used by AIOP). |
||
7184 | + * |
||
7185 | + * NOTE: There cannot be more than one active open for a |
||
7186 | + * given MC object, using the same MC portal. |
||
7187 | + */ |
||
7188 | + if (parent_mc_dev) { |
||
7189 | + /* |
||
7190 | + * device being added is a child DPRC device |
||
7191 | + */ |
||
7192 | + mc_io2 = parent_mc_dev->mc_io; |
||
7193 | + } else { |
||
7194 | + /* |
||
7195 | + * device being added is the root DPRC device |
||
7196 | + */ |
||
7197 | + if (!mc_io) { |
||
7198 | + error = -EINVAL; |
||
7199 | + goto error_cleanup_dev; |
||
7200 | + } |
||
7201 | + |
||
7202 | + mc_io2 = mc_io; |
||
7203 | + } |
||
7204 | + |
||
7205 | + error = get_dprc_icid(mc_io2, obj_desc->id, &mc_dev->icid); |
||
7206 | + if (error < 0) |
||
7207 | + goto error_cleanup_dev; |
||
7208 | + } else { |
||
7209 | + /* |
||
7210 | + * A non-DPRC object has to be a child of a DPRC, use the |
||
7211 | + * parent's ICID and interrupt domain. |
||
7212 | + */ |
||
7213 | + mc_dev->icid = parent_mc_dev->icid; |
||
7214 | + mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK; |
||
7215 | + mc_dev->dev.dma_mask = &mc_dev->dma_mask; |
||
7216 | + mc_dev->dev.coherent_dma_mask = mc_dev->dma_mask; |
||
7217 | + dev_set_msi_domain(&mc_dev->dev, |
||
7218 | + dev_get_msi_domain(&parent_mc_dev->dev)); |
||
7219 | + } |
||
7220 | + |
||
7221 | + /* |
||
7222 | + * Get MMIO regions for the device from the MC: |
||
7223 | + * |
||
7224 | + * NOTE: the root DPRC is a special case as its MMIO region is |
||
7225 | + * obtained from the device tree |
||
7226 | + */ |
||
7227 | + if (parent_mc_dev && obj_desc->region_count != 0) { |
||
7228 | + error = fsl_mc_device_get_mmio_regions(mc_dev, |
||
7229 | + parent_mc_dev); |
||
7230 | + if (error < 0) |
||
7231 | + goto error_cleanup_dev; |
||
7232 | + } |
||
7233 | + |
||
7234 | + /* |
||
7235 | + * The device-specific probe callback will get invoked by device_add() |
||
7236 | + */ |
||
7237 | + error = device_add(&mc_dev->dev); |
||
7238 | + if (error < 0) { |
||
7239 | + dev_err(parent_dev, |
||
7240 | + "device_add() failed for device %s: %d\n", |
||
7241 | + dev_name(&mc_dev->dev), error); |
||
7242 | + goto error_cleanup_dev; |
||
7243 | + } |
||
7244 | + |
||
7245 | + dev_dbg(parent_dev, "added %s\n", dev_name(&mc_dev->dev)); |
||
7246 | + |
||
7247 | + *new_mc_dev = mc_dev; |
||
7248 | + return 0; |
||
7249 | + |
||
7250 | +error_cleanup_dev: |
||
7251 | + kfree(mc_dev->regions); |
||
7252 | + kfree(mc_bus); |
||
7253 | + kfree(mc_dev); |
||
7254 | + |
||
7255 | + return error; |
||
7256 | +} |
||
7257 | +EXPORT_SYMBOL_GPL(fsl_mc_device_add); |
||
7258 | + |
||
7259 | +/** |
||
7260 | + * fsl_mc_device_remove - Remove an fsl-mc device from being visible to |
||
7261 | + * Linux |
||
7262 | + * |
||
7263 | + * @mc_dev: Pointer to an fsl-mc device |
||
7264 | + */ |
||
7265 | +void fsl_mc_device_remove(struct fsl_mc_device *mc_dev) |
||
7266 | +{ |
||
7267 | + kfree(mc_dev->driver_override); |
||
7268 | + mc_dev->driver_override = NULL; |
||
7269 | + |
||
7270 | + /* |
||
7271 | + * The device-specific remove callback will get invoked by device_del() |
||
7272 | + */ |
||
7273 | + device_del(&mc_dev->dev); |
||
7274 | + put_device(&mc_dev->dev); |
||
7275 | +} |
||
7276 | +EXPORT_SYMBOL_GPL(fsl_mc_device_remove); |
||
7277 | + |
||
7278 | +static int parse_mc_ranges(struct device *dev, |
||
7279 | + int *paddr_cells, |
||
7280 | + int *mc_addr_cells, |
||
7281 | + int *mc_size_cells, |
||
7282 | + const __be32 **ranges_start) |
||
7283 | +{ |
||
7284 | + const __be32 *prop; |
||
7285 | + int range_tuple_cell_count; |
||
7286 | + int ranges_len; |
||
7287 | + int tuple_len; |
||
7288 | + struct device_node *mc_node = dev->of_node; |
||
7289 | + |
||
7290 | + *ranges_start = of_get_property(mc_node, "ranges", &ranges_len); |
||
7291 | + if (!(*ranges_start) || !ranges_len) { |
||
7292 | + dev_warn(dev, |
||
7293 | + "missing or empty ranges property for device tree node '%s'\n", |
||
7294 | + mc_node->name); |
||
7295 | + return 0; |
||
7296 | + } |
||
7297 | + |
||
7298 | + *paddr_cells = of_n_addr_cells(mc_node); |
||
7299 | + |
||
7300 | + prop = of_get_property(mc_node, "#address-cells", NULL); |
||
7301 | + if (prop) |
||
7302 | + *mc_addr_cells = be32_to_cpup(prop); |
||
7303 | + else |
||
7304 | + *mc_addr_cells = *paddr_cells; |
||
7305 | + |
||
7306 | + prop = of_get_property(mc_node, "#size-cells", NULL); |
||
7307 | + if (prop) |
||
7308 | + *mc_size_cells = be32_to_cpup(prop); |
||
7309 | + else |
||
7310 | + *mc_size_cells = of_n_size_cells(mc_node); |
||
7311 | + |
||
7312 | + range_tuple_cell_count = *paddr_cells + *mc_addr_cells + |
||
7313 | + *mc_size_cells; |
||
7314 | + |
||
7315 | + tuple_len = range_tuple_cell_count * sizeof(__be32); |
||
7316 | + if (ranges_len % tuple_len != 0) { |
||
7317 | + dev_err(dev, "malformed ranges property '%s'\n", mc_node->name); |
||
7318 | + return -EINVAL; |
||
7319 | + } |
||
7320 | + |
||
7321 | + return ranges_len / tuple_len; |
||
7322 | +} |
||
7323 | + |
||
7324 | +static int get_mc_addr_translation_ranges(struct device *dev, |
||
7325 | + struct fsl_mc_addr_translation_range |
||
7326 | + **ranges, |
||
7327 | + u8 *num_ranges) |
||
7328 | +{ |
||
7329 | + int ret; |
||
7330 | + int paddr_cells; |
||
7331 | + int mc_addr_cells; |
||
7332 | + int mc_size_cells; |
||
7333 | + int i; |
||
7334 | + const __be32 *ranges_start; |
||
7335 | + const __be32 *cell; |
||
7336 | + |
||
7337 | + ret = parse_mc_ranges(dev, |
||
7338 | + &paddr_cells, |
||
7339 | + &mc_addr_cells, |
||
7340 | + &mc_size_cells, |
||
7341 | + &ranges_start); |
||
7342 | + if (ret < 0) |
||
7343 | + return ret; |
||
7344 | + |
||
7345 | + *num_ranges = ret; |
||
7346 | + if (!ret) { |
||
7347 | + /* |
||
7348 | + * Missing or empty ranges property ("ranges;") for the |
||
7349 | + * 'fsl,qoriq-mc' node. In this case, identity mapping |
||
7350 | + * will be used. |
||
7351 | + */ |
||
7352 | + *ranges = NULL; |
||
7353 | + return 0; |
||
7354 | + } |
||
7355 | + |
||
7356 | + *ranges = devm_kcalloc(dev, *num_ranges, |
||
7357 | + sizeof(struct fsl_mc_addr_translation_range), |
||
7358 | + GFP_KERNEL); |
||
7359 | + if (!(*ranges)) |
||
7360 | + return -ENOMEM; |
||
7361 | + |
||
7362 | + cell = ranges_start; |
||
7363 | + for (i = 0; i < *num_ranges; ++i) { |
||
7364 | + struct fsl_mc_addr_translation_range *range = &(*ranges)[i]; |
||
7365 | + |
||
7366 | + range->mc_region_type = of_read_number(cell, 1); |
||
7367 | + range->start_mc_offset = of_read_number(cell + 1, |
||
7368 | + mc_addr_cells - 1); |
||
7369 | + cell += mc_addr_cells; |
||
7370 | + range->start_phys_addr = of_read_number(cell, paddr_cells); |
||
7371 | + cell += paddr_cells; |
||
7372 | + range->end_mc_offset = range->start_mc_offset + |
||
7373 | + of_read_number(cell, mc_size_cells); |
||
7374 | + |
||
7375 | + cell += mc_size_cells; |
||
7376 | + } |
||
7377 | + |
||
7378 | + return 0; |
||
7379 | +} |
||
7380 | + |
||
7381 | +/** |
||
7382 | + * fsl_mc_bus_probe - callback invoked when the root MC bus is being |
||
7383 | + * added |
||
7384 | + */ |
||
7385 | +static int fsl_mc_bus_probe(struct platform_device *pdev) |
||
7386 | +{ |
||
7387 | + struct fsl_mc_obj_desc obj_desc; |
||
7388 | + int error; |
||
7389 | + struct fsl_mc *mc; |
||
7390 | + struct fsl_mc_device *mc_bus_dev = NULL; |
||
7391 | + struct fsl_mc_io *mc_io = NULL; |
||
7392 | + struct fsl_mc_bus *mc_bus = NULL; |
||
7393 | + int container_id; |
||
7394 | + phys_addr_t mc_portal_phys_addr; |
||
7395 | + u32 mc_portal_size; |
||
7396 | + struct mc_version mc_version; |
||
7397 | + struct resource res; |
||
7398 | + |
||
7399 | + mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL); |
||
7400 | + if (!mc) |
||
7401 | + return -ENOMEM; |
||
7402 | + |
||
7403 | + platform_set_drvdata(pdev, mc); |
||
7404 | + |
||
7405 | + /* |
||
7406 | + * Get physical address of MC portal for the root DPRC: |
||
7407 | + */ |
||
7408 | + error = of_address_to_resource(pdev->dev.of_node, 0, &res); |
||
7409 | + if (error < 0) { |
||
7410 | + dev_err(&pdev->dev, |
||
7411 | + "of_address_to_resource() failed for %pOF\n", |
||
7412 | + pdev->dev.of_node); |
||
7413 | + return error; |
||
7414 | + } |
||
7415 | + |
||
7416 | + mc_portal_phys_addr = res.start; |
||
7417 | + mc_portal_size = resource_size(&res); |
||
7418 | + error = fsl_create_mc_io(&pdev->dev, mc_portal_phys_addr, |
||
7419 | + mc_portal_size, NULL, |
||
7420 | + FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, &mc_io); |
||
7421 | + if (error < 0) |
||
7422 | + return error; |
||
7423 | + |
||
7424 | + error = mc_get_version(mc_io, 0, &mc_version); |
||
7425 | + if (error != 0) { |
||
7426 | + dev_err(&pdev->dev, |
||
7427 | + "mc_get_version() failed with error %d\n", error); |
||
7428 | + goto error_cleanup_mc_io; |
||
7429 | + } |
||
7430 | + |
||
7431 | + dev_info(&pdev->dev, "MC firmware version: %u.%u.%u\n", |
||
7432 | + mc_version.major, mc_version.minor, mc_version.revision); |
||
7433 | + |
||
7434 | + error = get_mc_addr_translation_ranges(&pdev->dev, |
||
7435 | + &mc->translation_ranges, |
||
7436 | + &mc->num_translation_ranges); |
||
7437 | + if (error < 0) |
||
7438 | + goto error_cleanup_mc_io; |
||
7439 | + |
||
7440 | + error = dprc_get_container_id(mc_io, 0, &container_id); |
||
7441 | + if (error < 0) { |
||
7442 | + dev_err(&pdev->dev, |
||
7443 | + "dprc_get_container_id() failed: %d\n", error); |
||
7444 | + goto error_cleanup_mc_io; |
||
7445 | + } |
||
7446 | + |
||
7447 | + memset(&obj_desc, 0, sizeof(struct fsl_mc_obj_desc)); |
||
7448 | + error = dprc_get_api_version(mc_io, 0, |
||
7449 | + &obj_desc.ver_major, |
||
7450 | + &obj_desc.ver_minor); |
||
7451 | + if (error < 0) |
||
7452 | + goto error_cleanup_mc_io; |
||
7453 | + |
||
7454 | + obj_desc.vendor = FSL_MC_VENDOR_FREESCALE; |
||
7455 | + strcpy(obj_desc.type, "dprc"); |
||
7456 | + obj_desc.id = container_id; |
||
7457 | + obj_desc.irq_count = 1; |
||
7458 | + obj_desc.region_count = 0; |
||
7459 | + |
||
7460 | + error = fsl_mc_device_add(&obj_desc, mc_io, &pdev->dev, NULL, |
||
7461 | + &mc_bus_dev); |
||
7462 | + if (error < 0) |
||
7463 | + goto error_cleanup_mc_io; |
||
7464 | + |
||
7465 | + mc_bus = to_fsl_mc_bus(mc_bus_dev); |
||
7466 | + error = fsl_mc_restool_create_device_file(mc_bus); |
||
7467 | + if (error < 0) |
||
7468 | + goto error_cleanup_device; |
||
7469 | + |
||
7470 | + mc->root_mc_bus_dev = mc_bus_dev; |
||
7471 | + |
||
7472 | + return 0; |
||
7473 | + |
||
7474 | +error_cleanup_device: |
||
7475 | + fsl_mc_device_remove(mc_bus_dev); |
||
7476 | + |
||
7477 | +error_cleanup_mc_io: |
||
7478 | + fsl_destroy_mc_io(mc_io); |
||
7479 | + return error; |
||
7480 | +} |
||
7481 | + |
||
7482 | +/** |
||
7483 | + * fsl_mc_bus_remove - callback invoked when the root MC bus is being |
||
7484 | + * removed |
||
7485 | + */ |
||
7486 | +static int fsl_mc_bus_remove(struct platform_device *pdev) |
||
7487 | +{ |
||
7488 | + struct fsl_mc *mc = platform_get_drvdata(pdev); |
||
7489 | + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc->root_mc_bus_dev); |
||
7490 | + |
||
7491 | + if (!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev)) |
||
7492 | + return -EINVAL; |
||
7493 | + |
||
7494 | + fsl_mc_restool_remove_device_file(mc_bus); |
||
7495 | + fsl_mc_device_remove(mc->root_mc_bus_dev); |
||
7496 | + |
||
7497 | + fsl_destroy_mc_io(mc->root_mc_bus_dev->mc_io); |
||
7498 | + mc->root_mc_bus_dev->mc_io = NULL; |
||
7499 | + |
||
7500 | + return 0; |
||
7501 | +} |
||
7502 | + |
||
7503 | +static const struct of_device_id fsl_mc_bus_match_table[] = { |
||
7504 | + {.compatible = "fsl,qoriq-mc",}, |
||
7505 | + {}, |
||
7506 | +}; |
||
7507 | + |
||
7508 | +MODULE_DEVICE_TABLE(of, fsl_mc_bus_match_table); |
||
7509 | + |
||
7510 | +static struct platform_driver fsl_mc_bus_driver = { |
||
7511 | + .driver = { |
||
7512 | + .name = "fsl_mc_bus", |
||
7513 | + .pm = NULL, |
||
7514 | + .of_match_table = fsl_mc_bus_match_table, |
||
7515 | + }, |
||
7516 | + .probe = fsl_mc_bus_probe, |
||
7517 | + .remove = fsl_mc_bus_remove, |
||
7518 | +}; |
||
7519 | + |
||
7520 | +static int __init fsl_mc_bus_driver_init(void) |
||
7521 | +{ |
||
7522 | + int error; |
||
7523 | + |
||
7524 | + error = bus_register(&fsl_mc_bus_type); |
||
7525 | + if (error < 0) { |
||
7526 | + pr_err("bus type registration failed: %d\n", error); |
||
7527 | + goto error_cleanup_cache; |
||
7528 | + } |
||
7529 | + |
||
7530 | + error = platform_driver_register(&fsl_mc_bus_driver); |
||
7531 | + if (error < 0) { |
||
7532 | + pr_err("platform_driver_register() failed: %d\n", error); |
||
7533 | + goto error_cleanup_bus; |
||
7534 | + } |
||
7535 | + |
||
7536 | + error = dprc_driver_init(); |
||
7537 | + if (error < 0) |
||
7538 | + goto error_cleanup_driver; |
||
7539 | + |
||
7540 | + error = fsl_mc_allocator_driver_init(); |
||
7541 | + if (error < 0) |
||
7542 | + goto error_cleanup_dprc_driver; |
||
7543 | + |
||
7544 | + error = fsl_mc_restool_init(); |
||
7545 | + if (error < 0) |
||
7546 | + goto error_cleanup_mc_allocator; |
||
7547 | + |
||
7548 | + return 0; |
||
7549 | + |
||
7550 | +error_cleanup_mc_allocator: |
||
7551 | + fsl_mc_allocator_driver_exit(); |
||
7552 | + |
||
7553 | +error_cleanup_dprc_driver: |
||
7554 | + dprc_driver_exit(); |
||
7555 | + |
||
7556 | +error_cleanup_driver: |
||
7557 | + platform_driver_unregister(&fsl_mc_bus_driver); |
||
7558 | + |
||
7559 | +error_cleanup_bus: |
||
7560 | + bus_unregister(&fsl_mc_bus_type); |
||
7561 | + |
||
7562 | +error_cleanup_cache: |
||
7563 | + return error; |
||
7564 | +} |
||
7565 | +postcore_initcall(fsl_mc_bus_driver_init); |
||
7566 | --- a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c |
||
7567 | +++ /dev/null |
||
7568 | @@ -1,285 +0,0 @@ |
||
7569 | -// SPDX-License-Identifier: GPL-2.0 |
||
7570 | -/* |
||
7571 | - * Freescale Management Complex (MC) bus driver MSI support |
||
7572 | - * |
||
7573 | - * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. |
||
7574 | - * Author: German Rivera <German.Rivera@freescale.com> |
||
7575 | - * |
||
7576 | - */ |
||
7577 | - |
||
7578 | -#include <linux/of_device.h> |
||
7579 | -#include <linux/of_address.h> |
||
7580 | -#include <linux/of_irq.h> |
||
7581 | -#include <linux/irq.h> |
||
7582 | -#include <linux/irqdomain.h> |
||
7583 | -#include <linux/msi.h> |
||
7584 | -#include "fsl-mc-private.h" |
||
7585 | - |
||
7586 | -#ifdef GENERIC_MSI_DOMAIN_OPS |
||
7587 | -/* |
||
7588 | - * Generate a unique ID identifying the interrupt (only used within the MSI |
||
7589 | - * irqdomain. Combine the icid with the interrupt index. |
||
7590 | - */ |
||
7591 | -static irq_hw_number_t fsl_mc_domain_calc_hwirq(struct fsl_mc_device *dev, |
||
7592 | - struct msi_desc *desc) |
||
7593 | -{ |
||
7594 | - /* |
||
7595 | - * Make the base hwirq value for ICID*10000 so it is readable |
||
7596 | - * as a decimal value in /proc/interrupts. |
||
7597 | - */ |
||
7598 | - return (irq_hw_number_t)(desc->fsl_mc.msi_index + (dev->icid * 10000)); |
||
7599 | -} |
||
7600 | - |
||
7601 | -static void fsl_mc_msi_set_desc(msi_alloc_info_t *arg, |
||
7602 | - struct msi_desc *desc) |
||
7603 | -{ |
||
7604 | - arg->desc = desc; |
||
7605 | - arg->hwirq = fsl_mc_domain_calc_hwirq(to_fsl_mc_device(desc->dev), |
||
7606 | - desc); |
||
7607 | -} |
||
7608 | -#else |
||
7609 | -#define fsl_mc_msi_set_desc NULL |
||
7610 | -#endif |
||
7611 | - |
||
7612 | -static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info) |
||
7613 | -{ |
||
7614 | - struct msi_domain_ops *ops = info->ops; |
||
7615 | - |
||
7616 | - if (WARN_ON(!ops)) |
||
7617 | - return; |
||
7618 | - |
||
7619 | - /* |
||
7620 | - * set_desc should not be set by the caller |
||
7621 | - */ |
||
7622 | - if (!ops->set_desc) |
||
7623 | - ops->set_desc = fsl_mc_msi_set_desc; |
||
7624 | -} |
||
7625 | - |
||
7626 | -static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev, |
||
7627 | - struct fsl_mc_device_irq *mc_dev_irq) |
||
7628 | -{ |
||
7629 | - int error; |
||
7630 | - struct fsl_mc_device *owner_mc_dev = mc_dev_irq->mc_dev; |
||
7631 | - struct msi_desc *msi_desc = mc_dev_irq->msi_desc; |
||
7632 | - struct dprc_irq_cfg irq_cfg; |
||
7633 | - |
||
7634 | - /* |
||
7635 | - * msi_desc->msg.address is 0x0 when this function is invoked in |
||
7636 | - * the free_irq() code path. In this case, for the MC, we don't |
||
7637 | - * really need to "unprogram" the MSI, so we just return. |
||
7638 | - */ |
||
7639 | - if (msi_desc->msg.address_lo == 0x0 && msi_desc->msg.address_hi == 0x0) |
||
7640 | - return; |
||
7641 | - |
||
7642 | - if (WARN_ON(!owner_mc_dev)) |
||
7643 | - return; |
||
7644 | - |
||
7645 | - irq_cfg.paddr = ((u64)msi_desc->msg.address_hi << 32) | |
||
7646 | - msi_desc->msg.address_lo; |
||
7647 | - irq_cfg.val = msi_desc->msg.data; |
||
7648 | - irq_cfg.irq_num = msi_desc->irq; |
||
7649 | - |
||
7650 | - if (owner_mc_dev == mc_bus_dev) { |
||
7651 | - /* |
||
7652 | - * IRQ is for the mc_bus_dev's DPRC itself |
||
7653 | - */ |
||
7654 | - error = dprc_set_irq(mc_bus_dev->mc_io, |
||
7655 | - MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI, |
||
7656 | - mc_bus_dev->mc_handle, |
||
7657 | - mc_dev_irq->dev_irq_index, |
||
7658 | - &irq_cfg); |
||
7659 | - if (error < 0) { |
||
7660 | - dev_err(&owner_mc_dev->dev, |
||
7661 | - "dprc_set_irq() failed: %d\n", error); |
||
7662 | - } |
||
7663 | - } else { |
||
7664 | - /* |
||
7665 | - * IRQ is for for a child device of mc_bus_dev |
||
7666 | - */ |
||
7667 | - error = dprc_set_obj_irq(mc_bus_dev->mc_io, |
||
7668 | - MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI, |
||
7669 | - mc_bus_dev->mc_handle, |
||
7670 | - owner_mc_dev->obj_desc.type, |
||
7671 | - owner_mc_dev->obj_desc.id, |
||
7672 | - mc_dev_irq->dev_irq_index, |
||
7673 | - &irq_cfg); |
||
7674 | - if (error < 0) { |
||
7675 | - dev_err(&owner_mc_dev->dev, |
||
7676 | - "dprc_obj_set_irq() failed: %d\n", error); |
||
7677 | - } |
||
7678 | - } |
||
7679 | -} |
||
7680 | - |
||
7681 | -/* |
||
7682 | - * NOTE: This function is invoked with interrupts disabled |
||
7683 | - */ |
||
7684 | -static void fsl_mc_msi_write_msg(struct irq_data *irq_data, |
||
7685 | - struct msi_msg *msg) |
||
7686 | -{ |
||
7687 | - struct msi_desc *msi_desc = irq_data_get_msi_desc(irq_data); |
||
7688 | - struct fsl_mc_device *mc_bus_dev = to_fsl_mc_device(msi_desc->dev); |
||
7689 | - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); |
||
7690 | - struct fsl_mc_device_irq *mc_dev_irq = |
||
7691 | - &mc_bus->irq_resources[msi_desc->fsl_mc.msi_index]; |
||
7692 | - |
||
7693 | - WARN_ON(mc_dev_irq->msi_desc != msi_desc); |
||
7694 | - msi_desc->msg = *msg; |
||
7695 | - |
||
7696 | - /* |
||
7697 | - * Program the MSI (paddr, value) pair in the device: |
||
7698 | - */ |
||
7699 | - __fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq); |
||
7700 | -} |
||
7701 | - |
||
7702 | -static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info) |
||
7703 | -{ |
||
7704 | - struct irq_chip *chip = info->chip; |
||
7705 | - |
||
7706 | - if (WARN_ON((!chip))) |
||
7707 | - return; |
||
7708 | - |
||
7709 | - /* |
||
7710 | - * irq_write_msi_msg should not be set by the caller |
||
7711 | - */ |
||
7712 | - if (!chip->irq_write_msi_msg) |
||
7713 | - chip->irq_write_msi_msg = fsl_mc_msi_write_msg; |
||
7714 | -} |
||
7715 | - |
||
7716 | -/** |
||
7717 | - * fsl_mc_msi_create_irq_domain - Create a fsl-mc MSI interrupt domain |
||
7718 | - * @np: Optional device-tree node of the interrupt controller |
||
7719 | - * @info: MSI domain info |
||
7720 | - * @parent: Parent irq domain |
||
7721 | - * |
||
7722 | - * Updates the domain and chip ops and creates a fsl-mc MSI |
||
7723 | - * interrupt domain. |
||
7724 | - * |
||
7725 | - * Returns: |
||
7726 | - * A domain pointer or NULL in case of failure. |
||
7727 | - */ |
||
7728 | -struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode, |
||
7729 | - struct msi_domain_info *info, |
||
7730 | - struct irq_domain *parent) |
||
7731 | -{ |
||
7732 | - struct irq_domain *domain; |
||
7733 | - |
||
7734 | - if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS) |
||
7735 | - fsl_mc_msi_update_dom_ops(info); |
||
7736 | - if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) |
||
7737 | - fsl_mc_msi_update_chip_ops(info); |
||
7738 | - |
||
7739 | - domain = msi_create_irq_domain(fwnode, info, parent); |
||
7740 | - if (domain) |
||
7741 | - irq_domain_update_bus_token(domain, DOMAIN_BUS_FSL_MC_MSI); |
||
7742 | - |
||
7743 | - return domain; |
||
7744 | -} |
||
7745 | - |
||
7746 | -int fsl_mc_find_msi_domain(struct device *mc_platform_dev, |
||
7747 | - struct irq_domain **mc_msi_domain) |
||
7748 | -{ |
||
7749 | - struct irq_domain *msi_domain; |
||
7750 | - struct device_node *mc_of_node = mc_platform_dev->of_node; |
||
7751 | - |
||
7752 | - msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node, |
||
7753 | - DOMAIN_BUS_FSL_MC_MSI); |
||
7754 | - if (!msi_domain) { |
||
7755 | - pr_err("Unable to find fsl-mc MSI domain for %pOF\n", |
||
7756 | - mc_of_node); |
||
7757 | - |
||
7758 | - return -ENOENT; |
||
7759 | - } |
||
7760 | - |
||
7761 | - *mc_msi_domain = msi_domain; |
||
7762 | - return 0; |
||
7763 | -} |
||
7764 | - |
||
7765 | -static void fsl_mc_msi_free_descs(struct device *dev) |
||
7766 | -{ |
||
7767 | - struct msi_desc *desc, *tmp; |
||
7768 | - |
||
7769 | - list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) { |
||
7770 | - list_del(&desc->list); |
||
7771 | - free_msi_entry(desc); |
||
7772 | - } |
||
7773 | -} |
||
7774 | - |
||
7775 | -static int fsl_mc_msi_alloc_descs(struct device *dev, unsigned int irq_count) |
||
7776 | - |
||
7777 | -{ |
||
7778 | - unsigned int i; |
||
7779 | - int error; |
||
7780 | - struct msi_desc *msi_desc; |
||
7781 | - |
||
7782 | - for (i = 0; i < irq_count; i++) { |
||
7783 | - msi_desc = alloc_msi_entry(dev, 1, NULL); |
||
7784 | - if (!msi_desc) { |
||
7785 | - dev_err(dev, "Failed to allocate msi entry\n"); |
||
7786 | - error = -ENOMEM; |
||
7787 | - goto cleanup_msi_descs; |
||
7788 | - } |
||
7789 | - |
||
7790 | - msi_desc->fsl_mc.msi_index = i; |
||
7791 | - INIT_LIST_HEAD(&msi_desc->list); |
||
7792 | - list_add_tail(&msi_desc->list, dev_to_msi_list(dev)); |
||
7793 | - } |
||
7794 | - |
||
7795 | - return 0; |
||
7796 | - |
||
7797 | -cleanup_msi_descs: |
||
7798 | - fsl_mc_msi_free_descs(dev); |
||
7799 | - return error; |
||
7800 | -} |
||
7801 | - |
||
7802 | -int fsl_mc_msi_domain_alloc_irqs(struct device *dev, |
||
7803 | - unsigned int irq_count) |
||
7804 | -{ |
||
7805 | - struct irq_domain *msi_domain; |
||
7806 | - int error; |
||
7807 | - |
||
7808 | - if (WARN_ON(!list_empty(dev_to_msi_list(dev)))) |
||
7809 | - return -EINVAL; |
||
7810 | - |
||
7811 | - error = fsl_mc_msi_alloc_descs(dev, irq_count); |
||
7812 | - if (error < 0) |
||
7813 | - return error; |
||
7814 | - |
||
7815 | - msi_domain = dev_get_msi_domain(dev); |
||
7816 | - if (WARN_ON(!msi_domain)) { |
||
7817 | - error = -EINVAL; |
||
7818 | - goto cleanup_msi_descs; |
||
7819 | - } |
||
7820 | - |
||
7821 | - /* |
||
7822 | - * NOTE: Calling this function will trigger the invocation of the |
||
7823 | - * its_fsl_mc_msi_prepare() callback |
||
7824 | - */ |
||
7825 | - error = msi_domain_alloc_irqs(msi_domain, dev, irq_count); |
||
7826 | - |
||
7827 | - if (error) { |
||
7828 | - dev_err(dev, "Failed to allocate IRQs\n"); |
||
7829 | - goto cleanup_msi_descs; |
||
7830 | - } |
||
7831 | - |
||
7832 | - return 0; |
||
7833 | - |
||
7834 | -cleanup_msi_descs: |
||
7835 | - fsl_mc_msi_free_descs(dev); |
||
7836 | - return error; |
||
7837 | -} |
||
7838 | - |
||
7839 | -void fsl_mc_msi_domain_free_irqs(struct device *dev) |
||
7840 | -{ |
||
7841 | - struct irq_domain *msi_domain; |
||
7842 | - |
||
7843 | - msi_domain = dev_get_msi_domain(dev); |
||
7844 | - if (WARN_ON(!msi_domain)) |
||
7845 | - return; |
||
7846 | - |
||
7847 | - msi_domain_free_irqs(msi_domain, dev); |
||
7848 | - |
||
7849 | - if (WARN_ON(list_empty(dev_to_msi_list(dev)))) |
||
7850 | - return; |
||
7851 | - |
||
7852 | - fsl_mc_msi_free_descs(dev); |
||
7853 | -} |
||
7854 | --- /dev/null |
||
7855 | +++ b/drivers/bus/fsl-mc/fsl-mc-msi.c |
||
7856 | @@ -0,0 +1,285 @@ |
||
7857 | +// SPDX-License-Identifier: GPL-2.0 |
||
7858 | +/* |
||
7859 | + * Freescale Management Complex (MC) bus driver MSI support |
||
7860 | + * |
||
7861 | + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. |
||
7862 | + * Author: German Rivera <German.Rivera@freescale.com> |
||
7863 | + * |
||
7864 | + */ |
||
7865 | + |
||
7866 | +#include <linux/of_device.h> |
||
7867 | +#include <linux/of_address.h> |
||
7868 | +#include <linux/of_irq.h> |
||
7869 | +#include <linux/irq.h> |
||
7870 | +#include <linux/irqdomain.h> |
||
7871 | +#include <linux/msi.h> |
||
7872 | + |
||
7873 | +#include "fsl-mc-private.h" |
||
7874 | + |
||
7875 | +#ifdef GENERIC_MSI_DOMAIN_OPS |
||
7876 | +/* |
||
7877 | + * Generate a unique ID identifying the interrupt (only used within the MSI |
||
7878 | + * irqdomain. Combine the icid with the interrupt index. |
||
7879 | + */ |
||
7880 | +static irq_hw_number_t fsl_mc_domain_calc_hwirq(struct fsl_mc_device *dev, |
||
7881 | + struct msi_desc *desc) |
||
7882 | +{ |
||
7883 | + /* |
||
7884 | + * Make the base hwirq value for ICID*10000 so it is readable |
||
7885 | + * as a decimal value in /proc/interrupts. |
||
7886 | + */ |
||
7887 | + return (irq_hw_number_t)(desc->fsl_mc.msi_index + (dev->icid * 10000)); |
||
7888 | +} |
||
7889 | + |
||
7890 | +static void fsl_mc_msi_set_desc(msi_alloc_info_t *arg, |
||
7891 | + struct msi_desc *desc) |
||
7892 | +{ |
||
7893 | + arg->desc = desc; |
||
7894 | + arg->hwirq = fsl_mc_domain_calc_hwirq(to_fsl_mc_device(desc->dev), |
||
7895 | + desc); |
||
7896 | +} |
||
7897 | +#else |
||
7898 | +#define fsl_mc_msi_set_desc NULL |
||
7899 | +#endif |
||
7900 | + |
||
7901 | +static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info) |
||
7902 | +{ |
||
7903 | + struct msi_domain_ops *ops = info->ops; |
||
7904 | + |
||
7905 | + if (!ops) |
||
7906 | + return; |
||
7907 | + |
||
7908 | + /* |
||
7909 | + * set_desc should not be set by the caller |
||
7910 | + */ |
||
7911 | + if (!ops->set_desc) |
||
7912 | + ops->set_desc = fsl_mc_msi_set_desc; |
||
7913 | +} |
||
7914 | + |
||
7915 | +static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev, |
||
7916 | + struct fsl_mc_device_irq *mc_dev_irq) |
||
7917 | +{ |
||
7918 | + int error; |
||
7919 | + struct fsl_mc_device *owner_mc_dev = mc_dev_irq->mc_dev; |
||
7920 | + struct msi_desc *msi_desc = mc_dev_irq->msi_desc; |
||
7921 | + struct dprc_irq_cfg irq_cfg; |
||
7922 | + |
||
7923 | + /* |
||
7924 | + * msi_desc->msg.address is 0x0 when this function is invoked in |
||
7925 | + * the free_irq() code path. In this case, for the MC, we don't |
||
7926 | + * really need to "unprogram" the MSI, so we just return. |
||
7927 | + */ |
||
7928 | + if (msi_desc->msg.address_lo == 0x0 && msi_desc->msg.address_hi == 0x0) |
||
7929 | + return; |
||
7930 | + |
||
7931 | + if (!owner_mc_dev) |
||
7932 | + return; |
||
7933 | + |
||
7934 | + irq_cfg.paddr = ((u64)msi_desc->msg.address_hi << 32) | |
||
7935 | + msi_desc->msg.address_lo; |
||
7936 | + irq_cfg.val = msi_desc->msg.data; |
||
7937 | + irq_cfg.irq_num = msi_desc->irq; |
||
7938 | + |
||
7939 | + if (owner_mc_dev == mc_bus_dev) { |
||
7940 | + /* |
||
7941 | + * IRQ is for the mc_bus_dev's DPRC itself |
||
7942 | + */ |
||
7943 | + error = dprc_set_irq(mc_bus_dev->mc_io, |
||
7944 | + MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI, |
||
7945 | + mc_bus_dev->mc_handle, |
||
7946 | + mc_dev_irq->dev_irq_index, |
||
7947 | + &irq_cfg); |
||
7948 | + if (error < 0) { |
||
7949 | + dev_err(&owner_mc_dev->dev, |
||
7950 | + "dprc_set_irq() failed: %d\n", error); |
||
7951 | + } |
||
7952 | + } else { |
||
7953 | + /* |
||
7954 | + * IRQ is for for a child device of mc_bus_dev |
||
7955 | + */ |
||
7956 | + error = dprc_set_obj_irq(mc_bus_dev->mc_io, |
||
7957 | + MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI, |
||
7958 | + mc_bus_dev->mc_handle, |
||
7959 | + owner_mc_dev->obj_desc.type, |
||
7960 | + owner_mc_dev->obj_desc.id, |
||
7961 | + mc_dev_irq->dev_irq_index, |
||
7962 | + &irq_cfg); |
||
7963 | + if (error < 0) { |
||
7964 | + dev_err(&owner_mc_dev->dev, |
||
7965 | + "dprc_obj_set_irq() failed: %d\n", error); |
||
7966 | + } |
||
7967 | + } |
||
7968 | +} |
||
7969 | + |
||
7970 | +/* |
||
7971 | + * NOTE: This function is invoked with interrupts disabled |
||
7972 | + */ |
||
7973 | +static void fsl_mc_msi_write_msg(struct irq_data *irq_data, |
||
7974 | + struct msi_msg *msg) |
||
7975 | +{ |
||
7976 | + struct msi_desc *msi_desc = irq_data_get_msi_desc(irq_data); |
||
7977 | + struct fsl_mc_device *mc_bus_dev = to_fsl_mc_device(msi_desc->dev); |
||
7978 | + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); |
||
7979 | + struct fsl_mc_device_irq *mc_dev_irq = |
||
7980 | + &mc_bus->irq_resources[msi_desc->fsl_mc.msi_index]; |
||
7981 | + |
||
7982 | + msi_desc->msg = *msg; |
||
7983 | + |
||
7984 | + /* |
||
7985 | + * Program the MSI (paddr, value) pair in the device: |
||
7986 | + */ |
||
7987 | + __fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq); |
||
7988 | +} |
||
7989 | + |
||
7990 | +static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info) |
||
7991 | +{ |
||
7992 | + struct irq_chip *chip = info->chip; |
||
7993 | + |
||
7994 | + if (!chip) |
||
7995 | + return; |
||
7996 | + |
||
7997 | + /* |
||
7998 | + * irq_write_msi_msg should not be set by the caller |
||
7999 | + */ |
||
8000 | + if (!chip->irq_write_msi_msg) |
||
8001 | + chip->irq_write_msi_msg = fsl_mc_msi_write_msg; |
||
8002 | +} |
||
8003 | + |
||
8004 | +/** |
||
8005 | + * fsl_mc_msi_create_irq_domain - Create a fsl-mc MSI interrupt domain |
||
8006 | + * @np: Optional device-tree node of the interrupt controller |
||
8007 | + * @info: MSI domain info |
||
8008 | + * @parent: Parent irq domain |
||
8009 | + * |
||
8010 | + * Updates the domain and chip ops and creates a fsl-mc MSI |
||
8011 | + * interrupt domain. |
||
8012 | + * |
||
8013 | + * Returns: |
||
8014 | + * A domain pointer or NULL in case of failure. |
||
8015 | + */ |
||
8016 | +struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode, |
||
8017 | + struct msi_domain_info *info, |
||
8018 | + struct irq_domain *parent) |
||
8019 | +{ |
||
8020 | + struct irq_domain *domain; |
||
8021 | + |
||
8022 | + if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS) |
||
8023 | + fsl_mc_msi_update_dom_ops(info); |
||
8024 | + if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) |
||
8025 | + fsl_mc_msi_update_chip_ops(info); |
||
8026 | + |
||
8027 | + domain = msi_create_irq_domain(fwnode, info, parent); |
||
8028 | + if (domain) |
||
8029 | + irq_domain_update_bus_token(domain, DOMAIN_BUS_FSL_MC_MSI); |
||
8030 | + |
||
8031 | + return domain; |
||
8032 | +} |
||
8033 | + |
||
8034 | +int fsl_mc_find_msi_domain(struct device *mc_platform_dev, |
||
8035 | + struct irq_domain **mc_msi_domain) |
||
8036 | +{ |
||
8037 | + struct irq_domain *msi_domain; |
||
8038 | + struct device_node *mc_of_node = mc_platform_dev->of_node; |
||
8039 | + |
||
8040 | + msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node, |
||
8041 | + DOMAIN_BUS_FSL_MC_MSI); |
||
8042 | + if (!msi_domain) { |
||
8043 | + pr_err("Unable to find fsl-mc MSI domain for %pOF\n", |
||
8044 | + mc_of_node); |
||
8045 | + |
||
8046 | + return -ENOENT; |
||
8047 | + } |
||
8048 | + |
||
8049 | + *mc_msi_domain = msi_domain; |
||
8050 | + return 0; |
||
8051 | +} |
||
8052 | + |
||
8053 | +static void fsl_mc_msi_free_descs(struct device *dev) |
||
8054 | +{ |
||
8055 | + struct msi_desc *desc, *tmp; |
||
8056 | + |
||
8057 | + list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) { |
||
8058 | + list_del(&desc->list); |
||
8059 | + free_msi_entry(desc); |
||
8060 | + } |
||
8061 | +} |
||
8062 | + |
||
8063 | +static int fsl_mc_msi_alloc_descs(struct device *dev, unsigned int irq_count) |
||
8064 | + |
||
8065 | +{ |
||
8066 | + unsigned int i; |
||
8067 | + int error; |
||
8068 | + struct msi_desc *msi_desc; |
||
8069 | + |
||
8070 | + for (i = 0; i < irq_count; i++) { |
||
8071 | + msi_desc = alloc_msi_entry(dev, 1, NULL); |
||
8072 | + if (!msi_desc) { |
||
8073 | + dev_err(dev, "Failed to allocate msi entry\n"); |
||
8074 | + error = -ENOMEM; |
||
8075 | + goto cleanup_msi_descs; |
||
8076 | + } |
||
8077 | + |
||
8078 | + msi_desc->fsl_mc.msi_index = i; |
||
8079 | + INIT_LIST_HEAD(&msi_desc->list); |
||
8080 | + list_add_tail(&msi_desc->list, dev_to_msi_list(dev)); |
||
8081 | + } |
||
8082 | + |
||
8083 | + return 0; |
||
8084 | + |
||
8085 | +cleanup_msi_descs: |
||
8086 | + fsl_mc_msi_free_descs(dev); |
||
8087 | + return error; |
||
8088 | +} |
||
8089 | + |
||
8090 | +int fsl_mc_msi_domain_alloc_irqs(struct device *dev, |
||
8091 | + unsigned int irq_count) |
||
8092 | +{ |
||
8093 | + struct irq_domain *msi_domain; |
||
8094 | + int error; |
||
8095 | + |
||
8096 | + if (!list_empty(dev_to_msi_list(dev))) |
||
8097 | + return -EINVAL; |
||
8098 | + |
||
8099 | + error = fsl_mc_msi_alloc_descs(dev, irq_count); |
||
8100 | + if (error < 0) |
||
8101 | + return error; |
||
8102 | + |
||
8103 | + msi_domain = dev_get_msi_domain(dev); |
||
8104 | + if (!msi_domain) { |
||
8105 | + error = -EINVAL; |
||
8106 | + goto cleanup_msi_descs; |
||
8107 | + } |
||
8108 | + |
||
8109 | + /* |
||
8110 | + * NOTE: Calling this function will trigger the invocation of the |
||
8111 | + * its_fsl_mc_msi_prepare() callback |
||
8112 | + */ |
||
8113 | + error = msi_domain_alloc_irqs(msi_domain, dev, irq_count); |
||
8114 | + |
||
8115 | + if (error) { |
||
8116 | + dev_err(dev, "Failed to allocate IRQs\n"); |
||
8117 | + goto cleanup_msi_descs; |
||
8118 | + } |
||
8119 | + |
||
8120 | + return 0; |
||
8121 | + |
||
8122 | +cleanup_msi_descs: |
||
8123 | + fsl_mc_msi_free_descs(dev); |
||
8124 | + return error; |
||
8125 | +} |
||
8126 | + |
||
8127 | +void fsl_mc_msi_domain_free_irqs(struct device *dev) |
||
8128 | +{ |
||
8129 | + struct irq_domain *msi_domain; |
||
8130 | + |
||
8131 | + msi_domain = dev_get_msi_domain(dev); |
||
8132 | + if (!msi_domain) |
||
8133 | + return; |
||
8134 | + |
||
8135 | + msi_domain_free_irqs(msi_domain, dev); |
||
8136 | + |
||
8137 | + if (list_empty(dev_to_msi_list(dev))) |
||
8138 | + return; |
||
8139 | + |
||
8140 | + fsl_mc_msi_free_descs(dev); |
||
8141 | +} |
||
8142 | --- /dev/null |
||
8143 | +++ b/drivers/bus/fsl-mc/fsl-mc-private.h |
||
8144 | @@ -0,0 +1,223 @@ |
||
8145 | +/* SPDX-License-Identifier: GPL-2.0 */ |
||
8146 | +/* |
||
8147 | + * Freescale Management Complex (MC) bus private declarations |
||
8148 | + * |
||
8149 | + * Copyright (C) 2016 Freescale Semiconductor, Inc. |
||
8150 | + * |
||
8151 | + */ |
||
8152 | +#ifndef _FSL_MC_PRIVATE_H_ |
||
8153 | +#define _FSL_MC_PRIVATE_H_ |
||
8154 | + |
||
8155 | +#include <linux/fsl/mc.h> |
||
8156 | +#include <linux/mutex.h> |
||
8157 | +#include <linux/cdev.h> |
||
8158 | +#include <linux/ioctl.h> |
||
8159 | + |
||
8160 | +/* |
||
8161 | + * Data Path Management Complex (DPMNG) General API |
||
8162 | + */ |
||
8163 | + |
||
8164 | +/* DPMNG command versioning */ |
||
8165 | +#define DPMNG_CMD_BASE_VERSION 1 |
||
8166 | +#define DPMNG_CMD_ID_OFFSET 4 |
||
8167 | + |
||
8168 | +#define DPMNG_CMD(id) (((id) << DPMNG_CMD_ID_OFFSET) | DPMNG_CMD_BASE_VERSION) |
||
8169 | + |
||
8170 | +/* DPMNG command IDs */ |
||
8171 | +#define DPMNG_CMDID_GET_VERSION DPMNG_CMD(0x831) |
||
8172 | + |
||
8173 | +struct dpmng_rsp_get_version { |
||
8174 | + __le32 revision; |
||
8175 | + __le32 version_major; |
||
8176 | + __le32 version_minor; |
||
8177 | +}; |
||
8178 | + |
||
8179 | +/* |
||
8180 | + * Data Path Management Command Portal (DPMCP) API |
||
8181 | + */ |
||
8182 | + |
||
8183 | +/* Minimal supported DPMCP Version */ |
||
8184 | +#define DPMCP_MIN_VER_MAJOR 3 |
||
8185 | +#define DPMCP_MIN_VER_MINOR 0 |
||
8186 | + |
||
8187 | +/* DPMCP command versioning */ |
||
8188 | +#define DPMCP_CMD_BASE_VERSION 1 |
||
8189 | +#define DPMCP_CMD_ID_OFFSET 4 |
||
8190 | + |
||
8191 | +#define DPMCP_CMD(id) (((id) << DPMCP_CMD_ID_OFFSET) | DPMCP_CMD_BASE_VERSION) |
||
8192 | + |
||
8193 | +/* DPMCP command IDs */ |
||
8194 | +#define DPMCP_CMDID_CLOSE DPMCP_CMD(0x800) |
||
8195 | +#define DPMCP_CMDID_OPEN DPMCP_CMD(0x80b) |
||
8196 | +#define DPMCP_CMDID_RESET DPMCP_CMD(0x005) |
||
8197 | + |
||
8198 | +struct dpmcp_cmd_open { |
||
8199 | + __le32 dpmcp_id; |
||
8200 | +}; |
||
8201 | + |
||
8202 | +/* |
||
8203 | + * Initialization and runtime control APIs for DPMCP |
||
8204 | + */ |
||
8205 | +int dpmcp_open(struct fsl_mc_io *mc_io, |
||
8206 | + u32 cmd_flags, |
||
8207 | + int dpmcp_id, |
||
8208 | + u16 *token); |
||
8209 | + |
||
8210 | +int dpmcp_close(struct fsl_mc_io *mc_io, |
||
8211 | + u32 cmd_flags, |
||
8212 | + u16 token); |
||
8213 | + |
||
8214 | +int dpmcp_reset(struct fsl_mc_io *mc_io, |
||
8215 | + u32 cmd_flags, |
||
8216 | + u16 token); |
||
8217 | + |
||
8218 | +/* |
||
8219 | + * Data Path Buffer Pool (DPBP) API |
||
8220 | + */ |
||
8221 | + |
||
8222 | +/* DPBP Version */ |
||
8223 | +#define DPBP_VER_MAJOR 3 |
||
8224 | +#define DPBP_VER_MINOR 2 |
||
8225 | + |
||
8226 | +/* Command versioning */ |
||
8227 | +#define DPBP_CMD_BASE_VERSION 1 |
||
8228 | +#define DPBP_CMD_ID_OFFSET 4 |
||
8229 | + |
||
8230 | +#define DPBP_CMD(id) (((id) << DPBP_CMD_ID_OFFSET) | DPBP_CMD_BASE_VERSION) |
||
8231 | + |
||
8232 | +/* Command IDs */ |
||
8233 | +#define DPBP_CMDID_CLOSE DPBP_CMD(0x800) |
||
8234 | +#define DPBP_CMDID_OPEN DPBP_CMD(0x804) |
||
8235 | + |
||
8236 | +#define DPBP_CMDID_ENABLE DPBP_CMD(0x002) |
||
8237 | +#define DPBP_CMDID_DISABLE DPBP_CMD(0x003) |
||
8238 | +#define DPBP_CMDID_GET_ATTR DPBP_CMD(0x004) |
||
8239 | +#define DPBP_CMDID_RESET DPBP_CMD(0x005) |
||
8240 | + |
||
8241 | +struct dpbp_cmd_open { |
||
8242 | + __le32 dpbp_id; |
||
8243 | +}; |
||
8244 | + |
||
8245 | +#define DPBP_ENABLE 0x1 |
||
8246 | + |
||
8247 | +struct dpbp_rsp_get_attributes { |
||
8248 | + /* response word 0 */ |
||
8249 | + __le16 pad; |
||
8250 | + __le16 bpid; |
||
8251 | + __le32 id; |
||
8252 | + /* response word 1 */ |
||
8253 | + __le16 version_major; |
||
8254 | + __le16 version_minor; |
||
8255 | +}; |
||
8256 | + |
||
8257 | +/* |
||
8258 | + * Data Path Concentrator (DPCON) API |
||
8259 | + */ |
||
8260 | + |
||
8261 | +/* DPCON Version */ |
||
8262 | +#define DPCON_VER_MAJOR 3 |
||
8263 | +#define DPCON_VER_MINOR 2 |
||
8264 | + |
||
8265 | +/* Command versioning */ |
||
8266 | +#define DPCON_CMD_BASE_VERSION 1 |
||
8267 | +#define DPCON_CMD_ID_OFFSET 4 |
||
8268 | + |
||
8269 | +#define DPCON_CMD(id) (((id) << DPCON_CMD_ID_OFFSET) | DPCON_CMD_BASE_VERSION) |
||
8270 | + |
||
8271 | +/* Command IDs */ |
||
8272 | +#define DPCON_CMDID_CLOSE DPCON_CMD(0x800) |
||
8273 | +#define DPCON_CMDID_OPEN DPCON_CMD(0x808) |
||
8274 | + |
||
8275 | +#define DPCON_CMDID_ENABLE DPCON_CMD(0x002) |
||
8276 | +#define DPCON_CMDID_DISABLE DPCON_CMD(0x003) |
||
8277 | +#define DPCON_CMDID_GET_ATTR DPCON_CMD(0x004) |
||
8278 | +#define DPCON_CMDID_RESET DPCON_CMD(0x005) |
||
8279 | + |
||
8280 | +#define DPCON_CMDID_SET_NOTIFICATION DPCON_CMD(0x100) |
||
8281 | + |
||
8282 | +struct dpcon_cmd_open { |
||
8283 | + __le32 dpcon_id; |
||
8284 | +}; |
||
8285 | + |
||
8286 | +#define DPCON_ENABLE 1 |
||
8287 | + |
||
8288 | +struct dpcon_rsp_get_attr { |
||
8289 | + /* response word 0 */ |
||
8290 | + __le32 id; |
||
8291 | + __le16 qbman_ch_id; |
||
8292 | + u8 num_priorities; |
||
8293 | + u8 pad; |
||
8294 | +}; |
||
8295 | + |
||
8296 | +struct dpcon_cmd_set_notification { |
||
8297 | + /* cmd word 0 */ |
||
8298 | + __le32 dpio_id; |
||
8299 | + u8 priority; |
||
8300 | + u8 pad[3]; |
||
8301 | + /* cmd word 1 */ |
||
8302 | + __le64 user_ctx; |
||
8303 | +}; |
||
8304 | + |
||
8305 | +int __must_check fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc, |
||
8306 | + struct fsl_mc_io *mc_io, |
||
8307 | + struct device *parent_dev, |
||
8308 | + const char *driver_override, |
||
8309 | + struct fsl_mc_device **new_mc_dev); |
||
8310 | + |
||
8311 | +int __init dprc_driver_init(void); |
||
8312 | + |
||
8313 | +void dprc_driver_exit(void); |
||
8314 | + |
||
8315 | +int __init fsl_mc_allocator_driver_init(void); |
||
8316 | + |
||
8317 | +void fsl_mc_allocator_driver_exit(void); |
||
8318 | + |
||
8319 | +int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, |
||
8320 | + enum fsl_mc_pool_type pool_type, |
||
8321 | + struct fsl_mc_resource |
||
8322 | + **new_resource); |
||
8323 | + |
||
8324 | +void fsl_mc_resource_free(struct fsl_mc_resource *resource); |
||
8325 | + |
||
8326 | +int fsl_mc_msi_domain_alloc_irqs(struct device *dev, |
||
8327 | + unsigned int irq_count); |
||
8328 | + |
||
8329 | +void fsl_mc_msi_domain_free_irqs(struct device *dev); |
||
8330 | + |
||
8331 | +int __must_check fsl_create_mc_io(struct device *dev, |
||
8332 | + phys_addr_t mc_portal_phys_addr, |
||
8333 | + u32 mc_portal_size, |
||
8334 | + struct fsl_mc_device *dpmcp_dev, |
||
8335 | + u32 flags, struct fsl_mc_io **new_mc_io); |
||
8336 | + |
||
8337 | +void fsl_destroy_mc_io(struct fsl_mc_io *mc_io); |
||
8338 | + |
||
8339 | +bool fsl_mc_is_root_dprc(struct device *dev); |
||
8340 | + |
||
8341 | +#ifdef CONFIG_FSL_MC_RESTOOL |
||
8342 | + |
||
8343 | +int fsl_mc_restool_create_device_file(struct fsl_mc_bus *mc_bus); |
||
8344 | + |
||
8345 | +void fsl_mc_restool_remove_device_file(struct fsl_mc_bus *mc_bus); |
||
8346 | + |
||
8347 | +int fsl_mc_restool_init(void); |
||
8348 | + |
||
8349 | +#else |
||
8350 | + |
||
8351 | +static inline int fsl_mc_restool_create_device_file(struct fsl_mc_bus *mc_bus) |
||
8352 | +{ |
||
8353 | + return 0; |
||
8354 | +} |
||
8355 | + |
||
8356 | +static inline void fsl_mc_restool_remove_device_file(struct fsl_mc_bus *mc_bus) |
||
8357 | +{ |
||
8358 | +} |
||
8359 | + |
||
8360 | +static inline int fsl_mc_restool_init(void) |
||
8361 | +{ |
||
8362 | + return 0; |
||
8363 | +} |
||
8364 | + |
||
8365 | +#endif |
||
8366 | + |
||
8367 | +#endif /* _FSL_MC_PRIVATE_H_ */ |
||
8368 | --- /dev/null |
||
8369 | +++ b/drivers/bus/fsl-mc/fsl-mc-restool.c |
||
8370 | @@ -0,0 +1,219 @@ |
||
8371 | +// SPDX-License-Identifier: GPL-2.0 |
||
8372 | +/* |
||
8373 | + * Management Complex (MC) restool support |
||
8374 | + * |
||
8375 | + * Copyright 2018 NXP |
||
8376 | + * |
||
8377 | + */ |
||
8378 | + |
||
8379 | +#include <linux/slab.h> |
||
8380 | +#include <linux/cdev.h> |
||
8381 | +#include <linux/fs.h> |
||
8382 | +#include <linux/uaccess.h> |
||
8383 | + |
||
8384 | +#include "fsl-mc-private.h" |
||
8385 | + |
||
8386 | +#define FSL_MC_BUS_MAX_MINORS 1 |
||
8387 | + |
||
8388 | +static struct class *fsl_mc_bus_class; |
||
8389 | +static int fsl_mc_bus_major; |
||
8390 | + |
||
8391 | +static int fsl_mc_restool_send_command(unsigned long arg, |
||
8392 | + struct fsl_mc_io *mc_io) |
||
8393 | +{ |
||
8394 | + struct fsl_mc_command mc_cmd; |
||
8395 | + int error; |
||
8396 | + |
||
8397 | + error = copy_from_user(&mc_cmd, (void __user *)arg, sizeof(mc_cmd)); |
||
8398 | + if (error) |
||
8399 | + return -EFAULT; |
||
8400 | + |
||
8401 | + error = mc_send_command(mc_io, &mc_cmd); |
||
8402 | + if (error) |
||
8403 | + return error; |
||
8404 | + |
||
8405 | + error = copy_to_user((void __user *)arg, &mc_cmd, sizeof(mc_cmd)); |
||
8406 | + if (error) |
||
8407 | + return -EFAULT; |
||
8408 | + |
||
8409 | + return 0; |
||
8410 | +} |
||
8411 | + |
||
8412 | +int fsl_mc_restool_init(void) |
||
8413 | +{ |
||
8414 | + dev_t dev; |
||
8415 | + int error; |
||
8416 | + |
||
8417 | + fsl_mc_bus_class = class_create(THIS_MODULE, "fsl_mc_bus"); |
||
8418 | + if (IS_ERR(fsl_mc_bus_class)) { |
||
8419 | + error = PTR_ERR(fsl_mc_bus_class); |
||
8420 | + return error; |
||
8421 | + } |
||
8422 | + |
||
8423 | + error = alloc_chrdev_region(&dev, 0, |
||
8424 | + FSL_MC_BUS_MAX_MINORS, |
||
8425 | + "fsl_mc_bus"); |
||
8426 | + if (error < 0) |
||
8427 | + return error; |
||
8428 | + |
||
8429 | + fsl_mc_bus_major = MAJOR(dev); |
||
8430 | + |
||
8431 | + return 0; |
||
8432 | +} |
||
8433 | + |
||
8434 | +static int fsl_mc_restool_dev_open(struct inode *inode, struct file *filep) |
||
8435 | +{ |
||
8436 | + struct fsl_mc_device *root_mc_device; |
||
8437 | + struct fsl_mc_restool *mc_restool; |
||
8438 | + struct fsl_mc_bus *mc_bus; |
||
8439 | + struct fsl_mc_io *dynamic_mc_io; |
||
8440 | + int error; |
||
8441 | + |
||
8442 | + mc_restool = container_of(inode->i_cdev, struct fsl_mc_restool, cdev); |
||
8443 | + mc_bus = container_of(mc_restool, struct fsl_mc_bus, restool_misc); |
||
8444 | + root_mc_device = &mc_bus->mc_dev; |
||
8445 | + |
||
8446 | + mutex_lock(&mc_restool->mutex); |
||
8447 | + |
||
8448 | + if (!mc_restool->local_instance_in_use) { |
||
8449 | + filep->private_data = root_mc_device->mc_io; |
||
8450 | + mc_restool->local_instance_in_use = true; |
||
8451 | + } else { |
||
8452 | + dynamic_mc_io = kzalloc(sizeof(*dynamic_mc_io), GFP_KERNEL); |
||
8453 | + if (!dynamic_mc_io) { |
||
8454 | + error = -ENOMEM; |
||
8455 | + goto error_alloc_mc_io; |
||
8456 | + } |
||
8457 | + |
||
8458 | + error = fsl_mc_portal_allocate(root_mc_device, 0, |
||
8459 | + &dynamic_mc_io); |
||
8460 | + if (error) { |
||
8461 | + pr_err("Could not allocate MC portal\n"); |
||
8462 | + goto error_portal_allocate; |
||
8463 | + } |
||
8464 | + |
||
8465 | + mc_restool->dynamic_instance_count++; |
||
8466 | + filep->private_data = dynamic_mc_io; |
||
8467 | + } |
||
8468 | + |
||
8469 | + mutex_unlock(&mc_restool->mutex); |
||
8470 | + |
||
8471 | + return 0; |
||
8472 | + |
||
8473 | +error_portal_allocate: |
||
8474 | + kfree(dynamic_mc_io); |
||
8475 | + |
||
8476 | +error_alloc_mc_io: |
||
8477 | + mutex_unlock(&mc_restool->mutex); |
||
8478 | + |
||
8479 | + return error; |
||
8480 | +} |
||
8481 | + |
||
8482 | +static int fsl_mc_restool_dev_release(struct inode *inode, struct file *filep) |
||
8483 | +{ |
||
8484 | + struct fsl_mc_device *root_mc_device; |
||
8485 | + struct fsl_mc_restool *mc_restool; |
||
8486 | + struct fsl_mc_bus *mc_bus; |
||
8487 | + struct fsl_mc_io *mc_io; |
||
8488 | + |
||
8489 | + mc_restool = container_of(inode->i_cdev, struct fsl_mc_restool, cdev); |
||
8490 | + mc_bus = container_of(mc_restool, struct fsl_mc_bus, restool_misc); |
||
8491 | + root_mc_device = &mc_bus->mc_dev; |
||
8492 | + mc_io = filep->private_data; |
||
8493 | + |
||
8494 | + mutex_lock(&mc_restool->mutex); |
||
8495 | + |
||
8496 | + if (WARN_ON(!mc_restool->local_instance_in_use && |
||
8497 | + mc_restool->dynamic_instance_count == 0)) { |
||
8498 | + mutex_unlock(&mc_restool->mutex); |
||
8499 | + return -EINVAL; |
||
8500 | + } |
||
8501 | + |
||
8502 | + if (filep->private_data == root_mc_device->mc_io) { |
||
8503 | + mc_restool->local_instance_in_use = false; |
||
8504 | + } else { |
||
8505 | + fsl_mc_portal_free(mc_io); |
||
8506 | + kfree(mc_io); |
||
8507 | + mc_restool->dynamic_instance_count--; |
||
8508 | + } |
||
8509 | + |
||
8510 | + filep->private_data = NULL; |
||
8511 | + mutex_unlock(&mc_restool->mutex); |
||
8512 | + |
||
8513 | + return 0; |
||
8514 | +} |
||
8515 | + |
||
8516 | +static long fsl_mc_restool_dev_ioctl(struct file *file, |
||
8517 | + unsigned int cmd, |
||
8518 | + unsigned long arg) |
||
8519 | +{ |
||
8520 | + int error; |
||
8521 | + |
||
8522 | + switch (cmd) { |
||
8523 | + case RESTOOL_SEND_MC_COMMAND: |
||
8524 | + error = fsl_mc_restool_send_command(arg, file->private_data); |
||
8525 | + break; |
||
8526 | + default: |
||
8527 | + pr_err("%s: unexpected ioctl call number\n", __func__); |
||
8528 | + error = -EINVAL; |
||
8529 | + } |
||
8530 | + |
||
8531 | + return error; |
||
8532 | +} |
||
8533 | + |
||
8534 | +static const struct file_operations fsl_mc_restool_dev_fops = { |
||
8535 | + .owner = THIS_MODULE, |
||
8536 | + .open = fsl_mc_restool_dev_open, |
||
8537 | + .release = fsl_mc_restool_dev_release, |
||
8538 | + .unlocked_ioctl = fsl_mc_restool_dev_ioctl, |
||
8539 | +}; |
||
8540 | + |
||
8541 | +int fsl_mc_restool_create_device_file(struct fsl_mc_bus *mc_bus) |
||
8542 | +{ |
||
8543 | + struct fsl_mc_device *mc_dev = &mc_bus->mc_dev; |
||
8544 | + struct fsl_mc_restool *mc_restool = &mc_bus->restool_misc; |
||
8545 | + int error; |
||
8546 | + |
||
8547 | + mc_restool = &mc_bus->restool_misc; |
||
8548 | + mc_restool->dev = MKDEV(fsl_mc_bus_major, 0); |
||
8549 | + cdev_init(&mc_restool->cdev, &fsl_mc_restool_dev_fops); |
||
8550 | + |
||
8551 | + error = cdev_add(&mc_restool->cdev, |
||
8552 | + mc_restool->dev, |
||
8553 | + FSL_MC_BUS_MAX_MINORS); |
||
8554 | + if (error) |
||
8555 | + return error; |
||
8556 | + |
||
8557 | + mc_restool->device = device_create(fsl_mc_bus_class, |
||
8558 | + NULL, |
||
8559 | + mc_restool->dev, |
||
8560 | + NULL, |
||
8561 | + "%s", |
||
8562 | + dev_name(&mc_dev->dev)); |
||
8563 | + if (IS_ERR(mc_restool->device)) { |
||
8564 | + error = PTR_ERR(mc_restool->device); |
||
8565 | + goto error_device_create; |
||
8566 | + } |
||
8567 | + |
||
8568 | + mutex_init(&mc_restool->mutex); |
||
8569 | + |
||
8570 | + return 0; |
||
8571 | + |
||
8572 | +error_device_create: |
||
8573 | + cdev_del(&mc_restool->cdev); |
||
8574 | + |
||
8575 | + return error; |
||
8576 | +} |
||
8577 | + |
||
8578 | +void fsl_mc_restool_remove_device_file(struct fsl_mc_bus *mc_bus) |
||
8579 | +{ |
||
8580 | + struct fsl_mc_restool *mc_restool = &mc_bus->restool_misc; |
||
8581 | + |
||
8582 | + if (WARN_ON(mc_restool->local_instance_in_use)) |
||
8583 | + return; |
||
8584 | + |
||
8585 | + if (WARN_ON(mc_restool->dynamic_instance_count != 0)) |
||
8586 | + return; |
||
8587 | + |
||
8588 | + cdev_del(&mc_restool->cdev); |
||
8589 | +} |
||
8590 | --- a/drivers/staging/fsl-mc/bus/mc-io.c |
||
8591 | +++ /dev/null |
||
8592 | @@ -1,292 +0,0 @@ |
||
8593 | -// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) |
||
8594 | -/* |
||
8595 | - * Copyright 2013-2016 Freescale Semiconductor Inc. |
||
8596 | - * |
||
8597 | - */ |
||
8598 | - |
||
8599 | -#include <linux/io.h> |
||
8600 | -#include "../include/mc.h" |
||
8601 | - |
||
8602 | -#include "fsl-mc-private.h" |
||
8603 | -#include "dpmcp.h" |
||
8604 | -#include "dpmcp-cmd.h" |
||
8605 | - |
||
8606 | -static int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io, |
||
8607 | - struct fsl_mc_device *dpmcp_dev) |
||
8608 | -{ |
||
8609 | - int error; |
||
8610 | - |
||
8611 | - if (WARN_ON(!dpmcp_dev)) |
||
8612 | - return -EINVAL; |
||
8613 | - |
||
8614 | - if (WARN_ON(mc_io->dpmcp_dev)) |
||
8615 | - return -EINVAL; |
||
8616 | - |
||
8617 | - if (WARN_ON(dpmcp_dev->mc_io)) |
||
8618 | - return -EINVAL; |
||
8619 | - |
||
8620 | - error = dpmcp_open(mc_io, |
||
8621 | - 0, |
||
8622 | - dpmcp_dev->obj_desc.id, |
||
8623 | - &dpmcp_dev->mc_handle); |
||
8624 | - if (error < 0) |
||
8625 | - return error; |
||
8626 | - |
||
8627 | - mc_io->dpmcp_dev = dpmcp_dev; |
||
8628 | - dpmcp_dev->mc_io = mc_io; |
||
8629 | - return 0; |
||
8630 | -} |
||
8631 | - |
||
8632 | -static void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io) |
||
8633 | -{ |
||
8634 | - int error; |
||
8635 | - struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; |
||
8636 | - |
||
8637 | - if (WARN_ON(!dpmcp_dev)) |
||
8638 | - return; |
||
8639 | - |
||
8640 | - if (WARN_ON(dpmcp_dev->mc_io != mc_io)) |
||
8641 | - return; |
||
8642 | - |
||
8643 | - error = dpmcp_close(mc_io, |
||
8644 | - 0, |
||
8645 | - dpmcp_dev->mc_handle); |
||
8646 | - if (error < 0) { |
||
8647 | - dev_err(&dpmcp_dev->dev, "dpmcp_close() failed: %d\n", |
||
8648 | - error); |
||
8649 | - } |
||
8650 | - |
||
8651 | - mc_io->dpmcp_dev = NULL; |
||
8652 | - dpmcp_dev->mc_io = NULL; |
||
8653 | -} |
||
8654 | - |
||
8655 | -/** |
||
8656 | - * Creates an MC I/O object |
||
8657 | - * |
||
8658 | - * @dev: device to be associated with the MC I/O object |
||
8659 | - * @mc_portal_phys_addr: physical address of the MC portal to use |
||
8660 | - * @mc_portal_size: size in bytes of the MC portal |
||
8661 | - * @dpmcp-dev: Pointer to the DPMCP object associated with this MC I/O |
||
8662 | - * object or NULL if none. |
||
8663 | - * @flags: flags for the new MC I/O object |
||
8664 | - * @new_mc_io: Area to return pointer to newly created MC I/O object |
||
8665 | - * |
||
8666 | - * Returns '0' on Success; Error code otherwise. |
||
8667 | - */ |
||
8668 | -int __must_check fsl_create_mc_io(struct device *dev, |
||
8669 | - phys_addr_t mc_portal_phys_addr, |
||
8670 | - u32 mc_portal_size, |
||
8671 | - struct fsl_mc_device *dpmcp_dev, |
||
8672 | - u32 flags, struct fsl_mc_io **new_mc_io) |
||
8673 | -{ |
||
8674 | - int error; |
||
8675 | - struct fsl_mc_io *mc_io; |
||
8676 | - void __iomem *mc_portal_virt_addr; |
||
8677 | - struct resource *res; |
||
8678 | - |
||
8679 | - mc_io = devm_kzalloc(dev, sizeof(*mc_io), GFP_KERNEL); |
||
8680 | - if (!mc_io) |
||
8681 | - return -ENOMEM; |
||
8682 | - |
||
8683 | - mc_io->dev = dev; |
||
8684 | - mc_io->flags = flags; |
||
8685 | - mc_io->portal_phys_addr = mc_portal_phys_addr; |
||
8686 | - mc_io->portal_size = mc_portal_size; |
||
8687 | - if (flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) |
||
8688 | - spin_lock_init(&mc_io->spinlock); |
||
8689 | - else |
||
8690 | - mutex_init(&mc_io->mutex); |
||
8691 | - |
||
8692 | - res = devm_request_mem_region(dev, |
||
8693 | - mc_portal_phys_addr, |
||
8694 | - mc_portal_size, |
||
8695 | - "mc_portal"); |
||
8696 | - if (!res) { |
||
8697 | - dev_err(dev, |
||
8698 | - "devm_request_mem_region failed for MC portal %pa\n", |
||
8699 | - &mc_portal_phys_addr); |
||
8700 | - return -EBUSY; |
||
8701 | - } |
||
8702 | - |
||
8703 | - mc_portal_virt_addr = devm_ioremap_nocache(dev, |
||
8704 | - mc_portal_phys_addr, |
||
8705 | - mc_portal_size); |
||
8706 | - if (!mc_portal_virt_addr) { |
||
8707 | - dev_err(dev, |
||
8708 | - "devm_ioremap_nocache failed for MC portal %pa\n", |
||
8709 | - &mc_portal_phys_addr); |
||
8710 | - return -ENXIO; |
||
8711 | - } |
||
8712 | - |
||
8713 | - mc_io->portal_virt_addr = mc_portal_virt_addr; |
||
8714 | - if (dpmcp_dev) { |
||
8715 | - error = fsl_mc_io_set_dpmcp(mc_io, dpmcp_dev); |
||
8716 | - if (error < 0) |
||
8717 | - goto error_destroy_mc_io; |
||
8718 | - } |
||
8719 | - |
||
8720 | - *new_mc_io = mc_io; |
||
8721 | - return 0; |
||
8722 | - |
||
8723 | -error_destroy_mc_io: |
||
8724 | - fsl_destroy_mc_io(mc_io); |
||
8725 | - return error; |
||
8726 | -} |
||
8727 | - |
||
8728 | -/** |
||
8729 | - * Destroys an MC I/O object |
||
8730 | - * |
||
8731 | - * @mc_io: MC I/O object to destroy |
||
8732 | - */ |
||
8733 | -void fsl_destroy_mc_io(struct fsl_mc_io *mc_io) |
||
8734 | -{ |
||
8735 | - struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; |
||
8736 | - |
||
8737 | - if (dpmcp_dev) |
||
8738 | - fsl_mc_io_unset_dpmcp(mc_io); |
||
8739 | - |
||
8740 | - devm_iounmap(mc_io->dev, mc_io->portal_virt_addr); |
||
8741 | - devm_release_mem_region(mc_io->dev, |
||
8742 | - mc_io->portal_phys_addr, |
||
8743 | - mc_io->portal_size); |
||
8744 | - |
||
8745 | - mc_io->portal_virt_addr = NULL; |
||
8746 | - devm_kfree(mc_io->dev, mc_io); |
||
8747 | -} |
||
8748 | - |
||
8749 | -/** |
||
8750 | - * fsl_mc_portal_allocate - Allocates an MC portal |
||
8751 | - * |
||
8752 | - * @mc_dev: MC device for which the MC portal is to be allocated |
||
8753 | - * @mc_io_flags: Flags for the fsl_mc_io object that wraps the allocated |
||
8754 | - * MC portal. |
||
8755 | - * @new_mc_io: Pointer to area where the pointer to the fsl_mc_io object |
||
8756 | - * that wraps the allocated MC portal is to be returned |
||
8757 | - * |
||
8758 | - * This function allocates an MC portal from the device's parent DPRC, |
||
8759 | - * from the corresponding MC bus' pool of MC portals and wraps |
||
8760 | - * it in a new fsl_mc_io object. If 'mc_dev' is a DPRC itself, the |
||
8761 | - * portal is allocated from its own MC bus. |
||
8762 | - */ |
||
8763 | -int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, |
||
8764 | - u16 mc_io_flags, |
||
8765 | - struct fsl_mc_io **new_mc_io) |
||
8766 | -{ |
||
8767 | - struct fsl_mc_device *mc_bus_dev; |
||
8768 | - struct fsl_mc_bus *mc_bus; |
||
8769 | - phys_addr_t mc_portal_phys_addr; |
||
8770 | - size_t mc_portal_size; |
||
8771 | - struct fsl_mc_device *dpmcp_dev; |
||
8772 | - int error = -EINVAL; |
||
8773 | - struct fsl_mc_resource *resource = NULL; |
||
8774 | - struct fsl_mc_io *mc_io = NULL; |
||
8775 | - |
||
8776 | - if (mc_dev->flags & FSL_MC_IS_DPRC) { |
||
8777 | - mc_bus_dev = mc_dev; |
||
8778 | - } else { |
||
8779 | - if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent))) |
||
8780 | - return error; |
||
8781 | - |
||
8782 | - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); |
||
8783 | - } |
||
8784 | - |
||
8785 | - mc_bus = to_fsl_mc_bus(mc_bus_dev); |
||
8786 | - *new_mc_io = NULL; |
||
8787 | - error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_DPMCP, &resource); |
||
8788 | - if (error < 0) |
||
8789 | - return error; |
||
8790 | - |
||
8791 | - error = -EINVAL; |
||
8792 | - dpmcp_dev = resource->data; |
||
8793 | - if (WARN_ON(!dpmcp_dev)) |
||
8794 | - goto error_cleanup_resource; |
||
8795 | - |
||
8796 | - if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR || |
||
8797 | - (dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR && |
||
8798 | - dpmcp_dev->obj_desc.ver_minor < DPMCP_MIN_VER_MINOR)) { |
||
8799 | - dev_err(&dpmcp_dev->dev, |
||
8800 | - "ERROR: Version %d.%d of DPMCP not supported.\n", |
||
8801 | - dpmcp_dev->obj_desc.ver_major, |
||
8802 | - dpmcp_dev->obj_desc.ver_minor); |
||
8803 | - error = -ENOTSUPP; |
||
8804 | - goto error_cleanup_resource; |
||
8805 | - } |
||
8806 | - |
||
8807 | - if (WARN_ON(dpmcp_dev->obj_desc.region_count == 0)) |
||
8808 | - goto error_cleanup_resource; |
||
8809 | - |
||
8810 | - mc_portal_phys_addr = dpmcp_dev->regions[0].start; |
||
8811 | - mc_portal_size = resource_size(dpmcp_dev->regions); |
||
8812 | - |
||
8813 | - if (WARN_ON(mc_portal_size != mc_bus_dev->mc_io->portal_size)) |
||
8814 | - goto error_cleanup_resource; |
||
8815 | - |
||
8816 | - error = fsl_create_mc_io(&mc_bus_dev->dev, |
||
8817 | - mc_portal_phys_addr, |
||
8818 | - mc_portal_size, dpmcp_dev, |
||
8819 | - mc_io_flags, &mc_io); |
||
8820 | - if (error < 0) |
||
8821 | - goto error_cleanup_resource; |
||
8822 | - |
||
8823 | - *new_mc_io = mc_io; |
||
8824 | - return 0; |
||
8825 | - |
||
8826 | -error_cleanup_resource: |
||
8827 | - fsl_mc_resource_free(resource); |
||
8828 | - return error; |
||
8829 | -} |
||
8830 | -EXPORT_SYMBOL_GPL(fsl_mc_portal_allocate); |
||
8831 | - |
||
8832 | -/** |
||
8833 | - * fsl_mc_portal_free - Returns an MC portal to the pool of free MC portals |
||
8834 | - * of a given MC bus |
||
8835 | - * |
||
8836 | - * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free |
||
8837 | - */ |
||
8838 | -void fsl_mc_portal_free(struct fsl_mc_io *mc_io) |
||
8839 | -{ |
||
8840 | - struct fsl_mc_device *dpmcp_dev; |
||
8841 | - struct fsl_mc_resource *resource; |
||
8842 | - |
||
8843 | - /* |
||
8844 | - * Every mc_io obtained by calling fsl_mc_portal_allocate() is supposed |
||
8845 | - * to have a DPMCP object associated with. |
||
8846 | - */ |
||
8847 | - dpmcp_dev = mc_io->dpmcp_dev; |
||
8848 | - if (WARN_ON(!dpmcp_dev)) |
||
8849 | - return; |
||
8850 | - |
||
8851 | - resource = dpmcp_dev->resource; |
||
8852 | - if (WARN_ON(!resource || resource->type != FSL_MC_POOL_DPMCP)) |
||
8853 | - return; |
||
8854 | - |
||
8855 | - if (WARN_ON(resource->data != dpmcp_dev)) |
||
8856 | - return; |
||
8857 | - |
||
8858 | - fsl_destroy_mc_io(mc_io); |
||
8859 | - fsl_mc_resource_free(resource); |
||
8860 | -} |
||
8861 | -EXPORT_SYMBOL_GPL(fsl_mc_portal_free); |
||
8862 | - |
||
8863 | -/** |
||
8864 | - * fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object |
||
8865 | - * |
||
8866 | - * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free |
||
8867 | - */ |
||
8868 | -int fsl_mc_portal_reset(struct fsl_mc_io *mc_io) |
||
8869 | -{ |
||
8870 | - int error; |
||
8871 | - struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; |
||
8872 | - |
||
8873 | - if (WARN_ON(!dpmcp_dev)) |
||
8874 | - return -EINVAL; |
||
8875 | - |
||
8876 | - error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle); |
||
8877 | - if (error < 0) { |
||
8878 | - dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error); |
||
8879 | - return error; |
||
8880 | - } |
||
8881 | - |
||
8882 | - return 0; |
||
8883 | -} |
||
8884 | -EXPORT_SYMBOL_GPL(fsl_mc_portal_reset); |
||
8885 | --- /dev/null |
||
8886 | +++ b/drivers/bus/fsl-mc/mc-io.c |
||
8887 | @@ -0,0 +1,268 @@ |
||
8888 | +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) |
||
8889 | +/* |
||
8890 | + * Copyright 2013-2016 Freescale Semiconductor Inc. |
||
8891 | + * |
||
8892 | + */ |
||
8893 | + |
||
8894 | +#include <linux/io.h> |
||
8895 | +#include <linux/fsl/mc.h> |
||
8896 | + |
||
8897 | +#include "fsl-mc-private.h" |
||
8898 | + |
||
8899 | +static int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io, |
||
8900 | + struct fsl_mc_device *dpmcp_dev) |
||
8901 | +{ |
||
8902 | + int error; |
||
8903 | + |
||
8904 | + if (mc_io->dpmcp_dev) |
||
8905 | + return -EINVAL; |
||
8906 | + |
||
8907 | + if (dpmcp_dev->mc_io) |
||
8908 | + return -EINVAL; |
||
8909 | + |
||
8910 | + error = dpmcp_open(mc_io, |
||
8911 | + 0, |
||
8912 | + dpmcp_dev->obj_desc.id, |
||
8913 | + &dpmcp_dev->mc_handle); |
||
8914 | + if (error < 0) |
||
8915 | + return error; |
||
8916 | + |
||
8917 | + mc_io->dpmcp_dev = dpmcp_dev; |
||
8918 | + dpmcp_dev->mc_io = mc_io; |
||
8919 | + return 0; |
||
8920 | +} |
||
8921 | + |
||
8922 | +static void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io) |
||
8923 | +{ |
||
8924 | + int error; |
||
8925 | + struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; |
||
8926 | + |
||
8927 | + error = dpmcp_close(mc_io, |
||
8928 | + 0, |
||
8929 | + dpmcp_dev->mc_handle); |
||
8930 | + if (error < 0) { |
||
8931 | + dev_err(&dpmcp_dev->dev, "dpmcp_close() failed: %d\n", |
||
8932 | + error); |
||
8933 | + } |
||
8934 | + |
||
8935 | + mc_io->dpmcp_dev = NULL; |
||
8936 | + dpmcp_dev->mc_io = NULL; |
||
8937 | +} |
||
8938 | + |
||
8939 | +/** |
||
8940 | + * Creates an MC I/O object |
||
8941 | + * |
||
8942 | + * @dev: device to be associated with the MC I/O object |
||
8943 | + * @mc_portal_phys_addr: physical address of the MC portal to use |
||
8944 | + * @mc_portal_size: size in bytes of the MC portal |
||
8945 | + * @dpmcp-dev: Pointer to the DPMCP object associated with this MC I/O |
||
8946 | + * object or NULL if none. |
||
8947 | + * @flags: flags for the new MC I/O object |
||
8948 | + * @new_mc_io: Area to return pointer to newly created MC I/O object |
||
8949 | + * |
||
8950 | + * Returns '0' on Success; Error code otherwise. |
||
8951 | + */ |
||
8952 | +int __must_check fsl_create_mc_io(struct device *dev, |
||
8953 | + phys_addr_t mc_portal_phys_addr, |
||
8954 | + u32 mc_portal_size, |
||
8955 | + struct fsl_mc_device *dpmcp_dev, |
||
8956 | + u32 flags, struct fsl_mc_io **new_mc_io) |
||
8957 | +{ |
||
8958 | + int error; |
||
8959 | + struct fsl_mc_io *mc_io; |
||
8960 | + void __iomem *mc_portal_virt_addr; |
||
8961 | + struct resource *res; |
||
8962 | + |
||
8963 | + mc_io = devm_kzalloc(dev, sizeof(*mc_io), GFP_KERNEL); |
||
8964 | + if (!mc_io) |
||
8965 | + return -ENOMEM; |
||
8966 | + |
||
8967 | + mc_io->dev = dev; |
||
8968 | + mc_io->flags = flags; |
||
8969 | + mc_io->portal_phys_addr = mc_portal_phys_addr; |
||
8970 | + mc_io->portal_size = mc_portal_size; |
||
8971 | + if (flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) |
||
8972 | + spin_lock_init(&mc_io->spinlock); |
||
8973 | + else |
||
8974 | + mutex_init(&mc_io->mutex); |
||
8975 | + |
||
8976 | + res = devm_request_mem_region(dev, |
||
8977 | + mc_portal_phys_addr, |
||
8978 | + mc_portal_size, |
||
8979 | + "mc_portal"); |
||
8980 | + if (!res) { |
||
8981 | + dev_err(dev, |
||
8982 | + "devm_request_mem_region failed for MC portal %pa\n", |
||
8983 | + &mc_portal_phys_addr); |
||
8984 | + return -EBUSY; |
||
8985 | + } |
||
8986 | + |
||
8987 | + mc_portal_virt_addr = devm_ioremap_nocache(dev, |
||
8988 | + mc_portal_phys_addr, |
||
8989 | + mc_portal_size); |
||
8990 | + if (!mc_portal_virt_addr) { |
||
8991 | + dev_err(dev, |
||
8992 | + "devm_ioremap_nocache failed for MC portal %pa\n", |
||
8993 | + &mc_portal_phys_addr); |
||
8994 | + return -ENXIO; |
||
8995 | + } |
||
8996 | + |
||
8997 | + mc_io->portal_virt_addr = mc_portal_virt_addr; |
||
8998 | + if (dpmcp_dev) { |
||
8999 | + error = fsl_mc_io_set_dpmcp(mc_io, dpmcp_dev); |
||
9000 | + if (error < 0) |
||
9001 | + goto error_destroy_mc_io; |
||
9002 | + } |
||
9003 | + |
||
9004 | + *new_mc_io = mc_io; |
||
9005 | + return 0; |
||
9006 | + |
||
9007 | +error_destroy_mc_io: |
||
9008 | + fsl_destroy_mc_io(mc_io); |
||
9009 | + return error; |
||
9010 | +} |
||
9011 | + |
||
9012 | +/** |
||
9013 | + * Destroys an MC I/O object |
||
9014 | + * |
||
9015 | + * @mc_io: MC I/O object to destroy |
||
9016 | + */ |
||
9017 | +void fsl_destroy_mc_io(struct fsl_mc_io *mc_io) |
||
9018 | +{ |
||
9019 | + struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; |
||
9020 | + |
||
9021 | + if (dpmcp_dev) |
||
9022 | + fsl_mc_io_unset_dpmcp(mc_io); |
||
9023 | + |
||
9024 | + devm_iounmap(mc_io->dev, mc_io->portal_virt_addr); |
||
9025 | + devm_release_mem_region(mc_io->dev, |
||
9026 | + mc_io->portal_phys_addr, |
||
9027 | + mc_io->portal_size); |
||
9028 | + |
||
9029 | + mc_io->portal_virt_addr = NULL; |
||
9030 | + devm_kfree(mc_io->dev, mc_io); |
||
9031 | +} |
||
9032 | + |
||
9033 | +/** |
||
9034 | + * fsl_mc_portal_allocate - Allocates an MC portal |
||
9035 | + * |
||
9036 | + * @mc_dev: MC device for which the MC portal is to be allocated |
||
9037 | + * @mc_io_flags: Flags for the fsl_mc_io object that wraps the allocated |
||
9038 | + * MC portal. |
||
9039 | + * @new_mc_io: Pointer to area where the pointer to the fsl_mc_io object |
||
9040 | + * that wraps the allocated MC portal is to be returned |
||
9041 | + * |
||
9042 | + * This function allocates an MC portal from the device's parent DPRC, |
||
9043 | + * from the corresponding MC bus' pool of MC portals and wraps |
||
9044 | + * it in a new fsl_mc_io object. If 'mc_dev' is a DPRC itself, the |
||
9045 | + * portal is allocated from its own MC bus. |
||
9046 | + */ |
||
9047 | +int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, |
||
9048 | + u16 mc_io_flags, |
||
9049 | + struct fsl_mc_io **new_mc_io) |
||
9050 | +{ |
||
9051 | + struct fsl_mc_device *mc_bus_dev; |
||
9052 | + struct fsl_mc_bus *mc_bus; |
||
9053 | + phys_addr_t mc_portal_phys_addr; |
||
9054 | + size_t mc_portal_size; |
||
9055 | + struct fsl_mc_device *dpmcp_dev; |
||
9056 | + int error = -EINVAL; |
||
9057 | + struct fsl_mc_resource *resource = NULL; |
||
9058 | + struct fsl_mc_io *mc_io = NULL; |
||
9059 | + |
||
9060 | + if (mc_dev->flags & FSL_MC_IS_DPRC) { |
||
9061 | + mc_bus_dev = mc_dev; |
||
9062 | + } else { |
||
9063 | + if (!dev_is_fsl_mc(mc_dev->dev.parent)) |
||
9064 | + return error; |
||
9065 | + |
||
9066 | + mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); |
||
9067 | + } |
||
9068 | + |
||
9069 | + mc_bus = to_fsl_mc_bus(mc_bus_dev); |
||
9070 | + *new_mc_io = NULL; |
||
9071 | + error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_DPMCP, &resource); |
||
9072 | + if (error < 0) |
||
9073 | + return error; |
||
9074 | + |
||
9075 | + error = -EINVAL; |
||
9076 | + dpmcp_dev = resource->data; |
||
9077 | + |
||
9078 | + if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR || |
||
9079 | + (dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR && |
||
9080 | + dpmcp_dev->obj_desc.ver_minor < DPMCP_MIN_VER_MINOR)) { |
||
9081 | + dev_err(&dpmcp_dev->dev, |
||
9082 | + "ERROR: Version %d.%d of DPMCP not supported.\n", |
||
9083 | + dpmcp_dev->obj_desc.ver_major, |
||
9084 | + dpmcp_dev->obj_desc.ver_minor); |
||
9085 | + error = -ENOTSUPP; |
||
9086 | + goto error_cleanup_resource; |
||
9087 | + } |
||
9088 | + |
||
9089 | + mc_portal_phys_addr = dpmcp_dev->regions[0].start; |
||
9090 | + mc_portal_size = resource_size(dpmcp_dev->regions); |
||
9091 | + |
||
9092 | + error = fsl_create_mc_io(&mc_bus_dev->dev, |
||
9093 | + mc_portal_phys_addr, |
||
9094 | + mc_portal_size, dpmcp_dev, |
||
9095 | + mc_io_flags, &mc_io); |
||
9096 | + if (error < 0) |
||
9097 | + goto error_cleanup_resource; |
||
9098 | + |
||
9099 | + *new_mc_io = mc_io; |
||
9100 | + return 0; |
||
9101 | + |
||
9102 | +error_cleanup_resource: |
||
9103 | + fsl_mc_resource_free(resource); |
||
9104 | + return error; |
||
9105 | +} |
||
9106 | +EXPORT_SYMBOL_GPL(fsl_mc_portal_allocate); |
||
9107 | + |
||
9108 | +/** |
||
9109 | + * fsl_mc_portal_free - Returns an MC portal to the pool of free MC portals |
||
9110 | + * of a given MC bus |
||
9111 | + * |
||
9112 | + * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free |
||
9113 | + */ |
||
9114 | +void fsl_mc_portal_free(struct fsl_mc_io *mc_io) |
||
9115 | +{ |
||
9116 | + struct fsl_mc_device *dpmcp_dev; |
||
9117 | + struct fsl_mc_resource *resource; |
||
9118 | + |
||
9119 | + /* |
||
9120 | + * Every mc_io obtained by calling fsl_mc_portal_allocate() is supposed |
||
9121 | + * to have a DPMCP object associated with. |
||
9122 | + */ |
||
9123 | + dpmcp_dev = mc_io->dpmcp_dev; |
||
9124 | + |
||
9125 | + resource = dpmcp_dev->resource; |
||
9126 | + if (!resource || resource->type != FSL_MC_POOL_DPMCP) |
||
9127 | + return; |
||
9128 | + |
||
9129 | + if (resource->data != dpmcp_dev) |
||
9130 | + return; |
||
9131 | + |
||
9132 | + fsl_destroy_mc_io(mc_io); |
||
9133 | + fsl_mc_resource_free(resource); |
||
9134 | +} |
||
9135 | +EXPORT_SYMBOL_GPL(fsl_mc_portal_free); |
||
9136 | + |
||
9137 | +/** |
||
9138 | + * fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object |
||
9139 | + * |
||
9140 | + * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free |
||
9141 | + */ |
||
9142 | +int fsl_mc_portal_reset(struct fsl_mc_io *mc_io) |
||
9143 | +{ |
||
9144 | + int error; |
||
9145 | + struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; |
||
9146 | + |
||
9147 | + error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle); |
||
9148 | + if (error < 0) { |
||
9149 | + dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error); |
||
9150 | + return error; |
||
9151 | + } |
||
9152 | + |
||
9153 | + return 0; |
||
9154 | +} |
||
9155 | +EXPORT_SYMBOL_GPL(fsl_mc_portal_reset); |
||
9156 | --- a/drivers/staging/fsl-mc/bus/mc-sys.c |
||
9157 | +++ /dev/null |
||
9158 | @@ -1,297 +0,0 @@ |
||
9159 | -// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) |
||
9160 | -/* |
||
9161 | - * Copyright 2013-2016 Freescale Semiconductor Inc. |
||
9162 | - * |
||
9163 | - * I/O services to send MC commands to the MC hardware |
||
9164 | - * |
||
9165 | - */ |
||
9166 | - |
||
9167 | -#include <linux/delay.h> |
||
9168 | -#include <linux/slab.h> |
||
9169 | -#include <linux/ioport.h> |
||
9170 | -#include <linux/device.h> |
||
9171 | -#include <linux/io.h> |
||
9172 | -#include <linux/io-64-nonatomic-hi-lo.h> |
||
9173 | -#include "../include/mc.h" |
||
9174 | - |
||
9175 | -#include "dpmcp.h" |
||
9176 | - |
||
9177 | -/** |
||
9178 | - * Timeout in milliseconds to wait for the completion of an MC command |
||
9179 | - */ |
||
9180 | -#define MC_CMD_COMPLETION_TIMEOUT_MS 500 |
||
9181 | - |
||
9182 | -/* |
||
9183 | - * usleep_range() min and max values used to throttle down polling |
||
9184 | - * iterations while waiting for MC command completion |
||
9185 | - */ |
||
9186 | -#define MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS 10 |
||
9187 | -#define MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS 500 |
||
9188 | - |
||
9189 | -static enum mc_cmd_status mc_cmd_hdr_read_status(struct mc_command *cmd) |
||
9190 | -{ |
||
9191 | - struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header; |
||
9192 | - |
||
9193 | - return (enum mc_cmd_status)hdr->status; |
||
9194 | -} |
||
9195 | - |
||
9196 | -static u16 mc_cmd_hdr_read_cmdid(struct mc_command *cmd) |
||
9197 | -{ |
||
9198 | - struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header; |
||
9199 | - u16 cmd_id = le16_to_cpu(hdr->cmd_id); |
||
9200 | - |
||
9201 | - return cmd_id; |
||
9202 | -} |
||
9203 | - |
||
9204 | -static int mc_status_to_error(enum mc_cmd_status status) |
||
9205 | -{ |
||
9206 | - static const int mc_status_to_error_map[] = { |
||
9207 | - [MC_CMD_STATUS_OK] = 0, |
||
9208 | - [MC_CMD_STATUS_AUTH_ERR] = -EACCES, |
||
9209 | - [MC_CMD_STATUS_NO_PRIVILEGE] = -EPERM, |
||
9210 | - [MC_CMD_STATUS_DMA_ERR] = -EIO, |
||
9211 | - [MC_CMD_STATUS_CONFIG_ERR] = -ENXIO, |
||
9212 | - [MC_CMD_STATUS_TIMEOUT] = -ETIMEDOUT, |
||
9213 | - [MC_CMD_STATUS_NO_RESOURCE] = -ENAVAIL, |
||
9214 | - [MC_CMD_STATUS_NO_MEMORY] = -ENOMEM, |
||
9215 | - [MC_CMD_STATUS_BUSY] = -EBUSY, |
||
9216 | - [MC_CMD_STATUS_UNSUPPORTED_OP] = -ENOTSUPP, |
||
9217 | - [MC_CMD_STATUS_INVALID_STATE] = -ENODEV, |
||
9218 | - }; |
||
9219 | - |
||
9220 | - if (WARN_ON((u32)status >= ARRAY_SIZE(mc_status_to_error_map))) |
||
9221 | - return -EINVAL; |
||
9222 | - |
||
9223 | - return mc_status_to_error_map[status]; |
||
9224 | -} |
||
9225 | - |
||
9226 | -static const char *mc_status_to_string(enum mc_cmd_status status) |
||
9227 | -{ |
||
9228 | - static const char *const status_strings[] = { |
||
9229 | - [MC_CMD_STATUS_OK] = "Command completed successfully", |
||
9230 | - [MC_CMD_STATUS_READY] = "Command ready to be processed", |
||
9231 | - [MC_CMD_STATUS_AUTH_ERR] = "Authentication error", |
||
9232 | - [MC_CMD_STATUS_NO_PRIVILEGE] = "No privilege", |
||
9233 | - [MC_CMD_STATUS_DMA_ERR] = "DMA or I/O error", |
||
9234 | - [MC_CMD_STATUS_CONFIG_ERR] = "Configuration error", |
||
9235 | - [MC_CMD_STATUS_TIMEOUT] = "Operation timed out", |
||
9236 | - [MC_CMD_STATUS_NO_RESOURCE] = "No resources", |
||
9237 | - [MC_CMD_STATUS_NO_MEMORY] = "No memory available", |
||
9238 | - [MC_CMD_STATUS_BUSY] = "Device is busy", |
||
9239 | - [MC_CMD_STATUS_UNSUPPORTED_OP] = "Unsupported operation", |
||
9240 | - [MC_CMD_STATUS_INVALID_STATE] = "Invalid state" |
||
9241 | - }; |
||
9242 | - |
||
9243 | - if ((unsigned int)status >= ARRAY_SIZE(status_strings)) |
||
9244 | - return "Unknown MC error"; |
||
9245 | - |
||
9246 | - return status_strings[status]; |
||
9247 | -} |
||
9248 | - |
||
9249 | -/** |
||
9250 | - * mc_write_command - writes a command to a Management Complex (MC) portal |
||
9251 | - * |
||
9252 | - * @portal: pointer to an MC portal |
||
9253 | - * @cmd: pointer to a filled command |
||
9254 | - */ |
||
9255 | -static inline void mc_write_command(struct mc_command __iomem *portal, |
||
9256 | - struct mc_command *cmd) |
||
9257 | -{ |
||
9258 | - int i; |
||
9259 | - |
||
9260 | - /* copy command parameters into the portal */ |
||
9261 | - for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++) |
||
9262 | - /* |
||
9263 | - * Data is already in the expected LE byte-order. Do an |
||
9264 | - * extra LE -> CPU conversion so that the CPU -> LE done in |
||
9265 | - * the device io write api puts it back in the right order. |
||
9266 | - */ |
||
9267 | - writeq_relaxed(le64_to_cpu(cmd->params[i]), &portal->params[i]); |
||
9268 | - |
||
9269 | - /* submit the command by writing the header */ |
||
9270 | - writeq(le64_to_cpu(cmd->header), &portal->header); |
||
9271 | -} |
||
9272 | - |
||
9273 | -/** |
||
9274 | - * mc_read_response - reads the response for the last MC command from a |
||
9275 | - * Management Complex (MC) portal |
||
9276 | - * |
||
9277 | - * @portal: pointer to an MC portal |
||
9278 | - * @resp: pointer to command response buffer |
||
9279 | - * |
||
9280 | - * Returns MC_CMD_STATUS_OK on Success; Error code otherwise. |
||
9281 | - */ |
||
9282 | -static inline enum mc_cmd_status mc_read_response(struct mc_command __iomem * |
||
9283 | - portal, |
||
9284 | - struct mc_command *resp) |
||
9285 | -{ |
||
9286 | - int i; |
||
9287 | - enum mc_cmd_status status; |
||
9288 | - |
||
9289 | - /* Copy command response header from MC portal: */ |
||
9290 | - resp->header = cpu_to_le64(readq_relaxed(&portal->header)); |
||
9291 | - status = mc_cmd_hdr_read_status(resp); |
||
9292 | - if (status != MC_CMD_STATUS_OK) |
||
9293 | - return status; |
||
9294 | - |
||
9295 | - /* Copy command response data from MC portal: */ |
||
9296 | - for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++) |
||
9297 | - /* |
||
9298 | - * Data is expected to be in LE byte-order. Do an |
||
9299 | - * extra CPU -> LE to revert the LE -> CPU done in |
||
9300 | - * the device io read api. |
||
9301 | - */ |
||
9302 | - resp->params[i] = |
||
9303 | - cpu_to_le64(readq_relaxed(&portal->params[i])); |
||
9304 | - |
||
9305 | - return status; |
||
9306 | -} |
||
9307 | - |
||
9308 | -/** |
||
9309 | - * Waits for the completion of an MC command doing preemptible polling. |
||
9310 | - * uslepp_range() is called between polling iterations. |
||
9311 | - * |
||
9312 | - * @mc_io: MC I/O object to be used |
||
9313 | - * @cmd: command buffer to receive MC response |
||
9314 | - * @mc_status: MC command completion status |
||
9315 | - */ |
||
9316 | -static int mc_polling_wait_preemptible(struct fsl_mc_io *mc_io, |
||
9317 | - struct mc_command *cmd, |
||
9318 | - enum mc_cmd_status *mc_status) |
||
9319 | -{ |
||
9320 | - enum mc_cmd_status status; |
||
9321 | - unsigned long jiffies_until_timeout = |
||
9322 | - jiffies + msecs_to_jiffies(MC_CMD_COMPLETION_TIMEOUT_MS); |
||
9323 | - |
||
9324 | - /* |
||
9325 | - * Wait for response from the MC hardware: |
||
9326 | - */ |
||
9327 | - for (;;) { |
||
9328 | - status = mc_read_response(mc_io->portal_virt_addr, cmd); |
||
9329 | - if (status != MC_CMD_STATUS_READY) |
||
9330 | - break; |
||
9331 | - |
||
9332 | - /* |
||
9333 | - * TODO: When MC command completion interrupts are supported |
||
9334 | - * call wait function here instead of usleep_range() |
||
9335 | - */ |
||
9336 | - usleep_range(MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS, |
||
9337 | - MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS); |
||
9338 | - |
||
9339 | - if (time_after_eq(jiffies, jiffies_until_timeout)) { |
||
9340 | - dev_dbg(mc_io->dev, |
||
9341 | - "MC command timed out (portal: %pa, dprc handle: %#x, command: %#x)\n", |
||
9342 | - &mc_io->portal_phys_addr, |
||
9343 | - (unsigned int)mc_cmd_hdr_read_token(cmd), |
||
9344 | - (unsigned int)mc_cmd_hdr_read_cmdid(cmd)); |
||
9345 | - |
||
9346 | - return -ETIMEDOUT; |
||
9347 | - } |
||
9348 | - } |
||
9349 | - |
||
9350 | - *mc_status = status; |
||
9351 | - return 0; |
||
9352 | -} |
||
9353 | - |
||
9354 | -/** |
||
9355 | - * Waits for the completion of an MC command doing atomic polling. |
||
9356 | - * udelay() is called between polling iterations. |
||
9357 | - * |
||
9358 | - * @mc_io: MC I/O object to be used |
||
9359 | - * @cmd: command buffer to receive MC response |
||
9360 | - * @mc_status: MC command completion status |
||
9361 | - */ |
||
9362 | -static int mc_polling_wait_atomic(struct fsl_mc_io *mc_io, |
||
9363 | - struct mc_command *cmd, |
||
9364 | - enum mc_cmd_status *mc_status) |
||
9365 | -{ |
||
9366 | - enum mc_cmd_status status; |
||
9367 | - unsigned long timeout_usecs = MC_CMD_COMPLETION_TIMEOUT_MS * 1000; |
||
9368 | - |
||
9369 | - BUILD_BUG_ON((MC_CMD_COMPLETION_TIMEOUT_MS * 1000) % |
||
9370 | - MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS != 0); |
||
9371 | - |
||
9372 | - for (;;) { |
||
9373 | - status = mc_read_response(mc_io->portal_virt_addr, cmd); |
||
9374 | - if (status != MC_CMD_STATUS_READY) |
||
9375 | - break; |
||
9376 | - |
||
9377 | - udelay(MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS); |
||
9378 | - timeout_usecs -= MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS; |
||
9379 | - if (timeout_usecs == 0) { |
||
9380 | - dev_dbg(mc_io->dev, |
||
9381 | - "MC command timed out (portal: %pa, dprc handle: %#x, command: %#x)\n", |
||
9382 | - &mc_io->portal_phys_addr, |
||
9383 | - (unsigned int)mc_cmd_hdr_read_token(cmd), |
||
9384 | - (unsigned int)mc_cmd_hdr_read_cmdid(cmd)); |
||
9385 | - |
||
9386 | - return -ETIMEDOUT; |
||
9387 | - } |
||
9388 | - } |
||
9389 | - |
||
9390 | - *mc_status = status; |
||
9391 | - return 0; |
||
9392 | -} |
||
9393 | - |
||
9394 | -/** |
||
9395 | - * Sends a command to the MC device using the given MC I/O object |
||
9396 | - * |
||
9397 | - * @mc_io: MC I/O object to be used |
||
9398 | - * @cmd: command to be sent |
||
9399 | - * |
||
9400 | - * Returns '0' on Success; Error code otherwise. |
||
9401 | - */ |
||
9402 | -int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd) |
||
9403 | -{ |
||
9404 | - int error; |
||
9405 | - enum mc_cmd_status status; |
||
9406 | - unsigned long irq_flags = 0; |
||
9407 | - |
||
9408 | - if (WARN_ON(in_irq() && |
||
9409 | - !(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL))) |
||
9410 | - return -EINVAL; |
||
9411 | - |
||
9412 | - if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) |
||
9413 | - spin_lock_irqsave(&mc_io->spinlock, irq_flags); |
||
9414 | - else |
||
9415 | - mutex_lock(&mc_io->mutex); |
||
9416 | - |
||
9417 | - /* |
||
9418 | - * Send command to the MC hardware: |
||
9419 | - */ |
||
9420 | - mc_write_command(mc_io->portal_virt_addr, cmd); |
||
9421 | - |
||
9422 | - /* |
||
9423 | - * Wait for response from the MC hardware: |
||
9424 | - */ |
||
9425 | - if (!(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)) |
||
9426 | - error = mc_polling_wait_preemptible(mc_io, cmd, &status); |
||
9427 | - else |
||
9428 | - error = mc_polling_wait_atomic(mc_io, cmd, &status); |
||
9429 | - |
||
9430 | - if (error < 0) |
||
9431 | - goto common_exit; |
||
9432 | - |
||
9433 | - if (status != MC_CMD_STATUS_OK) { |
||
9434 | - dev_dbg(mc_io->dev, |
||
9435 | - "MC command failed: portal: %pa, dprc handle: %#x, command: %#x, status: %s (%#x)\n", |
||
9436 | - &mc_io->portal_phys_addr, |
||
9437 | - (unsigned int)mc_cmd_hdr_read_token(cmd), |
||
9438 | - (unsigned int)mc_cmd_hdr_read_cmdid(cmd), |
||
9439 | - mc_status_to_string(status), |
||
9440 | - (unsigned int)status); |
||
9441 | - |
||
9442 | - error = mc_status_to_error(status); |
||
9443 | - goto common_exit; |
||
9444 | - } |
||
9445 | - |
||
9446 | - error = 0; |
||
9447 | -common_exit: |
||
9448 | - if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) |
||
9449 | - spin_unlock_irqrestore(&mc_io->spinlock, irq_flags); |
||
9450 | - else |
||
9451 | - mutex_unlock(&mc_io->mutex); |
||
9452 | - |
||
9453 | - return error; |
||
9454 | -} |
||
9455 | -EXPORT_SYMBOL(mc_send_command); |
||
9456 | --- /dev/null |
||
9457 | +++ b/drivers/bus/fsl-mc/mc-sys.c |
||
9458 | @@ -0,0 +1,296 @@ |
||
9459 | +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) |
||
9460 | +/* |
||
9461 | + * Copyright 2013-2016 Freescale Semiconductor Inc. |
||
9462 | + * |
||
9463 | + * I/O services to send MC commands to the MC hardware |
||
9464 | + * |
||
9465 | + */ |
||
9466 | + |
||
9467 | +#include <linux/delay.h> |
||
9468 | +#include <linux/slab.h> |
||
9469 | +#include <linux/ioport.h> |
||
9470 | +#include <linux/device.h> |
||
9471 | +#include <linux/io.h> |
||
9472 | +#include <linux/io-64-nonatomic-hi-lo.h> |
||
9473 | +#include <linux/fsl/mc.h> |
||
9474 | + |
||
9475 | +#include "fsl-mc-private.h" |
||
9476 | + |
||
9477 | +/** |
||
9478 | + * Timeout in milliseconds to wait for the completion of an MC command |
||
9479 | + */ |
||
9480 | +#define MC_CMD_COMPLETION_TIMEOUT_MS 15000 |
||
9481 | + |
||
9482 | +/* |
||
9483 | + * usleep_range() min and max values used to throttle down polling |
||
9484 | + * iterations while waiting for MC command completion |
||
9485 | + */ |
||
9486 | +#define MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS 10 |
||
9487 | +#define MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS 500 |
||
9488 | + |
||
9489 | +static enum mc_cmd_status mc_cmd_hdr_read_status(struct fsl_mc_command *cmd) |
||
9490 | +{ |
||
9491 | + struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header; |
||
9492 | + |
||
9493 | + return (enum mc_cmd_status)hdr->status; |
||
9494 | +} |
||
9495 | + |
||
9496 | +static u16 mc_cmd_hdr_read_cmdid(struct fsl_mc_command *cmd) |
||
9497 | +{ |
||
9498 | + struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header; |
||
9499 | + u16 cmd_id = le16_to_cpu(hdr->cmd_id); |
||
9500 | + |
||
9501 | + return cmd_id; |
||
9502 | +} |
||
9503 | + |
||
9504 | +static int mc_status_to_error(enum mc_cmd_status status) |
||
9505 | +{ |
||
9506 | + static const int mc_status_to_error_map[] = { |
||
9507 | + [MC_CMD_STATUS_OK] = 0, |
||
9508 | + [MC_CMD_STATUS_AUTH_ERR] = -EACCES, |
||
9509 | + [MC_CMD_STATUS_NO_PRIVILEGE] = -EPERM, |
||
9510 | + [MC_CMD_STATUS_DMA_ERR] = -EIO, |
||
9511 | + [MC_CMD_STATUS_CONFIG_ERR] = -ENXIO, |
||
9512 | + [MC_CMD_STATUS_TIMEOUT] = -ETIMEDOUT, |
||
9513 | + [MC_CMD_STATUS_NO_RESOURCE] = -ENAVAIL, |
||
9514 | + [MC_CMD_STATUS_NO_MEMORY] = -ENOMEM, |
||
9515 | + [MC_CMD_STATUS_BUSY] = -EBUSY, |
||
9516 | + [MC_CMD_STATUS_UNSUPPORTED_OP] = -ENOTSUPP, |
||
9517 | + [MC_CMD_STATUS_INVALID_STATE] = -ENODEV, |
||
9518 | + }; |
||
9519 | + |
||
9520 | + if ((u32)status >= ARRAY_SIZE(mc_status_to_error_map)) |
||
9521 | + return -EINVAL; |
||
9522 | + |
||
9523 | + return mc_status_to_error_map[status]; |
||
9524 | +} |
||
9525 | + |
||
9526 | +static const char *mc_status_to_string(enum mc_cmd_status status) |
||
9527 | +{ |
||
9528 | + static const char *const status_strings[] = { |
||
9529 | + [MC_CMD_STATUS_OK] = "Command completed successfully", |
||
9530 | + [MC_CMD_STATUS_READY] = "Command ready to be processed", |
||
9531 | + [MC_CMD_STATUS_AUTH_ERR] = "Authentication error", |
||
9532 | + [MC_CMD_STATUS_NO_PRIVILEGE] = "No privilege", |
||
9533 | + [MC_CMD_STATUS_DMA_ERR] = "DMA or I/O error", |
||
9534 | + [MC_CMD_STATUS_CONFIG_ERR] = "Configuration error", |
||
9535 | + [MC_CMD_STATUS_TIMEOUT] = "Operation timed out", |
||
9536 | + [MC_CMD_STATUS_NO_RESOURCE] = "No resources", |
||
9537 | + [MC_CMD_STATUS_NO_MEMORY] = "No memory available", |
||
9538 | + [MC_CMD_STATUS_BUSY] = "Device is busy", |
||
9539 | + [MC_CMD_STATUS_UNSUPPORTED_OP] = "Unsupported operation", |
||
9540 | + [MC_CMD_STATUS_INVALID_STATE] = "Invalid state" |
||
9541 | + }; |
||
9542 | + |
||
9543 | + if ((unsigned int)status >= ARRAY_SIZE(status_strings)) |
||
9544 | + return "Unknown MC error"; |
||
9545 | + |
||
9546 | + return status_strings[status]; |
||
9547 | +} |
||
9548 | + |
||
9549 | +/** |
||
9550 | + * mc_write_command - writes a command to a Management Complex (MC) portal |
||
9551 | + * |
||
9552 | + * @portal: pointer to an MC portal |
||
9553 | + * @cmd: pointer to a filled command |
||
9554 | + */ |
||
9555 | +static inline void mc_write_command(struct fsl_mc_command __iomem *portal, |
||
9556 | + struct fsl_mc_command *cmd) |
||
9557 | +{ |
||
9558 | + int i; |
||
9559 | + |
||
9560 | + /* copy command parameters into the portal */ |
||
9561 | + for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++) |
||
9562 | + /* |
||
9563 | + * Data is already in the expected LE byte-order. Do an |
||
9564 | + * extra LE -> CPU conversion so that the CPU -> LE done in |
||
9565 | + * the device io write api puts it back in the right order. |
||
9566 | + */ |
||
9567 | + writeq_relaxed(le64_to_cpu(cmd->params[i]), &portal->params[i]); |
||
9568 | + |
||
9569 | + /* submit the command by writing the header */ |
||
9570 | + writeq(le64_to_cpu(cmd->header), &portal->header); |
||
9571 | +} |
||
9572 | + |
||
9573 | +/** |
||
9574 | + * mc_read_response - reads the response for the last MC command from a |
||
9575 | + * Management Complex (MC) portal |
||
9576 | + * |
||
9577 | + * @portal: pointer to an MC portal |
||
9578 | + * @resp: pointer to command response buffer |
||
9579 | + * |
||
9580 | + * Returns MC_CMD_STATUS_OK on Success; Error code otherwise. |
||
9581 | + */ |
||
9582 | +static inline enum mc_cmd_status mc_read_response(struct fsl_mc_command __iomem |
||
9583 | + *portal, |
||
9584 | + struct fsl_mc_command *resp) |
||
9585 | +{ |
||
9586 | + int i; |
||
9587 | + enum mc_cmd_status status; |
||
9588 | + |
||
9589 | + /* Copy command response header from MC portal: */ |
||
9590 | + resp->header = cpu_to_le64(readq_relaxed(&portal->header)); |
||
9591 | + status = mc_cmd_hdr_read_status(resp); |
||
9592 | + if (status != MC_CMD_STATUS_OK) |
||
9593 | + return status; |
||
9594 | + |
||
9595 | + /* Copy command response data from MC portal: */ |
||
9596 | + for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++) |
||
9597 | + /* |
||
9598 | + * Data is expected to be in LE byte-order. Do an |
||
9599 | + * extra CPU -> LE to revert the LE -> CPU done in |
||
9600 | + * the device io read api. |
||
9601 | + */ |
||
9602 | + resp->params[i] = |
||
9603 | + cpu_to_le64(readq_relaxed(&portal->params[i])); |
||
9604 | + |
||
9605 | + return status; |
||
9606 | +} |
||
9607 | + |
||
9608 | +/** |
||
9609 | + * Waits for the completion of an MC command doing preemptible polling. |
||
9610 | + * uslepp_range() is called between polling iterations. |
||
9611 | + * |
||
9612 | + * @mc_io: MC I/O object to be used |
||
9613 | + * @cmd: command buffer to receive MC response |
||
9614 | + * @mc_status: MC command completion status |
||
9615 | + */ |
||
9616 | +static int mc_polling_wait_preemptible(struct fsl_mc_io *mc_io, |
||
9617 | + struct fsl_mc_command *cmd, |
||
9618 | + enum mc_cmd_status *mc_status) |
||
9619 | +{ |
||
9620 | + enum mc_cmd_status status; |
||
9621 | + unsigned long jiffies_until_timeout = |
||
9622 | + jiffies + msecs_to_jiffies(MC_CMD_COMPLETION_TIMEOUT_MS); |
||
9623 | + |
||
9624 | + /* |
||
9625 | + * Wait for response from the MC hardware: |
||
9626 | + */ |
||
9627 | + for (;;) { |
||
9628 | + status = mc_read_response(mc_io->portal_virt_addr, cmd); |
||
9629 | + if (status != MC_CMD_STATUS_READY) |
||
9630 | + break; |
||
9631 | + |
||
9632 | + /* |
||
9633 | + * TODO: When MC command completion interrupts are supported |
||
9634 | + * call wait function here instead of usleep_range() |
||
9635 | + */ |
||
9636 | + usleep_range(MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS, |
||
9637 | + MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS); |
||
9638 | + |
||
9639 | + if (time_after_eq(jiffies, jiffies_until_timeout)) { |
||
9640 | + dev_dbg(mc_io->dev, |
||
9641 | + "MC command timed out (portal: %pa, dprc handle: %#x, command: %#x)\n", |
||
9642 | + &mc_io->portal_phys_addr, |
||
9643 | + (unsigned int)mc_cmd_hdr_read_token(cmd), |
||
9644 | + (unsigned int)mc_cmd_hdr_read_cmdid(cmd)); |
||
9645 | + |
||
9646 | + return -ETIMEDOUT; |
||
9647 | + } |
||
9648 | + } |
||
9649 | + |
||
9650 | + *mc_status = status; |
||
9651 | + return 0; |
||
9652 | +} |
||
9653 | + |
||
9654 | +/** |
||
9655 | + * Waits for the completion of an MC command doing atomic polling. |
||
9656 | + * udelay() is called between polling iterations. |
||
9657 | + * |
||
9658 | + * @mc_io: MC I/O object to be used |
||
9659 | + * @cmd: command buffer to receive MC response |
||
9660 | + * @mc_status: MC command completion status |
||
9661 | + */ |
||
9662 | +static int mc_polling_wait_atomic(struct fsl_mc_io *mc_io, |
||
9663 | + struct fsl_mc_command *cmd, |
||
9664 | + enum mc_cmd_status *mc_status) |
||
9665 | +{ |
||
9666 | + enum mc_cmd_status status; |
||
9667 | + unsigned long timeout_usecs = MC_CMD_COMPLETION_TIMEOUT_MS * 1000; |
||
9668 | + |
||
9669 | + BUILD_BUG_ON((MC_CMD_COMPLETION_TIMEOUT_MS * 1000) % |
||
9670 | + MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS != 0); |
||
9671 | + |
||
9672 | + for (;;) { |
||
9673 | + status = mc_read_response(mc_io->portal_virt_addr, cmd); |
||
9674 | + if (status != MC_CMD_STATUS_READY) |
||
9675 | + break; |
||
9676 | + |
||
9677 | + udelay(MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS); |
||
9678 | + timeout_usecs -= MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS; |
||
9679 | + if (timeout_usecs == 0) { |
||
9680 | + dev_dbg(mc_io->dev, |
||
9681 | + "MC command timed out (portal: %pa, dprc handle: %#x, command: %#x)\n", |
||
9682 | + &mc_io->portal_phys_addr, |
||
9683 | + (unsigned int)mc_cmd_hdr_read_token(cmd), |
||
9684 | + (unsigned int)mc_cmd_hdr_read_cmdid(cmd)); |
||
9685 | + |
||
9686 | + return -ETIMEDOUT; |
||
9687 | + } |
||
9688 | + } |
||
9689 | + |
||
9690 | + *mc_status = status; |
||
9691 | + return 0; |
||
9692 | +} |
||
9693 | + |
||
9694 | +/** |
||
9695 | + * Sends a command to the MC device using the given MC I/O object |
||
9696 | + * |
||
9697 | + * @mc_io: MC I/O object to be used |
||
9698 | + * @cmd: command to be sent |
||
9699 | + * |
||
9700 | + * Returns '0' on Success; Error code otherwise. |
||
9701 | + */ |
||
9702 | +int mc_send_command(struct fsl_mc_io *mc_io, struct fsl_mc_command *cmd) |
||
9703 | +{ |
||
9704 | + int error; |
||
9705 | + enum mc_cmd_status status; |
||
9706 | + unsigned long irq_flags = 0; |
||
9707 | + |
||
9708 | + if (in_irq() && !(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)) |
||
9709 | + return -EINVAL; |
||
9710 | + |
||
9711 | + if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) |
||
9712 | + spin_lock_irqsave(&mc_io->spinlock, irq_flags); |
||
9713 | + else |
||
9714 | + mutex_lock(&mc_io->mutex); |
||
9715 | + |
||
9716 | + /* |
||
9717 | + * Send command to the MC hardware: |
||
9718 | + */ |
||
9719 | + mc_write_command(mc_io->portal_virt_addr, cmd); |
||
9720 | + |
||
9721 | + /* |
||
9722 | + * Wait for response from the MC hardware: |
||
9723 | + */ |
||
9724 | + if (!(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)) |
||
9725 | + error = mc_polling_wait_preemptible(mc_io, cmd, &status); |
||
9726 | + else |
||
9727 | + error = mc_polling_wait_atomic(mc_io, cmd, &status); |
||
9728 | + |
||
9729 | + if (error < 0) |
||
9730 | + goto common_exit; |
||
9731 | + |
||
9732 | + if (status != MC_CMD_STATUS_OK) { |
||
9733 | + dev_dbg(mc_io->dev, |
||
9734 | + "MC command failed: portal: %pa, dprc handle: %#x, command: %#x, status: %s (%#x)\n", |
||
9735 | + &mc_io->portal_phys_addr, |
||
9736 | + (unsigned int)mc_cmd_hdr_read_token(cmd), |
||
9737 | + (unsigned int)mc_cmd_hdr_read_cmdid(cmd), |
||
9738 | + mc_status_to_string(status), |
||
9739 | + (unsigned int)status); |
||
9740 | + |
||
9741 | + error = mc_status_to_error(status); |
||
9742 | + goto common_exit; |
||
9743 | + } |
||
9744 | + |
||
9745 | + error = 0; |
||
9746 | +common_exit: |
||
9747 | + if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) |
||
9748 | + spin_unlock_irqrestore(&mc_io->spinlock, irq_flags); |
||
9749 | + else |
||
9750 | + mutex_unlock(&mc_io->mutex); |
||
9751 | + |
||
9752 | + return error; |
||
9753 | +} |
||
9754 | +EXPORT_SYMBOL_GPL(mc_send_command); |
||
9755 | --- a/drivers/irqchip/Kconfig |
||
9756 | +++ b/drivers/irqchip/Kconfig |
||
9757 | @@ -42,6 +42,12 @@ config ARM_GIC_V3_ITS |
||
9758 | depends on PCI |
||
9759 | depends on PCI_MSI |
||
9760 | |||
9761 | +config ARM_GIC_V3_ITS_FSL_MC |
||
9762 | + bool |
||
9763 | + depends on ARM_GIC_V3_ITS |
||
9764 | + depends on FSL_MC_BUS |
||
9765 | + default ARM_GIC_V3_ITS |
||
9766 | + |
||
9767 | config ARM_NVIC |
||
9768 | bool |
||
9769 | select IRQ_DOMAIN |
||
9770 | --- a/drivers/irqchip/Makefile |
||
9771 | +++ b/drivers/irqchip/Makefile |
||
9772 | @@ -30,6 +30,7 @@ obj-$(CONFIG_ARCH_REALVIEW) += irq-gic- |
||
9773 | obj-$(CONFIG_ARM_GIC_V2M) += irq-gic-v2m.o |
||
9774 | obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-common.o |
||
9775 | obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o irq-gic-v3-its-pci-msi.o irq-gic-v3-its-platform-msi.o irq-gic-v4.o |
||
9776 | +obj-$(CONFIG_ARM_GIC_V3_ITS_FSL_MC) += irq-gic-v3-its-fsl-mc-msi.o |
||
9777 | obj-$(CONFIG_PARTITION_PERCPU) += irq-partition-percpu.o |
||
9778 | obj-$(CONFIG_HISILICON_IRQ_MBIGEN) += irq-mbigen.o |
||
9779 | obj-$(CONFIG_ARM_NVIC) += irq-nvic.o |
||
9780 | --- /dev/null |
||
9781 | +++ b/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c |
||
9782 | @@ -0,0 +1,98 @@ |
||
9783 | +// SPDX-License-Identifier: GPL-2.0 |
||
9784 | +/* |
||
9785 | + * Freescale Management Complex (MC) bus driver MSI support |
||
9786 | + * |
||
9787 | + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. |
||
9788 | + * Author: German Rivera <German.Rivera@freescale.com> |
||
9789 | + * |
||
9790 | + */ |
||
9791 | + |
||
9792 | +#include <linux/of_device.h> |
||
9793 | +#include <linux/of_address.h> |
||
9794 | +#include <linux/irq.h> |
||
9795 | +#include <linux/msi.h> |
||
9796 | +#include <linux/of.h> |
||
9797 | +#include <linux/of_irq.h> |
||
9798 | +#include <linux/fsl/mc.h> |
||
9799 | + |
||
9800 | +static struct irq_chip its_msi_irq_chip = { |
||
9801 | + .name = "ITS-fMSI", |
||
9802 | + .irq_mask = irq_chip_mask_parent, |
||
9803 | + .irq_unmask = irq_chip_unmask_parent, |
||
9804 | + .irq_eoi = irq_chip_eoi_parent, |
||
9805 | + .irq_set_affinity = msi_domain_set_affinity |
||
9806 | +}; |
||
9807 | + |
||
9808 | +static int its_fsl_mc_msi_prepare(struct irq_domain *msi_domain, |
||
9809 | + struct device *dev, |
||
9810 | + int nvec, msi_alloc_info_t *info) |
||
9811 | +{ |
||
9812 | + struct fsl_mc_device *mc_bus_dev; |
||
9813 | + struct msi_domain_info *msi_info; |
||
9814 | + |
||
9815 | + if (!dev_is_fsl_mc(dev)) |
||
9816 | + return -EINVAL; |
||
9817 | + |
||
9818 | + mc_bus_dev = to_fsl_mc_device(dev); |
||
9819 | + if (!(mc_bus_dev->flags & FSL_MC_IS_DPRC)) |
||
9820 | + return -EINVAL; |
||
9821 | + |
||
9822 | + /* |
||
9823 | + * Set the device Id to be passed to the GIC-ITS: |
||
9824 | + * |
||
9825 | + * NOTE: This device id corresponds to the IOMMU stream ID |
||
9826 | + * associated with the DPRC object (ICID). |
||
9827 | + */ |
||
9828 | + info->scratchpad[0].ul = mc_bus_dev->icid; |
||
9829 | + msi_info = msi_get_domain_info(msi_domain->parent); |
||
9830 | + return msi_info->ops->msi_prepare(msi_domain->parent, dev, nvec, info); |
||
9831 | +} |
||
9832 | + |
||
9833 | +static struct msi_domain_ops its_fsl_mc_msi_ops __ro_after_init = { |
||
9834 | + .msi_prepare = its_fsl_mc_msi_prepare, |
||
9835 | +}; |
||
9836 | + |
||
9837 | +static struct msi_domain_info its_fsl_mc_msi_domain_info = { |
||
9838 | + .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS), |
||
9839 | + .ops = &its_fsl_mc_msi_ops, |
||
9840 | + .chip = &its_msi_irq_chip, |
||
9841 | +}; |
||
9842 | + |
||
9843 | +static const struct of_device_id its_device_id[] = { |
||
9844 | + { .compatible = "arm,gic-v3-its", }, |
||
9845 | + {}, |
||
9846 | +}; |
||
9847 | + |
||
9848 | +static int __init its_fsl_mc_msi_init(void) |
||
9849 | +{ |
||
9850 | + struct device_node *np; |
||
9851 | + struct irq_domain *parent; |
||
9852 | + struct irq_domain *mc_msi_domain; |
||
9853 | + |
||
9854 | + for (np = of_find_matching_node(NULL, its_device_id); np; |
||
9855 | + np = of_find_matching_node(np, its_device_id)) { |
||
9856 | + if (!of_property_read_bool(np, "msi-controller")) |
||
9857 | + continue; |
||
9858 | + |
||
9859 | + parent = irq_find_matching_host(np, DOMAIN_BUS_NEXUS); |
||
9860 | + if (!parent || !msi_get_domain_info(parent)) { |
||
9861 | + pr_err("%pOF: unable to locate ITS domain\n", np); |
||
9862 | + continue; |
||
9863 | + } |
||
9864 | + |
||
9865 | + mc_msi_domain = fsl_mc_msi_create_irq_domain( |
||
9866 | + of_node_to_fwnode(np), |
||
9867 | + &its_fsl_mc_msi_domain_info, |
||
9868 | + parent); |
||
9869 | + if (!mc_msi_domain) { |
||
9870 | + pr_err("%pOF: unable to create fsl-mc domain\n", np); |
||
9871 | + continue; |
||
9872 | + } |
||
9873 | + |
||
9874 | + pr_info("fsl-mc MSI: %pOF domain created\n", np); |
||
9875 | + } |
||
9876 | + |
||
9877 | + return 0; |
||
9878 | +} |
||
9879 | + |
||
9880 | +early_initcall(its_fsl_mc_msi_init); |
||
9881 | --- a/drivers/staging/fsl-dpaa2/ethernet/README |
||
9882 | +++ b/drivers/staging/fsl-dpaa2/ethernet/README |
||
9883 | @@ -36,7 +36,7 @@ are treated as internal resources of oth |
||
9884 | |||
9885 | For a more detailed description of the DPAA2 architecture and its object |
||
9886 | abstractions see: |
||
9887 | - drivers/staging/fsl-mc/README.txt |
||
9888 | + Documentation/networking/dpaa2/overview.rst |
||
9889 | |||
9890 | Each Linux net device is built on top of a Datapath Network Interface (DPNI) |
||
9891 | object and uses Buffer Pools (DPBPs), I/O Portals (DPIOs) and Concentrators |
||
9892 | --- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c |
||
9893 | +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c |
||
9894 | @@ -43,7 +43,7 @@ |
||
9895 | #include <linux/filter.h> |
||
9896 | #include <linux/atomic.h> |
||
9897 | #include <net/sock.h> |
||
9898 | -#include "../../fsl-mc/include/mc.h" |
||
9899 | +#include <linux/fsl/mc.h> |
||
9900 | #include "dpaa2-eth.h" |
||
9901 | #include "dpaa2-eth-ceetm.h" |
||
9902 | |||
9903 | --- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h |
||
9904 | +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h |
||
9905 | @@ -36,11 +36,10 @@ |
||
9906 | #include <linux/dcbnl.h> |
||
9907 | #include <linux/netdevice.h> |
||
9908 | #include <linux/if_vlan.h> |
||
9909 | +#include <linux/fsl/mc.h> |
||
9910 | |||
9911 | #include "../../fsl-mc/include/dpaa2-io.h" |
||
9912 | #include "../../fsl-mc/include/dpaa2-fd.h" |
||
9913 | -#include "../../fsl-mc/include/dpbp.h" |
||
9914 | -#include "../../fsl-mc/include/dpcon.h" |
||
9915 | #include "dpni.h" |
||
9916 | #include "dpni-cmd.h" |
||
9917 | |||
9918 | --- a/drivers/staging/fsl-dpaa2/ethernet/dpni.c |
||
9919 | +++ b/drivers/staging/fsl-dpaa2/ethernet/dpni.c |
||
9920 | @@ -32,7 +32,7 @@ |
||
9921 | */ |
||
9922 | #include <linux/kernel.h> |
||
9923 | #include <linux/errno.h> |
||
9924 | -#include "../../fsl-mc/include/mc.h" |
||
9925 | +#include <linux/fsl/mc.h> |
||
9926 | #include "dpni.h" |
||
9927 | #include "dpni-cmd.h" |
||
9928 | |||
9929 | --- a/drivers/staging/fsl-mc/TODO |
||
9930 | +++ /dev/null |
||
9931 | @@ -1,18 +0,0 @@ |
||
9932 | -* Add at least one device driver for a DPAA2 object (child device of the |
||
9933 | - fsl-mc bus). Most likely candidate for this is adding DPAA2 Ethernet |
||
9934 | - driver support, which depends on drivers for several objects: DPNI, |
||
9935 | - DPIO, DPMAC. Other pre-requisites include: |
||
9936 | - |
||
9937 | - * MC firmware uprev. The MC firmware upon which the fsl-mc |
||
9938 | - bus driver and DPAA2 object drivers are based is continuing |
||
9939 | - to evolve, so minor updates are needed to keep in sync with binary |
||
9940 | - interface changes to the MC. |
||
9941 | - |
||
9942 | -* Cleanup |
||
9943 | - |
||
9944 | -Please send any patches to Greg Kroah-Hartman <gregkh@linuxfoundation.org>, |
||
9945 | -german.rivera@freescale.com, devel@driverdev.osuosl.org, |
||
9946 | -linux-kernel@vger.kernel.org |
||
9947 | - |
||
9948 | -[1] https://lkml.org/lkml/2015/7/9/93 |
||
9949 | -[2] https://lkml.org/lkml/2015/7/7/712 |
||
9950 | --- a/drivers/staging/fsl-mc/bus/Kconfig |
||
9951 | +++ b/drivers/staging/fsl-mc/bus/Kconfig |
||
9952 | @@ -5,16 +5,6 @@ |
||
9953 | # Copyright (C) 2014-2016 Freescale Semiconductor, Inc. |
||
9954 | # |
||
9955 | |||
9956 | -config FSL_MC_BUS |
||
9957 | - bool "QorIQ DPAA2 fsl-mc bus driver" |
||
9958 | - depends on OF && (ARCH_LAYERSCAPE || (COMPILE_TEST && (ARM || ARM64 || X86_LOCAL_APIC || PPC))) |
||
9959 | - select GENERIC_MSI_IRQ_DOMAIN |
||
9960 | - help |
||
9961 | - Driver to enable the bus infrastructure for the QorIQ DPAA2 |
||
9962 | - architecture. The fsl-mc bus driver handles discovery of |
||
9963 | - DPAA2 objects (which are represented as Linux devices) and |
||
9964 | - binding objects to drivers. |
||
9965 | - |
||
9966 | config FSL_MC_DPIO |
||
9967 | tristate "QorIQ DPAA2 DPIO driver" |
||
9968 | depends on FSL_MC_BUS |
||
9969 | @@ -24,3 +14,9 @@ config FSL_MC_DPIO |
||
9970 | other DPAA2 objects. This driver does not expose the DPIO |
||
9971 | objects individually, but groups them under a service layer |
||
9972 | API. |
||
9973 | + |
||
9974 | +config FSL_QBMAN_DEBUG |
||
9975 | + tristate "Freescale QBMAN Debug APIs" |
||
9976 | + depends on FSL_MC_DPIO |
||
9977 | + help |
||
9978 | + QBMan debug assistant APIs. |
||
9979 | --- a/drivers/staging/fsl-mc/bus/Makefile |
||
9980 | +++ b/drivers/staging/fsl-mc/bus/Makefile |
||
9981 | @@ -4,19 +4,6 @@ |
||
9982 | # |
||
9983 | # Copyright (C) 2014 Freescale Semiconductor, Inc. |
||
9984 | # |
||
9985 | -obj-$(CONFIG_FSL_MC_BUS) += mc-bus-driver.o |
||
9986 | - |
||
9987 | -mc-bus-driver-objs := fsl-mc-bus.o \ |
||
9988 | - mc-sys.o \ |
||
9989 | - mc-io.o \ |
||
9990 | - dprc.o \ |
||
9991 | - dprc-driver.o \ |
||
9992 | - fsl-mc-allocator.o \ |
||
9993 | - fsl-mc-msi.o \ |
||
9994 | - irq-gic-v3-its-fsl-mc-msi.o \ |
||
9995 | - dpmcp.o \ |
||
9996 | - dpbp.o \ |
||
9997 | - dpcon.o |
||
9998 | |||
9999 | # MC DPIO driver |
||
10000 | obj-$(CONFIG_FSL_MC_DPIO) += dpio/ |
||
10001 | --- a/drivers/staging/fsl-mc/bus/dpio/dpio-driver.c |
||
10002 | +++ b/drivers/staging/fsl-mc/bus/dpio/dpio-driver.c |
||
10003 | @@ -14,7 +14,7 @@ |
||
10004 | #include <linux/dma-mapping.h> |
||
10005 | #include <linux/delay.h> |
||
10006 | |||
10007 | -#include "../../include/mc.h" |
||
10008 | +#include <linux/fsl/mc.h> |
||
10009 | #include "../../include/dpaa2-io.h" |
||
10010 | |||
10011 | #include "qbman-portal.h" |
||
10012 | --- a/drivers/staging/fsl-mc/bus/dpio/dpio-service.c |
||
10013 | +++ b/drivers/staging/fsl-mc/bus/dpio/dpio-service.c |
||
10014 | @@ -5,7 +5,7 @@ |
||
10015 | * |
||
10016 | */ |
||
10017 | #include <linux/types.h> |
||
10018 | -#include "../../include/mc.h" |
||
10019 | +#include <linux/fsl/mc.h> |
||
10020 | #include "../../include/dpaa2-io.h" |
||
10021 | #include <linux/init.h> |
||
10022 | #include <linux/module.h> |
||
10023 | --- a/drivers/staging/fsl-mc/bus/dpio/dpio.c |
||
10024 | +++ b/drivers/staging/fsl-mc/bus/dpio/dpio.c |
||
10025 | @@ -5,7 +5,7 @@ |
||
10026 | * |
||
10027 | */ |
||
10028 | #include <linux/kernel.h> |
||
10029 | -#include "../../include/mc.h" |
||
10030 | +#include <linux/fsl/mc.h> |
||
10031 | |||
10032 | #include "dpio.h" |
||
10033 | #include "dpio-cmd.h" |
||
10034 | @@ -37,7 +37,7 @@ int dpio_open(struct fsl_mc_io *mc_io, |
||
10035 | int dpio_id, |
||
10036 | u16 *token) |
||
10037 | { |
||
10038 | - struct mc_command cmd = { 0 }; |
||
10039 | + struct fsl_mc_command cmd = { 0 }; |
||
10040 | struct dpio_cmd_open *dpio_cmd; |
||
10041 | int err; |
||
10042 | |||
10043 | @@ -70,7 +70,7 @@ int dpio_close(struct fsl_mc_io *mc_io, |
||
10044 | u32 cmd_flags, |
||
10045 | u16 token) |
||
10046 | { |
||
10047 | - struct mc_command cmd = { 0 }; |
||
10048 | + struct fsl_mc_command cmd = { 0 }; |
||
10049 | |||
10050 | /* prepare command */ |
||
10051 | cmd.header = mc_encode_cmd_header(DPIO_CMDID_CLOSE, |
||
10052 | @@ -92,7 +92,7 @@ int dpio_enable(struct fsl_mc_io *mc_io, |
||
10053 | u32 cmd_flags, |
||
10054 | u16 token) |
||
10055 | { |
||
10056 | - struct mc_command cmd = { 0 }; |
||
10057 | + struct fsl_mc_command cmd = { 0 }; |
||
10058 | |||
10059 | /* prepare command */ |
||
10060 | cmd.header = mc_encode_cmd_header(DPIO_CMDID_ENABLE, |
||
10061 | @@ -114,7 +114,7 @@ int dpio_disable(struct fsl_mc_io *mc_io |
||
10062 | u32 cmd_flags, |
||
10063 | u16 token) |
||
10064 | { |
||
10065 | - struct mc_command cmd = { 0 }; |
||
10066 | + struct fsl_mc_command cmd = { 0 }; |
||
10067 | |||
10068 | /* prepare command */ |
||
10069 | cmd.header = mc_encode_cmd_header(DPIO_CMDID_DISABLE, |
||
10070 | @@ -138,7 +138,7 @@ int dpio_get_attributes(struct fsl_mc_io |
||
10071 | u16 token, |
||
10072 | struct dpio_attr *attr) |
||
10073 | { |
||
10074 | - struct mc_command cmd = { 0 }; |
||
10075 | + struct fsl_mc_command cmd = { 0 }; |
||
10076 | struct dpio_rsp_get_attr *dpio_rsp; |
||
10077 | int err; |
||
10078 | |||
10079 | @@ -180,7 +180,7 @@ int dpio_get_api_version(struct fsl_mc_i |
||
10080 | u16 *major_ver, |
||
10081 | u16 *minor_ver) |
||
10082 | { |
||
10083 | - struct mc_command cmd = { 0 }; |
||
10084 | + struct fsl_mc_command cmd = { 0 }; |
||
10085 | int err; |
||
10086 | |||
10087 | /* prepare command */ |
||
10088 | --- a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h |
||
10089 | +++ /dev/null |
||
10090 | @@ -1,56 +0,0 @@ |
||
10091 | -/* |
||
10092 | - * Copyright 2013-2016 Freescale Semiconductor Inc. |
||
10093 | - * |
||
10094 | - * Redistribution and use in source and binary forms, with or without |
||
10095 | - * modification, are permitted provided that the following conditions are met: |
||
10096 | - * * Redistributions of source code must retain the above copyright |
||
10097 | - * notice, this list of conditions and the following disclaimer. |
||
10098 | - * * Redistributions in binary form must reproduce the above copyright |
||
10099 | - * notice, this list of conditions and the following disclaimer in the |
||
10100 | - * documentation and/or other materials provided with the distribution. |
||
10101 | - * * Neither the name of the above-listed copyright holders nor the |
||
10102 | - * names of any contributors may be used to endorse or promote products |
||
10103 | - * derived from this software without specific prior written permission. |
||
10104 | - * |
||
10105 | - * ALTERNATIVELY, this software may be distributed under the terms of the |
||
10106 | - * GNU General Public License ("GPL") as published by the Free Software |
||
10107 | - * Foundation, either version 2 of that License or (at your option) any |
||
10108 | - * later version. |
||
10109 | - * |
||
10110 | - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||
10111 | - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
10112 | - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
10113 | - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE |
||
10114 | - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||
10115 | - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||
10116 | - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||
10117 | - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||
10118 | - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||
10119 | - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||
10120 | - * POSSIBILITY OF SUCH DAMAGE. |
||
10121 | - */ |
||
10122 | -#ifndef _FSL_DPMCP_CMD_H |
||
10123 | -#define _FSL_DPMCP_CMD_H |
||
10124 | - |
||
10125 | -/* Minimal supported DPMCP Version */ |
||
10126 | -#define DPMCP_MIN_VER_MAJOR 3 |
||
10127 | -#define DPMCP_MIN_VER_MINOR 0 |
||
10128 | - |
||
10129 | -/* Command versioning */ |
||
10130 | -#define DPMCP_CMD_BASE_VERSION 1 |
||
10131 | -#define DPMCP_CMD_ID_OFFSET 4 |
||
10132 | - |
||
10133 | -#define DPMCP_CMD(id) (((id) << DPMCP_CMD_ID_OFFSET) | DPMCP_CMD_BASE_VERSION) |
||
10134 | - |
||
10135 | -/* Command IDs */ |
||
10136 | -#define DPMCP_CMDID_CLOSE DPMCP_CMD(0x800) |
||
10137 | -#define DPMCP_CMDID_OPEN DPMCP_CMD(0x80b) |
||
10138 | -#define DPMCP_CMDID_GET_API_VERSION DPMCP_CMD(0xa0b) |
||
10139 | - |
||
10140 | -#define DPMCP_CMDID_RESET DPMCP_CMD(0x005) |
||
10141 | - |
||
10142 | -struct dpmcp_cmd_open { |
||
10143 | - __le32 dpmcp_id; |
||
10144 | -}; |
||
10145 | - |
||
10146 | -#endif /* _FSL_DPMCP_CMD_H */ |
||
10147 | --- a/drivers/staging/fsl-mc/bus/dpmcp.h |
||
10148 | +++ /dev/null |
||
10149 | @@ -1,60 +0,0 @@ |
||
10150 | -/* |
||
10151 | - * Copyright 2013-2016 Freescale Semiconductor Inc. |
||
10152 | - * |
||
10153 | - * Redistribution and use in source and binary forms, with or without |
||
10154 | - * modification, are permitted provided that the following conditions are met: |
||
10155 | - * * Redistributions of source code must retain the above copyright |
||
10156 | - * notice, this list of conditions and the following disclaimer. |
||
10157 | - * * Redistributions in binary form must reproduce the above copyright |
||
10158 | - * notice, this list of conditions and the following disclaimer in the |
||
10159 | - * documentation and/or other materials provided with the distribution. |
||
10160 | - * * Neither the name of the above-listed copyright holders nor the |
||
10161 | - * names of any contributors may be used to endorse or promote products |
||
10162 | - * derived from this software without specific prior written permission. |
||
10163 | - * |
||
10164 | - * ALTERNATIVELY, this software may be distributed under the terms of the |
||
10165 | - * GNU General Public License ("GPL") as published by the Free Software |
||
10166 | - * Foundation, either version 2 of that License or (at your option) any |
||
10167 | - * later version. |
||
10168 | - * |
||
10169 | - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||
10170 | - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
10171 | - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
10172 | - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE |
||
10173 | - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||
10174 | - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||
10175 | - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||
10176 | - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||
10177 | - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||
10178 | - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||
10179 | - * POSSIBILITY OF SUCH DAMAGE. |
||
10180 | - */ |
||
10181 | -#ifndef __FSL_DPMCP_H |
||
10182 | -#define __FSL_DPMCP_H |
||
10183 | - |
||
10184 | -/* |
||
10185 | - * Data Path Management Command Portal API |
||
10186 | - * Contains initialization APIs and runtime control APIs for DPMCP |
||
10187 | - */ |
||
10188 | - |
||
10189 | -struct fsl_mc_io; |
||
10190 | - |
||
10191 | -int dpmcp_open(struct fsl_mc_io *mc_io, |
||
10192 | - u32 cmd_flags, |
||
10193 | - int dpmcp_id, |
||
10194 | - u16 *token); |
||
10195 | - |
||
10196 | -int dpmcp_close(struct fsl_mc_io *mc_io, |
||
10197 | - u32 cmd_flags, |
||
10198 | - u16 token); |
||
10199 | - |
||
10200 | -int dpmcp_get_api_version(struct fsl_mc_io *mc_io, |
||
10201 | - u32 cmd_flags, |
||
10202 | - u16 *major_ver, |
||
10203 | - u16 *minor_ver); |
||
10204 | - |
||
10205 | -int dpmcp_reset(struct fsl_mc_io *mc_io, |
||
10206 | - u32 cmd_flags, |
||
10207 | - u16 token); |
||
10208 | - |
||
10209 | -#endif /* __FSL_DPMCP_H */ |
||
10210 | --- a/drivers/staging/fsl-mc/bus/dpmng-cmd.h |
||
10211 | +++ /dev/null |
||
10212 | @@ -1,58 +0,0 @@ |
||
10213 | -/* |
||
10214 | - * Copyright 2013-2016 Freescale Semiconductor Inc. |
||
10215 | - * |
||
10216 | - * Redistribution and use in source and binary forms, with or without |
||
10217 | - * modification, are permitted provided that the following conditions are met: |
||
10218 | - * * Redistributions of source code must retain the above copyright |
||
10219 | - * notice, this list of conditions and the following disclaimer. |
||
10220 | - * * Redistributions in binary form must reproduce the above copyright |
||
10221 | - * notice, this list of conditions and the following disclaimer in the |
||
10222 | - * documentation and/or other materials provided with the distribution. |
||
10223 | - * * Neither the name of the above-listed copyright holders nor the |
||
10224 | - * names of any contributors may be used to endorse or promote products |
||
10225 | - * derived from this software without specific prior written permission. |
||
10226 | - * |
||
10227 | - * ALTERNATIVELY, this software may be distributed under the terms of the |
||
10228 | - * GNU General Public License ("GPL") as published by the Free Software |
||
10229 | - * Foundation, either version 2 of that License or (at your option) any |
||
10230 | - * later version. |
||
10231 | - * |
||
10232 | - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||
10233 | - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
10234 | - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
10235 | - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE |
||
10236 | - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||
10237 | - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||
10238 | - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||
10239 | - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||
10240 | - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||
10241 | - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||
10242 | - * POSSIBILITY OF SUCH DAMAGE. |
||
10243 | - */ |
||
10244 | - |
||
10245 | -/* |
||
10246 | - * dpmng-cmd.h |
||
10247 | - * |
||
10248 | - * defines portal commands |
||
10249 | - * |
||
10250 | - */ |
||
10251 | - |
||
10252 | -#ifndef __FSL_DPMNG_CMD_H |
||
10253 | -#define __FSL_DPMNG_CMD_H |
||
10254 | - |
||
10255 | -/* Command versioning */ |
||
10256 | -#define DPMNG_CMD_BASE_VERSION 1 |
||
10257 | -#define DPMNG_CMD_ID_OFFSET 4 |
||
10258 | - |
||
10259 | -#define DPMNG_CMD(id) (((id) << DPMNG_CMD_ID_OFFSET) | DPMNG_CMD_BASE_VERSION) |
||
10260 | - |
||
10261 | -/* Command IDs */ |
||
10262 | -#define DPMNG_CMDID_GET_VERSION DPMNG_CMD(0x831) |
||
10263 | - |
||
10264 | -struct dpmng_rsp_get_version { |
||
10265 | - __le32 revision; |
||
10266 | - __le32 version_major; |
||
10267 | - __le32 version_minor; |
||
10268 | -}; |
||
10269 | - |
||
10270 | -#endif /* __FSL_DPMNG_CMD_H */ |
||
10271 | --- a/drivers/staging/fsl-mc/bus/dprc-cmd.h |
||
10272 | +++ /dev/null |
||
10273 | @@ -1,451 +0,0 @@ |
||
10274 | -/* |
||
10275 | - * Copyright 2013-2016 Freescale Semiconductor Inc. |
||
10276 | - * |
||
10277 | - * Redistribution and use in source and binary forms, with or without |
||
10278 | - * modification, are permitted provided that the following conditions are met: |
||
10279 | - * * Redistributions of source code must retain the above copyright |
||
10280 | - * notice, this list of conditions and the following disclaimer. |
||
10281 | - * * Redistributions in binary form must reproduce the above copyright |
||
10282 | - * notice, this list of conditions and the following disclaimer in the |
||
10283 | - * documentation and/or other materials provided with the distribution. |
||
10284 | - * * Neither the name of the above-listed copyright holders nor the |
||
10285 | - * names of any contributors may be used to endorse or promote products |
||
10286 | - * derived from this software without specific prior written permission. |
||
10287 | - * |
||
10288 | - * ALTERNATIVELY, this software may be distributed under the terms of the |
||
10289 | - * GNU General Public License ("GPL") as published by the Free Software |
||
10290 | - * Foundation, either version 2 of that License or (at your option) any |
||
10291 | - * later version. |
||
10292 | - * |
||
10293 | - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||
10294 | - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
10295 | - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
10296 | - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE |
||
10297 | - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||
10298 | - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||
10299 | - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||
10300 | - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||
10301 | - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||
10302 | - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||
10303 | - * POSSIBILITY OF SUCH DAMAGE. |
||
10304 | - */ |
||
10305 | - |
||
10306 | -/* |
||
10307 | - * dprc-cmd.h |
||
10308 | - * |
||
10309 | - * defines dprc portal commands |
||
10310 | - * |
||
10311 | - */ |
||
10312 | - |
||
10313 | -#ifndef _FSL_DPRC_CMD_H |
||
10314 | -#define _FSL_DPRC_CMD_H |
||
10315 | - |
||
10316 | -/* Minimal supported DPRC Version */ |
||
10317 | -#define DPRC_MIN_VER_MAJOR 6 |
||
10318 | -#define DPRC_MIN_VER_MINOR 0 |
||
10319 | - |
||
10320 | -/* Command versioning */ |
||
10321 | -#define DPRC_CMD_BASE_VERSION 1 |
||
10322 | -#define DPRC_CMD_ID_OFFSET 4 |
||
10323 | - |
||
10324 | -#define DPRC_CMD(id) (((id) << DPRC_CMD_ID_OFFSET) | DPRC_CMD_BASE_VERSION) |
||
10325 | - |
||
10326 | -/* Command IDs */ |
||
10327 | -#define DPRC_CMDID_CLOSE DPRC_CMD(0x800) |
||
10328 | -#define DPRC_CMDID_OPEN DPRC_CMD(0x805) |
||
10329 | -#define DPRC_CMDID_GET_API_VERSION DPRC_CMD(0xa05) |
||
10330 | - |
||
10331 | -#define DPRC_CMDID_GET_ATTR DPRC_CMD(0x004) |
||
10332 | - |
||
10333 | -#define DPRC_CMDID_SET_IRQ DPRC_CMD(0x010) |
||
10334 | -#define DPRC_CMDID_GET_IRQ DPRC_CMD(0x011) |
||
10335 | -#define DPRC_CMDID_SET_IRQ_ENABLE DPRC_CMD(0x012) |
||
10336 | -#define DPRC_CMDID_GET_IRQ_ENABLE DPRC_CMD(0x013) |
||
10337 | -#define DPRC_CMDID_SET_IRQ_MASK DPRC_CMD(0x014) |
||
10338 | -#define DPRC_CMDID_GET_IRQ_MASK DPRC_CMD(0x015) |
||
10339 | -#define DPRC_CMDID_GET_IRQ_STATUS DPRC_CMD(0x016) |
||
10340 | -#define DPRC_CMDID_CLEAR_IRQ_STATUS DPRC_CMD(0x017) |
||
10341 | - |
||
10342 | -#define DPRC_CMDID_GET_CONT_ID DPRC_CMD(0x830) |
||
10343 | -#define DPRC_CMDID_GET_OBJ_COUNT DPRC_CMD(0x159) |
||
10344 | -#define DPRC_CMDID_GET_OBJ DPRC_CMD(0x15A) |
||
10345 | -#define DPRC_CMDID_GET_RES_COUNT DPRC_CMD(0x15B) |
||
10346 | -#define DPRC_CMDID_GET_OBJ_REG DPRC_CMD(0x15E) |
||
10347 | -#define DPRC_CMDID_SET_OBJ_IRQ DPRC_CMD(0x15F) |
||
10348 | -#define DPRC_CMDID_GET_OBJ_IRQ DPRC_CMD(0x160) |
||
10349 | - |
||
10350 | -struct dprc_cmd_open { |
||
10351 | - __le32 container_id; |
||
10352 | -}; |
||
10353 | - |
||
10354 | -struct dprc_cmd_create_container { |
||
10355 | - /* cmd word 0 */ |
||
10356 | - __le32 options; |
||
10357 | - __le16 icid; |
||
10358 | - __le16 pad0; |
||
10359 | - /* cmd word 1 */ |
||
10360 | - __le32 pad1; |
||
10361 | - __le32 portal_id; |
||
10362 | - /* cmd words 2-3 */ |
||
10363 | - u8 label[16]; |
||
10364 | -}; |
||
10365 | - |
||
10366 | -struct dprc_rsp_create_container { |
||
10367 | - /* response word 0 */ |
||
10368 | - __le64 pad0; |
||
10369 | - /* response word 1 */ |
||
10370 | - __le32 child_container_id; |
||
10371 | - __le32 pad1; |
||
10372 | - /* response word 2 */ |
||
10373 | - __le64 child_portal_addr; |
||
10374 | -}; |
||
10375 | - |
||
10376 | -struct dprc_cmd_destroy_container { |
||
10377 | - __le32 child_container_id; |
||
10378 | -}; |
||
10379 | - |
||
10380 | -struct dprc_cmd_reset_container { |
||
10381 | - __le32 child_container_id; |
||
10382 | -}; |
||
10383 | - |
||
10384 | -struct dprc_cmd_set_irq { |
||
10385 | - /* cmd word 0 */ |
||
10386 | - __le32 irq_val; |
||
10387 | - u8 irq_index; |
||
10388 | - u8 pad[3]; |
||
10389 | - /* cmd word 1 */ |
||
10390 | - __le64 irq_addr; |
||
10391 | - /* cmd word 2 */ |
||
10392 | - __le32 irq_num; |
||
10393 | -}; |
||
10394 | - |
||
10395 | -struct dprc_cmd_get_irq { |
||
10396 | - __le32 pad; |
||
10397 | - u8 irq_index; |
||
10398 | -}; |
||
10399 | - |
||
10400 | -struct dprc_rsp_get_irq { |
||
10401 | - /* response word 0 */ |
||
10402 | - __le32 irq_val; |
||
10403 | - __le32 pad; |
||
10404 | - /* response word 1 */ |
||
10405 | - __le64 irq_addr; |
||
10406 | - /* response word 2 */ |
||
10407 | - __le32 irq_num; |
||
10408 | - __le32 type; |
||
10409 | -}; |
||
10410 | - |
||
10411 | -#define DPRC_ENABLE 0x1 |
||
10412 | - |
||
10413 | -struct dprc_cmd_set_irq_enable { |
||
10414 | - u8 enable; |
||
10415 | - u8 pad[3]; |
||
10416 | - u8 irq_index; |
||
10417 | -}; |
||
10418 | - |
||
10419 | -struct dprc_cmd_get_irq_enable { |
||
10420 | - __le32 pad; |
||
10421 | - u8 irq_index; |
||
10422 | -}; |
||
10423 | - |
||
10424 | -struct dprc_rsp_get_irq_enable { |
||
10425 | - u8 enabled; |
||
10426 | -}; |
||
10427 | - |
||
10428 | -struct dprc_cmd_set_irq_mask { |
||
10429 | - __le32 mask; |
||
10430 | - u8 irq_index; |
||
10431 | -}; |
||
10432 | - |
||
10433 | -struct dprc_cmd_get_irq_mask { |
||
10434 | - __le32 pad; |
||
10435 | - u8 irq_index; |
||
10436 | -}; |
||
10437 | - |
||
10438 | -struct dprc_rsp_get_irq_mask { |
||
10439 | - __le32 mask; |
||
10440 | -}; |
||
10441 | - |
||
10442 | -struct dprc_cmd_get_irq_status { |
||
10443 | - __le32 status; |
||
10444 | - u8 irq_index; |
||
10445 | -}; |
||
10446 | - |
||
10447 | -struct dprc_rsp_get_irq_status { |
||
10448 | - __le32 status; |
||
10449 | -}; |
||
10450 | - |
||
10451 | -struct dprc_cmd_clear_irq_status { |
||
10452 | - __le32 status; |
||
10453 | - u8 irq_index; |
||
10454 | -}; |
||
10455 | - |
||
10456 | -struct dprc_rsp_get_attributes { |
||
10457 | - /* response word 0 */ |
||
10458 | - __le32 container_id; |
||
10459 | - __le16 icid; |
||
10460 | - __le16 pad; |
||
10461 | - /* response word 1 */ |
||
10462 | - __le32 options; |
||
10463 | - __le32 portal_id; |
||
10464 | -}; |
||
10465 | - |
||
10466 | -struct dprc_cmd_set_res_quota { |
||
10467 | - /* cmd word 0 */ |
||
10468 | - __le32 child_container_id; |
||
10469 | - __le16 quota; |
||
10470 | - __le16 pad; |
||
10471 | - /* cmd words 1-2 */ |
||
10472 | - u8 type[16]; |
||
10473 | -}; |
||
10474 | - |
||
10475 | -struct dprc_cmd_get_res_quota { |
||
10476 | - /* cmd word 0 */ |
||
10477 | - __le32 child_container_id; |
||
10478 | - __le32 pad; |
||
10479 | - /* cmd word 1-2 */ |
||
10480 | - u8 type[16]; |
||
10481 | -}; |
||
10482 | - |
||
10483 | -struct dprc_rsp_get_res_quota { |
||
10484 | - __le32 pad; |
||
10485 | - __le16 quota; |
||
10486 | -}; |
||
10487 | - |
||
10488 | -struct dprc_cmd_assign { |
||
10489 | - /* cmd word 0 */ |
||
10490 | - __le32 container_id; |
||
10491 | - __le32 options; |
||
10492 | - /* cmd word 1 */ |
||
10493 | - __le32 num; |
||
10494 | - __le32 id_base_align; |
||
10495 | - /* cmd word 2-3 */ |
||
10496 | - u8 type[16]; |
||
10497 | -}; |
||
10498 | - |
||
10499 | -struct dprc_cmd_unassign { |
||
10500 | - /* cmd word 0 */ |
||
10501 | - __le32 child_container_id; |
||
10502 | - __le32 options; |
||
10503 | - /* cmd word 1 */ |
||
10504 | - __le32 num; |
||
10505 | - __le32 id_base_align; |
||
10506 | - /* cmd word 2-3 */ |
||
10507 | - u8 type[16]; |
||
10508 | -}; |
||
10509 | - |
||
10510 | -struct dprc_rsp_get_pool_count { |
||
10511 | - __le32 pool_count; |
||
10512 | -}; |
||
10513 | - |
||
10514 | -struct dprc_cmd_get_pool { |
||
10515 | - __le32 pool_index; |
||
10516 | -}; |
||
10517 | - |
||
10518 | -struct dprc_rsp_get_pool { |
||
10519 | - /* response word 0 */ |
||
10520 | - __le64 pad; |
||
10521 | - /* response word 1-2 */ |
||
10522 | - u8 type[16]; |
||
10523 | -}; |
||
10524 | - |
||
10525 | -struct dprc_rsp_get_obj_count { |
||
10526 | - __le32 pad; |
||
10527 | - __le32 obj_count; |
||
10528 | -}; |
||
10529 | - |
||
10530 | -struct dprc_cmd_get_obj { |
||
10531 | - __le32 obj_index; |
||
10532 | -}; |
||
10533 | - |
||
10534 | -struct dprc_rsp_get_obj { |
||
10535 | - /* response word 0 */ |
||
10536 | - __le32 pad0; |
||
10537 | - __le32 id; |
||
10538 | - /* response word 1 */ |
||
10539 | - __le16 vendor; |
||
10540 | - u8 irq_count; |
||
10541 | - u8 region_count; |
||
10542 | - __le32 state; |
||
10543 | - /* response word 2 */ |
||
10544 | - __le16 version_major; |
||
10545 | - __le16 version_minor; |
||
10546 | - __le16 flags; |
||
10547 | - __le16 pad1; |
||
10548 | - /* response word 3-4 */ |
||
10549 | - u8 type[16]; |
||
10550 | - /* response word 5-6 */ |
||
10551 | - u8 label[16]; |
||
10552 | -}; |
||
10553 | - |
||
10554 | -struct dprc_cmd_get_obj_desc { |
||
10555 | - /* cmd word 0 */ |
||
10556 | - __le32 obj_id; |
||
10557 | - __le32 pad; |
||
10558 | - /* cmd word 1-2 */ |
||
10559 | - u8 type[16]; |
||
10560 | -}; |
||
10561 | - |
||
10562 | -struct dprc_rsp_get_obj_desc { |
||
10563 | - /* response word 0 */ |
||
10564 | - __le32 pad0; |
||
10565 | - __le32 id; |
||
10566 | - /* response word 1 */ |
||
10567 | - __le16 vendor; |
||
10568 | - u8 irq_count; |
||
10569 | - u8 region_count; |
||
10570 | - __le32 state; |
||
10571 | - /* response word 2 */ |
||
10572 | - __le16 version_major; |
||
10573 | - __le16 version_minor; |
||
10574 | - __le16 flags; |
||
10575 | - __le16 pad1; |
||
10576 | - /* response word 3-4 */ |
||
10577 | - u8 type[16]; |
||
10578 | - /* response word 5-6 */ |
||
10579 | - u8 label[16]; |
||
10580 | -}; |
||
10581 | - |
||
10582 | -struct dprc_cmd_get_res_count { |
||
10583 | - /* cmd word 0 */ |
||
10584 | - __le64 pad; |
||
10585 | - /* cmd word 1-2 */ |
||
10586 | - u8 type[16]; |
||
10587 | -}; |
||
10588 | - |
||
10589 | -struct dprc_rsp_get_res_count { |
||
10590 | - __le32 res_count; |
||
10591 | -}; |
||
10592 | - |
||
10593 | -struct dprc_cmd_get_res_ids { |
||
10594 | - /* cmd word 0 */ |
||
10595 | - u8 pad0[5]; |
||
10596 | - u8 iter_status; |
||
10597 | - __le16 pad1; |
||
10598 | - /* cmd word 1 */ |
||
10599 | - __le32 base_id; |
||
10600 | - __le32 last_id; |
||
10601 | - /* cmd word 2-3 */ |
||
10602 | - u8 type[16]; |
||
10603 | -}; |
||
10604 | - |
||
10605 | -struct dprc_rsp_get_res_ids { |
||
10606 | - /* response word 0 */ |
||
10607 | - u8 pad0[5]; |
||
10608 | - u8 iter_status; |
||
10609 | - __le16 pad1; |
||
10610 | - /* response word 1 */ |
||
10611 | - __le32 base_id; |
||
10612 | - __le32 last_id; |
||
10613 | -}; |
||
10614 | - |
||
10615 | -struct dprc_cmd_get_obj_region { |
||
10616 | - /* cmd word 0 */ |
||
10617 | - __le32 obj_id; |
||
10618 | - __le16 pad0; |
||
10619 | - u8 region_index; |
||
10620 | - u8 pad1; |
||
10621 | - /* cmd word 1-2 */ |
||
10622 | - __le64 pad2[2]; |
||
10623 | - /* cmd word 3-4 */ |
||
10624 | - u8 obj_type[16]; |
||
10625 | -}; |
||
10626 | - |
||
10627 | -struct dprc_rsp_get_obj_region { |
||
10628 | - /* response word 0 */ |
||
10629 | - __le64 pad; |
||
10630 | - /* response word 1 */ |
||
10631 | - __le64 base_addr; |
||
10632 | - /* response word 2 */ |
||
10633 | - __le32 size; |
||
10634 | -}; |
||
10635 | - |
||
10636 | -struct dprc_cmd_set_obj_label { |
||
10637 | - /* cmd word 0 */ |
||
10638 | - __le32 obj_id; |
||
10639 | - __le32 pad; |
||
10640 | - /* cmd word 1-2 */ |
||
10641 | - u8 label[16]; |
||
10642 | - /* cmd word 3-4 */ |
||
10643 | - u8 obj_type[16]; |
||
10644 | -}; |
||
10645 | - |
||
10646 | -struct dprc_cmd_set_obj_irq { |
||
10647 | - /* cmd word 0 */ |
||
10648 | - __le32 irq_val; |
||
10649 | - u8 irq_index; |
||
10650 | - u8 pad[3]; |
||
10651 | - /* cmd word 1 */ |
||
10652 | - __le64 irq_addr; |
||
10653 | - /* cmd word 2 */ |
||
10654 | - __le32 irq_num; |
||
10655 | - __le32 obj_id; |
||
10656 | - /* cmd word 3-4 */ |
||
10657 | - u8 obj_type[16]; |
||
10658 | -}; |
||
10659 | - |
||
10660 | -struct dprc_cmd_get_obj_irq { |
||
10661 | - /* cmd word 0 */ |
||
10662 | - __le32 obj_id; |
||
10663 | - u8 irq_index; |
||
10664 | - u8 pad[3]; |
||
10665 | - /* cmd word 1-2 */ |
||
10666 | - u8 obj_type[16]; |
||
10667 | -}; |
||
10668 | - |
||
10669 | -struct dprc_rsp_get_obj_irq { |
||
10670 | - /* response word 0 */ |
||
10671 | - __le32 irq_val; |
||
10672 | - __le32 pad; |
||
10673 | - /* response word 1 */ |
||
10674 | - __le64 irq_addr; |
||
10675 | - /* response word 2 */ |
||
10676 | - __le32 irq_num; |
||
10677 | - __le32 type; |
||
10678 | -}; |
||
10679 | - |
||
10680 | -struct dprc_cmd_connect { |
||
10681 | - /* cmd word 0 */ |
||
10682 | - __le32 ep1_id; |
||
10683 | - __le32 ep1_interface_id; |
||
10684 | - /* cmd word 1 */ |
||
10685 | - __le32 ep2_id; |
||
10686 | - __le32 ep2_interface_id; |
||
10687 | - /* cmd word 2-3 */ |
||
10688 | - u8 ep1_type[16]; |
||
10689 | - /* cmd word 4 */ |
||
10690 | - __le32 max_rate; |
||
10691 | - __le32 committed_rate; |
||
10692 | - /* cmd word 5-6 */ |
||
10693 | - u8 ep2_type[16]; |
||
10694 | -}; |
||
10695 | - |
||
10696 | -struct dprc_cmd_disconnect { |
||
10697 | - /* cmd word 0 */ |
||
10698 | - __le32 id; |
||
10699 | - __le32 interface_id; |
||
10700 | - /* cmd word 1-2 */ |
||
10701 | - u8 type[16]; |
||
10702 | -}; |
||
10703 | - |
||
10704 | -struct dprc_cmd_get_connection { |
||
10705 | - /* cmd word 0 */ |
||
10706 | - __le32 ep1_id; |
||
10707 | - __le32 ep1_interface_id; |
||
10708 | - /* cmd word 1-2 */ |
||
10709 | - u8 ep1_type[16]; |
||
10710 | -}; |
||
10711 | - |
||
10712 | -struct dprc_rsp_get_connection { |
||
10713 | - /* response word 0-2 */ |
||
10714 | - __le64 pad[3]; |
||
10715 | - /* response word 3 */ |
||
10716 | - __le32 ep2_id; |
||
10717 | - __le32 ep2_interface_id; |
||
10718 | - /* response word 4-5 */ |
||
10719 | - u8 ep2_type[16]; |
||
10720 | - /* response word 6 */ |
||
10721 | - __le32 state; |
||
10722 | -}; |
||
10723 | - |
||
10724 | -#endif /* _FSL_DPRC_CMD_H */ |
||
10725 | --- a/drivers/staging/fsl-mc/bus/dprc.h |
||
10726 | +++ /dev/null |
||
10727 | @@ -1,268 +0,0 @@ |
||
10728 | -/* |
||
10729 | - * Copyright 2013-2016 Freescale Semiconductor Inc. |
||
10730 | - * |
||
10731 | - * Redistribution and use in source and binary forms, with or without |
||
10732 | - * modification, are permitted provided that the following conditions are met: |
||
10733 | - * * Redistributions of source code must retain the above copyright |
||
10734 | - * notice, this list of conditions and the following disclaimer. |
||
10735 | - * * Redistributions in binary form must reproduce the above copyright |
||
10736 | - * notice, this list of conditions and the following disclaimer in the |
||
10737 | - * documentation and/or other materials provided with the distribution. |
||
10738 | - * * Neither the name of the above-listed copyright holders nor the |
||
10739 | - * names of any contributors may be used to endorse or promote products |
||
10740 | - * derived from this software without specific prior written permission. |
||
10741 | - * |
||
10742 | - * |
||
10743 | - * ALTERNATIVELY, this software may be distributed under the terms of the |
||
10744 | - * GNU General Public License ("GPL") as published by the Free Software |
||
10745 | - * Foundation, either version 2 of that License or (at your option) any |
||
10746 | - * later version. |
||
10747 | - * |
||
10748 | - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||
10749 | - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
10750 | - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
10751 | - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE |
||
10752 | - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||
10753 | - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||
10754 | - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||
10755 | - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||
10756 | - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||
10757 | - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||
10758 | - * POSSIBILITY OF SUCH DAMAGE. |
||
10759 | - */ |
||
10760 | -#ifndef _FSL_DPRC_H |
||
10761 | -#define _FSL_DPRC_H |
||
10762 | - |
||
10763 | -/* |
||
10764 | - * Data Path Resource Container API |
||
10765 | - * Contains DPRC API for managing and querying DPAA resources |
||
10766 | - */ |
||
10767 | - |
||
10768 | -struct fsl_mc_io; |
||
10769 | -struct fsl_mc_obj_desc; |
||
10770 | - |
||
10771 | -int dprc_open(struct fsl_mc_io *mc_io, |
||
10772 | - u32 cmd_flags, |
||
10773 | - int container_id, |
||
10774 | - u16 *token); |
||
10775 | - |
||
10776 | -int dprc_close(struct fsl_mc_io *mc_io, |
||
10777 | - u32 cmd_flags, |
||
10778 | - u16 token); |
||
10779 | - |
||
10780 | -/* IRQ */ |
||
10781 | - |
||
10782 | -/* IRQ index */ |
||
10783 | -#define DPRC_IRQ_INDEX 0 |
||
10784 | - |
||
10785 | -/* Number of dprc's IRQs */ |
||
10786 | -#define DPRC_NUM_OF_IRQS 1 |
||
10787 | - |
||
10788 | -/* DPRC IRQ events */ |
||
10789 | - |
||
10790 | -/* IRQ event - Indicates that a new object added to the container */ |
||
10791 | -#define DPRC_IRQ_EVENT_OBJ_ADDED 0x00000001 |
||
10792 | -/* IRQ event - Indicates that an object was removed from the container */ |
||
10793 | -#define DPRC_IRQ_EVENT_OBJ_REMOVED 0x00000002 |
||
10794 | -/* IRQ event - Indicates that resources added to the container */ |
||
10795 | -#define DPRC_IRQ_EVENT_RES_ADDED 0x00000004 |
||
10796 | -/* IRQ event - Indicates that resources removed from the container */ |
||
10797 | -#define DPRC_IRQ_EVENT_RES_REMOVED 0x00000008 |
||
10798 | -/* |
||
10799 | - * IRQ event - Indicates that one of the descendant containers that opened by |
||
10800 | - * this container is destroyed |
||
10801 | - */ |
||
10802 | -#define DPRC_IRQ_EVENT_CONTAINER_DESTROYED 0x00000010 |
||
10803 | - |
||
10804 | -/* |
||
10805 | - * IRQ event - Indicates that on one of the container's opened object is |
||
10806 | - * destroyed |
||
10807 | - */ |
||
10808 | -#define DPRC_IRQ_EVENT_OBJ_DESTROYED 0x00000020 |
||
10809 | - |
||
10810 | -/* Irq event - Indicates that object is created at the container */ |
||
10811 | -#define DPRC_IRQ_EVENT_OBJ_CREATED 0x00000040 |
||
10812 | - |
||
10813 | -/** |
||
10814 | - * struct dprc_irq_cfg - IRQ configuration |
||
10815 | - * @paddr: Address that must be written to signal a message-based interrupt |
||
10816 | - * @val: Value to write into irq_addr address |
||
10817 | - * @irq_num: A user defined number associated with this IRQ |
||
10818 | - */ |
||
10819 | -struct dprc_irq_cfg { |
||
10820 | - phys_addr_t paddr; |
||
10821 | - u32 val; |
||
10822 | - int irq_num; |
||
10823 | -}; |
||
10824 | - |
||
10825 | -int dprc_set_irq(struct fsl_mc_io *mc_io, |
||
10826 | - u32 cmd_flags, |
||
10827 | - u16 token, |
||
10828 | - u8 irq_index, |
||
10829 | - struct dprc_irq_cfg *irq_cfg); |
||
10830 | - |
||
10831 | -int dprc_get_irq(struct fsl_mc_io *mc_io, |
||
10832 | - u32 cmd_flags, |
||
10833 | - u16 token, |
||
10834 | - u8 irq_index, |
||
10835 | - int *type, |
||
10836 | - struct dprc_irq_cfg *irq_cfg); |
||
10837 | - |
||
10838 | -int dprc_set_irq_enable(struct fsl_mc_io *mc_io, |
||
10839 | - u32 cmd_flags, |
||
10840 | - u16 token, |
||
10841 | - u8 irq_index, |
||
10842 | - u8 en); |
||
10843 | - |
||
10844 | -int dprc_get_irq_enable(struct fsl_mc_io *mc_io, |
||
10845 | - u32 cmd_flags, |
||
10846 | - u16 token, |
||
10847 | - u8 irq_index, |
||
10848 | - u8 *en); |
||
10849 | - |
||
10850 | -int dprc_set_irq_mask(struct fsl_mc_io *mc_io, |
||
10851 | - u32 cmd_flags, |
||
10852 | - u16 token, |
||
10853 | - u8 irq_index, |
||
10854 | - u32 mask); |
||
10855 | - |
||
10856 | -int dprc_get_irq_mask(struct fsl_mc_io *mc_io, |
||
10857 | - u32 cmd_flags, |
||
10858 | - u16 token, |
||
10859 | - u8 irq_index, |
||
10860 | - u32 *mask); |
||
10861 | - |
||
10862 | -int dprc_get_irq_status(struct fsl_mc_io *mc_io, |
||
10863 | - u32 cmd_flags, |
||
10864 | - u16 token, |
||
10865 | - u8 irq_index, |
||
10866 | - u32 *status); |
||
10867 | - |
||
10868 | -int dprc_clear_irq_status(struct fsl_mc_io *mc_io, |
||
10869 | - u32 cmd_flags, |
||
10870 | - u16 token, |
||
10871 | - u8 irq_index, |
||
10872 | - u32 status); |
||
10873 | - |
||
10874 | -/** |
||
10875 | - * struct dprc_attributes - Container attributes |
||
10876 | - * @container_id: Container's ID |
||
10877 | - * @icid: Container's ICID |
||
10878 | - * @portal_id: Container's portal ID |
||
10879 | - * @options: Container's options as set at container's creation |
||
10880 | - */ |
||
10881 | -struct dprc_attributes { |
||
10882 | - int container_id; |
||
10883 | - u16 icid; |
||
10884 | - int portal_id; |
||
10885 | - u64 options; |
||
10886 | -}; |
||
10887 | - |
||
10888 | -int dprc_get_attributes(struct fsl_mc_io *mc_io, |
||
10889 | - u32 cmd_flags, |
||
10890 | - u16 token, |
||
10891 | - struct dprc_attributes *attributes); |
||
10892 | - |
||
10893 | -int dprc_get_obj_count(struct fsl_mc_io *mc_io, |
||
10894 | - u32 cmd_flags, |
||
10895 | - u16 token, |
||
10896 | - int *obj_count); |
||
10897 | - |
||
10898 | -int dprc_get_obj(struct fsl_mc_io *mc_io, |
||
10899 | - u32 cmd_flags, |
||
10900 | - u16 token, |
||
10901 | - int obj_index, |
||
10902 | - struct fsl_mc_obj_desc *obj_desc); |
||
10903 | - |
||
10904 | -int dprc_get_obj_desc(struct fsl_mc_io *mc_io, |
||
10905 | - u32 cmd_flags, |
||
10906 | - u16 token, |
||
10907 | - char *obj_type, |
||
10908 | - int obj_id, |
||
10909 | - struct fsl_mc_obj_desc *obj_desc); |
||
10910 | - |
||
10911 | -int dprc_set_obj_irq(struct fsl_mc_io *mc_io, |
||
10912 | - u32 cmd_flags, |
||
10913 | - u16 token, |
||
10914 | - char *obj_type, |
||
10915 | - int obj_id, |
||
10916 | - u8 irq_index, |
||
10917 | - struct dprc_irq_cfg *irq_cfg); |
||
10918 | - |
||
10919 | -int dprc_get_obj_irq(struct fsl_mc_io *mc_io, |
||
10920 | - u32 cmd_flags, |
||
10921 | - u16 token, |
||
10922 | - char *obj_type, |
||
10923 | - int obj_id, |
||
10924 | - u8 irq_index, |
||
10925 | - int *type, |
||
10926 | - struct dprc_irq_cfg *irq_cfg); |
||
10927 | - |
||
10928 | -int dprc_get_res_count(struct fsl_mc_io *mc_io, |
||
10929 | - u32 cmd_flags, |
||
10930 | - u16 token, |
||
10931 | - char *type, |
||
10932 | - int *res_count); |
||
10933 | - |
||
10934 | -/** |
||
10935 | - * enum dprc_iter_status - Iteration status |
||
10936 | - * @DPRC_ITER_STATUS_FIRST: Perform first iteration |
||
10937 | - * @DPRC_ITER_STATUS_MORE: Indicates more/next iteration is needed |
||
10938 | - * @DPRC_ITER_STATUS_LAST: Indicates last iteration |
||
10939 | - */ |
||
10940 | -enum dprc_iter_status { |
||
10941 | - DPRC_ITER_STATUS_FIRST = 0, |
||
10942 | - DPRC_ITER_STATUS_MORE = 1, |
||
10943 | - DPRC_ITER_STATUS_LAST = 2 |
||
10944 | -}; |
||
10945 | - |
||
10946 | -/* Region flags */ |
||
10947 | -/* Cacheable - Indicates that region should be mapped as cacheable */ |
||
10948 | -#define DPRC_REGION_CACHEABLE 0x00000001 |
||
10949 | - |
||
10950 | -/** |
||
10951 | - * enum dprc_region_type - Region type |
||
10952 | - * @DPRC_REGION_TYPE_MC_PORTAL: MC portal region |
||
10953 | - * @DPRC_REGION_TYPE_QBMAN_PORTAL: Qbman portal region |
||
10954 | - */ |
||
10955 | -enum dprc_region_type { |
||
10956 | - DPRC_REGION_TYPE_MC_PORTAL, |
||
10957 | - DPRC_REGION_TYPE_QBMAN_PORTAL |
||
10958 | -}; |
||
10959 | - |
||
10960 | -/** |
||
10961 | - * struct dprc_region_desc - Mappable region descriptor |
||
10962 | - * @base_offset: Region offset from region's base address. |
||
10963 | - * For DPMCP and DPRC objects, region base is offset from SoC MC portals |
||
10964 | - * base address; For DPIO, region base is offset from SoC QMan portals |
||
10965 | - * base address |
||
10966 | - * @size: Region size (in bytes) |
||
10967 | - * @flags: Region attributes |
||
10968 | - * @type: Portal region type |
||
10969 | - */ |
||
10970 | -struct dprc_region_desc { |
||
10971 | - u32 base_offset; |
||
10972 | - u32 size; |
||
10973 | - u32 flags; |
||
10974 | - enum dprc_region_type type; |
||
10975 | -}; |
||
10976 | - |
||
10977 | -int dprc_get_obj_region(struct fsl_mc_io *mc_io, |
||
10978 | - u32 cmd_flags, |
||
10979 | - u16 token, |
||
10980 | - char *obj_type, |
||
10981 | - int obj_id, |
||
10982 | - u8 region_index, |
||
10983 | - struct dprc_region_desc *region_desc); |
||
10984 | - |
||
10985 | -int dprc_get_api_version(struct fsl_mc_io *mc_io, |
||
10986 | - u32 cmd_flags, |
||
10987 | - u16 *major_ver, |
||
10988 | - u16 *minor_ver); |
||
10989 | - |
||
10990 | -int dprc_get_container_id(struct fsl_mc_io *mc_io, |
||
10991 | - u32 cmd_flags, |
||
10992 | - int *container_id); |
||
10993 | - |
||
10994 | -#endif /* _FSL_DPRC_H */ |
||
10995 | - |
||
10996 | --- a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c |
||
10997 | +++ b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c |
||
10998 | @@ -13,6 +13,7 @@ |
||
10999 | #include <linux/msi.h> |
||
11000 | #include <linux/of.h> |
||
11001 | #include <linux/of_irq.h> |
||
11002 | +#include <linux/fsl/mc.h> |
||
11003 | #include "fsl-mc-private.h" |
||
11004 | |||
11005 | static struct irq_chip its_msi_irq_chip = { |
||
11006 | --- /dev/null |
||
11007 | +++ b/include/linux/fsl/mc.h |
||
11008 | @@ -0,0 +1,1020 @@ |
||
11009 | +/* SPDX-License-Identifier: GPL-2.0 */ |
||
11010 | +/* |
||
11011 | + * Freescale Management Complex (MC) bus public interface |
||
11012 | + * |
||
11013 | + * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. |
||
11014 | + * Author: German Rivera <German.Rivera@freescale.com> |
||
11015 | + * |
||
11016 | + */ |
||
11017 | +#ifndef _FSL_MC_H_ |
||
11018 | +#define _FSL_MC_H_ |
||
11019 | + |
||
11020 | +#include <linux/device.h> |
||
11021 | +#include <linux/mod_devicetable.h> |
||
11022 | +#include <linux/interrupt.h> |
||
11023 | +#include <linux/cdev.h> |
||
11024 | +#include <uapi/linux/fsl_mc.h> |
||
11025 | + |
||
11026 | +#define FSL_MC_VENDOR_FREESCALE 0x1957 |
||
11027 | + |
||
11028 | +struct irq_domain; |
||
11029 | +struct msi_domain_info; |
||
11030 | + |
||
11031 | +struct fsl_mc_device; |
||
11032 | +struct fsl_mc_io; |
||
11033 | + |
||
11034 | +/** |
||
11035 | + * struct fsl_mc_driver - MC object device driver object |
||
11036 | + * @driver: Generic device driver |
||
11037 | + * @match_id_table: table of supported device matching Ids |
||
11038 | + * @probe: Function called when a device is added |
||
11039 | + * @remove: Function called when a device is removed |
||
11040 | + * @shutdown: Function called at shutdown time to quiesce the device |
||
11041 | + * @suspend: Function called when a device is stopped |
||
11042 | + * @resume: Function called when a device is resumed |
||
11043 | + * |
||
11044 | + * Generic DPAA device driver object for device drivers that are registered |
||
11045 | + * with a DPRC bus. This structure is to be embedded in each device-specific |
||
11046 | + * driver structure. |
||
11047 | + */ |
||
11048 | +struct fsl_mc_driver { |
||
11049 | + struct device_driver driver; |
||
11050 | + const struct fsl_mc_device_id *match_id_table; |
||
11051 | + int (*probe)(struct fsl_mc_device *dev); |
||
11052 | + int (*remove)(struct fsl_mc_device *dev); |
||
11053 | + void (*shutdown)(struct fsl_mc_device *dev); |
||
11054 | + int (*suspend)(struct fsl_mc_device *dev, pm_message_t state); |
||
11055 | + int (*resume)(struct fsl_mc_device *dev); |
||
11056 | +}; |
||
11057 | + |
||
11058 | +#define to_fsl_mc_driver(_drv) \ |
||
11059 | + container_of(_drv, struct fsl_mc_driver, driver) |
||
11060 | + |
||
11061 | +#define to_fsl_mc_bus(_mc_dev) \ |
||
11062 | + container_of(_mc_dev, struct fsl_mc_bus, mc_dev) |
||
11063 | + |
||
11064 | +/** |
||
11065 | + * enum fsl_mc_pool_type - Types of allocatable MC bus resources |
||
11066 | + * |
||
11067 | + * Entries in these enum are used as indices in the array of resource |
||
11068 | + * pools of an fsl_mc_bus object. |
||
11069 | + */ |
||
11070 | +enum fsl_mc_pool_type { |
||
11071 | + FSL_MC_POOL_DPMCP = 0x0, /* corresponds to "dpmcp" in the MC */ |
||
11072 | + FSL_MC_POOL_DPBP, /* corresponds to "dpbp" in the MC */ |
||
11073 | + FSL_MC_POOL_DPCON, /* corresponds to "dpcon" in the MC */ |
||
11074 | + FSL_MC_POOL_IRQ, |
||
11075 | + |
||
11076 | + /* |
||
11077 | + * NOTE: New resource pool types must be added before this entry |
||
11078 | + */ |
||
11079 | + FSL_MC_NUM_POOL_TYPES |
||
11080 | +}; |
||
11081 | + |
||
11082 | +/** |
||
11083 | + * struct fsl_mc_resource - MC generic resource |
||
11084 | + * @type: type of resource |
||
11085 | + * @id: unique MC resource Id within the resources of the same type |
||
11086 | + * @data: pointer to resource-specific data if the resource is currently |
||
11087 | + * allocated, or NULL if the resource is not currently allocated. |
||
11088 | + * @parent_pool: pointer to the parent resource pool from which this |
||
11089 | + * resource is allocated from. |
||
11090 | + * @node: Node in the free list of the corresponding resource pool |
||
11091 | + * |
||
11092 | + * NOTE: This structure is to be embedded as a field of specific |
||
11093 | + * MC resource structures. |
||
11094 | + */ |
||
11095 | +struct fsl_mc_resource { |
||
11096 | + enum fsl_mc_pool_type type; |
||
11097 | + s32 id; |
||
11098 | + void *data; |
||
11099 | + struct fsl_mc_resource_pool *parent_pool; |
||
11100 | + struct list_head node; |
||
11101 | +}; |
||
11102 | + |
||
11103 | +/** |
||
11104 | + * struct fsl_mc_device_irq - MC object device message-based interrupt |
||
11105 | + * @msi_desc: pointer to MSI descriptor allocated by fsl_mc_msi_alloc_descs() |
||
11106 | + * @mc_dev: MC object device that owns this interrupt |
||
11107 | + * @dev_irq_index: device-relative IRQ index |
||
11108 | + * @resource: MC generic resource associated with the interrupt |
||
11109 | + */ |
||
11110 | +struct fsl_mc_device_irq { |
||
11111 | + struct msi_desc *msi_desc; |
||
11112 | + struct fsl_mc_device *mc_dev; |
||
11113 | + u8 dev_irq_index; |
||
11114 | + struct fsl_mc_resource resource; |
||
11115 | +}; |
||
11116 | + |
||
11117 | +#define to_fsl_mc_irq(_mc_resource) \ |
||
11118 | + container_of(_mc_resource, struct fsl_mc_device_irq, resource) |
||
11119 | + |
||
11120 | +/* Opened state - Indicates that an object is open by at least one owner */ |
||
11121 | +#define FSL_MC_OBJ_STATE_OPEN 0x00000001 |
||
11122 | +/* Plugged state - Indicates that the object is plugged */ |
||
11123 | +#define FSL_MC_OBJ_STATE_PLUGGED 0x00000002 |
||
11124 | + |
||
11125 | +/** |
||
11126 | + * Shareability flag - Object flag indicating no memory shareability. |
||
11127 | + * the object generates memory accesses that are non coherent with other |
||
11128 | + * masters; |
||
11129 | + * user is responsible for proper memory handling through IOMMU configuration. |
||
11130 | + */ |
||
11131 | +#define FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY 0x0001 |
||
11132 | + |
||
11133 | +/** |
||
11134 | + * struct fsl_mc_obj_desc - Object descriptor |
||
11135 | + * @type: Type of object: NULL terminated string |
||
11136 | + * @id: ID of logical object resource |
||
11137 | + * @vendor: Object vendor identifier |
||
11138 | + * @ver_major: Major version number |
||
11139 | + * @ver_minor: Minor version number |
||
11140 | + * @irq_count: Number of interrupts supported by the object |
||
11141 | + * @region_count: Number of mappable regions supported by the object |
||
11142 | + * @state: Object state: combination of FSL_MC_OBJ_STATE_ states |
||
11143 | + * @label: Object label: NULL terminated string |
||
11144 | + * @flags: Object's flags |
||
11145 | + */ |
||
11146 | +struct fsl_mc_obj_desc { |
||
11147 | + char type[16]; |
||
11148 | + int id; |
||
11149 | + u16 vendor; |
||
11150 | + u16 ver_major; |
||
11151 | + u16 ver_minor; |
||
11152 | + u8 irq_count; |
||
11153 | + u8 region_count; |
||
11154 | + u32 state; |
||
11155 | + char label[16]; |
||
11156 | + u16 flags; |
||
11157 | +}; |
||
11158 | + |
||
11159 | +/** |
||
11160 | + * Bit masks for a MC object device (struct fsl_mc_device) flags |
||
11161 | + */ |
||
11162 | +#define FSL_MC_IS_DPRC 0x0001 |
||
11163 | + |
||
11164 | +/** |
||
11165 | + * struct fsl_mc_device - MC object device object |
||
11166 | + * @dev: Linux driver model device object |
||
11167 | + * @dma_mask: Default DMA mask |
||
11168 | + * @flags: MC object device flags |
||
11169 | + * @icid: Isolation context ID for the device |
||
11170 | + * @mc_handle: MC handle for the corresponding MC object opened |
||
11171 | + * @mc_io: Pointer to MC IO object assigned to this device or |
||
11172 | + * NULL if none. |
||
11173 | + * @obj_desc: MC description of the DPAA device |
||
11174 | + * @regions: pointer to array of MMIO region entries |
||
11175 | + * @irqs: pointer to array of pointers to interrupts allocated to this device |
||
11176 | + * @resource: generic resource associated with this MC object device, if any. |
||
11177 | + * @driver_override: Driver name to force a match |
||
11178 | + * |
||
11179 | + * Generic device object for MC object devices that are "attached" to a |
||
11180 | + * MC bus. |
||
11181 | + * |
||
11182 | + * NOTES: |
||
11183 | + * - For a non-DPRC object its icid is the same as its parent DPRC's icid. |
||
11184 | + * - The SMMU notifier callback gets invoked after device_add() has been |
||
11185 | + * called for an MC object device, but before the device-specific probe |
||
11186 | + * callback gets called. |
||
11187 | + * - DP_OBJ_DPRC objects are the only MC objects that have built-in MC |
||
11188 | + * portals. For all other MC objects, their device drivers are responsible for |
||
11189 | + * allocating MC portals for them by calling fsl_mc_portal_allocate(). |
||
11190 | + * - Some types of MC objects (e.g., DP_OBJ_DPBP, DP_OBJ_DPCON) are |
||
11191 | + * treated as resources that can be allocated/deallocated from the |
||
11192 | + * corresponding resource pool in the object's parent DPRC, using the |
||
11193 | + * fsl_mc_object_allocate()/fsl_mc_object_free() functions. These MC objects |
||
11194 | + * are known as "allocatable" objects. For them, the corresponding |
||
11195 | + * fsl_mc_device's 'resource' points to the associated resource object. |
||
11196 | + * For MC objects that are not allocatable (e.g., DP_OBJ_DPRC, DP_OBJ_DPNI), |
||
11197 | + * 'resource' is NULL. |
||
11198 | + */ |
||
11199 | +struct fsl_mc_device { |
||
11200 | + struct device dev; |
||
11201 | + u64 dma_mask; |
||
11202 | + u16 flags; |
||
11203 | + u32 icid; |
||
11204 | + u16 mc_handle; |
||
11205 | + struct fsl_mc_io *mc_io; |
||
11206 | + struct fsl_mc_obj_desc obj_desc; |
||
11207 | + struct resource *regions; |
||
11208 | + struct fsl_mc_device_irq **irqs; |
||
11209 | + struct fsl_mc_resource *resource; |
||
11210 | + const char *driver_override; |
||
11211 | +}; |
||
11212 | + |
||
11213 | +#define to_fsl_mc_device(_dev) \ |
||
11214 | + container_of(_dev, struct fsl_mc_device, dev) |
||
11215 | + |
||
11216 | +struct mc_cmd_header { |
||
11217 | + u8 src_id; |
||
11218 | + u8 flags_hw; |
||
11219 | + u8 status; |
||
11220 | + u8 flags_sw; |
||
11221 | + __le16 token; |
||
11222 | + __le16 cmd_id; |
||
11223 | +}; |
||
11224 | + |
||
11225 | +enum mc_cmd_status { |
||
11226 | + MC_CMD_STATUS_OK = 0x0, /* Completed successfully */ |
||
11227 | + MC_CMD_STATUS_READY = 0x1, /* Ready to be processed */ |
||
11228 | + MC_CMD_STATUS_AUTH_ERR = 0x3, /* Authentication error */ |
||
11229 | + MC_CMD_STATUS_NO_PRIVILEGE = 0x4, /* No privilege */ |
||
11230 | + MC_CMD_STATUS_DMA_ERR = 0x5, /* DMA or I/O error */ |
||
11231 | + MC_CMD_STATUS_CONFIG_ERR = 0x6, /* Configuration error */ |
||
11232 | + MC_CMD_STATUS_TIMEOUT = 0x7, /* Operation timed out */ |
||
11233 | + MC_CMD_STATUS_NO_RESOURCE = 0x8, /* No resources */ |
||
11234 | + MC_CMD_STATUS_NO_MEMORY = 0x9, /* No memory available */ |
||
11235 | + MC_CMD_STATUS_BUSY = 0xA, /* Device is busy */ |
||
11236 | + MC_CMD_STATUS_UNSUPPORTED_OP = 0xB, /* Unsupported operation */ |
||
11237 | + MC_CMD_STATUS_INVALID_STATE = 0xC /* Invalid state */ |
||
11238 | +}; |
||
11239 | + |
||
11240 | +/* |
||
11241 | + * MC command flags |
||
11242 | + */ |
||
11243 | + |
||
11244 | +/* High priority flag */ |
||
11245 | +#define MC_CMD_FLAG_PRI 0x80 |
||
11246 | +/* Command completion flag */ |
||
11247 | +#define MC_CMD_FLAG_INTR_DIS 0x01 |
||
11248 | + |
||
11249 | +static inline u64 mc_encode_cmd_header(u16 cmd_id, |
||
11250 | + u32 cmd_flags, |
||
11251 | + u16 token) |
||
11252 | +{ |
||
11253 | + u64 header = 0; |
||
11254 | + struct mc_cmd_header *hdr = (struct mc_cmd_header *)&header; |
||
11255 | + |
||
11256 | + hdr->cmd_id = cpu_to_le16(cmd_id); |
||
11257 | + hdr->token = cpu_to_le16(token); |
||
11258 | + hdr->status = MC_CMD_STATUS_READY; |
||
11259 | + if (cmd_flags & MC_CMD_FLAG_PRI) |
||
11260 | + hdr->flags_hw = MC_CMD_FLAG_PRI; |
||
11261 | + if (cmd_flags & MC_CMD_FLAG_INTR_DIS) |
||
11262 | + hdr->flags_sw = MC_CMD_FLAG_INTR_DIS; |
||
11263 | + |
||
11264 | + return header; |
||
11265 | +} |
||
11266 | + |
||
11267 | +static inline u16 mc_cmd_hdr_read_token(struct fsl_mc_command *cmd) |
||
11268 | +{ |
||
11269 | + struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header; |
||
11270 | + u16 token = le16_to_cpu(hdr->token); |
||
11271 | + |
||
11272 | + return token; |
||
11273 | +} |
||
11274 | + |
||
11275 | +struct mc_rsp_create { |
||
11276 | + __le32 object_id; |
||
11277 | +}; |
||
11278 | + |
||
11279 | +struct mc_rsp_api_ver { |
||
11280 | + __le16 major_ver; |
||
11281 | + __le16 minor_ver; |
||
11282 | +}; |
||
11283 | + |
||
11284 | +static inline u32 mc_cmd_read_object_id(struct fsl_mc_command *cmd) |
||
11285 | +{ |
||
11286 | + struct mc_rsp_create *rsp_params; |
||
11287 | + |
||
11288 | + rsp_params = (struct mc_rsp_create *)cmd->params; |
||
11289 | + return le32_to_cpu(rsp_params->object_id); |
||
11290 | +} |
||
11291 | + |
||
11292 | +static inline void mc_cmd_read_api_version(struct fsl_mc_command *cmd, |
||
11293 | + u16 *major_ver, |
||
11294 | + u16 *minor_ver) |
||
11295 | +{ |
||
11296 | + struct mc_rsp_api_ver *rsp_params; |
||
11297 | + |
||
11298 | + rsp_params = (struct mc_rsp_api_ver *)cmd->params; |
||
11299 | + *major_ver = le16_to_cpu(rsp_params->major_ver); |
||
11300 | + *minor_ver = le16_to_cpu(rsp_params->minor_ver); |
||
11301 | +} |
||
11302 | + |
||
11303 | +/** |
||
11304 | + * Bit masks for a MC I/O object (struct fsl_mc_io) flags |
||
11305 | + */ |
||
11306 | +#define FSL_MC_IO_ATOMIC_CONTEXT_PORTAL 0x0001 |
||
11307 | + |
||
11308 | +/** |
||
11309 | + * struct fsl_mc_io - MC I/O object to be passed-in to mc_send_command() |
||
11310 | + * @dev: device associated with this Mc I/O object |
||
11311 | + * @flags: flags for mc_send_command() |
||
11312 | + * @portal_size: MC command portal size in bytes |
||
11313 | + * @portal_phys_addr: MC command portal physical address |
||
11314 | + * @portal_virt_addr: MC command portal virtual address |
||
11315 | + * @dpmcp_dev: pointer to the DPMCP device associated with the MC portal. |
||
11316 | + * |
||
11317 | + * Fields are only meaningful if the FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is not |
||
11318 | + * set: |
||
11319 | + * @mutex: Mutex to serialize mc_send_command() calls that use the same MC |
||
11320 | + * portal, if the fsl_mc_io object was created with the |
||
11321 | + * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag off. mc_send_command() calls for this |
||
11322 | + * fsl_mc_io object must be made only from non-atomic context. |
||
11323 | + * |
||
11324 | + * Fields are only meaningful if the FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is |
||
11325 | + * set: |
||
11326 | + * @spinlock: Spinlock to serialize mc_send_command() calls that use the same MC |
||
11327 | + * portal, if the fsl_mc_io object was created with the |
||
11328 | + * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag on. mc_send_command() calls for this |
||
11329 | + * fsl_mc_io object can be made from atomic or non-atomic context. |
||
11330 | + */ |
||
11331 | +struct fsl_mc_io { |
||
11332 | + struct device *dev; |
||
11333 | + u16 flags; |
||
11334 | + u32 portal_size; |
||
11335 | + phys_addr_t portal_phys_addr; |
||
11336 | + void __iomem *portal_virt_addr; |
||
11337 | + struct fsl_mc_device *dpmcp_dev; |
||
11338 | + union { |
||
11339 | + /* |
||
11340 | + * This field is only meaningful if the |
||
11341 | + * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is not set |
||
11342 | + */ |
||
11343 | + struct mutex mutex; /* serializes mc_send_command() */ |
||
11344 | + |
||
11345 | + /* |
||
11346 | + * This field is only meaningful if the |
||
11347 | + * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is set |
||
11348 | + */ |
||
11349 | + spinlock_t spinlock; /* serializes mc_send_command() */ |
||
11350 | + }; |
||
11351 | +}; |
||
11352 | + |
||
11353 | +int mc_send_command(struct fsl_mc_io *mc_io, struct fsl_mc_command *cmd); |
||
11354 | + |
||
11355 | +#ifdef CONFIG_FSL_MC_BUS |
||
11356 | +#define dev_is_fsl_mc(_dev) ((_dev)->bus == &fsl_mc_bus_type) |
||
11357 | +#else |
||
11358 | +/* If fsl-mc bus is not present device cannot belong to fsl-mc bus */ |
||
11359 | +#define dev_is_fsl_mc(_dev) (0) |
||
11360 | +#endif |
||
11361 | + |
||
11362 | +/* Macro to check if a device is a container device */ |
||
11363 | +#define fsl_mc_is_cont_dev(_dev) (to_fsl_mc_device(_dev)->flags & \ |
||
11364 | + FSL_MC_IS_DPRC) |
||
11365 | + |
||
11366 | +/* Macro to get the container device of a MC device */ |
||
11367 | +#define fsl_mc_cont_dev(_dev) (fsl_mc_is_cont_dev(_dev) ? \ |
||
11368 | + (_dev) : (_dev)->parent) |
||
11369 | + |
||
11370 | +#define fsl_mc_is_dev_coherent(_dev) \ |
||
11371 | + (!((to_fsl_mc_device(_dev))->obj_desc.flags & \ |
||
11372 | + FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY)) |
||
11373 | + |
||
11374 | +/* |
||
11375 | + * module_fsl_mc_driver() - Helper macro for drivers that don't do |
||
11376 | + * anything special in module init/exit. This eliminates a lot of |
||
11377 | + * boilerplate. Each module may only use this macro once, and |
||
11378 | + * calling it replaces module_init() and module_exit() |
||
11379 | + */ |
||
11380 | +#define module_fsl_mc_driver(__fsl_mc_driver) \ |
||
11381 | + module_driver(__fsl_mc_driver, fsl_mc_driver_register, \ |
||
11382 | + fsl_mc_driver_unregister) |
||
11383 | + |
||
11384 | +void fsl_mc_device_remove(struct fsl_mc_device *mc_dev); |
||
11385 | + |
||
11386 | +/* |
||
11387 | + * Macro to avoid include chaining to get THIS_MODULE |
||
11388 | + */ |
||
11389 | +#define fsl_mc_driver_register(drv) \ |
||
11390 | + __fsl_mc_driver_register(drv, THIS_MODULE) |
||
11391 | + |
||
11392 | +int __must_check __fsl_mc_driver_register(struct fsl_mc_driver *fsl_mc_driver, |
||
11393 | + struct module *owner); |
||
11394 | + |
||
11395 | +void fsl_mc_driver_unregister(struct fsl_mc_driver *driver); |
||
11396 | + |
||
11397 | +int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, |
||
11398 | + u16 mc_io_flags, |
||
11399 | + struct fsl_mc_io **new_mc_io); |
||
11400 | + |
||
11401 | +void fsl_mc_portal_free(struct fsl_mc_io *mc_io); |
||
11402 | + |
||
11403 | +int fsl_mc_portal_reset(struct fsl_mc_io *mc_io); |
||
11404 | + |
||
11405 | +int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev, |
||
11406 | + enum fsl_mc_pool_type pool_type, |
||
11407 | + struct fsl_mc_device **new_mc_adev); |
||
11408 | + |
||
11409 | +void fsl_mc_object_free(struct fsl_mc_device *mc_adev); |
||
11410 | + |
||
11411 | +struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode, |
||
11412 | + struct msi_domain_info *info, |
||
11413 | + struct irq_domain *parent); |
||
11414 | + |
||
11415 | +int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev); |
||
11416 | + |
||
11417 | +void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev); |
||
11418 | + |
||
11419 | +extern struct bus_type fsl_mc_bus_type; |
||
11420 | + |
||
11421 | +extern struct device_type fsl_mc_bus_dprc_type; |
||
11422 | +extern struct device_type fsl_mc_bus_dpni_type; |
||
11423 | +extern struct device_type fsl_mc_bus_dpio_type; |
||
11424 | +extern struct device_type fsl_mc_bus_dpsw_type; |
||
11425 | +extern struct device_type fsl_mc_bus_dpdmux_type; |
||
11426 | +extern struct device_type fsl_mc_bus_dpbp_type; |
||
11427 | +extern struct device_type fsl_mc_bus_dpcon_type; |
||
11428 | +extern struct device_type fsl_mc_bus_dpmcp_type; |
||
11429 | +extern struct device_type fsl_mc_bus_dpmac_type; |
||
11430 | +extern struct device_type fsl_mc_bus_dprtc_type; |
||
11431 | +extern struct device_type fsl_mc_bus_dpseci_type; |
||
11432 | +extern struct device_type fsl_mc_bus_dpdcei_type; |
||
11433 | +extern struct device_type fsl_mc_bus_dpaiop_type; |
||
11434 | +extern struct device_type fsl_mc_bus_dpci_type; |
||
11435 | +extern struct device_type fsl_mc_bus_dpdmai_type; |
||
11436 | + |
||
11437 | +static inline bool is_fsl_mc_bus_dprc(const struct fsl_mc_device *mc_dev) |
||
11438 | +{ |
||
11439 | + return mc_dev->dev.type == &fsl_mc_bus_dprc_type; |
||
11440 | +} |
||
11441 | + |
||
11442 | +static inline bool is_fsl_mc_bus_dpni(const struct fsl_mc_device *mc_dev) |
||
11443 | +{ |
||
11444 | + return mc_dev->dev.type == &fsl_mc_bus_dpni_type; |
||
11445 | +} |
||
11446 | + |
||
11447 | +static inline bool is_fsl_mc_bus_dpio(const struct fsl_mc_device *mc_dev) |
||
11448 | +{ |
||
11449 | + return mc_dev->dev.type == &fsl_mc_bus_dpio_type; |
||
11450 | +} |
||
11451 | + |
||
11452 | +static inline bool is_fsl_mc_bus_dpsw(const struct fsl_mc_device *mc_dev) |
||
11453 | +{ |
||
11454 | + return mc_dev->dev.type == &fsl_mc_bus_dpsw_type; |
||
11455 | +} |
||
11456 | + |
||
11457 | +static inline bool is_fsl_mc_bus_dpdmux(const struct fsl_mc_device *mc_dev) |
||
11458 | +{ |
||
11459 | + return mc_dev->dev.type == &fsl_mc_bus_dpdmux_type; |
||
11460 | +} |
||
11461 | + |
||
11462 | +static inline bool is_fsl_mc_bus_dpbp(const struct fsl_mc_device *mc_dev) |
||
11463 | +{ |
||
11464 | + return mc_dev->dev.type == &fsl_mc_bus_dpbp_type; |
||
11465 | +} |
||
11466 | + |
||
11467 | +static inline bool is_fsl_mc_bus_dpcon(const struct fsl_mc_device *mc_dev) |
||
11468 | +{ |
||
11469 | + return mc_dev->dev.type == &fsl_mc_bus_dpcon_type; |
||
11470 | +} |
||
11471 | + |
||
11472 | +static inline bool is_fsl_mc_bus_dpmcp(const struct fsl_mc_device *mc_dev) |
||
11473 | +{ |
||
11474 | + return mc_dev->dev.type == &fsl_mc_bus_dpmcp_type; |
||
11475 | +} |
||
11476 | + |
||
11477 | +static inline bool is_fsl_mc_bus_dpmac(const struct fsl_mc_device *mc_dev) |
||
11478 | +{ |
||
11479 | + return mc_dev->dev.type == &fsl_mc_bus_dpmac_type; |
||
11480 | +} |
||
11481 | + |
||
11482 | +static inline bool is_fsl_mc_bus_dprtc(const struct fsl_mc_device *mc_dev) |
||
11483 | +{ |
||
11484 | + return mc_dev->dev.type == &fsl_mc_bus_dprtc_type; |
||
11485 | +} |
||
11486 | + |
||
11487 | +static inline bool is_fsl_mc_bus_dpseci(const struct fsl_mc_device *mc_dev) |
||
11488 | +{ |
||
11489 | + return mc_dev->dev.type == &fsl_mc_bus_dpseci_type; |
||
11490 | +} |
||
11491 | + |
||
11492 | +static inline bool is_fsl_mc_bus_dpdcei(const struct fsl_mc_device *mc_dev) |
||
11493 | +{ |
||
11494 | + return mc_dev->dev.type == &fsl_mc_bus_dpdcei_type; |
||
11495 | +} |
||
11496 | + |
||
11497 | +static inline bool is_fsl_mc_bus_dpaiop(const struct fsl_mc_device *mc_dev) |
||
11498 | +{ |
||
11499 | + return mc_dev->dev.type == &fsl_mc_bus_dpaiop_type; |
||
11500 | +} |
||
11501 | + |
||
11502 | +static inline bool is_fsl_mc_bus_dpci(const struct fsl_mc_device *mc_dev) |
||
11503 | +{ |
||
11504 | + return mc_dev->dev.type == &fsl_mc_bus_dpci_type; |
||
11505 | +} |
||
11506 | + |
||
11507 | +static inline bool is_fsl_mc_bus_dpdmai(const struct fsl_mc_device *mc_dev) |
||
11508 | +{ |
||
11509 | + return mc_dev->dev.type == &fsl_mc_bus_dpdmai_type; |
||
11510 | +} |
||
11511 | + |
||
11512 | +/* |
||
11513 | + * Data Path Resource Container (DPRC) API |
||
11514 | + */ |
||
11515 | + |
||
11516 | +/* Minimal supported DPRC Version */ |
||
11517 | +#define DPRC_MIN_VER_MAJOR 6 |
||
11518 | +#define DPRC_MIN_VER_MINOR 0 |
||
11519 | + |
||
11520 | +/* DPRC command versioning */ |
||
11521 | +#define DPRC_CMD_BASE_VERSION 1 |
||
11522 | +#define DPRC_CMD_ID_OFFSET 4 |
||
11523 | + |
||
11524 | +#define DPRC_CMD(id) (((id) << DPRC_CMD_ID_OFFSET) | DPRC_CMD_BASE_VERSION) |
||
11525 | + |
||
11526 | +/* DPRC command IDs */ |
||
11527 | +#define DPRC_CMDID_CLOSE DPRC_CMD(0x800) |
||
11528 | +#define DPRC_CMDID_OPEN DPRC_CMD(0x805) |
||
11529 | +#define DPRC_CMDID_GET_API_VERSION DPRC_CMD(0xa05) |
||
11530 | + |
||
11531 | +#define DPRC_CMDID_GET_ATTR DPRC_CMD(0x004) |
||
11532 | +#define DPRC_CMDID_RESET_CONT DPRC_CMD(0x005) |
||
11533 | + |
||
11534 | +#define DPRC_CMDID_SET_IRQ DPRC_CMD(0x010) |
||
11535 | +#define DPRC_CMDID_SET_IRQ_ENABLE DPRC_CMD(0x012) |
||
11536 | +#define DPRC_CMDID_SET_IRQ_MASK DPRC_CMD(0x014) |
||
11537 | +#define DPRC_CMDID_GET_IRQ_STATUS DPRC_CMD(0x016) |
||
11538 | +#define DPRC_CMDID_CLEAR_IRQ_STATUS DPRC_CMD(0x017) |
||
11539 | + |
||
11540 | +#define DPRC_CMDID_GET_CONT_ID DPRC_CMD(0x830) |
||
11541 | +#define DPRC_CMDID_GET_OBJ_COUNT DPRC_CMD(0x159) |
||
11542 | +#define DPRC_CMDID_GET_OBJ DPRC_CMD(0x15A) |
||
11543 | +#define DPRC_CMDID_GET_OBJ_REG DPRC_CMD(0x15E) |
||
11544 | +#define DPRC_CMDID_SET_OBJ_IRQ DPRC_CMD(0x15F) |
||
11545 | + |
||
11546 | +struct dprc_cmd_open { |
||
11547 | + __le32 container_id; |
||
11548 | +}; |
||
11549 | + |
||
11550 | +struct dprc_cmd_reset_container { |
||
11551 | + __le32 child_container_id; |
||
11552 | +}; |
||
11553 | + |
||
11554 | +struct dprc_cmd_set_irq { |
||
11555 | + /* cmd word 0 */ |
||
11556 | + __le32 irq_val; |
||
11557 | + u8 irq_index; |
||
11558 | + u8 pad[3]; |
||
11559 | + /* cmd word 1 */ |
||
11560 | + __le64 irq_addr; |
||
11561 | + /* cmd word 2 */ |
||
11562 | + __le32 irq_num; |
||
11563 | +}; |
||
11564 | + |
||
11565 | +#define DPRC_ENABLE 0x1 |
||
11566 | + |
||
11567 | +struct dprc_cmd_set_irq_enable { |
||
11568 | + u8 enable; |
||
11569 | + u8 pad[3]; |
||
11570 | + u8 irq_index; |
||
11571 | +}; |
||
11572 | + |
||
11573 | +struct dprc_cmd_set_irq_mask { |
||
11574 | + __le32 mask; |
||
11575 | + u8 irq_index; |
||
11576 | +}; |
||
11577 | + |
||
11578 | +struct dprc_cmd_get_irq_status { |
||
11579 | + __le32 status; |
||
11580 | + u8 irq_index; |
||
11581 | +}; |
||
11582 | + |
||
11583 | +struct dprc_rsp_get_irq_status { |
||
11584 | + __le32 status; |
||
11585 | +}; |
||
11586 | + |
||
11587 | +struct dprc_cmd_clear_irq_status { |
||
11588 | + __le32 status; |
||
11589 | + u8 irq_index; |
||
11590 | +}; |
||
11591 | + |
||
11592 | +struct dprc_rsp_get_attributes { |
||
11593 | + /* response word 0 */ |
||
11594 | + __le32 container_id; |
||
11595 | + __le32 icid; |
||
11596 | + /* response word 1 */ |
||
11597 | + __le32 options; |
||
11598 | + __le32 portal_id; |
||
11599 | +}; |
||
11600 | + |
||
11601 | +struct dprc_rsp_get_obj_count { |
||
11602 | + __le32 pad; |
||
11603 | + __le32 obj_count; |
||
11604 | +}; |
||
11605 | + |
||
11606 | +struct dprc_cmd_get_obj { |
||
11607 | + __le32 obj_index; |
||
11608 | +}; |
||
11609 | + |
||
11610 | +struct dprc_rsp_get_obj { |
||
11611 | + /* response word 0 */ |
||
11612 | + __le32 pad0; |
||
11613 | + __le32 id; |
||
11614 | + /* response word 1 */ |
||
11615 | + __le16 vendor; |
||
11616 | + u8 irq_count; |
||
11617 | + u8 region_count; |
||
11618 | + __le32 state; |
||
11619 | + /* response word 2 */ |
||
11620 | + __le16 version_major; |
||
11621 | + __le16 version_minor; |
||
11622 | + __le16 flags; |
||
11623 | + __le16 pad1; |
||
11624 | + /* response word 3-4 */ |
||
11625 | + u8 type[16]; |
||
11626 | + /* response word 5-6 */ |
||
11627 | + u8 label[16]; |
||
11628 | +}; |
||
11629 | + |
||
11630 | +struct dprc_cmd_get_obj_region { |
||
11631 | + /* cmd word 0 */ |
||
11632 | + __le32 obj_id; |
||
11633 | + __le16 pad0; |
||
11634 | + u8 region_index; |
||
11635 | + u8 pad1; |
||
11636 | + /* cmd word 1-2 */ |
||
11637 | + __le64 pad2[2]; |
||
11638 | + /* cmd word 3-4 */ |
||
11639 | + u8 obj_type[16]; |
||
11640 | +}; |
||
11641 | + |
||
11642 | +struct dprc_rsp_get_obj_region { |
||
11643 | + /* response word 0 */ |
||
11644 | + __le64 pad0; |
||
11645 | + /* response word 1 */ |
||
11646 | + __le32 base_addr; |
||
11647 | + __le32 pad1; |
||
11648 | + /* response word 2 */ |
||
11649 | + __le32 size; |
||
11650 | + u8 type; |
||
11651 | + u8 pad2[3]; |
||
11652 | + /* response word 3 */ |
||
11653 | + __le32 flags; |
||
11654 | +}; |
||
11655 | + |
||
11656 | +struct dprc_cmd_set_obj_irq { |
||
11657 | + /* cmd word 0 */ |
||
11658 | + __le32 irq_val; |
||
11659 | + u8 irq_index; |
||
11660 | + u8 pad[3]; |
||
11661 | + /* cmd word 1 */ |
||
11662 | + __le64 irq_addr; |
||
11663 | + /* cmd word 2 */ |
||
11664 | + __le32 irq_num; |
||
11665 | + __le32 obj_id; |
||
11666 | + /* cmd word 3-4 */ |
||
11667 | + u8 obj_type[16]; |
||
11668 | +}; |
||
11669 | + |
||
11670 | +/* |
||
11671 | + * DPRC API for managing and querying DPAA resources |
||
11672 | + */ |
||
11673 | +int dprc_open(struct fsl_mc_io *mc_io, |
||
11674 | + u32 cmd_flags, |
||
11675 | + int container_id, |
||
11676 | + u16 *token); |
||
11677 | + |
||
11678 | +int dprc_close(struct fsl_mc_io *mc_io, |
||
11679 | + u32 cmd_flags, |
||
11680 | + u16 token); |
||
11681 | + |
||
11682 | +/* DPRC IRQ events */ |
||
11683 | + |
||
11684 | +/* IRQ event - Indicates that a new object added to the container */ |
||
11685 | +#define DPRC_IRQ_EVENT_OBJ_ADDED 0x00000001 |
||
11686 | +/* IRQ event - Indicates that an object was removed from the container */ |
||
11687 | +#define DPRC_IRQ_EVENT_OBJ_REMOVED 0x00000002 |
||
11688 | +/* |
||
11689 | + * IRQ event - Indicates that one of the descendant containers that opened by |
||
11690 | + * this container is destroyed |
||
11691 | + */ |
||
11692 | +#define DPRC_IRQ_EVENT_CONTAINER_DESTROYED 0x00000010 |
||
11693 | + |
||
11694 | +/* |
||
11695 | + * IRQ event - Indicates that on one of the container's opened object is |
||
11696 | + * destroyed |
||
11697 | + */ |
||
11698 | +#define DPRC_IRQ_EVENT_OBJ_DESTROYED 0x00000020 |
||
11699 | + |
||
11700 | +/* Irq event - Indicates that object is created at the container */ |
||
11701 | +#define DPRC_IRQ_EVENT_OBJ_CREATED 0x00000040 |
||
11702 | + |
||
11703 | +/** |
||
11704 | + * struct dprc_irq_cfg - IRQ configuration |
||
11705 | + * @paddr: Address that must be written to signal a message-based interrupt |
||
11706 | + * @val: Value to write into irq_addr address |
||
11707 | + * @irq_num: A user defined number associated with this IRQ |
||
11708 | + */ |
||
11709 | +struct dprc_irq_cfg { |
||
11710 | + phys_addr_t paddr; |
||
11711 | + u32 val; |
||
11712 | + int irq_num; |
||
11713 | +}; |
||
11714 | + |
||
11715 | +int dprc_set_irq(struct fsl_mc_io *mc_io, |
||
11716 | + u32 cmd_flags, |
||
11717 | + u16 token, |
||
11718 | + u8 irq_index, |
||
11719 | + struct dprc_irq_cfg *irq_cfg); |
||
11720 | + |
||
11721 | +int dprc_set_irq_enable(struct fsl_mc_io *mc_io, |
||
11722 | + u32 cmd_flags, |
||
11723 | + u16 token, |
||
11724 | + u8 irq_index, |
||
11725 | + u8 en); |
||
11726 | + |
||
11727 | +int dprc_set_irq_mask(struct fsl_mc_io *mc_io, |
||
11728 | + u32 cmd_flags, |
||
11729 | + u16 token, |
||
11730 | + u8 irq_index, |
||
11731 | + u32 mask); |
||
11732 | + |
||
11733 | +int dprc_get_irq_status(struct fsl_mc_io *mc_io, |
||
11734 | + u32 cmd_flags, |
||
11735 | + u16 token, |
||
11736 | + u8 irq_index, |
||
11737 | + u32 *status); |
||
11738 | + |
||
11739 | +int dprc_clear_irq_status(struct fsl_mc_io *mc_io, |
||
11740 | + u32 cmd_flags, |
||
11741 | + u16 token, |
||
11742 | + u8 irq_index, |
||
11743 | + u32 status); |
||
11744 | + |
||
11745 | +/** |
||
11746 | + * struct dprc_attributes - Container attributes |
||
11747 | + * @container_id: Container's ID |
||
11748 | + * @icid: Container's ICID |
||
11749 | + * @portal_id: Container's portal ID |
||
11750 | + * @options: Container's options as set at container's creation |
||
11751 | + */ |
||
11752 | +struct dprc_attributes { |
||
11753 | + int container_id; |
||
11754 | + u32 icid; |
||
11755 | + int portal_id; |
||
11756 | + u64 options; |
||
11757 | +}; |
||
11758 | + |
||
11759 | +int dprc_get_attributes(struct fsl_mc_io *mc_io, |
||
11760 | + u32 cmd_flags, |
||
11761 | + u16 token, |
||
11762 | + struct dprc_attributes *attributes); |
||
11763 | + |
||
11764 | +int dprc_get_obj_count(struct fsl_mc_io *mc_io, |
||
11765 | + u32 cmd_flags, |
||
11766 | + u16 token, |
||
11767 | + int *obj_count); |
||
11768 | + |
||
11769 | +int dprc_get_obj(struct fsl_mc_io *mc_io, |
||
11770 | + u32 cmd_flags, |
||
11771 | + u16 token, |
||
11772 | + int obj_index, |
||
11773 | + struct fsl_mc_obj_desc *obj_desc); |
||
11774 | + |
||
11775 | +int dprc_set_obj_irq(struct fsl_mc_io *mc_io, |
||
11776 | + u32 cmd_flags, |
||
11777 | + u16 token, |
||
11778 | + char *obj_type, |
||
11779 | + int obj_id, |
||
11780 | + u8 irq_index, |
||
11781 | + struct dprc_irq_cfg *irq_cfg); |
||
11782 | + |
||
11783 | +/* Region flags */ |
||
11784 | +/* Cacheable - Indicates that region should be mapped as cacheable */ |
||
11785 | +#define DPRC_REGION_CACHEABLE 0x00000001 |
||
11786 | + |
||
11787 | +/** |
||
11788 | + * enum dprc_region_type - Region type |
||
11789 | + * @DPRC_REGION_TYPE_MC_PORTAL: MC portal region |
||
11790 | + * @DPRC_REGION_TYPE_QBMAN_PORTAL: Qbman portal region |
||
11791 | + */ |
||
11792 | +enum dprc_region_type { |
||
11793 | + DPRC_REGION_TYPE_MC_PORTAL, |
||
11794 | + DPRC_REGION_TYPE_QBMAN_PORTAL |
||
11795 | +}; |
||
11796 | + |
||
11797 | +/** |
||
11798 | + * struct dprc_region_desc - Mappable region descriptor |
||
11799 | + * @base_offset: Region offset from region's base address. |
||
11800 | + * For DPMCP and DPRC objects, region base is offset from SoC MC portals |
||
11801 | + * base address; For DPIO, region base is offset from SoC QMan portals |
||
11802 | + * base address |
||
11803 | + * @size: Region size (in bytes) |
||
11804 | + * @flags: Region attributes |
||
11805 | + * @type: Portal region type |
||
11806 | + */ |
||
11807 | +struct dprc_region_desc { |
||
11808 | + u32 base_offset; |
||
11809 | + u32 size; |
||
11810 | + u32 flags; |
||
11811 | + enum dprc_region_type type; |
||
11812 | +}; |
||
11813 | + |
||
11814 | +int dprc_get_obj_region(struct fsl_mc_io *mc_io, |
||
11815 | + u32 cmd_flags, |
||
11816 | + u16 token, |
||
11817 | + char *obj_type, |
||
11818 | + int obj_id, |
||
11819 | + u8 region_index, |
||
11820 | + struct dprc_region_desc *region_desc); |
||
11821 | + |
||
11822 | +int dprc_get_api_version(struct fsl_mc_io *mc_io, |
||
11823 | + u32 cmd_flags, |
||
11824 | + u16 *major_ver, |
||
11825 | + u16 *minor_ver); |
||
11826 | + |
||
11827 | +int dprc_get_container_id(struct fsl_mc_io *mc_io, |
||
11828 | + u32 cmd_flags, |
||
11829 | + int *container_id); |
||
11830 | + |
||
11831 | +int dprc_reset_container(struct fsl_mc_io *mc_io, |
||
11832 | + u32 cmd_flags, |
||
11833 | + u16 token, |
||
11834 | + int child_container_id); |
||
11835 | + |
||
11836 | +/* |
||
11837 | + * Data Path Buffer Pool (DPBP) API |
||
11838 | + * Contains initialization APIs and runtime control APIs for DPBP |
||
11839 | + */ |
||
11840 | + |
||
11841 | +int dpbp_open(struct fsl_mc_io *mc_io, |
||
11842 | + u32 cmd_flags, |
||
11843 | + int dpbp_id, |
||
11844 | + u16 *token); |
||
11845 | + |
||
11846 | +int dpbp_close(struct fsl_mc_io *mc_io, |
||
11847 | + u32 cmd_flags, |
||
11848 | + u16 token); |
||
11849 | + |
||
11850 | +int dpbp_enable(struct fsl_mc_io *mc_io, |
||
11851 | + u32 cmd_flags, |
||
11852 | + u16 token); |
||
11853 | + |
||
11854 | +int dpbp_disable(struct fsl_mc_io *mc_io, |
||
11855 | + u32 cmd_flags, |
||
11856 | + u16 token); |
||
11857 | + |
||
11858 | +int dpbp_reset(struct fsl_mc_io *mc_io, |
||
11859 | + u32 cmd_flags, |
||
11860 | + u16 token); |
||
11861 | + |
||
11862 | +/** |
||
11863 | + * struct dpbp_attr - Structure representing DPBP attributes |
||
11864 | + * @id: DPBP object ID |
||
11865 | + * @bpid: Hardware buffer pool ID; should be used as an argument in |
||
11866 | + * acquire/release operations on buffers |
||
11867 | + */ |
||
11868 | +struct dpbp_attr { |
||
11869 | + int id; |
||
11870 | + u16 bpid; |
||
11871 | +}; |
||
11872 | + |
||
11873 | +int dpbp_get_attributes(struct fsl_mc_io *mc_io, |
||
11874 | + u32 cmd_flags, |
||
11875 | + u16 token, |
||
11876 | + struct dpbp_attr *attr); |
||
11877 | + |
||
11878 | +/* Data Path Concentrator (DPCON) API |
||
11879 | + * Contains initialization APIs and runtime control APIs for DPCON |
||
11880 | + */ |
||
11881 | + |
||
11882 | +/** |
||
11883 | + * Use it to disable notifications; see dpcon_set_notification() |
||
11884 | + */ |
||
11885 | +#define DPCON_INVALID_DPIO_ID (int)(-1) |
||
11886 | + |
||
11887 | +int dpcon_open(struct fsl_mc_io *mc_io, |
||
11888 | + u32 cmd_flags, |
||
11889 | + int dpcon_id, |
||
11890 | + u16 *token); |
||
11891 | + |
||
11892 | +int dpcon_close(struct fsl_mc_io *mc_io, |
||
11893 | + u32 cmd_flags, |
||
11894 | + u16 token); |
||
11895 | + |
||
11896 | +int dpcon_enable(struct fsl_mc_io *mc_io, |
||
11897 | + u32 cmd_flags, |
||
11898 | + u16 token); |
||
11899 | + |
||
11900 | +int dpcon_disable(struct fsl_mc_io *mc_io, |
||
11901 | + u32 cmd_flags, |
||
11902 | + u16 token); |
||
11903 | + |
||
11904 | +int dpcon_reset(struct fsl_mc_io *mc_io, |
||
11905 | + u32 cmd_flags, |
||
11906 | + u16 token); |
||
11907 | + |
||
11908 | +/** |
||
11909 | + * struct dpcon_attr - Structure representing DPCON attributes |
||
11910 | + * @id: DPCON object ID |
||
11911 | + * @qbman_ch_id: Channel ID to be used by dequeue operation |
||
11912 | + * @num_priorities: Number of priorities for the DPCON channel (1-8) |
||
11913 | + */ |
||
11914 | +struct dpcon_attr { |
||
11915 | + int id; |
||
11916 | + u16 qbman_ch_id; |
||
11917 | + u8 num_priorities; |
||
11918 | +}; |
||
11919 | + |
||
11920 | +int dpcon_get_attributes(struct fsl_mc_io *mc_io, |
||
11921 | + u32 cmd_flags, |
||
11922 | + u16 token, |
||
11923 | + struct dpcon_attr *attr); |
||
11924 | + |
||
11925 | +/** |
||
11926 | + * struct dpcon_notification_cfg - Structure representing notification params |
||
11927 | + * @dpio_id: DPIO object ID; must be configured with a notification channel; |
||
11928 | + * to disable notifications set it to 'DPCON_INVALID_DPIO_ID'; |
||
11929 | + * @priority: Priority selection within the DPIO channel; valid values |
||
11930 | + * are 0-7, depending on the number of priorities in that channel |
||
11931 | + * @user_ctx: User context value provided with each CDAN message |
||
11932 | + */ |
||
11933 | +struct dpcon_notification_cfg { |
||
11934 | + int dpio_id; |
||
11935 | + u8 priority; |
||
11936 | + u64 user_ctx; |
||
11937 | +}; |
||
11938 | + |
||
11939 | +int dpcon_set_notification(struct fsl_mc_io *mc_io, |
||
11940 | + u32 cmd_flags, |
||
11941 | + u16 token, |
||
11942 | + struct dpcon_notification_cfg *cfg); |
||
11943 | + |
||
11944 | +struct irq_domain; |
||
11945 | +struct msi_domain_info; |
||
11946 | + |
||
11947 | +/** |
||
11948 | + * Maximum number of total IRQs that can be pre-allocated for an MC bus' |
||
11949 | + * IRQ pool |
||
11950 | + */ |
||
11951 | +#define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256 |
||
11952 | + |
||
11953 | +/** |
||
11954 | + * struct fsl_mc_resource_pool - Pool of MC resources of a given |
||
11955 | + * type |
||
11956 | + * @type: type of resources in the pool |
||
11957 | + * @max_count: maximum number of resources in the pool |
||
11958 | + * @free_count: number of free resources in the pool |
||
11959 | + * @mutex: mutex to serialize access to the pool's free list |
||
11960 | + * @free_list: anchor node of list of free resources in the pool |
||
11961 | + * @mc_bus: pointer to the MC bus that owns this resource pool |
||
11962 | + */ |
||
11963 | +struct fsl_mc_resource_pool { |
||
11964 | + enum fsl_mc_pool_type type; |
||
11965 | + int max_count; |
||
11966 | + int free_count; |
||
11967 | + struct mutex mutex; /* serializes access to free_list */ |
||
11968 | + struct list_head free_list; |
||
11969 | + struct fsl_mc_bus *mc_bus; |
||
11970 | +}; |
||
11971 | + |
||
11972 | +/** |
||
11973 | + * struct fsl_mc_restool - information associated with a restool device file |
||
11974 | + * @cdev: struct char device linked to the root dprc |
||
11975 | + * @dev: dev_t for the char device to be added |
||
11976 | + * @device: newly created device in /dev |
||
11977 | + * @mutex: mutex lock to serialize the open/release operations |
||
11978 | + * @local_instance_in_use: local MC I/O instance in use or not |
||
11979 | + * @dynamic_instance_count: number of dynamically created MC I/O instances |
||
11980 | + */ |
||
11981 | +struct fsl_mc_restool { |
||
11982 | + struct cdev cdev; |
||
11983 | + dev_t dev; |
||
11984 | + struct device *device; |
||
11985 | + struct mutex mutex; /* serialize open/release operations */ |
||
11986 | + bool local_instance_in_use; |
||
11987 | + u32 dynamic_instance_count; |
||
11988 | +}; |
||
11989 | + |
||
11990 | +/** |
||
11991 | + * struct fsl_mc_bus - logical bus that corresponds to a physical DPRC |
||
11992 | + * @mc_dev: fsl-mc device for the bus device itself. |
||
11993 | + * @resource_pools: array of resource pools (one pool per resource type) |
||
11994 | + * for this MC bus. These resources represent allocatable entities |
||
11995 | + * from the physical DPRC. |
||
11996 | + * @irq_resources: Pointer to array of IRQ objects for the IRQ pool |
||
11997 | + * @scan_mutex: Serializes bus scanning |
||
11998 | + * @dprc_attr: DPRC attributes |
||
11999 | + * @restool_misc: struct that abstracts the interaction with userspace restool |
||
12000 | + */ |
||
12001 | +struct fsl_mc_bus { |
||
12002 | + struct fsl_mc_device mc_dev; |
||
12003 | + struct fsl_mc_resource_pool resource_pools[FSL_MC_NUM_POOL_TYPES]; |
||
12004 | + struct fsl_mc_device_irq *irq_resources; |
||
12005 | + struct mutex scan_mutex; /* serializes bus scanning */ |
||
12006 | + struct dprc_attributes dprc_attr; |
||
12007 | + struct fsl_mc_restool restool_misc; |
||
12008 | +}; |
||
12009 | + |
||
12010 | +int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, |
||
12011 | + const char *driver_override, |
||
12012 | + unsigned int *total_irq_count); |
||
12013 | + |
||
12014 | +int fsl_mc_find_msi_domain(struct device *mc_platform_dev, |
||
12015 | + struct irq_domain **mc_msi_domain); |
||
12016 | + |
||
12017 | +int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, |
||
12018 | + unsigned int irq_count); |
||
12019 | + |
||
12020 | +void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus); |
||
12021 | + |
||
12022 | +void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev); |
||
12023 | + |
||
12024 | +void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev); |
||
12025 | + |
||
12026 | +void fsl_mc_get_root_dprc(struct device *dev, struct device **root_dprc_dev); |
||
12027 | + |
||
12028 | +#endif /* _FSL_MC_H_ */ |
||
12029 | --- /dev/null |
||
12030 | +++ b/include/uapi/linux/fsl_mc.h |
||
12031 | @@ -0,0 +1,31 @@ |
||
12032 | +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ |
||
12033 | +/* |
||
12034 | + * Management Complex (MC) userspace public interface |
||
12035 | + * |
||
12036 | + * Copyright 2018 NXP |
||
12037 | + * |
||
12038 | + */ |
||
12039 | +#ifndef _UAPI_FSL_MC_H_ |
||
12040 | +#define _UAPI_FSL_MC_H_ |
||
12041 | + |
||
12042 | +#define MC_CMD_NUM_OF_PARAMS 7 |
||
12043 | + |
||
12044 | +/** |
||
12045 | + * struct fsl_mc_command - Management Complex (MC) command structure |
||
12046 | + * @header: MC command header |
||
12047 | + * @params: MC command parameters |
||
12048 | + * |
||
12049 | + * Used by RESTOOL_SEND_MC_COMMAND |
||
12050 | + */ |
||
12051 | +struct fsl_mc_command { |
||
12052 | + __u64 header; |
||
12053 | + __u64 params[MC_CMD_NUM_OF_PARAMS]; |
||
12054 | +}; |
||
12055 | + |
||
12056 | +#define RESTOOL_IOCTL_TYPE 'R' |
||
12057 | +#define RESTOOL_IOCTL_SEQ 0xE0 |
||
12058 | + |
||
12059 | +#define RESTOOL_SEND_MC_COMMAND \ |
||
12060 | + _IOWR(RESTOOL_IOCTL_TYPE, RESTOOL_IOCTL_SEQ, struct fsl_mc_command) |
||
12061 | + |
||
12062 | +#endif /* _UAPI_FSL_MC_H_ */ |