kernel: bump 4.14 to 4.14.206
[openwrt/openwrt.git] / target / linux / layerscape / patches-4.14 / 708-mc-bus-support-layerscape.patch
1 From ab58c737bc723f52e787e1767bbbf0fcbe39a27b Mon Sep 17 00:00:00 2001
2 From: Biwen Li <biwen.li@nxp.com>
3 Date: Wed, 17 Apr 2019 18:58:43 +0800
4 Subject: [PATCH] mc-bus: support layerscape
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 This is an integrated patch of mc-bus for layerscape
10
11 Signed-off-by: Bharat Bhushan <Bharat.Bhushan@nxp.com>
12 Signed-off-by: Biwen Li <biwen.li@nxp.com>
13 Signed-off-by: Bogdan Purcareata <bogdan.purcareata@nxp.com>
14 Signed-off-by: Cristian Sovaiala <cristian.sovaiala@freescale.com>
15 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
16 Signed-off-by: Guanhua Gao <guanhua.gao@nxp.com>
17 Signed-off-by: Horia Geantă <horia.geanta@nxp.com>
18 Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
19 Signed-off-by: Ioana Radulescu <ruxandra.radulescu@nxp.com>
20 Signed-off-by: J. German Rivera <German.Rivera@freescale.com>
21 Signed-off-by: Laurentiu Tudor <laurentiu.tudor@nxp.com>
22 Signed-off-by: Lijun Pan <Lijun.Pan@freescale.com>
23 Signed-off-by: Nipun Gupta <nipun.gupta@nxp.com>
24 Signed-off-by: Radu Alexe <radu.alexe@nxp.com>
25 Signed-off-by: Razvan Stefanescu <razvan.stefanescu@nxp.com>
26 Signed-off-by: Roy Pledge <roy.pledge@nxp.com>
27 Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>
28 ---
29 drivers/bus/Kconfig | 2 +
30 drivers/bus/Makefile | 4 +
31 drivers/bus/fsl-mc/Kconfig | 23 +
32 drivers/bus/fsl-mc/Makefile | 21 +
33 .../{staging/fsl-mc/bus => bus/fsl-mc}/dpbp.c | 97 +-
34 .../fsl-mc/bus => bus/fsl-mc}/dpcon.c | 103 +-
35 drivers/bus/fsl-mc/dpmcp.c | 99 ++
36 .../fsl-mc/bus => bus/fsl-mc}/dprc-driver.c | 96 +-
37 .../{staging/fsl-mc/bus => bus/fsl-mc}/dprc.c | 289 +----
38 .../bus => bus/fsl-mc}/fsl-mc-allocator.c | 123 +-
39 .../fsl-mc/bus => bus/fsl-mc}/fsl-mc-bus.c | 322 +++++-
40 .../fsl-mc/bus => bus/fsl-mc}/fsl-mc-msi.c | 16 +-
41 drivers/bus/fsl-mc/fsl-mc-private.h | 223 ++++
42 drivers/bus/fsl-mc/fsl-mc-restool.c | 219 ++++
43 .../fsl-mc/bus => bus/fsl-mc}/mc-io.c | 51 +-
44 .../fsl-mc/bus => bus/fsl-mc}/mc-sys.c | 33 +-
45 drivers/irqchip/Kconfig | 6 +
46 drivers/irqchip/Makefile | 1 +
47 drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c | 98 ++
48 .../staging/fsl-dpaa2/ethernet/dpaa2-eth.c | 2 +-
49 .../staging/fsl-dpaa2/ethernet/dpaa2-eth.h | 3 +-
50 drivers/staging/fsl-dpaa2/ethernet/dpni.c | 2 +-
51 drivers/staging/fsl-mc/bus/Kconfig | 15 +-
52 drivers/staging/fsl-mc/bus/Makefile | 13 -
53 drivers/staging/fsl-mc/bus/dpio/dpio-driver.c | 2 +-
54 .../staging/fsl-mc/bus/dpio/dpio-service.c | 2 +-
55 drivers/staging/fsl-mc/bus/dpio/dpio.c | 14 +-
56 drivers/staging/fsl-mc/bus/dpmcp-cmd.h | 56 -
57 drivers/staging/fsl-mc/bus/dpmcp.h | 60 -
58 drivers/staging/fsl-mc/bus/dpmng-cmd.h | 58 -
59 drivers/staging/fsl-mc/bus/dprc-cmd.h | 451 --------
60 drivers/staging/fsl-mc/bus/dprc.h | 268 -----
61 .../fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c | 1 +
62 include/linux/fsl/mc.h | 1029 +++++++++++++++++
63 include/uapi/linux/fsl_mc.h | 31 +
64 35 files changed, 2302 insertions(+), 1531 deletions(-)
65 create mode 100644 drivers/bus/fsl-mc/Kconfig
66 create mode 100644 drivers/bus/fsl-mc/Makefile
67 rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpbp.c (67%)
68 rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpcon.c (70%)
69 create mode 100644 drivers/bus/fsl-mc/dpmcp.c
70 rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dprc-driver.c (93%)
71 rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dprc.c (68%)
72 rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-allocator.c (84%)
73 rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-bus.c (75%)
74 rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-msi.c (96%)
75 create mode 100644 drivers/bus/fsl-mc/fsl-mc-private.h
76 create mode 100644 drivers/bus/fsl-mc/fsl-mc-restool.c
77 rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/mc-io.c (89%)
78 rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/mc-sys.c (90%)
79 create mode 100644 drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c
80 delete mode 100644 drivers/staging/fsl-mc/bus/dpmcp-cmd.h
81 delete mode 100644 drivers/staging/fsl-mc/bus/dpmcp.h
82 delete mode 100644 drivers/staging/fsl-mc/bus/dpmng-cmd.h
83 delete mode 100644 drivers/staging/fsl-mc/bus/dprc-cmd.h
84 delete mode 100644 drivers/staging/fsl-mc/bus/dprc.h
85 create mode 100644 include/linux/fsl/mc.h
86 create mode 100644 include/uapi/linux/fsl_mc.h
87
88 --- a/drivers/bus/Kconfig
89 +++ b/drivers/bus/Kconfig
90 @@ -184,4 +184,6 @@ config DA8XX_MSTPRI
91 configuration. Allows to adjust the priorities of all master
92 peripherals.
93
94 +source "drivers/bus/fsl-mc/Kconfig"
95 +
96 endmenu
97 --- a/drivers/bus/Makefile
98 +++ b/drivers/bus/Makefile
99 @@ -8,6 +8,10 @@ obj-$(CONFIG_ARM_CCI) += arm-cci.o
100 obj-$(CONFIG_ARM_CCN) += arm-ccn.o
101
102 obj-$(CONFIG_BRCMSTB_GISB_ARB) += brcmstb_gisb.o
103 +
104 +# DPAA2 fsl-mc bus
105 +obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/
106 +
107 obj-$(CONFIG_IMX_WEIM) += imx-weim.o
108 obj-$(CONFIG_MIPS_CDMM) += mips_cdmm.o
109 obj-$(CONFIG_MVEBU_MBUS) += mvebu-mbus.o
110 --- /dev/null
111 +++ b/drivers/bus/fsl-mc/Kconfig
112 @@ -0,0 +1,23 @@
113 +# SPDX-License-Identifier: GPL-2.0
114 +#
115 +# DPAA2 fsl-mc bus
116 +#
117 +# Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
118 +#
119 +
120 +config FSL_MC_BUS
121 + bool "QorIQ DPAA2 fsl-mc bus driver"
122 + depends on OF && (ARCH_LAYERSCAPE || (COMPILE_TEST && (ARM || ARM64 || X86 || PPC)))
123 + select GENERIC_MSI_IRQ_DOMAIN
124 + help
125 + Driver to enable the bus infrastructure for the QorIQ DPAA2
126 + architecture. The fsl-mc bus driver handles discovery of
127 + DPAA2 objects (which are represented as Linux devices) and
128 + binding objects to drivers.
129 +
130 +config FSL_MC_RESTOOL
131 + bool "Management Complex (MC) restool support"
132 + depends on FSL_MC_BUS
133 + help
134 + Provides kernel support for the Management Complex resource
135 + manager user-space tool - restool.
136 --- /dev/null
137 +++ b/drivers/bus/fsl-mc/Makefile
138 @@ -0,0 +1,21 @@
139 +# SPDX-License-Identifier: GPL-2.0
140 +#
141 +# Freescale Management Complex (MC) bus drivers
142 +#
143 +# Copyright (C) 2014 Freescale Semiconductor, Inc.
144 +#
145 +obj-$(CONFIG_FSL_MC_BUS) += mc-bus-driver.o
146 +
147 +mc-bus-driver-objs := fsl-mc-bus.o \
148 + mc-sys.o \
149 + mc-io.o \
150 + dpbp.o \
151 + dpcon.o \
152 + dprc.o \
153 + dprc-driver.o \
154 + fsl-mc-allocator.o \
155 + fsl-mc-msi.o \
156 + dpmcp.o
157 +
158 +# MC restool kernel support
159 +obj-$(CONFIG_FSL_MC_RESTOOL) += fsl-mc-restool.o
160 --- a/drivers/staging/fsl-mc/bus/dpbp.c
161 +++ /dev/null
162 @@ -1,253 +0,0 @@
163 -// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
164 -/*
165 - * Copyright 2013-2016 Freescale Semiconductor Inc.
166 - *
167 - */
168 -#include <linux/kernel.h>
169 -#include "../include/mc.h"
170 -#include "../include/dpbp.h"
171 -
172 -#include "dpbp-cmd.h"
173 -
174 -/**
175 - * dpbp_open() - Open a control session for the specified object.
176 - * @mc_io: Pointer to MC portal's I/O object
177 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
178 - * @dpbp_id: DPBP unique ID
179 - * @token: Returned token; use in subsequent API calls
180 - *
181 - * This function can be used to open a control session for an
182 - * already created object; an object may have been declared in
183 - * the DPL or by calling the dpbp_create function.
184 - * This function returns a unique authentication token,
185 - * associated with the specific object ID and the specific MC
186 - * portal; this token must be used in all subsequent commands for
187 - * this specific object
188 - *
189 - * Return: '0' on Success; Error code otherwise.
190 - */
191 -int dpbp_open(struct fsl_mc_io *mc_io,
192 - u32 cmd_flags,
193 - int dpbp_id,
194 - u16 *token)
195 -{
196 - struct mc_command cmd = { 0 };
197 - struct dpbp_cmd_open *cmd_params;
198 - int err;
199 -
200 - /* prepare command */
201 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_OPEN,
202 - cmd_flags, 0);
203 - cmd_params = (struct dpbp_cmd_open *)cmd.params;
204 - cmd_params->dpbp_id = cpu_to_le32(dpbp_id);
205 -
206 - /* send command to mc*/
207 - err = mc_send_command(mc_io, &cmd);
208 - if (err)
209 - return err;
210 -
211 - /* retrieve response parameters */
212 - *token = mc_cmd_hdr_read_token(&cmd);
213 -
214 - return err;
215 -}
216 -EXPORT_SYMBOL(dpbp_open);
217 -
218 -/**
219 - * dpbp_close() - Close the control session of the object
220 - * @mc_io: Pointer to MC portal's I/O object
221 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
222 - * @token: Token of DPBP object
223 - *
224 - * After this function is called, no further operations are
225 - * allowed on the object without opening a new control session.
226 - *
227 - * Return: '0' on Success; Error code otherwise.
228 - */
229 -int dpbp_close(struct fsl_mc_io *mc_io,
230 - u32 cmd_flags,
231 - u16 token)
232 -{
233 - struct mc_command cmd = { 0 };
234 -
235 - /* prepare command */
236 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLOSE, cmd_flags,
237 - token);
238 -
239 - /* send command to mc*/
240 - return mc_send_command(mc_io, &cmd);
241 -}
242 -EXPORT_SYMBOL(dpbp_close);
243 -
244 -/**
245 - * dpbp_enable() - Enable the DPBP.
246 - * @mc_io: Pointer to MC portal's I/O object
247 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
248 - * @token: Token of DPBP object
249 - *
250 - * Return: '0' on Success; Error code otherwise.
251 - */
252 -int dpbp_enable(struct fsl_mc_io *mc_io,
253 - u32 cmd_flags,
254 - u16 token)
255 -{
256 - struct mc_command cmd = { 0 };
257 -
258 - /* prepare command */
259 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_ENABLE, cmd_flags,
260 - token);
261 -
262 - /* send command to mc*/
263 - return mc_send_command(mc_io, &cmd);
264 -}
265 -EXPORT_SYMBOL(dpbp_enable);
266 -
267 -/**
268 - * dpbp_disable() - Disable the DPBP.
269 - * @mc_io: Pointer to MC portal's I/O object
270 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
271 - * @token: Token of DPBP object
272 - *
273 - * Return: '0' on Success; Error code otherwise.
274 - */
275 -int dpbp_disable(struct fsl_mc_io *mc_io,
276 - u32 cmd_flags,
277 - u16 token)
278 -{
279 - struct mc_command cmd = { 0 };
280 -
281 - /* prepare command */
282 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_DISABLE,
283 - cmd_flags, token);
284 -
285 - /* send command to mc*/
286 - return mc_send_command(mc_io, &cmd);
287 -}
288 -EXPORT_SYMBOL(dpbp_disable);
289 -
290 -/**
291 - * dpbp_is_enabled() - Check if the DPBP is enabled.
292 - * @mc_io: Pointer to MC portal's I/O object
293 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
294 - * @token: Token of DPBP object
295 - * @en: Returns '1' if object is enabled; '0' otherwise
296 - *
297 - * Return: '0' on Success; Error code otherwise.
298 - */
299 -int dpbp_is_enabled(struct fsl_mc_io *mc_io,
300 - u32 cmd_flags,
301 - u16 token,
302 - int *en)
303 -{
304 - struct mc_command cmd = { 0 };
305 - struct dpbp_rsp_is_enabled *rsp_params;
306 - int err;
307 - /* prepare command */
308 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_IS_ENABLED, cmd_flags,
309 - token);
310 -
311 - /* send command to mc*/
312 - err = mc_send_command(mc_io, &cmd);
313 - if (err)
314 - return err;
315 -
316 - /* retrieve response parameters */
317 - rsp_params = (struct dpbp_rsp_is_enabled *)cmd.params;
318 - *en = rsp_params->enabled & DPBP_ENABLE;
319 -
320 - return 0;
321 -}
322 -EXPORT_SYMBOL(dpbp_is_enabled);
323 -
324 -/**
325 - * dpbp_reset() - Reset the DPBP, returns the object to initial state.
326 - * @mc_io: Pointer to MC portal's I/O object
327 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
328 - * @token: Token of DPBP object
329 - *
330 - * Return: '0' on Success; Error code otherwise.
331 - */
332 -int dpbp_reset(struct fsl_mc_io *mc_io,
333 - u32 cmd_flags,
334 - u16 token)
335 -{
336 - struct mc_command cmd = { 0 };
337 -
338 - /* prepare command */
339 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_RESET,
340 - cmd_flags, token);
341 -
342 - /* send command to mc*/
343 - return mc_send_command(mc_io, &cmd);
344 -}
345 -EXPORT_SYMBOL(dpbp_reset);
346 -
347 -/**
348 - * dpbp_get_attributes - Retrieve DPBP attributes.
349 - *
350 - * @mc_io: Pointer to MC portal's I/O object
351 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
352 - * @token: Token of DPBP object
353 - * @attr: Returned object's attributes
354 - *
355 - * Return: '0' on Success; Error code otherwise.
356 - */
357 -int dpbp_get_attributes(struct fsl_mc_io *mc_io,
358 - u32 cmd_flags,
359 - u16 token,
360 - struct dpbp_attr *attr)
361 -{
362 - struct mc_command cmd = { 0 };
363 - struct dpbp_rsp_get_attributes *rsp_params;
364 - int err;
365 -
366 - /* prepare command */
367 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_ATTR,
368 - cmd_flags, token);
369 -
370 - /* send command to mc*/
371 - err = mc_send_command(mc_io, &cmd);
372 - if (err)
373 - return err;
374 -
375 - /* retrieve response parameters */
376 - rsp_params = (struct dpbp_rsp_get_attributes *)cmd.params;
377 - attr->bpid = le16_to_cpu(rsp_params->bpid);
378 - attr->id = le32_to_cpu(rsp_params->id);
379 -
380 - return 0;
381 -}
382 -EXPORT_SYMBOL(dpbp_get_attributes);
383 -
384 -/**
385 - * dpbp_get_api_version - Get Data Path Buffer Pool API version
386 - * @mc_io: Pointer to Mc portal's I/O object
387 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
388 - * @major_ver: Major version of Buffer Pool API
389 - * @minor_ver: Minor version of Buffer Pool API
390 - *
391 - * Return: '0' on Success; Error code otherwise.
392 - */
393 -int dpbp_get_api_version(struct fsl_mc_io *mc_io,
394 - u32 cmd_flags,
395 - u16 *major_ver,
396 - u16 *minor_ver)
397 -{
398 - struct mc_command cmd = { 0 };
399 - int err;
400 -
401 - /* prepare command */
402 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_API_VERSION,
403 - cmd_flags, 0);
404 -
405 - /* send command to mc */
406 - err = mc_send_command(mc_io, &cmd);
407 - if (err)
408 - return err;
409 -
410 - /* retrieve response parameters */
411 - mc_cmd_read_api_version(&cmd, major_ver, minor_ver);
412 -
413 - return 0;
414 -}
415 -EXPORT_SYMBOL(dpbp_get_api_version);
416 --- /dev/null
417 +++ b/drivers/bus/fsl-mc/dpbp.c
418 @@ -0,0 +1,186 @@
419 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
420 +/*
421 + * Copyright 2013-2016 Freescale Semiconductor Inc.
422 + *
423 + */
424 +#include <linux/kernel.h>
425 +#include <linux/fsl/mc.h>
426 +#include <linux/fsl/mc.h>
427 +
428 +#include "fsl-mc-private.h"
429 +
430 +/**
431 + * dpbp_open() - Open a control session for the specified object.
432 + * @mc_io: Pointer to MC portal's I/O object
433 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
434 + * @dpbp_id: DPBP unique ID
435 + * @token: Returned token; use in subsequent API calls
436 + *
437 + * This function can be used to open a control session for an
438 + * already created object; an object may have been declared in
439 + * the DPL or by calling the dpbp_create function.
440 + * This function returns a unique authentication token,
441 + * associated with the specific object ID and the specific MC
442 + * portal; this token must be used in all subsequent commands for
443 + * this specific object
444 + *
445 + * Return: '0' on Success; Error code otherwise.
446 + */
447 +int dpbp_open(struct fsl_mc_io *mc_io,
448 + u32 cmd_flags,
449 + int dpbp_id,
450 + u16 *token)
451 +{
452 + struct fsl_mc_command cmd = { 0 };
453 + struct dpbp_cmd_open *cmd_params;
454 + int err;
455 +
456 + /* prepare command */
457 + cmd.header = mc_encode_cmd_header(DPBP_CMDID_OPEN,
458 + cmd_flags, 0);
459 + cmd_params = (struct dpbp_cmd_open *)cmd.params;
460 + cmd_params->dpbp_id = cpu_to_le32(dpbp_id);
461 +
462 + /* send command to mc*/
463 + err = mc_send_command(mc_io, &cmd);
464 + if (err)
465 + return err;
466 +
467 + /* retrieve response parameters */
468 + *token = mc_cmd_hdr_read_token(&cmd);
469 +
470 + return err;
471 +}
472 +EXPORT_SYMBOL_GPL(dpbp_open);
473 +
474 +/**
475 + * dpbp_close() - Close the control session of the object
476 + * @mc_io: Pointer to MC portal's I/O object
477 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
478 + * @token: Token of DPBP object
479 + *
480 + * After this function is called, no further operations are
481 + * allowed on the object without opening a new control session.
482 + *
483 + * Return: '0' on Success; Error code otherwise.
484 + */
485 +int dpbp_close(struct fsl_mc_io *mc_io,
486 + u32 cmd_flags,
487 + u16 token)
488 +{
489 + struct fsl_mc_command cmd = { 0 };
490 +
491 + /* prepare command */
492 + cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLOSE, cmd_flags,
493 + token);
494 +
495 + /* send command to mc*/
496 + return mc_send_command(mc_io, &cmd);
497 +}
498 +EXPORT_SYMBOL_GPL(dpbp_close);
499 +
500 +/**
501 + * dpbp_enable() - Enable the DPBP.
502 + * @mc_io: Pointer to MC portal's I/O object
503 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
504 + * @token: Token of DPBP object
505 + *
506 + * Return: '0' on Success; Error code otherwise.
507 + */
508 +int dpbp_enable(struct fsl_mc_io *mc_io,
509 + u32 cmd_flags,
510 + u16 token)
511 +{
512 + struct fsl_mc_command cmd = { 0 };
513 +
514 + /* prepare command */
515 + cmd.header = mc_encode_cmd_header(DPBP_CMDID_ENABLE, cmd_flags,
516 + token);
517 +
518 + /* send command to mc*/
519 + return mc_send_command(mc_io, &cmd);
520 +}
521 +EXPORT_SYMBOL_GPL(dpbp_enable);
522 +
523 +/**
524 + * dpbp_disable() - Disable the DPBP.
525 + * @mc_io: Pointer to MC portal's I/O object
526 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
527 + * @token: Token of DPBP object
528 + *
529 + * Return: '0' on Success; Error code otherwise.
530 + */
531 +int dpbp_disable(struct fsl_mc_io *mc_io,
532 + u32 cmd_flags,
533 + u16 token)
534 +{
535 + struct fsl_mc_command cmd = { 0 };
536 +
537 + /* prepare command */
538 + cmd.header = mc_encode_cmd_header(DPBP_CMDID_DISABLE,
539 + cmd_flags, token);
540 +
541 + /* send command to mc*/
542 + return mc_send_command(mc_io, &cmd);
543 +}
544 +EXPORT_SYMBOL_GPL(dpbp_disable);
545 +
546 +/**
547 + * dpbp_reset() - Reset the DPBP, returns the object to initial state.
548 + * @mc_io: Pointer to MC portal's I/O object
549 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
550 + * @token: Token of DPBP object
551 + *
552 + * Return: '0' on Success; Error code otherwise.
553 + */
554 +int dpbp_reset(struct fsl_mc_io *mc_io,
555 + u32 cmd_flags,
556 + u16 token)
557 +{
558 + struct fsl_mc_command cmd = { 0 };
559 +
560 + /* prepare command */
561 + cmd.header = mc_encode_cmd_header(DPBP_CMDID_RESET,
562 + cmd_flags, token);
563 +
564 + /* send command to mc*/
565 + return mc_send_command(mc_io, &cmd);
566 +}
567 +EXPORT_SYMBOL_GPL(dpbp_reset);
568 +
569 +/**
570 + * dpbp_get_attributes - Retrieve DPBP attributes.
571 + *
572 + * @mc_io: Pointer to MC portal's I/O object
573 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
574 + * @token: Token of DPBP object
575 + * @attr: Returned object's attributes
576 + *
577 + * Return: '0' on Success; Error code otherwise.
578 + */
579 +int dpbp_get_attributes(struct fsl_mc_io *mc_io,
580 + u32 cmd_flags,
581 + u16 token,
582 + struct dpbp_attr *attr)
583 +{
584 + struct fsl_mc_command cmd = { 0 };
585 + struct dpbp_rsp_get_attributes *rsp_params;
586 + int err;
587 +
588 + /* prepare command */
589 + cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_ATTR,
590 + cmd_flags, token);
591 +
592 + /* send command to mc*/
593 + err = mc_send_command(mc_io, &cmd);
594 + if (err)
595 + return err;
596 +
597 + /* retrieve response parameters */
598 + rsp_params = (struct dpbp_rsp_get_attributes *)cmd.params;
599 + attr->bpid = le16_to_cpu(rsp_params->bpid);
600 + attr->id = le32_to_cpu(rsp_params->id);
601 +
602 + return 0;
603 +}
604 +EXPORT_SYMBOL_GPL(dpbp_get_attributes);
605 --- a/drivers/staging/fsl-mc/bus/dpcon.c
606 +++ /dev/null
607 @@ -1,291 +0,0 @@
608 -// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
609 -/*
610 - * Copyright 2013-2016 Freescale Semiconductor Inc.
611 - *
612 - */
613 -#include <linux/kernel.h>
614 -#include "../include/mc.h"
615 -#include "../include/dpcon.h"
616 -
617 -#include "dpcon-cmd.h"
618 -
619 -/**
620 - * dpcon_open() - Open a control session for the specified object
621 - * @mc_io: Pointer to MC portal's I/O object
622 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
623 - * @dpcon_id: DPCON unique ID
624 - * @token: Returned token; use in subsequent API calls
625 - *
626 - * This function can be used to open a control session for an
627 - * already created object; an object may have been declared in
628 - * the DPL or by calling the dpcon_create() function.
629 - * This function returns a unique authentication token,
630 - * associated with the specific object ID and the specific MC
631 - * portal; this token must be used in all subsequent commands for
632 - * this specific object.
633 - *
634 - * Return: '0' on Success; Error code otherwise.
635 - */
636 -int dpcon_open(struct fsl_mc_io *mc_io,
637 - u32 cmd_flags,
638 - int dpcon_id,
639 - u16 *token)
640 -{
641 - struct mc_command cmd = { 0 };
642 - struct dpcon_cmd_open *dpcon_cmd;
643 - int err;
644 -
645 - /* prepare command */
646 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_OPEN,
647 - cmd_flags,
648 - 0);
649 - dpcon_cmd = (struct dpcon_cmd_open *)cmd.params;
650 - dpcon_cmd->dpcon_id = cpu_to_le32(dpcon_id);
651 -
652 - /* send command to mc*/
653 - err = mc_send_command(mc_io, &cmd);
654 - if (err)
655 - return err;
656 -
657 - /* retrieve response parameters */
658 - *token = mc_cmd_hdr_read_token(&cmd);
659 -
660 - return 0;
661 -}
662 -EXPORT_SYMBOL(dpcon_open);
663 -
664 -/**
665 - * dpcon_close() - Close the control session of the object
666 - * @mc_io: Pointer to MC portal's I/O object
667 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
668 - * @token: Token of DPCON object
669 - *
670 - * After this function is called, no further operations are
671 - * allowed on the object without opening a new control session.
672 - *
673 - * Return: '0' on Success; Error code otherwise.
674 - */
675 -int dpcon_close(struct fsl_mc_io *mc_io,
676 - u32 cmd_flags,
677 - u16 token)
678 -{
679 - struct mc_command cmd = { 0 };
680 -
681 - /* prepare command */
682 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_CLOSE,
683 - cmd_flags,
684 - token);
685 -
686 - /* send command to mc*/
687 - return mc_send_command(mc_io, &cmd);
688 -}
689 -EXPORT_SYMBOL(dpcon_close);
690 -
691 -/**
692 - * dpcon_enable() - Enable the DPCON
693 - * @mc_io: Pointer to MC portal's I/O object
694 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
695 - * @token: Token of DPCON object
696 - *
697 - * Return: '0' on Success; Error code otherwise
698 - */
699 -int dpcon_enable(struct fsl_mc_io *mc_io,
700 - u32 cmd_flags,
701 - u16 token)
702 -{
703 - struct mc_command cmd = { 0 };
704 -
705 - /* prepare command */
706 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_ENABLE,
707 - cmd_flags,
708 - token);
709 -
710 - /* send command to mc*/
711 - return mc_send_command(mc_io, &cmd);
712 -}
713 -EXPORT_SYMBOL(dpcon_enable);
714 -
715 -/**
716 - * dpcon_disable() - Disable the DPCON
717 - * @mc_io: Pointer to MC portal's I/O object
718 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
719 - * @token: Token of DPCON object
720 - *
721 - * Return: '0' on Success; Error code otherwise
722 - */
723 -int dpcon_disable(struct fsl_mc_io *mc_io,
724 - u32 cmd_flags,
725 - u16 token)
726 -{
727 - struct mc_command cmd = { 0 };
728 -
729 - /* prepare command */
730 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_DISABLE,
731 - cmd_flags,
732 - token);
733 -
734 - /* send command to mc*/
735 - return mc_send_command(mc_io, &cmd);
736 -}
737 -EXPORT_SYMBOL(dpcon_disable);
738 -
739 -/**
740 - * dpcon_is_enabled() - Check if the DPCON is enabled.
741 - * @mc_io: Pointer to MC portal's I/O object
742 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
743 - * @token: Token of DPCON object
744 - * @en: Returns '1' if object is enabled; '0' otherwise
745 - *
746 - * Return: '0' on Success; Error code otherwise.
747 - */
748 -int dpcon_is_enabled(struct fsl_mc_io *mc_io,
749 - u32 cmd_flags,
750 - u16 token,
751 - int *en)
752 -{
753 - struct mc_command cmd = { 0 };
754 - struct dpcon_rsp_is_enabled *dpcon_rsp;
755 - int err;
756 -
757 - /* prepare command */
758 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_IS_ENABLED,
759 - cmd_flags,
760 - token);
761 -
762 - /* send command to mc*/
763 - err = mc_send_command(mc_io, &cmd);
764 - if (err)
765 - return err;
766 -
767 - /* retrieve response parameters */
768 - dpcon_rsp = (struct dpcon_rsp_is_enabled *)cmd.params;
769 - *en = dpcon_rsp->enabled & DPCON_ENABLE;
770 -
771 - return 0;
772 -}
773 -EXPORT_SYMBOL(dpcon_is_enabled);
774 -
775 -/**
776 - * dpcon_reset() - Reset the DPCON, returns the object to initial state.
777 - * @mc_io: Pointer to MC portal's I/O object
778 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
779 - * @token: Token of DPCON object
780 - *
781 - * Return: '0' on Success; Error code otherwise.
782 - */
783 -int dpcon_reset(struct fsl_mc_io *mc_io,
784 - u32 cmd_flags,
785 - u16 token)
786 -{
787 - struct mc_command cmd = { 0 };
788 -
789 - /* prepare command */
790 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_RESET,
791 - cmd_flags, token);
792 -
793 - /* send command to mc*/
794 - return mc_send_command(mc_io, &cmd);
795 -}
796 -EXPORT_SYMBOL(dpcon_reset);
797 -
798 -/**
799 - * dpcon_get_attributes() - Retrieve DPCON attributes.
800 - * @mc_io: Pointer to MC portal's I/O object
801 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
802 - * @token: Token of DPCON object
803 - * @attr: Object's attributes
804 - *
805 - * Return: '0' on Success; Error code otherwise.
806 - */
807 -int dpcon_get_attributes(struct fsl_mc_io *mc_io,
808 - u32 cmd_flags,
809 - u16 token,
810 - struct dpcon_attr *attr)
811 -{
812 - struct mc_command cmd = { 0 };
813 - struct dpcon_rsp_get_attr *dpcon_rsp;
814 - int err;
815 -
816 - /* prepare command */
817 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_ATTR,
818 - cmd_flags,
819 - token);
820 -
821 - /* send command to mc*/
822 - err = mc_send_command(mc_io, &cmd);
823 - if (err)
824 - return err;
825 -
826 - /* retrieve response parameters */
827 - dpcon_rsp = (struct dpcon_rsp_get_attr *)cmd.params;
828 - attr->id = le32_to_cpu(dpcon_rsp->id);
829 - attr->qbman_ch_id = le16_to_cpu(dpcon_rsp->qbman_ch_id);
830 - attr->num_priorities = dpcon_rsp->num_priorities;
831 -
832 - return 0;
833 -}
834 -EXPORT_SYMBOL(dpcon_get_attributes);
835 -
836 -/**
837 - * dpcon_set_notification() - Set DPCON notification destination
838 - * @mc_io: Pointer to MC portal's I/O object
839 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
840 - * @token: Token of DPCON object
841 - * @cfg: Notification parameters
842 - *
843 - * Return: '0' on Success; Error code otherwise
844 - */
845 -int dpcon_set_notification(struct fsl_mc_io *mc_io,
846 - u32 cmd_flags,
847 - u16 token,
848 - struct dpcon_notification_cfg *cfg)
849 -{
850 - struct mc_command cmd = { 0 };
851 - struct dpcon_cmd_set_notification *dpcon_cmd;
852 -
853 - /* prepare command */
854 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_SET_NOTIFICATION,
855 - cmd_flags,
856 - token);
857 - dpcon_cmd = (struct dpcon_cmd_set_notification *)cmd.params;
858 - dpcon_cmd->dpio_id = cpu_to_le32(cfg->dpio_id);
859 - dpcon_cmd->priority = cfg->priority;
860 - dpcon_cmd->user_ctx = cpu_to_le64(cfg->user_ctx);
861 -
862 - /* send command to mc*/
863 - return mc_send_command(mc_io, &cmd);
864 -}
865 -EXPORT_SYMBOL(dpcon_set_notification);
866 -
867 -/**
868 - * dpcon_get_api_version - Get Data Path Concentrator API version
869 - * @mc_io: Pointer to MC portal's DPCON object
870 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
871 - * @major_ver: Major version of DPCON API
872 - * @minor_ver: Minor version of DPCON API
873 - *
874 - * Return: '0' on Success; Error code otherwise
875 - */
876 -int dpcon_get_api_version(struct fsl_mc_io *mc_io,
877 - u32 cmd_flags,
878 - u16 *major_ver,
879 - u16 *minor_ver)
880 -{
881 - struct mc_command cmd = { 0 };
882 - int err;
883 -
884 - /* prepare command */
885 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_API_VERSION,
886 - cmd_flags, 0);
887 -
888 - /* send command to mc */
889 - err = mc_send_command(mc_io, &cmd);
890 - if (err)
891 - return err;
892 -
893 - /* retrieve response parameters */
894 - mc_cmd_read_api_version(&cmd, major_ver, minor_ver);
895 -
896 - return 0;
897 -}
898 -EXPORT_SYMBOL(dpcon_get_api_version);
899 --- /dev/null
900 +++ b/drivers/bus/fsl-mc/dpcon.c
901 @@ -0,0 +1,222 @@
902 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
903 +/*
904 + * Copyright 2013-2016 Freescale Semiconductor Inc.
905 + *
906 + */
907 +#include <linux/kernel.h>
908 +#include <linux/fsl/mc.h>
909 +#include <linux/fsl/mc.h>
910 +
911 +#include "fsl-mc-private.h"
912 +
913 +/**
914 + * dpcon_open() - Open a control session for the specified object
915 + * @mc_io: Pointer to MC portal's I/O object
916 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
917 + * @dpcon_id: DPCON unique ID
918 + * @token: Returned token; use in subsequent API calls
919 + *
920 + * This function can be used to open a control session for an
921 + * already created object; an object may have been declared in
922 + * the DPL or by calling the dpcon_create() function.
923 + * This function returns a unique authentication token,
924 + * associated with the specific object ID and the specific MC
925 + * portal; this token must be used in all subsequent commands for
926 + * this specific object.
927 + *
928 + * Return: '0' on Success; Error code otherwise.
929 + */
930 +int dpcon_open(struct fsl_mc_io *mc_io,
931 + u32 cmd_flags,
932 + int dpcon_id,
933 + u16 *token)
934 +{
935 + struct fsl_mc_command cmd = { 0 };
936 + struct dpcon_cmd_open *dpcon_cmd;
937 + int err;
938 +
939 + /* prepare command */
940 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_OPEN,
941 + cmd_flags,
942 + 0);
943 + dpcon_cmd = (struct dpcon_cmd_open *)cmd.params;
944 + dpcon_cmd->dpcon_id = cpu_to_le32(dpcon_id);
945 +
946 + /* send command to mc*/
947 + err = mc_send_command(mc_io, &cmd);
948 + if (err)
949 + return err;
950 +
951 + /* retrieve response parameters */
952 + *token = mc_cmd_hdr_read_token(&cmd);
953 +
954 + return 0;
955 +}
956 +EXPORT_SYMBOL_GPL(dpcon_open);
957 +
958 +/**
959 + * dpcon_close() - Close the control session of the object
960 + * @mc_io: Pointer to MC portal's I/O object
961 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
962 + * @token: Token of DPCON object
963 + *
964 + * After this function is called, no further operations are
965 + * allowed on the object without opening a new control session.
966 + *
967 + * Return: '0' on Success; Error code otherwise.
968 + */
969 +int dpcon_close(struct fsl_mc_io *mc_io,
970 + u32 cmd_flags,
971 + u16 token)
972 +{
973 + struct fsl_mc_command cmd = { 0 };
974 +
975 + /* prepare command */
976 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_CLOSE,
977 + cmd_flags,
978 + token);
979 +
980 + /* send command to mc*/
981 + return mc_send_command(mc_io, &cmd);
982 +}
983 +EXPORT_SYMBOL_GPL(dpcon_close);
984 +
985 +/**
986 + * dpcon_enable() - Enable the DPCON
987 + * @mc_io: Pointer to MC portal's I/O object
988 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
989 + * @token: Token of DPCON object
990 + *
991 + * Return: '0' on Success; Error code otherwise
992 + */
993 +int dpcon_enable(struct fsl_mc_io *mc_io,
994 + u32 cmd_flags,
995 + u16 token)
996 +{
997 + struct fsl_mc_command cmd = { 0 };
998 +
999 + /* prepare command */
1000 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_ENABLE,
1001 + cmd_flags,
1002 + token);
1003 +
1004 + /* send command to mc*/
1005 + return mc_send_command(mc_io, &cmd);
1006 +}
1007 +EXPORT_SYMBOL_GPL(dpcon_enable);
1008 +
1009 +/**
1010 + * dpcon_disable() - Disable the DPCON
1011 + * @mc_io: Pointer to MC portal's I/O object
1012 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1013 + * @token: Token of DPCON object
1014 + *
1015 + * Return: '0' on Success; Error code otherwise
1016 + */
1017 +int dpcon_disable(struct fsl_mc_io *mc_io,
1018 + u32 cmd_flags,
1019 + u16 token)
1020 +{
1021 + struct fsl_mc_command cmd = { 0 };
1022 +
1023 + /* prepare command */
1024 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_DISABLE,
1025 + cmd_flags,
1026 + token);
1027 +
1028 + /* send command to mc*/
1029 + return mc_send_command(mc_io, &cmd);
1030 +}
1031 +EXPORT_SYMBOL_GPL(dpcon_disable);
1032 +
1033 +/**
1034 + * dpcon_reset() - Reset the DPCON, returns the object to initial state.
1035 + * @mc_io: Pointer to MC portal's I/O object
1036 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1037 + * @token: Token of DPCON object
1038 + *
1039 + * Return: '0' on Success; Error code otherwise.
1040 + */
1041 +int dpcon_reset(struct fsl_mc_io *mc_io,
1042 + u32 cmd_flags,
1043 + u16 token)
1044 +{
1045 + struct fsl_mc_command cmd = { 0 };
1046 +
1047 + /* prepare command */
1048 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_RESET,
1049 + cmd_flags, token);
1050 +
1051 + /* send command to mc*/
1052 + return mc_send_command(mc_io, &cmd);
1053 +}
1054 +EXPORT_SYMBOL_GPL(dpcon_reset);
1055 +
1056 +/**
1057 + * dpcon_get_attributes() - Retrieve DPCON attributes.
1058 + * @mc_io: Pointer to MC portal's I/O object
1059 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1060 + * @token: Token of DPCON object
1061 + * @attr: Object's attributes
1062 + *
1063 + * Return: '0' on Success; Error code otherwise.
1064 + */
1065 +int dpcon_get_attributes(struct fsl_mc_io *mc_io,
1066 + u32 cmd_flags,
1067 + u16 token,
1068 + struct dpcon_attr *attr)
1069 +{
1070 + struct fsl_mc_command cmd = { 0 };
1071 + struct dpcon_rsp_get_attr *dpcon_rsp;
1072 + int err;
1073 +
1074 + /* prepare command */
1075 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_ATTR,
1076 + cmd_flags,
1077 + token);
1078 +
1079 + /* send command to mc*/
1080 + err = mc_send_command(mc_io, &cmd);
1081 + if (err)
1082 + return err;
1083 +
1084 + /* retrieve response parameters */
1085 + dpcon_rsp = (struct dpcon_rsp_get_attr *)cmd.params;
1086 + attr->id = le32_to_cpu(dpcon_rsp->id);
1087 + attr->qbman_ch_id = le16_to_cpu(dpcon_rsp->qbman_ch_id);
1088 + attr->num_priorities = dpcon_rsp->num_priorities;
1089 +
1090 + return 0;
1091 +}
1092 +EXPORT_SYMBOL_GPL(dpcon_get_attributes);
1093 +
1094 +/**
1095 + * dpcon_set_notification() - Set DPCON notification destination
1096 + * @mc_io: Pointer to MC portal's I/O object
1097 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1098 + * @token: Token of DPCON object
1099 + * @cfg: Notification parameters
1100 + *
1101 + * Return: '0' on Success; Error code otherwise
1102 + */
1103 +int dpcon_set_notification(struct fsl_mc_io *mc_io,
1104 + u32 cmd_flags,
1105 + u16 token,
1106 + struct dpcon_notification_cfg *cfg)
1107 +{
1108 + struct fsl_mc_command cmd = { 0 };
1109 + struct dpcon_cmd_set_notification *dpcon_cmd;
1110 +
1111 + /* prepare command */
1112 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_SET_NOTIFICATION,
1113 + cmd_flags,
1114 + token);
1115 + dpcon_cmd = (struct dpcon_cmd_set_notification *)cmd.params;
1116 + dpcon_cmd->dpio_id = cpu_to_le32(cfg->dpio_id);
1117 + dpcon_cmd->priority = cfg->priority;
1118 + dpcon_cmd->user_ctx = cpu_to_le64(cfg->user_ctx);
1119 +
1120 + /* send command to mc*/
1121 + return mc_send_command(mc_io, &cmd);
1122 +}
1123 +EXPORT_SYMBOL_GPL(dpcon_set_notification);
1124 --- /dev/null
1125 +++ b/drivers/bus/fsl-mc/dpmcp.c
1126 @@ -0,0 +1,99 @@
1127 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
1128 +/*
1129 + * Copyright 2013-2016 Freescale Semiconductor Inc.
1130 + *
1131 + */
1132 +#include <linux/kernel.h>
1133 +#include <linux/fsl/mc.h>
1134 +
1135 +#include "fsl-mc-private.h"
1136 +
1137 +/**
1138 + * dpmcp_open() - Open a control session for the specified object.
1139 + * @mc_io: Pointer to MC portal's I/O object
1140 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1141 + * @dpmcp_id: DPMCP unique ID
1142 + * @token: Returned token; use in subsequent API calls
1143 + *
1144 + * This function can be used to open a control session for an
1145 + * already created object; an object may have been declared in
1146 + * the DPL or by calling the dpmcp_create function.
1147 + * This function returns a unique authentication token,
1148 + * associated with the specific object ID and the specific MC
1149 + * portal; this token must be used in all subsequent commands for
1150 + * this specific object
1151 + *
1152 + * Return: '0' on Success; Error code otherwise.
1153 + */
1154 +int dpmcp_open(struct fsl_mc_io *mc_io,
1155 + u32 cmd_flags,
1156 + int dpmcp_id,
1157 + u16 *token)
1158 +{
1159 + struct fsl_mc_command cmd = { 0 };
1160 + struct dpmcp_cmd_open *cmd_params;
1161 + int err;
1162 +
1163 + /* prepare command */
1164 + cmd.header = mc_encode_cmd_header(DPMCP_CMDID_OPEN,
1165 + cmd_flags, 0);
1166 + cmd_params = (struct dpmcp_cmd_open *)cmd.params;
1167 + cmd_params->dpmcp_id = cpu_to_le32(dpmcp_id);
1168 +
1169 + /* send command to mc*/
1170 + err = mc_send_command(mc_io, &cmd);
1171 + if (err)
1172 + return err;
1173 +
1174 + /* retrieve response parameters */
1175 + *token = mc_cmd_hdr_read_token(&cmd);
1176 +
1177 + return err;
1178 +}
1179 +
1180 +/**
1181 + * dpmcp_close() - Close the control session of the object
1182 + * @mc_io: Pointer to MC portal's I/O object
1183 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1184 + * @token: Token of DPMCP object
1185 + *
1186 + * After this function is called, no further operations are
1187 + * allowed on the object without opening a new control session.
1188 + *
1189 + * Return: '0' on Success; Error code otherwise.
1190 + */
1191 +int dpmcp_close(struct fsl_mc_io *mc_io,
1192 + u32 cmd_flags,
1193 + u16 token)
1194 +{
1195 + struct fsl_mc_command cmd = { 0 };
1196 +
1197 + /* prepare command */
1198 + cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CLOSE,
1199 + cmd_flags, token);
1200 +
1201 + /* send command to mc*/
1202 + return mc_send_command(mc_io, &cmd);
1203 +}
1204 +
1205 +/**
1206 + * dpmcp_reset() - Reset the DPMCP, returns the object to initial state.
1207 + * @mc_io: Pointer to MC portal's I/O object
1208 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1209 + * @token: Token of DPMCP object
1210 + *
1211 + * Return: '0' on Success; Error code otherwise.
1212 + */
1213 +int dpmcp_reset(struct fsl_mc_io *mc_io,
1214 + u32 cmd_flags,
1215 + u16 token)
1216 +{
1217 + struct fsl_mc_command cmd = { 0 };
1218 +
1219 + /* prepare command */
1220 + cmd.header = mc_encode_cmd_header(DPMCP_CMDID_RESET,
1221 + cmd_flags, token);
1222 +
1223 + /* send command to mc*/
1224 + return mc_send_command(mc_io, &cmd);
1225 +}
1226 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c
1227 +++ /dev/null
1228 @@ -1,813 +0,0 @@
1229 -// SPDX-License-Identifier: GPL-2.0
1230 -/*
1231 - * Freescale data path resource container (DPRC) driver
1232 - *
1233 - * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
1234 - * Author: German Rivera <German.Rivera@freescale.com>
1235 - *
1236 - */
1237 -
1238 -#include <linux/module.h>
1239 -#include <linux/slab.h>
1240 -#include <linux/interrupt.h>
1241 -#include <linux/msi.h>
1242 -#include "../include/mc.h"
1243 -
1244 -#include "dprc-cmd.h"
1245 -#include "fsl-mc-private.h"
1246 -
1247 -#define FSL_MC_DPRC_DRIVER_NAME "fsl_mc_dprc"
1248 -
1249 -struct fsl_mc_child_objs {
1250 - int child_count;
1251 - struct fsl_mc_obj_desc *child_array;
1252 -};
1253 -
1254 -static bool fsl_mc_device_match(struct fsl_mc_device *mc_dev,
1255 - struct fsl_mc_obj_desc *obj_desc)
1256 -{
1257 - return mc_dev->obj_desc.id == obj_desc->id &&
1258 - strcmp(mc_dev->obj_desc.type, obj_desc->type) == 0;
1259 -
1260 -}
1261 -
1262 -static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data)
1263 -{
1264 - int i;
1265 - struct fsl_mc_child_objs *objs;
1266 - struct fsl_mc_device *mc_dev;
1267 -
1268 - WARN_ON(!dev);
1269 - WARN_ON(!data);
1270 - mc_dev = to_fsl_mc_device(dev);
1271 - objs = data;
1272 -
1273 - for (i = 0; i < objs->child_count; i++) {
1274 - struct fsl_mc_obj_desc *obj_desc = &objs->child_array[i];
1275 -
1276 - if (strlen(obj_desc->type) != 0 &&
1277 - fsl_mc_device_match(mc_dev, obj_desc))
1278 - break;
1279 - }
1280 -
1281 - if (i == objs->child_count)
1282 - fsl_mc_device_remove(mc_dev);
1283 -
1284 - return 0;
1285 -}
1286 -
1287 -static int __fsl_mc_device_remove(struct device *dev, void *data)
1288 -{
1289 - WARN_ON(!dev);
1290 - WARN_ON(data);
1291 - fsl_mc_device_remove(to_fsl_mc_device(dev));
1292 - return 0;
1293 -}
1294 -
1295 -/**
1296 - * dprc_remove_devices - Removes devices for objects removed from a DPRC
1297 - *
1298 - * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
1299 - * @obj_desc_array: array of object descriptors for child objects currently
1300 - * present in the DPRC in the MC.
1301 - * @num_child_objects_in_mc: number of entries in obj_desc_array
1302 - *
1303 - * Synchronizes the state of the Linux bus driver with the actual state of
1304 - * the MC by removing devices that represent MC objects that have
1305 - * been dynamically removed in the physical DPRC.
1306 - */
1307 -static void dprc_remove_devices(struct fsl_mc_device *mc_bus_dev,
1308 - struct fsl_mc_obj_desc *obj_desc_array,
1309 - int num_child_objects_in_mc)
1310 -{
1311 - if (num_child_objects_in_mc != 0) {
1312 - /*
1313 - * Remove child objects that are in the DPRC in Linux,
1314 - * but not in the MC:
1315 - */
1316 - struct fsl_mc_child_objs objs;
1317 -
1318 - objs.child_count = num_child_objects_in_mc;
1319 - objs.child_array = obj_desc_array;
1320 - device_for_each_child(&mc_bus_dev->dev, &objs,
1321 - __fsl_mc_device_remove_if_not_in_mc);
1322 - } else {
1323 - /*
1324 - * There are no child objects for this DPRC in the MC.
1325 - * So, remove all the child devices from Linux:
1326 - */
1327 - device_for_each_child(&mc_bus_dev->dev, NULL,
1328 - __fsl_mc_device_remove);
1329 - }
1330 -}
1331 -
1332 -static int __fsl_mc_device_match(struct device *dev, void *data)
1333 -{
1334 - struct fsl_mc_obj_desc *obj_desc = data;
1335 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
1336 -
1337 - return fsl_mc_device_match(mc_dev, obj_desc);
1338 -}
1339 -
1340 -static struct fsl_mc_device *fsl_mc_device_lookup(struct fsl_mc_obj_desc
1341 - *obj_desc,
1342 - struct fsl_mc_device
1343 - *mc_bus_dev)
1344 -{
1345 - struct device *dev;
1346 -
1347 - dev = device_find_child(&mc_bus_dev->dev, obj_desc,
1348 - __fsl_mc_device_match);
1349 -
1350 - return dev ? to_fsl_mc_device(dev) : NULL;
1351 -}
1352 -
1353 -/**
1354 - * check_plugged_state_change - Check change in an MC object's plugged state
1355 - *
1356 - * @mc_dev: pointer to the fsl-mc device for a given MC object
1357 - * @obj_desc: pointer to the MC object's descriptor in the MC
1358 - *
1359 - * If the plugged state has changed from unplugged to plugged, the fsl-mc
1360 - * device is bound to the corresponding device driver.
1361 - * If the plugged state has changed from plugged to unplugged, the fsl-mc
1362 - * device is unbound from the corresponding device driver.
1363 - */
1364 -static void check_plugged_state_change(struct fsl_mc_device *mc_dev,
1365 - struct fsl_mc_obj_desc *obj_desc)
1366 -{
1367 - int error;
1368 - u32 plugged_flag_at_mc =
1369 - obj_desc->state & FSL_MC_OBJ_STATE_PLUGGED;
1370 -
1371 - if (plugged_flag_at_mc !=
1372 - (mc_dev->obj_desc.state & FSL_MC_OBJ_STATE_PLUGGED)) {
1373 - if (plugged_flag_at_mc) {
1374 - mc_dev->obj_desc.state |= FSL_MC_OBJ_STATE_PLUGGED;
1375 - error = device_attach(&mc_dev->dev);
1376 - if (error < 0) {
1377 - dev_err(&mc_dev->dev,
1378 - "device_attach() failed: %d\n",
1379 - error);
1380 - }
1381 - } else {
1382 - mc_dev->obj_desc.state &= ~FSL_MC_OBJ_STATE_PLUGGED;
1383 - device_release_driver(&mc_dev->dev);
1384 - }
1385 - }
1386 -}
1387 -
1388 -/**
1389 - * dprc_add_new_devices - Adds devices to the logical bus for a DPRC
1390 - *
1391 - * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
1392 - * @obj_desc_array: array of device descriptors for child devices currently
1393 - * present in the physical DPRC.
1394 - * @num_child_objects_in_mc: number of entries in obj_desc_array
1395 - *
1396 - * Synchronizes the state of the Linux bus driver with the actual
1397 - * state of the MC by adding objects that have been newly discovered
1398 - * in the physical DPRC.
1399 - */
1400 -static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev,
1401 - struct fsl_mc_obj_desc *obj_desc_array,
1402 - int num_child_objects_in_mc)
1403 -{
1404 - int error;
1405 - int i;
1406 -
1407 - for (i = 0; i < num_child_objects_in_mc; i++) {
1408 - struct fsl_mc_device *child_dev;
1409 - struct fsl_mc_obj_desc *obj_desc = &obj_desc_array[i];
1410 -
1411 - if (strlen(obj_desc->type) == 0)
1412 - continue;
1413 -
1414 - /*
1415 - * Check if device is already known to Linux:
1416 - */
1417 - child_dev = fsl_mc_device_lookup(obj_desc, mc_bus_dev);
1418 - if (child_dev) {
1419 - check_plugged_state_change(child_dev, obj_desc);
1420 - put_device(&child_dev->dev);
1421 - continue;
1422 - }
1423 -
1424 - error = fsl_mc_device_add(obj_desc, NULL, &mc_bus_dev->dev,
1425 - &child_dev);
1426 - if (error < 0)
1427 - continue;
1428 - }
1429 -}
1430 -
1431 -/**
1432 - * dprc_scan_objects - Discover objects in a DPRC
1433 - *
1434 - * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
1435 - * @total_irq_count: total number of IRQs needed by objects in the DPRC.
1436 - *
1437 - * Detects objects added and removed from a DPRC and synchronizes the
1438 - * state of the Linux bus driver, MC by adding and removing
1439 - * devices accordingly.
1440 - * Two types of devices can be found in a DPRC: allocatable objects (e.g.,
1441 - * dpbp, dpmcp) and non-allocatable devices (e.g., dprc, dpni).
1442 - * All allocatable devices needed to be probed before all non-allocatable
1443 - * devices, to ensure that device drivers for non-allocatable
1444 - * devices can allocate any type of allocatable devices.
1445 - * That is, we need to ensure that the corresponding resource pools are
1446 - * populated before they can get allocation requests from probe callbacks
1447 - * of the device drivers for the non-allocatable devices.
1448 - */
1449 -static int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
1450 - unsigned int *total_irq_count)
1451 -{
1452 - int num_child_objects;
1453 - int dprc_get_obj_failures;
1454 - int error;
1455 - unsigned int irq_count = mc_bus_dev->obj_desc.irq_count;
1456 - struct fsl_mc_obj_desc *child_obj_desc_array = NULL;
1457 -
1458 - error = dprc_get_obj_count(mc_bus_dev->mc_io,
1459 - 0,
1460 - mc_bus_dev->mc_handle,
1461 - &num_child_objects);
1462 - if (error < 0) {
1463 - dev_err(&mc_bus_dev->dev, "dprc_get_obj_count() failed: %d\n",
1464 - error);
1465 - return error;
1466 - }
1467 -
1468 - if (num_child_objects != 0) {
1469 - int i;
1470 -
1471 - child_obj_desc_array =
1472 - devm_kmalloc_array(&mc_bus_dev->dev, num_child_objects,
1473 - sizeof(*child_obj_desc_array),
1474 - GFP_KERNEL);
1475 - if (!child_obj_desc_array)
1476 - return -ENOMEM;
1477 -
1478 - /*
1479 - * Discover objects currently present in the physical DPRC:
1480 - */
1481 - dprc_get_obj_failures = 0;
1482 - for (i = 0; i < num_child_objects; i++) {
1483 - struct fsl_mc_obj_desc *obj_desc =
1484 - &child_obj_desc_array[i];
1485 -
1486 - error = dprc_get_obj(mc_bus_dev->mc_io,
1487 - 0,
1488 - mc_bus_dev->mc_handle,
1489 - i, obj_desc);
1490 - if (error < 0) {
1491 - dev_err(&mc_bus_dev->dev,
1492 - "dprc_get_obj(i=%d) failed: %d\n",
1493 - i, error);
1494 - /*
1495 - * Mark the obj entry as "invalid", by using the
1496 - * empty string as obj type:
1497 - */
1498 - obj_desc->type[0] = '\0';
1499 - obj_desc->id = error;
1500 - dprc_get_obj_failures++;
1501 - continue;
1502 - }
1503 -
1504 - /*
1505 - * add a quirk for all versions of dpsec < 4.0...none
1506 - * are coherent regardless of what the MC reports.
1507 - */
1508 - if ((strcmp(obj_desc->type, "dpseci") == 0) &&
1509 - (obj_desc->ver_major < 4))
1510 - obj_desc->flags |=
1511 - FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY;
1512 -
1513 - irq_count += obj_desc->irq_count;
1514 - dev_dbg(&mc_bus_dev->dev,
1515 - "Discovered object: type %s, id %d\n",
1516 - obj_desc->type, obj_desc->id);
1517 - }
1518 -
1519 - if (dprc_get_obj_failures != 0) {
1520 - dev_err(&mc_bus_dev->dev,
1521 - "%d out of %d devices could not be retrieved\n",
1522 - dprc_get_obj_failures, num_child_objects);
1523 - }
1524 - }
1525 -
1526 - *total_irq_count = irq_count;
1527 - dprc_remove_devices(mc_bus_dev, child_obj_desc_array,
1528 - num_child_objects);
1529 -
1530 - dprc_add_new_devices(mc_bus_dev, child_obj_desc_array,
1531 - num_child_objects);
1532 -
1533 - if (child_obj_desc_array)
1534 - devm_kfree(&mc_bus_dev->dev, child_obj_desc_array);
1535 -
1536 - return 0;
1537 -}
1538 -
1539 -/**
1540 - * dprc_scan_container - Scans a physical DPRC and synchronizes Linux bus state
1541 - *
1542 - * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
1543 - *
1544 - * Scans the physical DPRC and synchronizes the state of the Linux
1545 - * bus driver with the actual state of the MC by adding and removing
1546 - * devices as appropriate.
1547 - */
1548 -static int dprc_scan_container(struct fsl_mc_device *mc_bus_dev)
1549 -{
1550 - int error;
1551 - unsigned int irq_count;
1552 - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
1553 -
1554 - fsl_mc_init_all_resource_pools(mc_bus_dev);
1555 -
1556 - /*
1557 - * Discover objects in the DPRC:
1558 - */
1559 - mutex_lock(&mc_bus->scan_mutex);
1560 - error = dprc_scan_objects(mc_bus_dev, &irq_count);
1561 - mutex_unlock(&mc_bus->scan_mutex);
1562 - if (error < 0)
1563 - goto error;
1564 -
1565 - if (dev_get_msi_domain(&mc_bus_dev->dev) && !mc_bus->irq_resources) {
1566 - if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) {
1567 - dev_warn(&mc_bus_dev->dev,
1568 - "IRQs needed (%u) exceed IRQs preallocated (%u)\n",
1569 - irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
1570 - }
1571 -
1572 - error = fsl_mc_populate_irq_pool(
1573 - mc_bus,
1574 - FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
1575 - if (error < 0)
1576 - goto error;
1577 - }
1578 -
1579 - return 0;
1580 -error:
1581 - fsl_mc_cleanup_all_resource_pools(mc_bus_dev);
1582 - return error;
1583 -}
1584 -
1585 -/**
1586 - * dprc_irq0_handler - Regular ISR for DPRC interrupt 0
1587 - *
1588 - * @irq: IRQ number of the interrupt being handled
1589 - * @arg: Pointer to device structure
1590 - */
1591 -static irqreturn_t dprc_irq0_handler(int irq_num, void *arg)
1592 -{
1593 - return IRQ_WAKE_THREAD;
1594 -}
1595 -
1596 -/**
1597 - * dprc_irq0_handler_thread - Handler thread function for DPRC interrupt 0
1598 - *
1599 - * @irq: IRQ number of the interrupt being handled
1600 - * @arg: Pointer to device structure
1601 - */
1602 -static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg)
1603 -{
1604 - int error;
1605 - u32 status;
1606 - struct device *dev = arg;
1607 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
1608 - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
1609 - struct fsl_mc_io *mc_io = mc_dev->mc_io;
1610 - struct msi_desc *msi_desc = mc_dev->irqs[0]->msi_desc;
1611 -
1612 - dev_dbg(dev, "DPRC IRQ %d triggered on CPU %u\n",
1613 - irq_num, smp_processor_id());
1614 -
1615 - if (WARN_ON(!(mc_dev->flags & FSL_MC_IS_DPRC)))
1616 - return IRQ_HANDLED;
1617 -
1618 - mutex_lock(&mc_bus->scan_mutex);
1619 - if (WARN_ON(!msi_desc || msi_desc->irq != (u32)irq_num))
1620 - goto out;
1621 -
1622 - status = 0;
1623 - error = dprc_get_irq_status(mc_io, 0, mc_dev->mc_handle, 0,
1624 - &status);
1625 - if (error < 0) {
1626 - dev_err(dev,
1627 - "dprc_get_irq_status() failed: %d\n", error);
1628 - goto out;
1629 - }
1630 -
1631 - error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0,
1632 - status);
1633 - if (error < 0) {
1634 - dev_err(dev,
1635 - "dprc_clear_irq_status() failed: %d\n", error);
1636 - goto out;
1637 - }
1638 -
1639 - if (status & (DPRC_IRQ_EVENT_OBJ_ADDED |
1640 - DPRC_IRQ_EVENT_OBJ_REMOVED |
1641 - DPRC_IRQ_EVENT_CONTAINER_DESTROYED |
1642 - DPRC_IRQ_EVENT_OBJ_DESTROYED |
1643 - DPRC_IRQ_EVENT_OBJ_CREATED)) {
1644 - unsigned int irq_count;
1645 -
1646 - error = dprc_scan_objects(mc_dev, &irq_count);
1647 - if (error < 0) {
1648 - /*
1649 - * If the error is -ENXIO, we ignore it, as it indicates
1650 - * that the object scan was aborted, as we detected that
1651 - * an object was removed from the DPRC in the MC, while
1652 - * we were scanning the DPRC.
1653 - */
1654 - if (error != -ENXIO) {
1655 - dev_err(dev, "dprc_scan_objects() failed: %d\n",
1656 - error);
1657 - }
1658 -
1659 - goto out;
1660 - }
1661 -
1662 - if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) {
1663 - dev_warn(dev,
1664 - "IRQs needed (%u) exceed IRQs preallocated (%u)\n",
1665 - irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
1666 - }
1667 - }
1668 -
1669 -out:
1670 - mutex_unlock(&mc_bus->scan_mutex);
1671 - return IRQ_HANDLED;
1672 -}
1673 -
1674 -/*
1675 - * Disable and clear interrupt for a given DPRC object
1676 - */
1677 -static int disable_dprc_irq(struct fsl_mc_device *mc_dev)
1678 -{
1679 - int error;
1680 - struct fsl_mc_io *mc_io = mc_dev->mc_io;
1681 -
1682 - WARN_ON(mc_dev->obj_desc.irq_count != 1);
1683 -
1684 - /*
1685 - * Disable generation of interrupt, while we configure it:
1686 - */
1687 - error = dprc_set_irq_enable(mc_io, 0, mc_dev->mc_handle, 0, 0);
1688 - if (error < 0) {
1689 - dev_err(&mc_dev->dev,
1690 - "Disabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n",
1691 - error);
1692 - return error;
1693 - }
1694 -
1695 - /*
1696 - * Disable all interrupt causes for the interrupt:
1697 - */
1698 - error = dprc_set_irq_mask(mc_io, 0, mc_dev->mc_handle, 0, 0x0);
1699 - if (error < 0) {
1700 - dev_err(&mc_dev->dev,
1701 - "Disabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n",
1702 - error);
1703 - return error;
1704 - }
1705 -
1706 - /*
1707 - * Clear any leftover interrupts:
1708 - */
1709 - error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, ~0x0U);
1710 - if (error < 0) {
1711 - dev_err(&mc_dev->dev,
1712 - "Disabling DPRC IRQ failed: dprc_clear_irq_status() failed: %d\n",
1713 - error);
1714 - return error;
1715 - }
1716 -
1717 - return 0;
1718 -}
1719 -
1720 -static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev)
1721 -{
1722 - int error;
1723 - struct fsl_mc_device_irq *irq = mc_dev->irqs[0];
1724 -
1725 - WARN_ON(mc_dev->obj_desc.irq_count != 1);
1726 -
1727 - /*
1728 - * NOTE: devm_request_threaded_irq() invokes the device-specific
1729 - * function that programs the MSI physically in the device
1730 - */
1731 - error = devm_request_threaded_irq(&mc_dev->dev,
1732 - irq->msi_desc->irq,
1733 - dprc_irq0_handler,
1734 - dprc_irq0_handler_thread,
1735 - IRQF_NO_SUSPEND | IRQF_ONESHOT,
1736 - dev_name(&mc_dev->dev),
1737 - &mc_dev->dev);
1738 - if (error < 0) {
1739 - dev_err(&mc_dev->dev,
1740 - "devm_request_threaded_irq() failed: %d\n",
1741 - error);
1742 - return error;
1743 - }
1744 -
1745 - return 0;
1746 -}
1747 -
1748 -static int enable_dprc_irq(struct fsl_mc_device *mc_dev)
1749 -{
1750 - int error;
1751 -
1752 - /*
1753 - * Enable all interrupt causes for the interrupt:
1754 - */
1755 - error = dprc_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle, 0,
1756 - ~0x0u);
1757 - if (error < 0) {
1758 - dev_err(&mc_dev->dev,
1759 - "Enabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n",
1760 - error);
1761 -
1762 - return error;
1763 - }
1764 -
1765 - /*
1766 - * Enable generation of the interrupt:
1767 - */
1768 - error = dprc_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, 1);
1769 - if (error < 0) {
1770 - dev_err(&mc_dev->dev,
1771 - "Enabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n",
1772 - error);
1773 -
1774 - return error;
1775 - }
1776 -
1777 - return 0;
1778 -}
1779 -
1780 -/*
1781 - * Setup interrupt for a given DPRC device
1782 - */
1783 -static int dprc_setup_irq(struct fsl_mc_device *mc_dev)
1784 -{
1785 - int error;
1786 -
1787 - error = fsl_mc_allocate_irqs(mc_dev);
1788 - if (error < 0)
1789 - return error;
1790 -
1791 - error = disable_dprc_irq(mc_dev);
1792 - if (error < 0)
1793 - goto error_free_irqs;
1794 -
1795 - error = register_dprc_irq_handler(mc_dev);
1796 - if (error < 0)
1797 - goto error_free_irqs;
1798 -
1799 - error = enable_dprc_irq(mc_dev);
1800 - if (error < 0)
1801 - goto error_free_irqs;
1802 -
1803 - return 0;
1804 -
1805 -error_free_irqs:
1806 - fsl_mc_free_irqs(mc_dev);
1807 - return error;
1808 -}
1809 -
1810 -/**
1811 - * dprc_probe - callback invoked when a DPRC is being bound to this driver
1812 - *
1813 - * @mc_dev: Pointer to fsl-mc device representing a DPRC
1814 - *
1815 - * It opens the physical DPRC in the MC.
1816 - * It scans the DPRC to discover the MC objects contained in it.
1817 - * It creates the interrupt pool for the MC bus associated with the DPRC.
1818 - * It configures the interrupts for the DPRC device itself.
1819 - */
1820 -static int dprc_probe(struct fsl_mc_device *mc_dev)
1821 -{
1822 - int error;
1823 - size_t region_size;
1824 - struct device *parent_dev = mc_dev->dev.parent;
1825 - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
1826 - bool mc_io_created = false;
1827 - bool msi_domain_set = false;
1828 - u16 major_ver, minor_ver;
1829 -
1830 - if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0))
1831 - return -EINVAL;
1832 -
1833 - if (WARN_ON(dev_get_msi_domain(&mc_dev->dev)))
1834 - return -EINVAL;
1835 -
1836 - if (!mc_dev->mc_io) {
1837 - /*
1838 - * This is a child DPRC:
1839 - */
1840 - if (WARN_ON(!dev_is_fsl_mc(parent_dev)))
1841 - return -EINVAL;
1842 -
1843 - if (WARN_ON(mc_dev->obj_desc.region_count == 0))
1844 - return -EINVAL;
1845 -
1846 - region_size = resource_size(mc_dev->regions);
1847 -
1848 - error = fsl_create_mc_io(&mc_dev->dev,
1849 - mc_dev->regions[0].start,
1850 - region_size,
1851 - NULL,
1852 - FSL_MC_IO_ATOMIC_CONTEXT_PORTAL,
1853 - &mc_dev->mc_io);
1854 - if (error < 0)
1855 - return error;
1856 -
1857 - mc_io_created = true;
1858 -
1859 - /*
1860 - * Inherit parent MSI domain:
1861 - */
1862 - dev_set_msi_domain(&mc_dev->dev,
1863 - dev_get_msi_domain(parent_dev));
1864 - msi_domain_set = true;
1865 - } else {
1866 - /*
1867 - * This is a root DPRC
1868 - */
1869 - struct irq_domain *mc_msi_domain;
1870 -
1871 - if (WARN_ON(dev_is_fsl_mc(parent_dev)))
1872 - return -EINVAL;
1873 -
1874 - error = fsl_mc_find_msi_domain(parent_dev,
1875 - &mc_msi_domain);
1876 - if (error < 0) {
1877 - dev_warn(&mc_dev->dev,
1878 - "WARNING: MC bus without interrupt support\n");
1879 - } else {
1880 - dev_set_msi_domain(&mc_dev->dev, mc_msi_domain);
1881 - msi_domain_set = true;
1882 - }
1883 - }
1884 -
1885 - error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
1886 - &mc_dev->mc_handle);
1887 - if (error < 0) {
1888 - dev_err(&mc_dev->dev, "dprc_open() failed: %d\n", error);
1889 - goto error_cleanup_msi_domain;
1890 - }
1891 -
1892 - error = dprc_get_attributes(mc_dev->mc_io, 0, mc_dev->mc_handle,
1893 - &mc_bus->dprc_attr);
1894 - if (error < 0) {
1895 - dev_err(&mc_dev->dev, "dprc_get_attributes() failed: %d\n",
1896 - error);
1897 - goto error_cleanup_open;
1898 - }
1899 -
1900 - error = dprc_get_api_version(mc_dev->mc_io, 0,
1901 - &major_ver,
1902 - &minor_ver);
1903 - if (error < 0) {
1904 - dev_err(&mc_dev->dev, "dprc_get_api_version() failed: %d\n",
1905 - error);
1906 - goto error_cleanup_open;
1907 - }
1908 -
1909 - if (major_ver < DPRC_MIN_VER_MAJOR ||
1910 - (major_ver == DPRC_MIN_VER_MAJOR &&
1911 - minor_ver < DPRC_MIN_VER_MINOR)) {
1912 - dev_err(&mc_dev->dev,
1913 - "ERROR: DPRC version %d.%d not supported\n",
1914 - major_ver, minor_ver);
1915 - error = -ENOTSUPP;
1916 - goto error_cleanup_open;
1917 - }
1918 -
1919 - mutex_init(&mc_bus->scan_mutex);
1920 -
1921 - /*
1922 - * Discover MC objects in DPRC object:
1923 - */
1924 - error = dprc_scan_container(mc_dev);
1925 - if (error < 0)
1926 - goto error_cleanup_open;
1927 -
1928 - /*
1929 - * Configure interrupt for the DPRC object associated with this MC bus:
1930 - */
1931 - error = dprc_setup_irq(mc_dev);
1932 - if (error < 0)
1933 - goto error_cleanup_open;
1934 -
1935 - dev_info(&mc_dev->dev, "DPRC device bound to driver");
1936 - return 0;
1937 -
1938 -error_cleanup_open:
1939 - (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
1940 -
1941 -error_cleanup_msi_domain:
1942 - if (msi_domain_set)
1943 - dev_set_msi_domain(&mc_dev->dev, NULL);
1944 -
1945 - if (mc_io_created) {
1946 - fsl_destroy_mc_io(mc_dev->mc_io);
1947 - mc_dev->mc_io = NULL;
1948 - }
1949 -
1950 - return error;
1951 -}
1952 -
1953 -/*
1954 - * Tear down interrupt for a given DPRC object
1955 - */
1956 -static void dprc_teardown_irq(struct fsl_mc_device *mc_dev)
1957 -{
1958 - struct fsl_mc_device_irq *irq = mc_dev->irqs[0];
1959 -
1960 - (void)disable_dprc_irq(mc_dev);
1961 -
1962 - devm_free_irq(&mc_dev->dev, irq->msi_desc->irq, &mc_dev->dev);
1963 -
1964 - fsl_mc_free_irqs(mc_dev);
1965 -}
1966 -
1967 -/**
1968 - * dprc_remove - callback invoked when a DPRC is being unbound from this driver
1969 - *
1970 - * @mc_dev: Pointer to fsl-mc device representing the DPRC
1971 - *
1972 - * It removes the DPRC's child objects from Linux (not from the MC) and
1973 - * closes the DPRC device in the MC.
1974 - * It tears down the interrupts that were configured for the DPRC device.
1975 - * It destroys the interrupt pool associated with this MC bus.
1976 - */
1977 -static int dprc_remove(struct fsl_mc_device *mc_dev)
1978 -{
1979 - int error;
1980 - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
1981 -
1982 - if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0))
1983 - return -EINVAL;
1984 - if (WARN_ON(!mc_dev->mc_io))
1985 - return -EINVAL;
1986 -
1987 - if (WARN_ON(!mc_bus->irq_resources))
1988 - return -EINVAL;
1989 -
1990 - if (dev_get_msi_domain(&mc_dev->dev))
1991 - dprc_teardown_irq(mc_dev);
1992 -
1993 - device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove);
1994 -
1995 - if (dev_get_msi_domain(&mc_dev->dev)) {
1996 - fsl_mc_cleanup_irq_pool(mc_bus);
1997 - dev_set_msi_domain(&mc_dev->dev, NULL);
1998 - }
1999 -
2000 - fsl_mc_cleanup_all_resource_pools(mc_dev);
2001 -
2002 - error = dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
2003 - if (error < 0)
2004 - dev_err(&mc_dev->dev, "dprc_close() failed: %d\n", error);
2005 -
2006 - if (!fsl_mc_is_root_dprc(&mc_dev->dev)) {
2007 - fsl_destroy_mc_io(mc_dev->mc_io);
2008 - mc_dev->mc_io = NULL;
2009 - }
2010 -
2011 - dev_info(&mc_dev->dev, "DPRC device unbound from driver");
2012 - return 0;
2013 -}
2014 -
2015 -static const struct fsl_mc_device_id match_id_table[] = {
2016 - {
2017 - .vendor = FSL_MC_VENDOR_FREESCALE,
2018 - .obj_type = "dprc"},
2019 - {.vendor = 0x0},
2020 -};
2021 -
2022 -static struct fsl_mc_driver dprc_driver = {
2023 - .driver = {
2024 - .name = FSL_MC_DPRC_DRIVER_NAME,
2025 - .owner = THIS_MODULE,
2026 - .pm = NULL,
2027 - },
2028 - .match_id_table = match_id_table,
2029 - .probe = dprc_probe,
2030 - .remove = dprc_remove,
2031 -};
2032 -
2033 -int __init dprc_driver_init(void)
2034 -{
2035 - return fsl_mc_driver_register(&dprc_driver);
2036 -}
2037 -
2038 -void dprc_driver_exit(void)
2039 -{
2040 - fsl_mc_driver_unregister(&dprc_driver);
2041 -}
2042 --- /dev/null
2043 +++ b/drivers/bus/fsl-mc/dprc-driver.c
2044 @@ -0,0 +1,815 @@
2045 +// SPDX-License-Identifier: GPL-2.0
2046 +/*
2047 + * Freescale data path resource container (DPRC) driver
2048 + *
2049 + * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
2050 + * Author: German Rivera <German.Rivera@freescale.com>
2051 + *
2052 + */
2053 +
2054 +#include <linux/module.h>
2055 +#include <linux/slab.h>
2056 +#include <linux/interrupt.h>
2057 +#include <linux/msi.h>
2058 +#include <linux/fsl/mc.h>
2059 +
2060 +#include "fsl-mc-private.h"
2061 +
2062 +#define FSL_MC_DPRC_DRIVER_NAME "fsl_mc_dprc"
2063 +
2064 +struct fsl_mc_child_objs {
2065 + int child_count;
2066 + struct fsl_mc_obj_desc *child_array;
2067 +};
2068 +
2069 +static bool fsl_mc_device_match(struct fsl_mc_device *mc_dev,
2070 + struct fsl_mc_obj_desc *obj_desc)
2071 +{
2072 + return mc_dev->obj_desc.id == obj_desc->id &&
2073 + strcmp(mc_dev->obj_desc.type, obj_desc->type) == 0;
2074 +
2075 +}
2076 +
2077 +static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data)
2078 +{
2079 + int i;
2080 + struct fsl_mc_child_objs *objs;
2081 + struct fsl_mc_device *mc_dev;
2082 +
2083 + mc_dev = to_fsl_mc_device(dev);
2084 + objs = data;
2085 +
2086 + for (i = 0; i < objs->child_count; i++) {
2087 + struct fsl_mc_obj_desc *obj_desc = &objs->child_array[i];
2088 +
2089 + if (strlen(obj_desc->type) != 0 &&
2090 + fsl_mc_device_match(mc_dev, obj_desc))
2091 + break;
2092 + }
2093 +
2094 + if (i == objs->child_count)
2095 + fsl_mc_device_remove(mc_dev);
2096 +
2097 + return 0;
2098 +}
2099 +
2100 +static int __fsl_mc_device_remove(struct device *dev, void *data)
2101 +{
2102 + fsl_mc_device_remove(to_fsl_mc_device(dev));
2103 + return 0;
2104 +}
2105 +
2106 +/**
2107 + * dprc_remove_devices - Removes devices for objects removed from a DPRC
2108 + *
2109 + * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
2110 + * @obj_desc_array: array of object descriptors for child objects currently
2111 + * present in the DPRC in the MC.
2112 + * @num_child_objects_in_mc: number of entries in obj_desc_array
2113 + *
2114 + * Synchronizes the state of the Linux bus driver with the actual state of
2115 + * the MC by removing devices that represent MC objects that have
2116 + * been dynamically removed in the physical DPRC.
2117 + */
2118 +static void dprc_remove_devices(struct fsl_mc_device *mc_bus_dev,
2119 + struct fsl_mc_obj_desc *obj_desc_array,
2120 + int num_child_objects_in_mc)
2121 +{
2122 + if (num_child_objects_in_mc != 0) {
2123 + /*
2124 + * Remove child objects that are in the DPRC in Linux,
2125 + * but not in the MC:
2126 + */
2127 + struct fsl_mc_child_objs objs;
2128 +
2129 + objs.child_count = num_child_objects_in_mc;
2130 + objs.child_array = obj_desc_array;
2131 + device_for_each_child(&mc_bus_dev->dev, &objs,
2132 + __fsl_mc_device_remove_if_not_in_mc);
2133 + } else {
2134 + /*
2135 + * There are no child objects for this DPRC in the MC.
2136 + * So, remove all the child devices from Linux:
2137 + */
2138 + device_for_each_child(&mc_bus_dev->dev, NULL,
2139 + __fsl_mc_device_remove);
2140 + }
2141 +}
2142 +
2143 +static int __fsl_mc_device_match(struct device *dev, void *data)
2144 +{
2145 + struct fsl_mc_obj_desc *obj_desc = data;
2146 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
2147 +
2148 + return fsl_mc_device_match(mc_dev, obj_desc);
2149 +}
2150 +
2151 +static struct fsl_mc_device *fsl_mc_device_lookup(struct fsl_mc_obj_desc
2152 + *obj_desc,
2153 + struct fsl_mc_device
2154 + *mc_bus_dev)
2155 +{
2156 + struct device *dev;
2157 +
2158 + dev = device_find_child(&mc_bus_dev->dev, obj_desc,
2159 + __fsl_mc_device_match);
2160 +
2161 + return dev ? to_fsl_mc_device(dev) : NULL;
2162 +}
2163 +
2164 +/**
2165 + * check_plugged_state_change - Check change in an MC object's plugged state
2166 + *
2167 + * @mc_dev: pointer to the fsl-mc device for a given MC object
2168 + * @obj_desc: pointer to the MC object's descriptor in the MC
2169 + *
2170 + * If the plugged state has changed from unplugged to plugged, the fsl-mc
2171 + * device is bound to the corresponding device driver.
2172 + * If the plugged state has changed from plugged to unplugged, the fsl-mc
2173 + * device is unbound from the corresponding device driver.
2174 + */
2175 +static void check_plugged_state_change(struct fsl_mc_device *mc_dev,
2176 + struct fsl_mc_obj_desc *obj_desc)
2177 +{
2178 + int error;
2179 + u32 plugged_flag_at_mc =
2180 + obj_desc->state & FSL_MC_OBJ_STATE_PLUGGED;
2181 +
2182 + if (plugged_flag_at_mc !=
2183 + (mc_dev->obj_desc.state & FSL_MC_OBJ_STATE_PLUGGED)) {
2184 + if (plugged_flag_at_mc) {
2185 + mc_dev->obj_desc.state |= FSL_MC_OBJ_STATE_PLUGGED;
2186 + error = device_attach(&mc_dev->dev);
2187 + if (error < 0) {
2188 + dev_err(&mc_dev->dev,
2189 + "device_attach() failed: %d\n",
2190 + error);
2191 + }
2192 + } else {
2193 + mc_dev->obj_desc.state &= ~FSL_MC_OBJ_STATE_PLUGGED;
2194 + device_release_driver(&mc_dev->dev);
2195 + }
2196 + }
2197 +}
2198 +
2199 +/**
2200 + * dprc_add_new_devices - Adds devices to the logical bus for a DPRC
2201 + *
2202 + * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
2203 + * @driver_override: driver override to apply to new objects found in the
2204 + * DPRC, or NULL, if none.
2205 + * @obj_desc_array: array of device descriptors for child devices currently
2206 + * present in the physical DPRC.
2207 + * @num_child_objects_in_mc: number of entries in obj_desc_array
2208 + *
2209 + * Synchronizes the state of the Linux bus driver with the actual
2210 + * state of the MC by adding objects that have been newly discovered
2211 + * in the physical DPRC.
2212 + */
2213 +static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev,
2214 + const char *driver_override,
2215 + struct fsl_mc_obj_desc *obj_desc_array,
2216 + int num_child_objects_in_mc)
2217 +{
2218 + int error;
2219 + int i;
2220 +
2221 + for (i = 0; i < num_child_objects_in_mc; i++) {
2222 + struct fsl_mc_device *child_dev;
2223 + struct fsl_mc_obj_desc *obj_desc = &obj_desc_array[i];
2224 +
2225 + if (strlen(obj_desc->type) == 0)
2226 + continue;
2227 +
2228 + /*
2229 + * Check if device is already known to Linux:
2230 + */
2231 + child_dev = fsl_mc_device_lookup(obj_desc, mc_bus_dev);
2232 + if (child_dev) {
2233 + check_plugged_state_change(child_dev, obj_desc);
2234 + put_device(&child_dev->dev);
2235 + continue;
2236 + }
2237 +
2238 + error = fsl_mc_device_add(obj_desc, NULL, &mc_bus_dev->dev,
2239 + driver_override, &child_dev);
2240 + if (error < 0)
2241 + continue;
2242 + }
2243 +}
2244 +
2245 +/**
2246 + * dprc_scan_objects - Discover objects in a DPRC
2247 + *
2248 + * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
2249 + * @driver_override: driver override to apply to new objects found in the
2250 + * DPRC, or NULL, if none.
2251 + * @total_irq_count: If argument is provided the function populates the
2252 + * total number of IRQs created by objects in the DPRC.
2253 + *
2254 + * Detects objects added and removed from a DPRC and synchronizes the
2255 + * state of the Linux bus driver, MC by adding and removing
2256 + * devices accordingly.
2257 + * Two types of devices can be found in a DPRC: allocatable objects (e.g.,
2258 + * dpbp, dpmcp) and non-allocatable devices (e.g., dprc, dpni).
2259 + * All allocatable devices needed to be probed before all non-allocatable
2260 + * devices, to ensure that device drivers for non-allocatable
2261 + * devices can allocate any type of allocatable devices.
2262 + * That is, we need to ensure that the corresponding resource pools are
2263 + * populated before they can get allocation requests from probe callbacks
2264 + * of the device drivers for the non-allocatable devices.
2265 + */
2266 +int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
2267 + const char *driver_override,
2268 + unsigned int *total_irq_count)
2269 +{
2270 + int num_child_objects;
2271 + int dprc_get_obj_failures;
2272 + int error;
2273 + unsigned int irq_count = mc_bus_dev->obj_desc.irq_count;
2274 + struct fsl_mc_obj_desc *child_obj_desc_array = NULL;
2275 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
2276 +
2277 + error = dprc_get_obj_count(mc_bus_dev->mc_io,
2278 + 0,
2279 + mc_bus_dev->mc_handle,
2280 + &num_child_objects);
2281 + if (error < 0) {
2282 + dev_err(&mc_bus_dev->dev, "dprc_get_obj_count() failed: %d\n",
2283 + error);
2284 + return error;
2285 + }
2286 +
2287 + if (num_child_objects != 0) {
2288 + int i;
2289 +
2290 + child_obj_desc_array =
2291 + devm_kmalloc_array(&mc_bus_dev->dev, num_child_objects,
2292 + sizeof(*child_obj_desc_array),
2293 + GFP_KERNEL);
2294 + if (!child_obj_desc_array)
2295 + return -ENOMEM;
2296 +
2297 + /*
2298 + * Discover objects currently present in the physical DPRC:
2299 + */
2300 + dprc_get_obj_failures = 0;
2301 + for (i = 0; i < num_child_objects; i++) {
2302 + struct fsl_mc_obj_desc *obj_desc =
2303 + &child_obj_desc_array[i];
2304 +
2305 + error = dprc_get_obj(mc_bus_dev->mc_io,
2306 + 0,
2307 + mc_bus_dev->mc_handle,
2308 + i, obj_desc);
2309 + if (error < 0) {
2310 + dev_err(&mc_bus_dev->dev,
2311 + "dprc_get_obj(i=%d) failed: %d\n",
2312 + i, error);
2313 + /*
2314 + * Mark the obj entry as "invalid", by using the
2315 + * empty string as obj type:
2316 + */
2317 + obj_desc->type[0] = '\0';
2318 + obj_desc->id = error;
2319 + dprc_get_obj_failures++;
2320 + continue;
2321 + }
2322 +
2323 + /*
2324 + * add a quirk for all versions of dpsec < 4.0...none
2325 + * are coherent regardless of what the MC reports.
2326 + */
2327 + if ((strcmp(obj_desc->type, "dpseci") == 0) &&
2328 + (obj_desc->ver_major < 4))
2329 + obj_desc->flags |=
2330 + FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY;
2331 +
2332 + irq_count += obj_desc->irq_count;
2333 + dev_dbg(&mc_bus_dev->dev,
2334 + "Discovered object: type %s, id %d\n",
2335 + obj_desc->type, obj_desc->id);
2336 + }
2337 +
2338 + if (dprc_get_obj_failures != 0) {
2339 + dev_err(&mc_bus_dev->dev,
2340 + "%d out of %d devices could not be retrieved\n",
2341 + dprc_get_obj_failures, num_child_objects);
2342 + }
2343 + }
2344 +
2345 + /*
2346 + * Allocate IRQ's before binding the scanned devices with their
2347 + * respective drivers.
2348 + */
2349 + if (dev_get_msi_domain(&mc_bus_dev->dev) && !mc_bus->irq_resources) {
2350 + if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) {
2351 + dev_warn(&mc_bus_dev->dev,
2352 + "IRQs needed (%u) exceed IRQs preallocated (%u)\n",
2353 + irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
2354 + }
2355 +
2356 + error = fsl_mc_populate_irq_pool(mc_bus,
2357 + FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
2358 + if (error < 0)
2359 + return error;
2360 + }
2361 +
2362 + if (total_irq_count)
2363 + *total_irq_count = irq_count;
2364 +
2365 + dprc_remove_devices(mc_bus_dev, child_obj_desc_array,
2366 + num_child_objects);
2367 +
2368 + dprc_add_new_devices(mc_bus_dev, driver_override, child_obj_desc_array,
2369 + num_child_objects);
2370 +
2371 + if (child_obj_desc_array)
2372 + devm_kfree(&mc_bus_dev->dev, child_obj_desc_array);
2373 +
2374 + return 0;
2375 +}
2376 +
2377 +/**
2378 + * dprc_scan_container - Scans a physical DPRC and synchronizes Linux bus state
2379 + *
2380 + * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
2381 + *
2382 + * Scans the physical DPRC and synchronizes the state of the Linux
2383 + * bus driver with the actual state of the MC by adding and removing
2384 + * devices as appropriate.
2385 + */
2386 +static int dprc_scan_container(struct fsl_mc_device *mc_bus_dev)
2387 +{
2388 + int error;
2389 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
2390 +
2391 + fsl_mc_init_all_resource_pools(mc_bus_dev);
2392 +
2393 + /*
2394 + * Discover objects in the DPRC:
2395 + */
2396 + mutex_lock(&mc_bus->scan_mutex);
2397 + error = dprc_scan_objects(mc_bus_dev, NULL, NULL);
2398 + mutex_unlock(&mc_bus->scan_mutex);
2399 + if (error < 0) {
2400 + fsl_mc_cleanup_all_resource_pools(mc_bus_dev);
2401 + return error;
2402 + }
2403 +
2404 + return 0;
2405 +}
2406 +
2407 +/**
2408 + * dprc_irq0_handler - Regular ISR for DPRC interrupt 0
2409 + *
2410 + * @irq: IRQ number of the interrupt being handled
2411 + * @arg: Pointer to device structure
2412 + */
2413 +static irqreturn_t dprc_irq0_handler(int irq_num, void *arg)
2414 +{
2415 + return IRQ_WAKE_THREAD;
2416 +}
2417 +
2418 +/**
2419 + * dprc_irq0_handler_thread - Handler thread function for DPRC interrupt 0
2420 + *
2421 + * @irq: IRQ number of the interrupt being handled
2422 + * @arg: Pointer to device structure
2423 + */
2424 +static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg)
2425 +{
2426 + int error;
2427 + u32 status;
2428 + struct device *dev = arg;
2429 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
2430 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
2431 + struct fsl_mc_io *mc_io = mc_dev->mc_io;
2432 + struct msi_desc *msi_desc = mc_dev->irqs[0]->msi_desc;
2433 +
2434 + dev_dbg(dev, "DPRC IRQ %d triggered on CPU %u\n",
2435 + irq_num, smp_processor_id());
2436 +
2437 + if (!(mc_dev->flags & FSL_MC_IS_DPRC))
2438 + return IRQ_HANDLED;
2439 +
2440 + mutex_lock(&mc_bus->scan_mutex);
2441 + if (!msi_desc || msi_desc->irq != (u32)irq_num)
2442 + goto out;
2443 +
2444 + status = 0;
2445 + error = dprc_get_irq_status(mc_io, 0, mc_dev->mc_handle, 0,
2446 + &status);
2447 + if (error < 0) {
2448 + dev_err(dev,
2449 + "dprc_get_irq_status() failed: %d\n", error);
2450 + goto out;
2451 + }
2452 +
2453 + error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0,
2454 + status);
2455 + if (error < 0) {
2456 + dev_err(dev,
2457 + "dprc_clear_irq_status() failed: %d\n", error);
2458 + goto out;
2459 + }
2460 +
2461 + if (status & (DPRC_IRQ_EVENT_OBJ_ADDED |
2462 + DPRC_IRQ_EVENT_OBJ_REMOVED |
2463 + DPRC_IRQ_EVENT_CONTAINER_DESTROYED |
2464 + DPRC_IRQ_EVENT_OBJ_DESTROYED |
2465 + DPRC_IRQ_EVENT_OBJ_CREATED)) {
2466 + unsigned int irq_count;
2467 +
2468 + error = dprc_scan_objects(mc_dev, NULL, &irq_count);
2469 + if (error < 0) {
2470 + /*
2471 + * If the error is -ENXIO, we ignore it, as it indicates
2472 + * that the object scan was aborted, as we detected that
2473 + * an object was removed from the DPRC in the MC, while
2474 + * we were scanning the DPRC.
2475 + */
2476 + if (error != -ENXIO) {
2477 + dev_err(dev, "dprc_scan_objects() failed: %d\n",
2478 + error);
2479 + }
2480 +
2481 + goto out;
2482 + }
2483 +
2484 + if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) {
2485 + dev_warn(dev,
2486 + "IRQs needed (%u) exceed IRQs preallocated (%u)\n",
2487 + irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
2488 + }
2489 + }
2490 +
2491 +out:
2492 + mutex_unlock(&mc_bus->scan_mutex);
2493 + return IRQ_HANDLED;
2494 +}
2495 +
2496 +/*
2497 + * Disable and clear interrupt for a given DPRC object
2498 + */
2499 +static int disable_dprc_irq(struct fsl_mc_device *mc_dev)
2500 +{
2501 + int error;
2502 + struct fsl_mc_io *mc_io = mc_dev->mc_io;
2503 +
2504 + /*
2505 + * Disable generation of interrupt, while we configure it:
2506 + */
2507 + error = dprc_set_irq_enable(mc_io, 0, mc_dev->mc_handle, 0, 0);
2508 + if (error < 0) {
2509 + dev_err(&mc_dev->dev,
2510 + "Disabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n",
2511 + error);
2512 + return error;
2513 + }
2514 +
2515 + /*
2516 + * Disable all interrupt causes for the interrupt:
2517 + */
2518 + error = dprc_set_irq_mask(mc_io, 0, mc_dev->mc_handle, 0, 0x0);
2519 + if (error < 0) {
2520 + dev_err(&mc_dev->dev,
2521 + "Disabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n",
2522 + error);
2523 + return error;
2524 + }
2525 +
2526 + /*
2527 + * Clear any leftover interrupts:
2528 + */
2529 + error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, ~0x0U);
2530 + if (error < 0) {
2531 + dev_err(&mc_dev->dev,
2532 + "Disabling DPRC IRQ failed: dprc_clear_irq_status() failed: %d\n",
2533 + error);
2534 + return error;
2535 + }
2536 +
2537 + return 0;
2538 +}
2539 +
2540 +static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev)
2541 +{
2542 + int error;
2543 + struct fsl_mc_device_irq *irq = mc_dev->irqs[0];
2544 +
2545 + /*
2546 + * NOTE: devm_request_threaded_irq() invokes the device-specific
2547 + * function that programs the MSI physically in the device
2548 + */
2549 + error = devm_request_threaded_irq(&mc_dev->dev,
2550 + irq->msi_desc->irq,
2551 + dprc_irq0_handler,
2552 + dprc_irq0_handler_thread,
2553 + IRQF_NO_SUSPEND | IRQF_ONESHOT,
2554 + dev_name(&mc_dev->dev),
2555 + &mc_dev->dev);
2556 + if (error < 0) {
2557 + dev_err(&mc_dev->dev,
2558 + "devm_request_threaded_irq() failed: %d\n",
2559 + error);
2560 + return error;
2561 + }
2562 +
2563 + return 0;
2564 +}
2565 +
2566 +static int enable_dprc_irq(struct fsl_mc_device *mc_dev)
2567 +{
2568 + int error;
2569 +
2570 + /*
2571 + * Enable all interrupt causes for the interrupt:
2572 + */
2573 + error = dprc_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle, 0,
2574 + ~0x0u);
2575 + if (error < 0) {
2576 + dev_err(&mc_dev->dev,
2577 + "Enabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n",
2578 + error);
2579 +
2580 + return error;
2581 + }
2582 +
2583 + /*
2584 + * Enable generation of the interrupt:
2585 + */
2586 + error = dprc_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, 1);
2587 + if (error < 0) {
2588 + dev_err(&mc_dev->dev,
2589 + "Enabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n",
2590 + error);
2591 +
2592 + return error;
2593 + }
2594 +
2595 + return 0;
2596 +}
2597 +
2598 +/*
2599 + * Setup interrupt for a given DPRC device
2600 + */
2601 +static int dprc_setup_irq(struct fsl_mc_device *mc_dev)
2602 +{
2603 + int error;
2604 +
2605 + error = fsl_mc_allocate_irqs(mc_dev);
2606 + if (error < 0)
2607 + return error;
2608 +
2609 + error = disable_dprc_irq(mc_dev);
2610 + if (error < 0)
2611 + goto error_free_irqs;
2612 +
2613 + error = register_dprc_irq_handler(mc_dev);
2614 + if (error < 0)
2615 + goto error_free_irqs;
2616 +
2617 + error = enable_dprc_irq(mc_dev);
2618 + if (error < 0)
2619 + goto error_free_irqs;
2620 +
2621 + return 0;
2622 +
2623 +error_free_irqs:
2624 + fsl_mc_free_irqs(mc_dev);
2625 + return error;
2626 +}
2627 +
2628 +/**
2629 + * dprc_probe - callback invoked when a DPRC is being bound to this driver
2630 + *
2631 + * @mc_dev: Pointer to fsl-mc device representing a DPRC
2632 + *
2633 + * It opens the physical DPRC in the MC.
2634 + * It scans the DPRC to discover the MC objects contained in it.
2635 + * It creates the interrupt pool for the MC bus associated with the DPRC.
2636 + * It configures the interrupts for the DPRC device itself.
2637 + */
2638 +static int dprc_probe(struct fsl_mc_device *mc_dev)
2639 +{
2640 + int error;
2641 + size_t region_size;
2642 + struct device *parent_dev = mc_dev->dev.parent;
2643 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
2644 + bool mc_io_created = false;
2645 + bool msi_domain_set = false;
2646 + u16 major_ver, minor_ver;
2647 +
2648 + if (!is_fsl_mc_bus_dprc(mc_dev))
2649 + return -EINVAL;
2650 +
2651 + if (dev_get_msi_domain(&mc_dev->dev))
2652 + return -EINVAL;
2653 +
2654 + if (!mc_dev->mc_io) {
2655 + /*
2656 + * This is a child DPRC:
2657 + */
2658 + if (!dev_is_fsl_mc(parent_dev))
2659 + return -EINVAL;
2660 +
2661 + if (mc_dev->obj_desc.region_count == 0)
2662 + return -EINVAL;
2663 +
2664 + region_size = resource_size(mc_dev->regions);
2665 +
2666 + error = fsl_create_mc_io(&mc_dev->dev,
2667 + mc_dev->regions[0].start,
2668 + region_size,
2669 + NULL,
2670 + FSL_MC_IO_ATOMIC_CONTEXT_PORTAL,
2671 + &mc_dev->mc_io);
2672 + if (error < 0)
2673 + return error;
2674 +
2675 + mc_io_created = true;
2676 +
2677 + /*
2678 + * Inherit parent MSI domain:
2679 + */
2680 + dev_set_msi_domain(&mc_dev->dev,
2681 + dev_get_msi_domain(parent_dev));
2682 + msi_domain_set = true;
2683 + } else {
2684 + /*
2685 + * This is a root DPRC
2686 + */
2687 + struct irq_domain *mc_msi_domain;
2688 +
2689 + if (dev_is_fsl_mc(parent_dev))
2690 + return -EINVAL;
2691 +
2692 + error = fsl_mc_find_msi_domain(parent_dev,
2693 + &mc_msi_domain);
2694 + if (error < 0) {
2695 + dev_warn(&mc_dev->dev,
2696 + "WARNING: MC bus without interrupt support\n");
2697 + } else {
2698 + dev_set_msi_domain(&mc_dev->dev, mc_msi_domain);
2699 + msi_domain_set = true;
2700 + }
2701 + }
2702 +
2703 + error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
2704 + &mc_dev->mc_handle);
2705 + if (error < 0) {
2706 + dev_err(&mc_dev->dev, "dprc_open() failed: %d\n", error);
2707 + goto error_cleanup_msi_domain;
2708 + }
2709 +
2710 + error = dprc_get_attributes(mc_dev->mc_io, 0, mc_dev->mc_handle,
2711 + &mc_bus->dprc_attr);
2712 + if (error < 0) {
2713 + dev_err(&mc_dev->dev, "dprc_get_attributes() failed: %d\n",
2714 + error);
2715 + goto error_cleanup_open;
2716 + }
2717 +
2718 + error = dprc_get_api_version(mc_dev->mc_io, 0,
2719 + &major_ver,
2720 + &minor_ver);
2721 + if (error < 0) {
2722 + dev_err(&mc_dev->dev, "dprc_get_api_version() failed: %d\n",
2723 + error);
2724 + goto error_cleanup_open;
2725 + }
2726 +
2727 + if (major_ver < DPRC_MIN_VER_MAJOR ||
2728 + (major_ver == DPRC_MIN_VER_MAJOR &&
2729 + minor_ver < DPRC_MIN_VER_MINOR)) {
2730 + dev_err(&mc_dev->dev,
2731 + "ERROR: DPRC version %d.%d not supported\n",
2732 + major_ver, minor_ver);
2733 + error = -ENOTSUPP;
2734 + goto error_cleanup_open;
2735 + }
2736 +
2737 + mutex_init(&mc_bus->scan_mutex);
2738 +
2739 + /*
2740 + * Discover MC objects in DPRC object:
2741 + */
2742 + error = dprc_scan_container(mc_dev);
2743 + if (error < 0)
2744 + goto error_cleanup_open;
2745 +
2746 + /*
2747 + * Configure interrupt for the DPRC object associated with this MC bus:
2748 + */
2749 + error = dprc_setup_irq(mc_dev);
2750 + if (error < 0)
2751 + goto error_cleanup_open;
2752 +
2753 + dev_info(&mc_dev->dev, "DPRC device bound to driver");
2754 + return 0;
2755 +
2756 +error_cleanup_open:
2757 + (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
2758 +
2759 +error_cleanup_msi_domain:
2760 + if (msi_domain_set)
2761 + dev_set_msi_domain(&mc_dev->dev, NULL);
2762 +
2763 + if (mc_io_created) {
2764 + fsl_destroy_mc_io(mc_dev->mc_io);
2765 + mc_dev->mc_io = NULL;
2766 + }
2767 +
2768 + return error;
2769 +}
2770 +
2771 +/*
2772 + * Tear down interrupt for a given DPRC object
2773 + */
2774 +static void dprc_teardown_irq(struct fsl_mc_device *mc_dev)
2775 +{
2776 + struct fsl_mc_device_irq *irq = mc_dev->irqs[0];
2777 +
2778 + (void)disable_dprc_irq(mc_dev);
2779 +
2780 + devm_free_irq(&mc_dev->dev, irq->msi_desc->irq, &mc_dev->dev);
2781 +
2782 + fsl_mc_free_irqs(mc_dev);
2783 +}
2784 +
2785 +/**
2786 + * dprc_remove - callback invoked when a DPRC is being unbound from this driver
2787 + *
2788 + * @mc_dev: Pointer to fsl-mc device representing the DPRC
2789 + *
2790 + * It removes the DPRC's child objects from Linux (not from the MC) and
2791 + * closes the DPRC device in the MC.
2792 + * It tears down the interrupts that were configured for the DPRC device.
2793 + * It destroys the interrupt pool associated with this MC bus.
2794 + */
2795 +static int dprc_remove(struct fsl_mc_device *mc_dev)
2796 +{
2797 + int error;
2798 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
2799 +
2800 + if (!is_fsl_mc_bus_dprc(mc_dev))
2801 + return -EINVAL;
2802 + if (!mc_dev->mc_io)
2803 + return -EINVAL;
2804 +
2805 + if (!mc_bus->irq_resources)
2806 + return -EINVAL;
2807 +
2808 + if (dev_get_msi_domain(&mc_dev->dev))
2809 + dprc_teardown_irq(mc_dev);
2810 +
2811 + device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove);
2812 +
2813 + if (dev_get_msi_domain(&mc_dev->dev)) {
2814 + fsl_mc_cleanup_irq_pool(mc_bus);
2815 + dev_set_msi_domain(&mc_dev->dev, NULL);
2816 + }
2817 +
2818 + fsl_mc_cleanup_all_resource_pools(mc_dev);
2819 +
2820 + error = dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
2821 + if (error < 0)
2822 + dev_err(&mc_dev->dev, "dprc_close() failed: %d\n", error);
2823 +
2824 + if (!fsl_mc_is_root_dprc(&mc_dev->dev)) {
2825 + fsl_destroy_mc_io(mc_dev->mc_io);
2826 + mc_dev->mc_io = NULL;
2827 + }
2828 +
2829 + dev_info(&mc_dev->dev, "DPRC device unbound from driver");
2830 + return 0;
2831 +}
2832 +
2833 +static const struct fsl_mc_device_id match_id_table[] = {
2834 + {
2835 + .vendor = FSL_MC_VENDOR_FREESCALE,
2836 + .obj_type = "dprc"},
2837 + {.vendor = 0x0},
2838 +};
2839 +
2840 +static struct fsl_mc_driver dprc_driver = {
2841 + .driver = {
2842 + .name = FSL_MC_DPRC_DRIVER_NAME,
2843 + .owner = THIS_MODULE,
2844 + .pm = NULL,
2845 + },
2846 + .match_id_table = match_id_table,
2847 + .probe = dprc_probe,
2848 + .remove = dprc_remove,
2849 +};
2850 +
2851 +int __init dprc_driver_init(void)
2852 +{
2853 + return fsl_mc_driver_register(&dprc_driver);
2854 +}
2855 +
2856 +void dprc_driver_exit(void)
2857 +{
2858 + fsl_mc_driver_unregister(&dprc_driver);
2859 +}
2860 --- a/drivers/staging/fsl-mc/bus/dprc.c
2861 +++ /dev/null
2862 @@ -1,757 +0,0 @@
2863 -// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
2864 -/*
2865 - * Copyright 2013-2016 Freescale Semiconductor Inc.
2866 - *
2867 - */
2868 -#include <linux/kernel.h>
2869 -#include "../include/mc.h"
2870 -#include "dprc.h"
2871 -
2872 -#include "dprc-cmd.h"
2873 -
2874 -/**
2875 - * dprc_open() - Open DPRC object for use
2876 - * @mc_io: Pointer to MC portal's I/O object
2877 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
2878 - * @container_id: Container ID to open
2879 - * @token: Returned token of DPRC object
2880 - *
2881 - * Return: '0' on Success; Error code otherwise.
2882 - *
2883 - * @warning Required before any operation on the object.
2884 - */
2885 -int dprc_open(struct fsl_mc_io *mc_io,
2886 - u32 cmd_flags,
2887 - int container_id,
2888 - u16 *token)
2889 -{
2890 - struct mc_command cmd = { 0 };
2891 - struct dprc_cmd_open *cmd_params;
2892 - int err;
2893 -
2894 - /* prepare command */
2895 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_OPEN, cmd_flags,
2896 - 0);
2897 - cmd_params = (struct dprc_cmd_open *)cmd.params;
2898 - cmd_params->container_id = cpu_to_le32(container_id);
2899 -
2900 - /* send command to mc*/
2901 - err = mc_send_command(mc_io, &cmd);
2902 - if (err)
2903 - return err;
2904 -
2905 - /* retrieve response parameters */
2906 - *token = mc_cmd_hdr_read_token(&cmd);
2907 -
2908 - return 0;
2909 -}
2910 -EXPORT_SYMBOL(dprc_open);
2911 -
2912 -/**
2913 - * dprc_close() - Close the control session of the object
2914 - * @mc_io: Pointer to MC portal's I/O object
2915 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
2916 - * @token: Token of DPRC object
2917 - *
2918 - * After this function is called, no further operations are
2919 - * allowed on the object without opening a new control session.
2920 - *
2921 - * Return: '0' on Success; Error code otherwise.
2922 - */
2923 -int dprc_close(struct fsl_mc_io *mc_io,
2924 - u32 cmd_flags,
2925 - u16 token)
2926 -{
2927 - struct mc_command cmd = { 0 };
2928 -
2929 - /* prepare command */
2930 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLOSE, cmd_flags,
2931 - token);
2932 -
2933 - /* send command to mc*/
2934 - return mc_send_command(mc_io, &cmd);
2935 -}
2936 -EXPORT_SYMBOL(dprc_close);
2937 -
2938 -/**
2939 - * dprc_get_irq() - Get IRQ information from the DPRC.
2940 - * @mc_io: Pointer to MC portal's I/O object
2941 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
2942 - * @token: Token of DPRC object
2943 - * @irq_index: The interrupt index to configure
2944 - * @type: Interrupt type: 0 represents message interrupt
2945 - * type (both irq_addr and irq_val are valid)
2946 - * @irq_cfg: IRQ attributes
2947 - *
2948 - * Return: '0' on Success; Error code otherwise.
2949 - */
2950 -int dprc_get_irq(struct fsl_mc_io *mc_io,
2951 - u32 cmd_flags,
2952 - u16 token,
2953 - u8 irq_index,
2954 - int *type,
2955 - struct dprc_irq_cfg *irq_cfg)
2956 -{
2957 - struct mc_command cmd = { 0 };
2958 - struct dprc_cmd_get_irq *cmd_params;
2959 - struct dprc_rsp_get_irq *rsp_params;
2960 - int err;
2961 -
2962 - /* prepare command */
2963 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ,
2964 - cmd_flags,
2965 - token);
2966 - cmd_params = (struct dprc_cmd_get_irq *)cmd.params;
2967 - cmd_params->irq_index = irq_index;
2968 -
2969 - /* send command to mc*/
2970 - err = mc_send_command(mc_io, &cmd);
2971 - if (err)
2972 - return err;
2973 -
2974 - /* retrieve response parameters */
2975 - rsp_params = (struct dprc_rsp_get_irq *)cmd.params;
2976 - irq_cfg->val = le32_to_cpu(rsp_params->irq_val);
2977 - irq_cfg->paddr = le64_to_cpu(rsp_params->irq_addr);
2978 - irq_cfg->irq_num = le32_to_cpu(rsp_params->irq_num);
2979 - *type = le32_to_cpu(rsp_params->type);
2980 -
2981 - return 0;
2982 -}
2983 -
2984 -/**
2985 - * dprc_set_irq() - Set IRQ information for the DPRC to trigger an interrupt.
2986 - * @mc_io: Pointer to MC portal's I/O object
2987 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
2988 - * @token: Token of DPRC object
2989 - * @irq_index: Identifies the interrupt index to configure
2990 - * @irq_cfg: IRQ configuration
2991 - *
2992 - * Return: '0' on Success; Error code otherwise.
2993 - */
2994 -int dprc_set_irq(struct fsl_mc_io *mc_io,
2995 - u32 cmd_flags,
2996 - u16 token,
2997 - u8 irq_index,
2998 - struct dprc_irq_cfg *irq_cfg)
2999 -{
3000 - struct mc_command cmd = { 0 };
3001 - struct dprc_cmd_set_irq *cmd_params;
3002 -
3003 - /* prepare command */
3004 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ,
3005 - cmd_flags,
3006 - token);
3007 - cmd_params = (struct dprc_cmd_set_irq *)cmd.params;
3008 - cmd_params->irq_val = cpu_to_le32(irq_cfg->val);
3009 - cmd_params->irq_index = irq_index;
3010 - cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr);
3011 - cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num);
3012 -
3013 - /* send command to mc*/
3014 - return mc_send_command(mc_io, &cmd);
3015 -}
3016 -
3017 -/**
3018 - * dprc_get_irq_enable() - Get overall interrupt state.
3019 - * @mc_io: Pointer to MC portal's I/O object
3020 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3021 - * @token: Token of DPRC object
3022 - * @irq_index: The interrupt index to configure
3023 - * @en: Returned interrupt state - enable = 1, disable = 0
3024 - *
3025 - * Return: '0' on Success; Error code otherwise.
3026 - */
3027 -int dprc_get_irq_enable(struct fsl_mc_io *mc_io,
3028 - u32 cmd_flags,
3029 - u16 token,
3030 - u8 irq_index,
3031 - u8 *en)
3032 -{
3033 - struct mc_command cmd = { 0 };
3034 - struct dprc_cmd_get_irq_enable *cmd_params;
3035 - struct dprc_rsp_get_irq_enable *rsp_params;
3036 - int err;
3037 -
3038 - /* prepare command */
3039 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_ENABLE,
3040 - cmd_flags, token);
3041 - cmd_params = (struct dprc_cmd_get_irq_enable *)cmd.params;
3042 - cmd_params->irq_index = irq_index;
3043 -
3044 - /* send command to mc*/
3045 - err = mc_send_command(mc_io, &cmd);
3046 - if (err)
3047 - return err;
3048 -
3049 - /* retrieve response parameters */
3050 - rsp_params = (struct dprc_rsp_get_irq_enable *)cmd.params;
3051 - *en = rsp_params->enabled & DPRC_ENABLE;
3052 -
3053 - return 0;
3054 -}
3055 -
3056 -/**
3057 - * dprc_set_irq_enable() - Set overall interrupt state.
3058 - * @mc_io: Pointer to MC portal's I/O object
3059 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3060 - * @token: Token of DPRC object
3061 - * @irq_index: The interrupt index to configure
3062 - * @en: Interrupt state - enable = 1, disable = 0
3063 - *
3064 - * Allows GPP software to control when interrupts are generated.
3065 - * Each interrupt can have up to 32 causes. The enable/disable control's the
3066 - * overall interrupt state. if the interrupt is disabled no causes will cause
3067 - * an interrupt.
3068 - *
3069 - * Return: '0' on Success; Error code otherwise.
3070 - */
3071 -int dprc_set_irq_enable(struct fsl_mc_io *mc_io,
3072 - u32 cmd_flags,
3073 - u16 token,
3074 - u8 irq_index,
3075 - u8 en)
3076 -{
3077 - struct mc_command cmd = { 0 };
3078 - struct dprc_cmd_set_irq_enable *cmd_params;
3079 -
3080 - /* prepare command */
3081 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_ENABLE,
3082 - cmd_flags, token);
3083 - cmd_params = (struct dprc_cmd_set_irq_enable *)cmd.params;
3084 - cmd_params->enable = en & DPRC_ENABLE;
3085 - cmd_params->irq_index = irq_index;
3086 -
3087 - /* send command to mc*/
3088 - return mc_send_command(mc_io, &cmd);
3089 -}
3090 -
3091 -/**
3092 - * dprc_get_irq_mask() - Get interrupt mask.
3093 - * @mc_io: Pointer to MC portal's I/O object
3094 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3095 - * @token: Token of DPRC object
3096 - * @irq_index: The interrupt index to configure
3097 - * @mask: Returned event mask to trigger interrupt
3098 - *
3099 - * Every interrupt can have up to 32 causes and the interrupt model supports
3100 - * masking/unmasking each cause independently
3101 - *
3102 - * Return: '0' on Success; Error code otherwise.
3103 - */
3104 -int dprc_get_irq_mask(struct fsl_mc_io *mc_io,
3105 - u32 cmd_flags,
3106 - u16 token,
3107 - u8 irq_index,
3108 - u32 *mask)
3109 -{
3110 - struct mc_command cmd = { 0 };
3111 - struct dprc_cmd_get_irq_mask *cmd_params;
3112 - struct dprc_rsp_get_irq_mask *rsp_params;
3113 - int err;
3114 -
3115 - /* prepare command */
3116 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_MASK,
3117 - cmd_flags, token);
3118 - cmd_params = (struct dprc_cmd_get_irq_mask *)cmd.params;
3119 - cmd_params->irq_index = irq_index;
3120 -
3121 - /* send command to mc*/
3122 - err = mc_send_command(mc_io, &cmd);
3123 - if (err)
3124 - return err;
3125 -
3126 - /* retrieve response parameters */
3127 - rsp_params = (struct dprc_rsp_get_irq_mask *)cmd.params;
3128 - *mask = le32_to_cpu(rsp_params->mask);
3129 -
3130 - return 0;
3131 -}
3132 -
3133 -/**
3134 - * dprc_set_irq_mask() - Set interrupt mask.
3135 - * @mc_io: Pointer to MC portal's I/O object
3136 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3137 - * @token: Token of DPRC object
3138 - * @irq_index: The interrupt index to configure
3139 - * @mask: event mask to trigger interrupt;
3140 - * each bit:
3141 - * 0 = ignore event
3142 - * 1 = consider event for asserting irq
3143 - *
3144 - * Every interrupt can have up to 32 causes and the interrupt model supports
3145 - * masking/unmasking each cause independently
3146 - *
3147 - * Return: '0' on Success; Error code otherwise.
3148 - */
3149 -int dprc_set_irq_mask(struct fsl_mc_io *mc_io,
3150 - u32 cmd_flags,
3151 - u16 token,
3152 - u8 irq_index,
3153 - u32 mask)
3154 -{
3155 - struct mc_command cmd = { 0 };
3156 - struct dprc_cmd_set_irq_mask *cmd_params;
3157 -
3158 - /* prepare command */
3159 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_MASK,
3160 - cmd_flags, token);
3161 - cmd_params = (struct dprc_cmd_set_irq_mask *)cmd.params;
3162 - cmd_params->mask = cpu_to_le32(mask);
3163 - cmd_params->irq_index = irq_index;
3164 -
3165 - /* send command to mc*/
3166 - return mc_send_command(mc_io, &cmd);
3167 -}
3168 -
3169 -/**
3170 - * dprc_get_irq_status() - Get the current status of any pending interrupts.
3171 - * @mc_io: Pointer to MC portal's I/O object
3172 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3173 - * @token: Token of DPRC object
3174 - * @irq_index: The interrupt index to configure
3175 - * @status: Returned interrupts status - one bit per cause:
3176 - * 0 = no interrupt pending
3177 - * 1 = interrupt pending
3178 - *
3179 - * Return: '0' on Success; Error code otherwise.
3180 - */
3181 -int dprc_get_irq_status(struct fsl_mc_io *mc_io,
3182 - u32 cmd_flags,
3183 - u16 token,
3184 - u8 irq_index,
3185 - u32 *status)
3186 -{
3187 - struct mc_command cmd = { 0 };
3188 - struct dprc_cmd_get_irq_status *cmd_params;
3189 - struct dprc_rsp_get_irq_status *rsp_params;
3190 - int err;
3191 -
3192 - /* prepare command */
3193 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_STATUS,
3194 - cmd_flags, token);
3195 - cmd_params = (struct dprc_cmd_get_irq_status *)cmd.params;
3196 - cmd_params->status = cpu_to_le32(*status);
3197 - cmd_params->irq_index = irq_index;
3198 -
3199 - /* send command to mc*/
3200 - err = mc_send_command(mc_io, &cmd);
3201 - if (err)
3202 - return err;
3203 -
3204 - /* retrieve response parameters */
3205 - rsp_params = (struct dprc_rsp_get_irq_status *)cmd.params;
3206 - *status = le32_to_cpu(rsp_params->status);
3207 -
3208 - return 0;
3209 -}
3210 -
3211 -/**
3212 - * dprc_clear_irq_status() - Clear a pending interrupt's status
3213 - * @mc_io: Pointer to MC portal's I/O object
3214 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3215 - * @token: Token of DPRC object
3216 - * @irq_index: The interrupt index to configure
3217 - * @status: bits to clear (W1C) - one bit per cause:
3218 - * 0 = don't change
3219 - * 1 = clear status bit
3220 - *
3221 - * Return: '0' on Success; Error code otherwise.
3222 - */
3223 -int dprc_clear_irq_status(struct fsl_mc_io *mc_io,
3224 - u32 cmd_flags,
3225 - u16 token,
3226 - u8 irq_index,
3227 - u32 status)
3228 -{
3229 - struct mc_command cmd = { 0 };
3230 - struct dprc_cmd_clear_irq_status *cmd_params;
3231 -
3232 - /* prepare command */
3233 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLEAR_IRQ_STATUS,
3234 - cmd_flags, token);
3235 - cmd_params = (struct dprc_cmd_clear_irq_status *)cmd.params;
3236 - cmd_params->status = cpu_to_le32(status);
3237 - cmd_params->irq_index = irq_index;
3238 -
3239 - /* send command to mc*/
3240 - return mc_send_command(mc_io, &cmd);
3241 -}
3242 -
3243 -/**
3244 - * dprc_get_attributes() - Obtains container attributes
3245 - * @mc_io: Pointer to MC portal's I/O object
3246 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3247 - * @token: Token of DPRC object
3248 - * @attributes Returned container attributes
3249 - *
3250 - * Return: '0' on Success; Error code otherwise.
3251 - */
3252 -int dprc_get_attributes(struct fsl_mc_io *mc_io,
3253 - u32 cmd_flags,
3254 - u16 token,
3255 - struct dprc_attributes *attr)
3256 -{
3257 - struct mc_command cmd = { 0 };
3258 - struct dprc_rsp_get_attributes *rsp_params;
3259 - int err;
3260 -
3261 - /* prepare command */
3262 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_ATTR,
3263 - cmd_flags,
3264 - token);
3265 -
3266 - /* send command to mc*/
3267 - err = mc_send_command(mc_io, &cmd);
3268 - if (err)
3269 - return err;
3270 -
3271 - /* retrieve response parameters */
3272 - rsp_params = (struct dprc_rsp_get_attributes *)cmd.params;
3273 - attr->container_id = le32_to_cpu(rsp_params->container_id);
3274 - attr->icid = le16_to_cpu(rsp_params->icid);
3275 - attr->options = le32_to_cpu(rsp_params->options);
3276 - attr->portal_id = le32_to_cpu(rsp_params->portal_id);
3277 -
3278 - return 0;
3279 -}
3280 -
3281 -/**
3282 - * dprc_get_obj_count() - Obtains the number of objects in the DPRC
3283 - * @mc_io: Pointer to MC portal's I/O object
3284 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3285 - * @token: Token of DPRC object
3286 - * @obj_count: Number of objects assigned to the DPRC
3287 - *
3288 - * Return: '0' on Success; Error code otherwise.
3289 - */
3290 -int dprc_get_obj_count(struct fsl_mc_io *mc_io,
3291 - u32 cmd_flags,
3292 - u16 token,
3293 - int *obj_count)
3294 -{
3295 - struct mc_command cmd = { 0 };
3296 - struct dprc_rsp_get_obj_count *rsp_params;
3297 - int err;
3298 -
3299 - /* prepare command */
3300 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_COUNT,
3301 - cmd_flags, token);
3302 -
3303 - /* send command to mc*/
3304 - err = mc_send_command(mc_io, &cmd);
3305 - if (err)
3306 - return err;
3307 -
3308 - /* retrieve response parameters */
3309 - rsp_params = (struct dprc_rsp_get_obj_count *)cmd.params;
3310 - *obj_count = le32_to_cpu(rsp_params->obj_count);
3311 -
3312 - return 0;
3313 -}
3314 -EXPORT_SYMBOL(dprc_get_obj_count);
3315 -
3316 -/**
3317 - * dprc_get_obj() - Get general information on an object
3318 - * @mc_io: Pointer to MC portal's I/O object
3319 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3320 - * @token: Token of DPRC object
3321 - * @obj_index: Index of the object to be queried (< obj_count)
3322 - * @obj_desc: Returns the requested object descriptor
3323 - *
3324 - * The object descriptors are retrieved one by one by incrementing
3325 - * obj_index up to (not including) the value of obj_count returned
3326 - * from dprc_get_obj_count(). dprc_get_obj_count() must
3327 - * be called prior to dprc_get_obj().
3328 - *
3329 - * Return: '0' on Success; Error code otherwise.
3330 - */
3331 -int dprc_get_obj(struct fsl_mc_io *mc_io,
3332 - u32 cmd_flags,
3333 - u16 token,
3334 - int obj_index,
3335 - struct fsl_mc_obj_desc *obj_desc)
3336 -{
3337 - struct mc_command cmd = { 0 };
3338 - struct dprc_cmd_get_obj *cmd_params;
3339 - struct dprc_rsp_get_obj *rsp_params;
3340 - int err;
3341 -
3342 - /* prepare command */
3343 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ,
3344 - cmd_flags,
3345 - token);
3346 - cmd_params = (struct dprc_cmd_get_obj *)cmd.params;
3347 - cmd_params->obj_index = cpu_to_le32(obj_index);
3348 -
3349 - /* send command to mc*/
3350 - err = mc_send_command(mc_io, &cmd);
3351 - if (err)
3352 - return err;
3353 -
3354 - /* retrieve response parameters */
3355 - rsp_params = (struct dprc_rsp_get_obj *)cmd.params;
3356 - obj_desc->id = le32_to_cpu(rsp_params->id);
3357 - obj_desc->vendor = le16_to_cpu(rsp_params->vendor);
3358 - obj_desc->irq_count = rsp_params->irq_count;
3359 - obj_desc->region_count = rsp_params->region_count;
3360 - obj_desc->state = le32_to_cpu(rsp_params->state);
3361 - obj_desc->ver_major = le16_to_cpu(rsp_params->version_major);
3362 - obj_desc->ver_minor = le16_to_cpu(rsp_params->version_minor);
3363 - obj_desc->flags = le16_to_cpu(rsp_params->flags);
3364 - strncpy(obj_desc->type, rsp_params->type, 16);
3365 - obj_desc->type[15] = '\0';
3366 - strncpy(obj_desc->label, rsp_params->label, 16);
3367 - obj_desc->label[15] = '\0';
3368 - return 0;
3369 -}
3370 -EXPORT_SYMBOL(dprc_get_obj);
3371 -
3372 -/**
3373 - * dprc_set_obj_irq() - Set IRQ information for object to trigger an interrupt.
3374 - * @mc_io: Pointer to MC portal's I/O object
3375 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3376 - * @token: Token of DPRC object
3377 - * @obj_type: Type of the object to set its IRQ
3378 - * @obj_id: ID of the object to set its IRQ
3379 - * @irq_index: The interrupt index to configure
3380 - * @irq_cfg: IRQ configuration
3381 - *
3382 - * Return: '0' on Success; Error code otherwise.
3383 - */
3384 -int dprc_set_obj_irq(struct fsl_mc_io *mc_io,
3385 - u32 cmd_flags,
3386 - u16 token,
3387 - char *obj_type,
3388 - int obj_id,
3389 - u8 irq_index,
3390 - struct dprc_irq_cfg *irq_cfg)
3391 -{
3392 - struct mc_command cmd = { 0 };
3393 - struct dprc_cmd_set_obj_irq *cmd_params;
3394 -
3395 - /* prepare command */
3396 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_OBJ_IRQ,
3397 - cmd_flags,
3398 - token);
3399 - cmd_params = (struct dprc_cmd_set_obj_irq *)cmd.params;
3400 - cmd_params->irq_val = cpu_to_le32(irq_cfg->val);
3401 - cmd_params->irq_index = irq_index;
3402 - cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr);
3403 - cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num);
3404 - cmd_params->obj_id = cpu_to_le32(obj_id);
3405 - strncpy(cmd_params->obj_type, obj_type, 16);
3406 - cmd_params->obj_type[15] = '\0';
3407 -
3408 - /* send command to mc*/
3409 - return mc_send_command(mc_io, &cmd);
3410 -}
3411 -EXPORT_SYMBOL(dprc_set_obj_irq);
3412 -
3413 -/**
3414 - * dprc_get_obj_irq() - Get IRQ information from object.
3415 - * @mc_io: Pointer to MC portal's I/O object
3416 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3417 - * @token: Token of DPRC object
3418 - * @obj_type: Type od the object to get its IRQ
3419 - * @obj_id: ID of the object to get its IRQ
3420 - * @irq_index: The interrupt index to configure
3421 - * @type: Interrupt type: 0 represents message interrupt
3422 - * type (both irq_addr and irq_val are valid)
3423 - * @irq_cfg: The returned IRQ attributes
3424 - *
3425 - * Return: '0' on Success; Error code otherwise.
3426 - */
3427 -int dprc_get_obj_irq(struct fsl_mc_io *mc_io,
3428 - u32 cmd_flags,
3429 - u16 token,
3430 - char *obj_type,
3431 - int obj_id,
3432 - u8 irq_index,
3433 - int *type,
3434 - struct dprc_irq_cfg *irq_cfg)
3435 -{
3436 - struct mc_command cmd = { 0 };
3437 - struct dprc_cmd_get_obj_irq *cmd_params;
3438 - struct dprc_rsp_get_obj_irq *rsp_params;
3439 - int err;
3440 -
3441 - /* prepare command */
3442 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_IRQ,
3443 - cmd_flags,
3444 - token);
3445 - cmd_params = (struct dprc_cmd_get_obj_irq *)cmd.params;
3446 - cmd_params->obj_id = cpu_to_le32(obj_id);
3447 - cmd_params->irq_index = irq_index;
3448 - strncpy(cmd_params->obj_type, obj_type, 16);
3449 - cmd_params->obj_type[15] = '\0';
3450 -
3451 - /* send command to mc*/
3452 - err = mc_send_command(mc_io, &cmd);
3453 - if (err)
3454 - return err;
3455 -
3456 - /* retrieve response parameters */
3457 - rsp_params = (struct dprc_rsp_get_obj_irq *)cmd.params;
3458 - irq_cfg->val = le32_to_cpu(rsp_params->irq_val);
3459 - irq_cfg->paddr = le64_to_cpu(rsp_params->irq_addr);
3460 - irq_cfg->irq_num = le32_to_cpu(rsp_params->irq_num);
3461 - *type = le32_to_cpu(rsp_params->type);
3462 -
3463 - return 0;
3464 -}
3465 -EXPORT_SYMBOL(dprc_get_obj_irq);
3466 -
3467 -/**
3468 - * dprc_get_res_count() - Obtains the number of free resources that are assigned
3469 - * to this container, by pool type
3470 - * @mc_io: Pointer to MC portal's I/O object
3471 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3472 - * @token: Token of DPRC object
3473 - * @type: pool type
3474 - * @res_count: Returned number of free resources of the given
3475 - * resource type that are assigned to this DPRC
3476 - *
3477 - * Return: '0' on Success; Error code otherwise.
3478 - */
3479 -int dprc_get_res_count(struct fsl_mc_io *mc_io,
3480 - u32 cmd_flags,
3481 - u16 token,
3482 - char *type,
3483 - int *res_count)
3484 -{
3485 - struct mc_command cmd = { 0 };
3486 - struct dprc_cmd_get_res_count *cmd_params;
3487 - struct dprc_rsp_get_res_count *rsp_params;
3488 - int err;
3489 -
3490 - /* prepare command */
3491 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_COUNT,
3492 - cmd_flags, token);
3493 - cmd_params = (struct dprc_cmd_get_res_count *)cmd.params;
3494 - strncpy(cmd_params->type, type, 16);
3495 - cmd_params->type[15] = '\0';
3496 -
3497 - /* send command to mc*/
3498 - err = mc_send_command(mc_io, &cmd);
3499 - if (err)
3500 - return err;
3501 -
3502 - /* retrieve response parameters */
3503 - rsp_params = (struct dprc_rsp_get_res_count *)cmd.params;
3504 - *res_count = le32_to_cpu(rsp_params->res_count);
3505 -
3506 - return 0;
3507 -}
3508 -EXPORT_SYMBOL(dprc_get_res_count);
3509 -
3510 -/**
3511 - * dprc_get_obj_region() - Get region information for a specified object.
3512 - * @mc_io: Pointer to MC portal's I/O object
3513 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3514 - * @token: Token of DPRC object
3515 - * @obj_type; Object type as returned in dprc_get_obj()
3516 - * @obj_id: Unique object instance as returned in dprc_get_obj()
3517 - * @region_index: The specific region to query
3518 - * @region_desc: Returns the requested region descriptor
3519 - *
3520 - * Return: '0' on Success; Error code otherwise.
3521 - */
3522 -int dprc_get_obj_region(struct fsl_mc_io *mc_io,
3523 - u32 cmd_flags,
3524 - u16 token,
3525 - char *obj_type,
3526 - int obj_id,
3527 - u8 region_index,
3528 - struct dprc_region_desc *region_desc)
3529 -{
3530 - struct mc_command cmd = { 0 };
3531 - struct dprc_cmd_get_obj_region *cmd_params;
3532 - struct dprc_rsp_get_obj_region *rsp_params;
3533 - int err;
3534 -
3535 - /* prepare command */
3536 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG,
3537 - cmd_flags, token);
3538 - cmd_params = (struct dprc_cmd_get_obj_region *)cmd.params;
3539 - cmd_params->obj_id = cpu_to_le32(obj_id);
3540 - cmd_params->region_index = region_index;
3541 - strncpy(cmd_params->obj_type, obj_type, 16);
3542 - cmd_params->obj_type[15] = '\0';
3543 -
3544 - /* send command to mc*/
3545 - err = mc_send_command(mc_io, &cmd);
3546 - if (err)
3547 - return err;
3548 -
3549 - /* retrieve response parameters */
3550 - rsp_params = (struct dprc_rsp_get_obj_region *)cmd.params;
3551 - region_desc->base_offset = le64_to_cpu(rsp_params->base_addr);
3552 - region_desc->size = le32_to_cpu(rsp_params->size);
3553 -
3554 - return 0;
3555 -}
3556 -EXPORT_SYMBOL(dprc_get_obj_region);
3557 -
3558 -/**
3559 - * dprc_get_api_version - Get Data Path Resource Container API version
3560 - * @mc_io: Pointer to Mc portal's I/O object
3561 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3562 - * @major_ver: Major version of Data Path Resource Container API
3563 - * @minor_ver: Minor version of Data Path Resource Container API
3564 - *
3565 - * Return: '0' on Success; Error code otherwise.
3566 - */
3567 -int dprc_get_api_version(struct fsl_mc_io *mc_io,
3568 - u32 cmd_flags,
3569 - u16 *major_ver,
3570 - u16 *minor_ver)
3571 -{
3572 - struct mc_command cmd = { 0 };
3573 - int err;
3574 -
3575 - /* prepare command */
3576 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_API_VERSION,
3577 - cmd_flags, 0);
3578 -
3579 - /* send command to mc */
3580 - err = mc_send_command(mc_io, &cmd);
3581 - if (err)
3582 - return err;
3583 -
3584 - /* retrieve response parameters */
3585 - mc_cmd_read_api_version(&cmd, major_ver, minor_ver);
3586 -
3587 - return 0;
3588 -}
3589 -
3590 -/**
3591 - * dprc_get_container_id - Get container ID associated with a given portal.
3592 - * @mc_io: Pointer to Mc portal's I/O object
3593 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3594 - * @container_id: Requested container id
3595 - *
3596 - * Return: '0' on Success; Error code otherwise.
3597 - */
3598 -int dprc_get_container_id(struct fsl_mc_io *mc_io,
3599 - u32 cmd_flags,
3600 - int *container_id)
3601 -{
3602 - struct mc_command cmd = { 0 };
3603 - int err;
3604 -
3605 - /* prepare command */
3606 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONT_ID,
3607 - cmd_flags,
3608 - 0);
3609 -
3610 - /* send command to mc*/
3611 - err = mc_send_command(mc_io, &cmd);
3612 - if (err)
3613 - return err;
3614 -
3615 - /* retrieve response parameters */
3616 - *container_id = (int)mc_cmd_read_object_id(&cmd);
3617 -
3618 - return 0;
3619 -}
3620 --- /dev/null
3621 +++ b/drivers/bus/fsl-mc/dprc.c
3622 @@ -0,0 +1,576 @@
3623 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
3624 +/*
3625 + * Copyright 2013-2016 Freescale Semiconductor Inc.
3626 + *
3627 + */
3628 +#include <linux/kernel.h>
3629 +#include <linux/fsl/mc.h>
3630 +
3631 +#include "fsl-mc-private.h"
3632 +
3633 +/**
3634 + * dprc_open() - Open DPRC object for use
3635 + * @mc_io: Pointer to MC portal's I/O object
3636 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3637 + * @container_id: Container ID to open
3638 + * @token: Returned token of DPRC object
3639 + *
3640 + * Return: '0' on Success; Error code otherwise.
3641 + *
3642 + * @warning Required before any operation on the object.
3643 + */
3644 +int dprc_open(struct fsl_mc_io *mc_io,
3645 + u32 cmd_flags,
3646 + int container_id,
3647 + u16 *token)
3648 +{
3649 + struct fsl_mc_command cmd = { 0 };
3650 + struct dprc_cmd_open *cmd_params;
3651 + int err;
3652 +
3653 + /* prepare command */
3654 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_OPEN, cmd_flags,
3655 + 0);
3656 + cmd_params = (struct dprc_cmd_open *)cmd.params;
3657 + cmd_params->container_id = cpu_to_le32(container_id);
3658 +
3659 + /* send command to mc*/
3660 + err = mc_send_command(mc_io, &cmd);
3661 + if (err)
3662 + return err;
3663 +
3664 + /* retrieve response parameters */
3665 + *token = mc_cmd_hdr_read_token(&cmd);
3666 +
3667 + return 0;
3668 +}
3669 +EXPORT_SYMBOL_GPL(dprc_open);
3670 +
3671 +/**
3672 + * dprc_close() - Close the control session of the object
3673 + * @mc_io: Pointer to MC portal's I/O object
3674 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3675 + * @token: Token of DPRC object
3676 + *
3677 + * After this function is called, no further operations are
3678 + * allowed on the object without opening a new control session.
3679 + *
3680 + * Return: '0' on Success; Error code otherwise.
3681 + */
3682 +int dprc_close(struct fsl_mc_io *mc_io,
3683 + u32 cmd_flags,
3684 + u16 token)
3685 +{
3686 + struct fsl_mc_command cmd = { 0 };
3687 +
3688 + /* prepare command */
3689 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLOSE, cmd_flags,
3690 + token);
3691 +
3692 + /* send command to mc*/
3693 + return mc_send_command(mc_io, &cmd);
3694 +}
3695 +EXPORT_SYMBOL_GPL(dprc_close);
3696 +
3697 +/**
3698 + * dprc_reset_container - Reset child container.
3699 + * @mc_io: Pointer to MC portal's I/O object
3700 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3701 + * @token: Token of DPRC object
3702 + * @child_container_id: ID of the container to reset
3703 + *
3704 + * In case a software context crashes or becomes non-responsive, the parent
3705 + * may wish to reset its resources container before the software context is
3706 + * restarted.
3707 + *
3708 + * This routine informs all objects assigned to the child container that the
3709 + * container is being reset, so they may perform any cleanup operations that are
3710 + * needed. All objects handles that were owned by the child container shall be
3711 + * closed.
3712 + *
3713 + * Note that such request may be submitted even if the child software context
3714 + * has not crashed, but the resulting object cleanup operations will not be
3715 + * aware of that.
3716 + *
3717 + * Return: '0' on Success; Error code otherwise.
3718 + */
3719 +int dprc_reset_container(struct fsl_mc_io *mc_io,
3720 + u32 cmd_flags,
3721 + u16 token,
3722 + int child_container_id)
3723 +{
3724 + struct fsl_mc_command cmd = { 0 };
3725 + struct dprc_cmd_reset_container *cmd_params;
3726 +
3727 + /* prepare command */
3728 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_RESET_CONT,
3729 + cmd_flags, token);
3730 + cmd_params = (struct dprc_cmd_reset_container *)cmd.params;
3731 + cmd_params->child_container_id = cpu_to_le32(child_container_id);
3732 +
3733 + /* send command to mc*/
3734 + return mc_send_command(mc_io, &cmd);
3735 +}
3736 +EXPORT_SYMBOL_GPL(dprc_reset_container);
3737 +
3738 +/**
3739 + * dprc_set_irq() - Set IRQ information for the DPRC to trigger an interrupt.
3740 + * @mc_io: Pointer to MC portal's I/O object
3741 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3742 + * @token: Token of DPRC object
3743 + * @irq_index: Identifies the interrupt index to configure
3744 + * @irq_cfg: IRQ configuration
3745 + *
3746 + * Return: '0' on Success; Error code otherwise.
3747 + */
3748 +int dprc_set_irq(struct fsl_mc_io *mc_io,
3749 + u32 cmd_flags,
3750 + u16 token,
3751 + u8 irq_index,
3752 + struct dprc_irq_cfg *irq_cfg)
3753 +{
3754 + struct fsl_mc_command cmd = { 0 };
3755 + struct dprc_cmd_set_irq *cmd_params;
3756 +
3757 + /* prepare command */
3758 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ,
3759 + cmd_flags,
3760 + token);
3761 + cmd_params = (struct dprc_cmd_set_irq *)cmd.params;
3762 + cmd_params->irq_val = cpu_to_le32(irq_cfg->val);
3763 + cmd_params->irq_index = irq_index;
3764 + cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr);
3765 + cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num);
3766 +
3767 + /* send command to mc*/
3768 + return mc_send_command(mc_io, &cmd);
3769 +}
3770 +
3771 +/**
3772 + * dprc_set_irq_enable() - Set overall interrupt state.
3773 + * @mc_io: Pointer to MC portal's I/O object
3774 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3775 + * @token: Token of DPRC object
3776 + * @irq_index: The interrupt index to configure
3777 + * @en: Interrupt state - enable = 1, disable = 0
3778 + *
3779 + * Allows GPP software to control when interrupts are generated.
3780 + * Each interrupt can have up to 32 causes. The enable/disable control's the
3781 + * overall interrupt state. if the interrupt is disabled no causes will cause
3782 + * an interrupt.
3783 + *
3784 + * Return: '0' on Success; Error code otherwise.
3785 + */
3786 +int dprc_set_irq_enable(struct fsl_mc_io *mc_io,
3787 + u32 cmd_flags,
3788 + u16 token,
3789 + u8 irq_index,
3790 + u8 en)
3791 +{
3792 + struct fsl_mc_command cmd = { 0 };
3793 + struct dprc_cmd_set_irq_enable *cmd_params;
3794 +
3795 + /* prepare command */
3796 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_ENABLE,
3797 + cmd_flags, token);
3798 + cmd_params = (struct dprc_cmd_set_irq_enable *)cmd.params;
3799 + cmd_params->enable = en & DPRC_ENABLE;
3800 + cmd_params->irq_index = irq_index;
3801 +
3802 + /* send command to mc*/
3803 + return mc_send_command(mc_io, &cmd);
3804 +}
3805 +
3806 +/**
3807 + * dprc_set_irq_mask() - Set interrupt mask.
3808 + * @mc_io: Pointer to MC portal's I/O object
3809 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3810 + * @token: Token of DPRC object
3811 + * @irq_index: The interrupt index to configure
3812 + * @mask: event mask to trigger interrupt;
3813 + * each bit:
3814 + * 0 = ignore event
3815 + * 1 = consider event for asserting irq
3816 + *
3817 + * Every interrupt can have up to 32 causes and the interrupt model supports
3818 + * masking/unmasking each cause independently
3819 + *
3820 + * Return: '0' on Success; Error code otherwise.
3821 + */
3822 +int dprc_set_irq_mask(struct fsl_mc_io *mc_io,
3823 + u32 cmd_flags,
3824 + u16 token,
3825 + u8 irq_index,
3826 + u32 mask)
3827 +{
3828 + struct fsl_mc_command cmd = { 0 };
3829 + struct dprc_cmd_set_irq_mask *cmd_params;
3830 +
3831 + /* prepare command */
3832 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_MASK,
3833 + cmd_flags, token);
3834 + cmd_params = (struct dprc_cmd_set_irq_mask *)cmd.params;
3835 + cmd_params->mask = cpu_to_le32(mask);
3836 + cmd_params->irq_index = irq_index;
3837 +
3838 + /* send command to mc*/
3839 + return mc_send_command(mc_io, &cmd);
3840 +}
3841 +
3842 +/**
3843 + * dprc_get_irq_status() - Get the current status of any pending interrupts.
3844 + * @mc_io: Pointer to MC portal's I/O object
3845 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3846 + * @token: Token of DPRC object
3847 + * @irq_index: The interrupt index to configure
3848 + * @status: Returned interrupts status - one bit per cause:
3849 + * 0 = no interrupt pending
3850 + * 1 = interrupt pending
3851 + *
3852 + * Return: '0' on Success; Error code otherwise.
3853 + */
3854 +int dprc_get_irq_status(struct fsl_mc_io *mc_io,
3855 + u32 cmd_flags,
3856 + u16 token,
3857 + u8 irq_index,
3858 + u32 *status)
3859 +{
3860 + struct fsl_mc_command cmd = { 0 };
3861 + struct dprc_cmd_get_irq_status *cmd_params;
3862 + struct dprc_rsp_get_irq_status *rsp_params;
3863 + int err;
3864 +
3865 + /* prepare command */
3866 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_STATUS,
3867 + cmd_flags, token);
3868 + cmd_params = (struct dprc_cmd_get_irq_status *)cmd.params;
3869 + cmd_params->status = cpu_to_le32(*status);
3870 + cmd_params->irq_index = irq_index;
3871 +
3872 + /* send command to mc*/
3873 + err = mc_send_command(mc_io, &cmd);
3874 + if (err)
3875 + return err;
3876 +
3877 + /* retrieve response parameters */
3878 + rsp_params = (struct dprc_rsp_get_irq_status *)cmd.params;
3879 + *status = le32_to_cpu(rsp_params->status);
3880 +
3881 + return 0;
3882 +}
3883 +
3884 +/**
3885 + * dprc_clear_irq_status() - Clear a pending interrupt's status
3886 + * @mc_io: Pointer to MC portal's I/O object
3887 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3888 + * @token: Token of DPRC object
3889 + * @irq_index: The interrupt index to configure
3890 + * @status: bits to clear (W1C) - one bit per cause:
3891 + * 0 = don't change
3892 + * 1 = clear status bit
3893 + *
3894 + * Return: '0' on Success; Error code otherwise.
3895 + */
3896 +int dprc_clear_irq_status(struct fsl_mc_io *mc_io,
3897 + u32 cmd_flags,
3898 + u16 token,
3899 + u8 irq_index,
3900 + u32 status)
3901 +{
3902 + struct fsl_mc_command cmd = { 0 };
3903 + struct dprc_cmd_clear_irq_status *cmd_params;
3904 +
3905 + /* prepare command */
3906 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLEAR_IRQ_STATUS,
3907 + cmd_flags, token);
3908 + cmd_params = (struct dprc_cmd_clear_irq_status *)cmd.params;
3909 + cmd_params->status = cpu_to_le32(status);
3910 + cmd_params->irq_index = irq_index;
3911 +
3912 + /* send command to mc*/
3913 + return mc_send_command(mc_io, &cmd);
3914 +}
3915 +
3916 +/**
3917 + * dprc_get_attributes() - Obtains container attributes
3918 + * @mc_io: Pointer to MC portal's I/O object
3919 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3920 + * @token: Token of DPRC object
3921 + * @attributes Returned container attributes
3922 + *
3923 + * Return: '0' on Success; Error code otherwise.
3924 + */
3925 +int dprc_get_attributes(struct fsl_mc_io *mc_io,
3926 + u32 cmd_flags,
3927 + u16 token,
3928 + struct dprc_attributes *attr)
3929 +{
3930 + struct fsl_mc_command cmd = { 0 };
3931 + struct dprc_rsp_get_attributes *rsp_params;
3932 + int err;
3933 +
3934 + /* prepare command */
3935 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_ATTR,
3936 + cmd_flags,
3937 + token);
3938 +
3939 + /* send command to mc*/
3940 + err = mc_send_command(mc_io, &cmd);
3941 + if (err)
3942 + return err;
3943 +
3944 + /* retrieve response parameters */
3945 + rsp_params = (struct dprc_rsp_get_attributes *)cmd.params;
3946 + attr->container_id = le32_to_cpu(rsp_params->container_id);
3947 + attr->icid = le32_to_cpu(rsp_params->icid);
3948 + attr->options = le32_to_cpu(rsp_params->options);
3949 + attr->portal_id = le32_to_cpu(rsp_params->portal_id);
3950 +
3951 + return 0;
3952 +}
3953 +
3954 +/**
3955 + * dprc_get_obj_count() - Obtains the number of objects in the DPRC
3956 + * @mc_io: Pointer to MC portal's I/O object
3957 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3958 + * @token: Token of DPRC object
3959 + * @obj_count: Number of objects assigned to the DPRC
3960 + *
3961 + * Return: '0' on Success; Error code otherwise.
3962 + */
3963 +int dprc_get_obj_count(struct fsl_mc_io *mc_io,
3964 + u32 cmd_flags,
3965 + u16 token,
3966 + int *obj_count)
3967 +{
3968 + struct fsl_mc_command cmd = { 0 };
3969 + struct dprc_rsp_get_obj_count *rsp_params;
3970 + int err;
3971 +
3972 + /* prepare command */
3973 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_COUNT,
3974 + cmd_flags, token);
3975 +
3976 + /* send command to mc*/
3977 + err = mc_send_command(mc_io, &cmd);
3978 + if (err)
3979 + return err;
3980 +
3981 + /* retrieve response parameters */
3982 + rsp_params = (struct dprc_rsp_get_obj_count *)cmd.params;
3983 + *obj_count = le32_to_cpu(rsp_params->obj_count);
3984 +
3985 + return 0;
3986 +}
3987 +EXPORT_SYMBOL_GPL(dprc_get_obj_count);
3988 +
3989 +/**
3990 + * dprc_get_obj() - Get general information on an object
3991 + * @mc_io: Pointer to MC portal's I/O object
3992 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3993 + * @token: Token of DPRC object
3994 + * @obj_index: Index of the object to be queried (< obj_count)
3995 + * @obj_desc: Returns the requested object descriptor
3996 + *
3997 + * The object descriptors are retrieved one by one by incrementing
3998 + * obj_index up to (not including) the value of obj_count returned
3999 + * from dprc_get_obj_count(). dprc_get_obj_count() must
4000 + * be called prior to dprc_get_obj().
4001 + *
4002 + * Return: '0' on Success; Error code otherwise.
4003 + */
4004 +int dprc_get_obj(struct fsl_mc_io *mc_io,
4005 + u32 cmd_flags,
4006 + u16 token,
4007 + int obj_index,
4008 + struct fsl_mc_obj_desc *obj_desc)
4009 +{
4010 + struct fsl_mc_command cmd = { 0 };
4011 + struct dprc_cmd_get_obj *cmd_params;
4012 + struct dprc_rsp_get_obj *rsp_params;
4013 + int err;
4014 +
4015 + /* prepare command */
4016 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ,
4017 + cmd_flags,
4018 + token);
4019 + cmd_params = (struct dprc_cmd_get_obj *)cmd.params;
4020 + cmd_params->obj_index = cpu_to_le32(obj_index);
4021 +
4022 + /* send command to mc*/
4023 + err = mc_send_command(mc_io, &cmd);
4024 + if (err)
4025 + return err;
4026 +
4027 + /* retrieve response parameters */
4028 + rsp_params = (struct dprc_rsp_get_obj *)cmd.params;
4029 + obj_desc->id = le32_to_cpu(rsp_params->id);
4030 + obj_desc->vendor = le16_to_cpu(rsp_params->vendor);
4031 + obj_desc->irq_count = rsp_params->irq_count;
4032 + obj_desc->region_count = rsp_params->region_count;
4033 + obj_desc->state = le32_to_cpu(rsp_params->state);
4034 + obj_desc->ver_major = le16_to_cpu(rsp_params->version_major);
4035 + obj_desc->ver_minor = le16_to_cpu(rsp_params->version_minor);
4036 + obj_desc->flags = le16_to_cpu(rsp_params->flags);
4037 + strncpy(obj_desc->type, rsp_params->type, 16);
4038 + obj_desc->type[15] = '\0';
4039 + strncpy(obj_desc->label, rsp_params->label, 16);
4040 + obj_desc->label[15] = '\0';
4041 + return 0;
4042 +}
4043 +EXPORT_SYMBOL_GPL(dprc_get_obj);
4044 +
4045 +/**
4046 + * dprc_set_obj_irq() - Set IRQ information for object to trigger an interrupt.
4047 + * @mc_io: Pointer to MC portal's I/O object
4048 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4049 + * @token: Token of DPRC object
4050 + * @obj_type: Type of the object to set its IRQ
4051 + * @obj_id: ID of the object to set its IRQ
4052 + * @irq_index: The interrupt index to configure
4053 + * @irq_cfg: IRQ configuration
4054 + *
4055 + * Return: '0' on Success; Error code otherwise.
4056 + */
4057 +int dprc_set_obj_irq(struct fsl_mc_io *mc_io,
4058 + u32 cmd_flags,
4059 + u16 token,
4060 + char *obj_type,
4061 + int obj_id,
4062 + u8 irq_index,
4063 + struct dprc_irq_cfg *irq_cfg)
4064 +{
4065 + struct fsl_mc_command cmd = { 0 };
4066 + struct dprc_cmd_set_obj_irq *cmd_params;
4067 +
4068 + /* prepare command */
4069 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_OBJ_IRQ,
4070 + cmd_flags,
4071 + token);
4072 + cmd_params = (struct dprc_cmd_set_obj_irq *)cmd.params;
4073 + cmd_params->irq_val = cpu_to_le32(irq_cfg->val);
4074 + cmd_params->irq_index = irq_index;
4075 + cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr);
4076 + cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num);
4077 + cmd_params->obj_id = cpu_to_le32(obj_id);
4078 + strncpy(cmd_params->obj_type, obj_type, 16);
4079 + cmd_params->obj_type[15] = '\0';
4080 +
4081 + /* send command to mc*/
4082 + return mc_send_command(mc_io, &cmd);
4083 +}
4084 +EXPORT_SYMBOL_GPL(dprc_set_obj_irq);
4085 +
4086 +/**
4087 + * dprc_get_obj_region() - Get region information for a specified object.
4088 + * @mc_io: Pointer to MC portal's I/O object
4089 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4090 + * @token: Token of DPRC object
4091 + * @obj_type; Object type as returned in dprc_get_obj()
4092 + * @obj_id: Unique object instance as returned in dprc_get_obj()
4093 + * @region_index: The specific region to query
4094 + * @region_desc: Returns the requested region descriptor
4095 + *
4096 + * Return: '0' on Success; Error code otherwise.
4097 + */
4098 +int dprc_get_obj_region(struct fsl_mc_io *mc_io,
4099 + u32 cmd_flags,
4100 + u16 token,
4101 + char *obj_type,
4102 + int obj_id,
4103 + u8 region_index,
4104 + struct dprc_region_desc *region_desc)
4105 +{
4106 + struct fsl_mc_command cmd = { 0 };
4107 + struct dprc_cmd_get_obj_region *cmd_params;
4108 + struct dprc_rsp_get_obj_region *rsp_params;
4109 + int err;
4110 +
4111 + /* prepare command */
4112 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG,
4113 + cmd_flags, token);
4114 + cmd_params = (struct dprc_cmd_get_obj_region *)cmd.params;
4115 + cmd_params->obj_id = cpu_to_le32(obj_id);
4116 + cmd_params->region_index = region_index;
4117 + strncpy(cmd_params->obj_type, obj_type, 16);
4118 + cmd_params->obj_type[15] = '\0';
4119 +
4120 + /* send command to mc*/
4121 + err = mc_send_command(mc_io, &cmd);
4122 + if (err)
4123 + return err;
4124 +
4125 + /* retrieve response parameters */
4126 + rsp_params = (struct dprc_rsp_get_obj_region *)cmd.params;
4127 + region_desc->base_offset = le32_to_cpu(rsp_params->base_offset);
4128 + region_desc->size = le32_to_cpu(rsp_params->size);
4129 + region_desc->type = rsp_params->type;
4130 + region_desc->flags = le32_to_cpu(rsp_params->flags);
4131 + region_desc->base_address = le64_to_cpu(rsp_params->base_addr);
4132 +
4133 + return 0;
4134 +}
4135 +EXPORT_SYMBOL_GPL(dprc_get_obj_region);
4136 +
4137 +/**
4138 + * dprc_get_api_version - Get Data Path Resource Container API version
4139 + * @mc_io: Pointer to Mc portal's I/O object
4140 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4141 + * @major_ver: Major version of Data Path Resource Container API
4142 + * @minor_ver: Minor version of Data Path Resource Container API
4143 + *
4144 + * Return: '0' on Success; Error code otherwise.
4145 + */
4146 +int dprc_get_api_version(struct fsl_mc_io *mc_io,
4147 + u32 cmd_flags,
4148 + u16 *major_ver,
4149 + u16 *minor_ver)
4150 +{
4151 + struct fsl_mc_command cmd = { 0 };
4152 + int err;
4153 +
4154 + /* prepare command */
4155 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_API_VERSION,
4156 + cmd_flags, 0);
4157 +
4158 + /* send command to mc */
4159 + err = mc_send_command(mc_io, &cmd);
4160 + if (err)
4161 + return err;
4162 +
4163 + /* retrieve response parameters */
4164 + mc_cmd_read_api_version(&cmd, major_ver, minor_ver);
4165 +
4166 + return 0;
4167 +}
4168 +
4169 +/**
4170 + * dprc_get_container_id - Get container ID associated with a given portal.
4171 + * @mc_io: Pointer to Mc portal's I/O object
4172 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4173 + * @container_id: Requested container id
4174 + *
4175 + * Return: '0' on Success; Error code otherwise.
4176 + */
4177 +int dprc_get_container_id(struct fsl_mc_io *mc_io,
4178 + u32 cmd_flags,
4179 + int *container_id)
4180 +{
4181 + struct fsl_mc_command cmd = { 0 };
4182 + int err;
4183 +
4184 + /* prepare command */
4185 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONT_ID,
4186 + cmd_flags,
4187 + 0);
4188 +
4189 + /* send command to mc*/
4190 + err = mc_send_command(mc_io, &cmd);
4191 + if (err)
4192 + return err;
4193 +
4194 + /* retrieve response parameters */
4195 + *container_id = (int)mc_cmd_read_object_id(&cmd);
4196 +
4197 + return 0;
4198 +}
4199 --- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c
4200 +++ /dev/null
4201 @@ -1,663 +0,0 @@
4202 -// SPDX-License-Identifier: GPL-2.0
4203 -/*
4204 - * fsl-mc object allocator driver
4205 - *
4206 - * Copyright (C) 2013-2016 Freescale Semiconductor, Inc.
4207 - *
4208 - */
4209 -
4210 -#include <linux/module.h>
4211 -#include <linux/msi.h>
4212 -#include "../include/mc.h"
4213 -
4214 -#include "fsl-mc-private.h"
4215 -
4216 -static bool __must_check fsl_mc_is_allocatable(const char *obj_type)
4217 -{
4218 - return strcmp(obj_type, "dpbp") == 0 ||
4219 - strcmp(obj_type, "dpmcp") == 0 ||
4220 - strcmp(obj_type, "dpcon") == 0;
4221 -}
4222 -
4223 -/**
4224 - * fsl_mc_resource_pool_add_device - add allocatable object to a resource
4225 - * pool of a given fsl-mc bus
4226 - *
4227 - * @mc_bus: pointer to the fsl-mc bus
4228 - * @pool_type: pool type
4229 - * @mc_dev: pointer to allocatable fsl-mc device
4230 - */
4231 -static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus
4232 - *mc_bus,
4233 - enum fsl_mc_pool_type
4234 - pool_type,
4235 - struct fsl_mc_device
4236 - *mc_dev)
4237 -{
4238 - struct fsl_mc_resource_pool *res_pool;
4239 - struct fsl_mc_resource *resource;
4240 - struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
4241 - int error = -EINVAL;
4242 -
4243 - if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES))
4244 - goto out;
4245 - if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type)))
4246 - goto out;
4247 - if (WARN_ON(mc_dev->resource))
4248 - goto out;
4249 -
4250 - res_pool = &mc_bus->resource_pools[pool_type];
4251 - if (WARN_ON(res_pool->type != pool_type))
4252 - goto out;
4253 - if (WARN_ON(res_pool->mc_bus != mc_bus))
4254 - goto out;
4255 -
4256 - mutex_lock(&res_pool->mutex);
4257 -
4258 - if (WARN_ON(res_pool->max_count < 0))
4259 - goto out_unlock;
4260 - if (WARN_ON(res_pool->free_count < 0 ||
4261 - res_pool->free_count > res_pool->max_count))
4262 - goto out_unlock;
4263 -
4264 - resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource),
4265 - GFP_KERNEL);
4266 - if (!resource) {
4267 - error = -ENOMEM;
4268 - dev_err(&mc_bus_dev->dev,
4269 - "Failed to allocate memory for fsl_mc_resource\n");
4270 - goto out_unlock;
4271 - }
4272 -
4273 - resource->type = pool_type;
4274 - resource->id = mc_dev->obj_desc.id;
4275 - resource->data = mc_dev;
4276 - resource->parent_pool = res_pool;
4277 - INIT_LIST_HEAD(&resource->node);
4278 - list_add_tail(&resource->node, &res_pool->free_list);
4279 - mc_dev->resource = resource;
4280 - res_pool->free_count++;
4281 - res_pool->max_count++;
4282 - error = 0;
4283 -out_unlock:
4284 - mutex_unlock(&res_pool->mutex);
4285 -out:
4286 - return error;
4287 -}
4288 -
4289 -/**
4290 - * fsl_mc_resource_pool_remove_device - remove an allocatable device from a
4291 - * resource pool
4292 - *
4293 - * @mc_dev: pointer to allocatable fsl-mc device
4294 - *
4295 - * It permanently removes an allocatable fsl-mc device from the resource
4296 - * pool. It's an error if the device is in use.
4297 - */
4298 -static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device
4299 - *mc_dev)
4300 -{
4301 - struct fsl_mc_device *mc_bus_dev;
4302 - struct fsl_mc_bus *mc_bus;
4303 - struct fsl_mc_resource_pool *res_pool;
4304 - struct fsl_mc_resource *resource;
4305 - int error = -EINVAL;
4306 -
4307 - if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type)))
4308 - goto out;
4309 -
4310 - resource = mc_dev->resource;
4311 - if (WARN_ON(!resource || resource->data != mc_dev))
4312 - goto out;
4313 -
4314 - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
4315 - mc_bus = to_fsl_mc_bus(mc_bus_dev);
4316 - res_pool = resource->parent_pool;
4317 - if (WARN_ON(res_pool != &mc_bus->resource_pools[resource->type]))
4318 - goto out;
4319 -
4320 - mutex_lock(&res_pool->mutex);
4321 -
4322 - if (WARN_ON(res_pool->max_count <= 0))
4323 - goto out_unlock;
4324 - if (WARN_ON(res_pool->free_count <= 0 ||
4325 - res_pool->free_count > res_pool->max_count))
4326 - goto out_unlock;
4327 -
4328 - /*
4329 - * If the device is currently allocated, its resource is not
4330 - * in the free list and thus, the device cannot be removed.
4331 - */
4332 - if (list_empty(&resource->node)) {
4333 - error = -EBUSY;
4334 - dev_err(&mc_bus_dev->dev,
4335 - "Device %s cannot be removed from resource pool\n",
4336 - dev_name(&mc_dev->dev));
4337 - goto out_unlock;
4338 - }
4339 -
4340 - list_del_init(&resource->node);
4341 - res_pool->free_count--;
4342 - res_pool->max_count--;
4343 -
4344 - devm_kfree(&mc_bus_dev->dev, resource);
4345 - mc_dev->resource = NULL;
4346 - error = 0;
4347 -out_unlock:
4348 - mutex_unlock(&res_pool->mutex);
4349 -out:
4350 - return error;
4351 -}
4352 -
4353 -static const char *const fsl_mc_pool_type_strings[] = {
4354 - [FSL_MC_POOL_DPMCP] = "dpmcp",
4355 - [FSL_MC_POOL_DPBP] = "dpbp",
4356 - [FSL_MC_POOL_DPCON] = "dpcon",
4357 - [FSL_MC_POOL_IRQ] = "irq",
4358 -};
4359 -
4360 -static int __must_check object_type_to_pool_type(const char *object_type,
4361 - enum fsl_mc_pool_type
4362 - *pool_type)
4363 -{
4364 - unsigned int i;
4365 -
4366 - for (i = 0; i < ARRAY_SIZE(fsl_mc_pool_type_strings); i++) {
4367 - if (strcmp(object_type, fsl_mc_pool_type_strings[i]) == 0) {
4368 - *pool_type = i;
4369 - return 0;
4370 - }
4371 - }
4372 -
4373 - return -EINVAL;
4374 -}
4375 -
4376 -int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus,
4377 - enum fsl_mc_pool_type pool_type,
4378 - struct fsl_mc_resource **new_resource)
4379 -{
4380 - struct fsl_mc_resource_pool *res_pool;
4381 - struct fsl_mc_resource *resource;
4382 - struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
4383 - int error = -EINVAL;
4384 -
4385 - BUILD_BUG_ON(ARRAY_SIZE(fsl_mc_pool_type_strings) !=
4386 - FSL_MC_NUM_POOL_TYPES);
4387 -
4388 - *new_resource = NULL;
4389 - if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES))
4390 - goto out;
4391 -
4392 - res_pool = &mc_bus->resource_pools[pool_type];
4393 - if (WARN_ON(res_pool->mc_bus != mc_bus))
4394 - goto out;
4395 -
4396 - mutex_lock(&res_pool->mutex);
4397 - resource = list_first_entry_or_null(&res_pool->free_list,
4398 - struct fsl_mc_resource, node);
4399 -
4400 - if (!resource) {
4401 - WARN_ON(res_pool->free_count != 0);
4402 - error = -ENXIO;
4403 - dev_err(&mc_bus_dev->dev,
4404 - "No more resources of type %s left\n",
4405 - fsl_mc_pool_type_strings[pool_type]);
4406 - goto out_unlock;
4407 - }
4408 -
4409 - if (WARN_ON(resource->type != pool_type))
4410 - goto out_unlock;
4411 - if (WARN_ON(resource->parent_pool != res_pool))
4412 - goto out_unlock;
4413 - if (WARN_ON(res_pool->free_count <= 0 ||
4414 - res_pool->free_count > res_pool->max_count))
4415 - goto out_unlock;
4416 -
4417 - list_del_init(&resource->node);
4418 -
4419 - res_pool->free_count--;
4420 - error = 0;
4421 -out_unlock:
4422 - mutex_unlock(&res_pool->mutex);
4423 - *new_resource = resource;
4424 -out:
4425 - return error;
4426 -}
4427 -EXPORT_SYMBOL_GPL(fsl_mc_resource_allocate);
4428 -
4429 -void fsl_mc_resource_free(struct fsl_mc_resource *resource)
4430 -{
4431 - struct fsl_mc_resource_pool *res_pool;
4432 -
4433 - res_pool = resource->parent_pool;
4434 - if (WARN_ON(resource->type != res_pool->type))
4435 - return;
4436 -
4437 - mutex_lock(&res_pool->mutex);
4438 - if (WARN_ON(res_pool->free_count < 0 ||
4439 - res_pool->free_count >= res_pool->max_count))
4440 - goto out_unlock;
4441 -
4442 - if (WARN_ON(!list_empty(&resource->node)))
4443 - goto out_unlock;
4444 -
4445 - list_add_tail(&resource->node, &res_pool->free_list);
4446 - res_pool->free_count++;
4447 -out_unlock:
4448 - mutex_unlock(&res_pool->mutex);
4449 -}
4450 -EXPORT_SYMBOL_GPL(fsl_mc_resource_free);
4451 -
4452 -/**
4453 - * fsl_mc_object_allocate - Allocates an fsl-mc object of the given
4454 - * pool type from a given fsl-mc bus instance
4455 - *
4456 - * @mc_dev: fsl-mc device which is used in conjunction with the
4457 - * allocated object
4458 - * @pool_type: pool type
4459 - * @new_mc_dev: pointer to area where the pointer to the allocated device
4460 - * is to be returned
4461 - *
4462 - * Allocatable objects are always used in conjunction with some functional
4463 - * device. This function allocates an object of the specified type from
4464 - * the DPRC containing the functional device.
4465 - *
4466 - * NOTE: pool_type must be different from FSL_MC_POOL_MCP, since MC
4467 - * portals are allocated using fsl_mc_portal_allocate(), instead of
4468 - * this function.
4469 - */
4470 -int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
4471 - enum fsl_mc_pool_type pool_type,
4472 - struct fsl_mc_device **new_mc_adev)
4473 -{
4474 - struct fsl_mc_device *mc_bus_dev;
4475 - struct fsl_mc_bus *mc_bus;
4476 - struct fsl_mc_device *mc_adev;
4477 - int error = -EINVAL;
4478 - struct fsl_mc_resource *resource = NULL;
4479 -
4480 - *new_mc_adev = NULL;
4481 - if (WARN_ON(mc_dev->flags & FSL_MC_IS_DPRC))
4482 - goto error;
4483 -
4484 - if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent)))
4485 - goto error;
4486 -
4487 - if (WARN_ON(pool_type == FSL_MC_POOL_DPMCP))
4488 - goto error;
4489 -
4490 - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
4491 - mc_bus = to_fsl_mc_bus(mc_bus_dev);
4492 - error = fsl_mc_resource_allocate(mc_bus, pool_type, &resource);
4493 - if (error < 0)
4494 - goto error;
4495 -
4496 - mc_adev = resource->data;
4497 - if (WARN_ON(!mc_adev))
4498 - goto error;
4499 -
4500 - *new_mc_adev = mc_adev;
4501 - return 0;
4502 -error:
4503 - if (resource)
4504 - fsl_mc_resource_free(resource);
4505 -
4506 - return error;
4507 -}
4508 -EXPORT_SYMBOL_GPL(fsl_mc_object_allocate);
4509 -
4510 -/**
4511 - * fsl_mc_object_free - Returns an fsl-mc object to the resource
4512 - * pool where it came from.
4513 - * @mc_adev: Pointer to the fsl-mc device
4514 - */
4515 -void fsl_mc_object_free(struct fsl_mc_device *mc_adev)
4516 -{
4517 - struct fsl_mc_resource *resource;
4518 -
4519 - resource = mc_adev->resource;
4520 - if (WARN_ON(resource->type == FSL_MC_POOL_DPMCP))
4521 - return;
4522 - if (WARN_ON(resource->data != mc_adev))
4523 - return;
4524 -
4525 - fsl_mc_resource_free(resource);
4526 -}
4527 -EXPORT_SYMBOL_GPL(fsl_mc_object_free);
4528 -
4529 -/*
4530 - * A DPRC and the devices in the DPRC all share the same GIC-ITS device
4531 - * ID. A block of IRQs is pre-allocated and maintained in a pool
4532 - * from which devices can allocate them when needed.
4533 - */
4534 -
4535 -/*
4536 - * Initialize the interrupt pool associated with an fsl-mc bus.
4537 - * It allocates a block of IRQs from the GIC-ITS.
4538 - */
4539 -int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
4540 - unsigned int irq_count)
4541 -{
4542 - unsigned int i;
4543 - struct msi_desc *msi_desc;
4544 - struct fsl_mc_device_irq *irq_resources;
4545 - struct fsl_mc_device_irq *mc_dev_irq;
4546 - int error;
4547 - struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
4548 - struct fsl_mc_resource_pool *res_pool =
4549 - &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
4550 -
4551 - if (WARN_ON(irq_count == 0 ||
4552 - irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS))
4553 - return -EINVAL;
4554 -
4555 - error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count);
4556 - if (error < 0)
4557 - return error;
4558 -
4559 - irq_resources = devm_kzalloc(&mc_bus_dev->dev,
4560 - sizeof(*irq_resources) * irq_count,
4561 - GFP_KERNEL);
4562 - if (!irq_resources) {
4563 - error = -ENOMEM;
4564 - goto cleanup_msi_irqs;
4565 - }
4566 -
4567 - for (i = 0; i < irq_count; i++) {
4568 - mc_dev_irq = &irq_resources[i];
4569 -
4570 - /*
4571 - * NOTE: This mc_dev_irq's MSI addr/value pair will be set
4572 - * by the fsl_mc_msi_write_msg() callback
4573 - */
4574 - mc_dev_irq->resource.type = res_pool->type;
4575 - mc_dev_irq->resource.data = mc_dev_irq;
4576 - mc_dev_irq->resource.parent_pool = res_pool;
4577 - INIT_LIST_HEAD(&mc_dev_irq->resource.node);
4578 - list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list);
4579 - }
4580 -
4581 - for_each_msi_entry(msi_desc, &mc_bus_dev->dev) {
4582 - mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index];
4583 - mc_dev_irq->msi_desc = msi_desc;
4584 - mc_dev_irq->resource.id = msi_desc->irq;
4585 - }
4586 -
4587 - res_pool->max_count = irq_count;
4588 - res_pool->free_count = irq_count;
4589 - mc_bus->irq_resources = irq_resources;
4590 - return 0;
4591 -
4592 -cleanup_msi_irqs:
4593 - fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
4594 - return error;
4595 -}
4596 -EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool);
4597 -
4598 -/**
4599 - * Teardown the interrupt pool associated with an fsl-mc bus.
4600 - * It frees the IRQs that were allocated to the pool, back to the GIC-ITS.
4601 - */
4602 -void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus)
4603 -{
4604 - struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
4605 - struct fsl_mc_resource_pool *res_pool =
4606 - &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
4607 -
4608 - if (WARN_ON(!mc_bus->irq_resources))
4609 - return;
4610 -
4611 - if (WARN_ON(res_pool->max_count == 0))
4612 - return;
4613 -
4614 - if (WARN_ON(res_pool->free_count != res_pool->max_count))
4615 - return;
4616 -
4617 - INIT_LIST_HEAD(&res_pool->free_list);
4618 - res_pool->max_count = 0;
4619 - res_pool->free_count = 0;
4620 - mc_bus->irq_resources = NULL;
4621 - fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
4622 -}
4623 -EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool);
4624 -
4625 -/**
4626 - * Allocate the IRQs required by a given fsl-mc device.
4627 - */
4628 -int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev)
4629 -{
4630 - int i;
4631 - int irq_count;
4632 - int res_allocated_count = 0;
4633 - int error = -EINVAL;
4634 - struct fsl_mc_device_irq **irqs = NULL;
4635 - struct fsl_mc_bus *mc_bus;
4636 - struct fsl_mc_resource_pool *res_pool;
4637 -
4638 - if (WARN_ON(mc_dev->irqs))
4639 - return -EINVAL;
4640 -
4641 - irq_count = mc_dev->obj_desc.irq_count;
4642 - if (WARN_ON(irq_count == 0))
4643 - return -EINVAL;
4644 -
4645 - if (strcmp(mc_dev->obj_desc.type, "dprc") == 0)
4646 - mc_bus = to_fsl_mc_bus(mc_dev);
4647 - else
4648 - mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
4649 -
4650 - if (WARN_ON(!mc_bus->irq_resources))
4651 - return -EINVAL;
4652 -
4653 - res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
4654 - if (res_pool->free_count < irq_count) {
4655 - dev_err(&mc_dev->dev,
4656 - "Not able to allocate %u irqs for device\n", irq_count);
4657 - return -ENOSPC;
4658 - }
4659 -
4660 - irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]),
4661 - GFP_KERNEL);
4662 - if (!irqs)
4663 - return -ENOMEM;
4664 -
4665 - for (i = 0; i < irq_count; i++) {
4666 - struct fsl_mc_resource *resource;
4667 -
4668 - error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ,
4669 - &resource);
4670 - if (error < 0)
4671 - goto error_resource_alloc;
4672 -
4673 - irqs[i] = to_fsl_mc_irq(resource);
4674 - res_allocated_count++;
4675 -
4676 - WARN_ON(irqs[i]->mc_dev);
4677 - irqs[i]->mc_dev = mc_dev;
4678 - irqs[i]->dev_irq_index = i;
4679 - }
4680 -
4681 - mc_dev->irqs = irqs;
4682 - return 0;
4683 -
4684 -error_resource_alloc:
4685 - for (i = 0; i < res_allocated_count; i++) {
4686 - irqs[i]->mc_dev = NULL;
4687 - fsl_mc_resource_free(&irqs[i]->resource);
4688 - }
4689 -
4690 - return error;
4691 -}
4692 -EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs);
4693 -
4694 -/*
4695 - * Frees the IRQs that were allocated for an fsl-mc device.
4696 - */
4697 -void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev)
4698 -{
4699 - int i;
4700 - int irq_count;
4701 - struct fsl_mc_bus *mc_bus;
4702 - struct fsl_mc_device_irq **irqs = mc_dev->irqs;
4703 -
4704 - if (WARN_ON(!irqs))
4705 - return;
4706 -
4707 - irq_count = mc_dev->obj_desc.irq_count;
4708 -
4709 - if (strcmp(mc_dev->obj_desc.type, "dprc") == 0)
4710 - mc_bus = to_fsl_mc_bus(mc_dev);
4711 - else
4712 - mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
4713 -
4714 - if (WARN_ON(!mc_bus->irq_resources))
4715 - return;
4716 -
4717 - for (i = 0; i < irq_count; i++) {
4718 - WARN_ON(!irqs[i]->mc_dev);
4719 - irqs[i]->mc_dev = NULL;
4720 - fsl_mc_resource_free(&irqs[i]->resource);
4721 - }
4722 -
4723 - mc_dev->irqs = NULL;
4724 -}
4725 -EXPORT_SYMBOL_GPL(fsl_mc_free_irqs);
4726 -
4727 -void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
4728 -{
4729 - int pool_type;
4730 - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
4731 -
4732 - for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) {
4733 - struct fsl_mc_resource_pool *res_pool =
4734 - &mc_bus->resource_pools[pool_type];
4735 -
4736 - res_pool->type = pool_type;
4737 - res_pool->max_count = 0;
4738 - res_pool->free_count = 0;
4739 - res_pool->mc_bus = mc_bus;
4740 - INIT_LIST_HEAD(&res_pool->free_list);
4741 - mutex_init(&res_pool->mutex);
4742 - }
4743 -}
4744 -
4745 -static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev,
4746 - enum fsl_mc_pool_type pool_type)
4747 -{
4748 - struct fsl_mc_resource *resource;
4749 - struct fsl_mc_resource *next;
4750 - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
4751 - struct fsl_mc_resource_pool *res_pool =
4752 - &mc_bus->resource_pools[pool_type];
4753 - int free_count = 0;
4754 -
4755 - WARN_ON(res_pool->type != pool_type);
4756 - WARN_ON(res_pool->free_count != res_pool->max_count);
4757 -
4758 - list_for_each_entry_safe(resource, next, &res_pool->free_list, node) {
4759 - free_count++;
4760 - WARN_ON(resource->type != res_pool->type);
4761 - WARN_ON(resource->parent_pool != res_pool);
4762 - devm_kfree(&mc_bus_dev->dev, resource);
4763 - }
4764 -
4765 - WARN_ON(free_count != res_pool->free_count);
4766 -}
4767 -
4768 -void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
4769 -{
4770 - int pool_type;
4771 -
4772 - for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++)
4773 - fsl_mc_cleanup_resource_pool(mc_bus_dev, pool_type);
4774 -}
4775 -
4776 -/**
4777 - * fsl_mc_allocator_probe - callback invoked when an allocatable device is
4778 - * being added to the system
4779 - */
4780 -static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev)
4781 -{
4782 - enum fsl_mc_pool_type pool_type;
4783 - struct fsl_mc_device *mc_bus_dev;
4784 - struct fsl_mc_bus *mc_bus;
4785 - int error;
4786 -
4787 - if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type)))
4788 - return -EINVAL;
4789 -
4790 - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
4791 - if (WARN_ON(!dev_is_fsl_mc(&mc_bus_dev->dev)))
4792 - return -EINVAL;
4793 -
4794 - mc_bus = to_fsl_mc_bus(mc_bus_dev);
4795 - error = object_type_to_pool_type(mc_dev->obj_desc.type, &pool_type);
4796 - if (error < 0)
4797 - return error;
4798 -
4799 - error = fsl_mc_resource_pool_add_device(mc_bus, pool_type, mc_dev);
4800 - if (error < 0)
4801 - return error;
4802 -
4803 - dev_dbg(&mc_dev->dev,
4804 - "Allocatable fsl-mc device bound to fsl_mc_allocator driver");
4805 - return 0;
4806 -}
4807 -
4808 -/**
4809 - * fsl_mc_allocator_remove - callback invoked when an allocatable device is
4810 - * being removed from the system
4811 - */
4812 -static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev)
4813 -{
4814 - int error;
4815 -
4816 - if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type)))
4817 - return -EINVAL;
4818 -
4819 - if (mc_dev->resource) {
4820 - error = fsl_mc_resource_pool_remove_device(mc_dev);
4821 - if (error < 0)
4822 - return error;
4823 - }
4824 -
4825 - dev_dbg(&mc_dev->dev,
4826 - "Allocatable fsl-mc device unbound from fsl_mc_allocator driver");
4827 - return 0;
4828 -}
4829 -
4830 -static const struct fsl_mc_device_id match_id_table[] = {
4831 - {
4832 - .vendor = FSL_MC_VENDOR_FREESCALE,
4833 - .obj_type = "dpbp",
4834 - },
4835 - {
4836 - .vendor = FSL_MC_VENDOR_FREESCALE,
4837 - .obj_type = "dpmcp",
4838 - },
4839 - {
4840 - .vendor = FSL_MC_VENDOR_FREESCALE,
4841 - .obj_type = "dpcon",
4842 - },
4843 - {.vendor = 0x0},
4844 -};
4845 -
4846 -static struct fsl_mc_driver fsl_mc_allocator_driver = {
4847 - .driver = {
4848 - .name = "fsl_mc_allocator",
4849 - .pm = NULL,
4850 - },
4851 - .match_id_table = match_id_table,
4852 - .probe = fsl_mc_allocator_probe,
4853 - .remove = fsl_mc_allocator_remove,
4854 -};
4855 -
4856 -int __init fsl_mc_allocator_driver_init(void)
4857 -{
4858 - return fsl_mc_driver_register(&fsl_mc_allocator_driver);
4859 -}
4860 -
4861 -void fsl_mc_allocator_driver_exit(void)
4862 -{
4863 - fsl_mc_driver_unregister(&fsl_mc_allocator_driver);
4864 -}
4865 --- /dev/null
4866 +++ b/drivers/bus/fsl-mc/fsl-mc-allocator.c
4867 @@ -0,0 +1,666 @@
4868 +// SPDX-License-Identifier: GPL-2.0
4869 +/*
4870 + * fsl-mc object allocator driver
4871 + *
4872 + * Copyright (C) 2013-2016 Freescale Semiconductor, Inc.
4873 + *
4874 + */
4875 +
4876 +#include <linux/module.h>
4877 +#include <linux/msi.h>
4878 +#include <linux/fsl/mc.h>
4879 +
4880 +#include "fsl-mc-private.h"
4881 +
4882 +static bool __must_check fsl_mc_is_allocatable(struct fsl_mc_device *mc_dev)
4883 +{
4884 + return is_fsl_mc_bus_dpbp(mc_dev) ||
4885 + is_fsl_mc_bus_dpmcp(mc_dev) ||
4886 + is_fsl_mc_bus_dpcon(mc_dev);
4887 +}
4888 +
4889 +/**
4890 + * fsl_mc_resource_pool_add_device - add allocatable object to a resource
4891 + * pool of a given fsl-mc bus
4892 + *
4893 + * @mc_bus: pointer to the fsl-mc bus
4894 + * @pool_type: pool type
4895 + * @mc_dev: pointer to allocatable fsl-mc device
4896 + */
4897 +static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus
4898 + *mc_bus,
4899 + enum fsl_mc_pool_type
4900 + pool_type,
4901 + struct fsl_mc_device
4902 + *mc_dev)
4903 +{
4904 + struct fsl_mc_resource_pool *res_pool;
4905 + struct fsl_mc_resource *resource;
4906 + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
4907 + int error = -EINVAL;
4908 +
4909 + if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)
4910 + goto out;
4911 + if (!fsl_mc_is_allocatable(mc_dev))
4912 + goto out;
4913 + if (mc_dev->resource)
4914 + goto out;
4915 +
4916 + res_pool = &mc_bus->resource_pools[pool_type];
4917 + if (res_pool->type != pool_type)
4918 + goto out;
4919 + if (res_pool->mc_bus != mc_bus)
4920 + goto out;
4921 +
4922 + mutex_lock(&res_pool->mutex);
4923 +
4924 + if (res_pool->max_count < 0)
4925 + goto out_unlock;
4926 + if (res_pool->free_count < 0 ||
4927 + res_pool->free_count > res_pool->max_count)
4928 + goto out_unlock;
4929 +
4930 + resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource),
4931 + GFP_KERNEL);
4932 + if (!resource) {
4933 + error = -ENOMEM;
4934 + dev_err(&mc_bus_dev->dev,
4935 + "Failed to allocate memory for fsl_mc_resource\n");
4936 + goto out_unlock;
4937 + }
4938 +
4939 + resource->type = pool_type;
4940 + resource->id = mc_dev->obj_desc.id;
4941 + resource->data = mc_dev;
4942 + resource->parent_pool = res_pool;
4943 + INIT_LIST_HEAD(&resource->node);
4944 + list_add_tail(&resource->node, &res_pool->free_list);
4945 + mc_dev->resource = resource;
4946 + res_pool->free_count++;
4947 + res_pool->max_count++;
4948 + error = 0;
4949 +out_unlock:
4950 + mutex_unlock(&res_pool->mutex);
4951 +out:
4952 + return error;
4953 +}
4954 +
4955 +/**
4956 + * fsl_mc_resource_pool_remove_device - remove an allocatable device from a
4957 + * resource pool
4958 + *
4959 + * @mc_dev: pointer to allocatable fsl-mc device
4960 + *
4961 + * It permanently removes an allocatable fsl-mc device from the resource
4962 + * pool. It's an error if the device is in use.
4963 + */
4964 +static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device
4965 + *mc_dev)
4966 +{
4967 + struct fsl_mc_device *mc_bus_dev;
4968 + struct fsl_mc_bus *mc_bus;
4969 + struct fsl_mc_resource_pool *res_pool;
4970 + struct fsl_mc_resource *resource;
4971 + int error = -EINVAL;
4972 +
4973 + if (!fsl_mc_is_allocatable(mc_dev))
4974 + goto out;
4975 +
4976 + resource = mc_dev->resource;
4977 + if (!resource || resource->data != mc_dev)
4978 + goto out;
4979 +
4980 + mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
4981 + mc_bus = to_fsl_mc_bus(mc_bus_dev);
4982 + res_pool = resource->parent_pool;
4983 + if (res_pool != &mc_bus->resource_pools[resource->type])
4984 + goto out;
4985 +
4986 + mutex_lock(&res_pool->mutex);
4987 +
4988 + if (res_pool->max_count <= 0)
4989 + goto out_unlock;
4990 + if (res_pool->free_count <= 0 ||
4991 + res_pool->free_count > res_pool->max_count)
4992 + goto out_unlock;
4993 +
4994 + /*
4995 + * If the device is currently allocated, its resource is not
4996 + * in the free list and thus, the device cannot be removed.
4997 + */
4998 + if (list_empty(&resource->node)) {
4999 + error = -EBUSY;
5000 + dev_err(&mc_bus_dev->dev,
5001 + "Device %s cannot be removed from resource pool\n",
5002 + dev_name(&mc_dev->dev));
5003 + goto out_unlock;
5004 + }
5005 +
5006 + list_del_init(&resource->node);
5007 + res_pool->free_count--;
5008 + res_pool->max_count--;
5009 +
5010 + devm_kfree(&mc_bus_dev->dev, resource);
5011 + mc_dev->resource = NULL;
5012 + error = 0;
5013 +out_unlock:
5014 + mutex_unlock(&res_pool->mutex);
5015 +out:
5016 + return error;
5017 +}
5018 +
5019 +static const char *const fsl_mc_pool_type_strings[] = {
5020 + [FSL_MC_POOL_DPMCP] = "dpmcp",
5021 + [FSL_MC_POOL_DPBP] = "dpbp",
5022 + [FSL_MC_POOL_DPCON] = "dpcon",
5023 + [FSL_MC_POOL_IRQ] = "irq",
5024 +};
5025 +
5026 +static int __must_check object_type_to_pool_type(const char *object_type,
5027 + enum fsl_mc_pool_type
5028 + *pool_type)
5029 +{
5030 + unsigned int i;
5031 +
5032 + for (i = 0; i < ARRAY_SIZE(fsl_mc_pool_type_strings); i++) {
5033 + if (strcmp(object_type, fsl_mc_pool_type_strings[i]) == 0) {
5034 + *pool_type = i;
5035 + return 0;
5036 + }
5037 + }
5038 +
5039 + return -EINVAL;
5040 +}
5041 +
5042 +int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus,
5043 + enum fsl_mc_pool_type pool_type,
5044 + struct fsl_mc_resource **new_resource)
5045 +{
5046 + struct fsl_mc_resource_pool *res_pool;
5047 + struct fsl_mc_resource *resource;
5048 + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
5049 + int error = -EINVAL;
5050 +
5051 + BUILD_BUG_ON(ARRAY_SIZE(fsl_mc_pool_type_strings) !=
5052 + FSL_MC_NUM_POOL_TYPES);
5053 +
5054 + *new_resource = NULL;
5055 + if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)
5056 + goto out;
5057 +
5058 + res_pool = &mc_bus->resource_pools[pool_type];
5059 + if (res_pool->mc_bus != mc_bus)
5060 + goto out;
5061 +
5062 + mutex_lock(&res_pool->mutex);
5063 + resource = list_first_entry_or_null(&res_pool->free_list,
5064 + struct fsl_mc_resource, node);
5065 +
5066 + if (!resource) {
5067 + error = -ENXIO;
5068 + dev_err(&mc_bus_dev->dev,
5069 + "No more resources of type %s left\n",
5070 + fsl_mc_pool_type_strings[pool_type]);
5071 + goto out_unlock;
5072 + }
5073 +
5074 + if (resource->type != pool_type)
5075 + goto out_unlock;
5076 + if (resource->parent_pool != res_pool)
5077 + goto out_unlock;
5078 + if (res_pool->free_count <= 0 ||
5079 + res_pool->free_count > res_pool->max_count)
5080 + goto out_unlock;
5081 +
5082 + list_del_init(&resource->node);
5083 +
5084 + res_pool->free_count--;
5085 + error = 0;
5086 +out_unlock:
5087 + mutex_unlock(&res_pool->mutex);
5088 + *new_resource = resource;
5089 +out:
5090 + return error;
5091 +}
5092 +EXPORT_SYMBOL_GPL(fsl_mc_resource_allocate);
5093 +
5094 +void fsl_mc_resource_free(struct fsl_mc_resource *resource)
5095 +{
5096 + struct fsl_mc_resource_pool *res_pool;
5097 +
5098 + res_pool = resource->parent_pool;
5099 + if (resource->type != res_pool->type)
5100 + return;
5101 +
5102 + mutex_lock(&res_pool->mutex);
5103 + if (res_pool->free_count < 0 ||
5104 + res_pool->free_count >= res_pool->max_count)
5105 + goto out_unlock;
5106 +
5107 + if (!list_empty(&resource->node))
5108 + goto out_unlock;
5109 +
5110 + list_add_tail(&resource->node, &res_pool->free_list);
5111 + res_pool->free_count++;
5112 +out_unlock:
5113 + mutex_unlock(&res_pool->mutex);
5114 +}
5115 +EXPORT_SYMBOL_GPL(fsl_mc_resource_free);
5116 +
5117 +/**
5118 + * fsl_mc_object_allocate - Allocates an fsl-mc object of the given
5119 + * pool type from a given fsl-mc bus instance
5120 + *
5121 + * @mc_dev: fsl-mc device which is used in conjunction with the
5122 + * allocated object
5123 + * @pool_type: pool type
5124 + * @new_mc_dev: pointer to area where the pointer to the allocated device
5125 + * is to be returned
5126 + *
5127 + * Allocatable objects are always used in conjunction with some functional
5128 + * device. This function allocates an object of the specified type from
5129 + * the DPRC containing the functional device.
5130 + *
5131 + * NOTE: pool_type must be different from FSL_MC_POOL_MCP, since MC
5132 + * portals are allocated using fsl_mc_portal_allocate(), instead of
5133 + * this function.
5134 + */
5135 +int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
5136 + enum fsl_mc_pool_type pool_type,
5137 + struct fsl_mc_device **new_mc_adev)
5138 +{
5139 + struct fsl_mc_device *mc_bus_dev;
5140 + struct fsl_mc_bus *mc_bus;
5141 + struct fsl_mc_device *mc_adev;
5142 + int error = -EINVAL;
5143 + struct fsl_mc_resource *resource = NULL;
5144 +
5145 + *new_mc_adev = NULL;
5146 + if (mc_dev->flags & FSL_MC_IS_DPRC)
5147 + goto error;
5148 +
5149 + if (!dev_is_fsl_mc(mc_dev->dev.parent))
5150 + goto error;
5151 +
5152 + if (pool_type == FSL_MC_POOL_DPMCP)
5153 + goto error;
5154 +
5155 + mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
5156 + mc_bus = to_fsl_mc_bus(mc_bus_dev);
5157 + error = fsl_mc_resource_allocate(mc_bus, pool_type, &resource);
5158 + if (error < 0)
5159 + goto error;
5160 +
5161 + mc_adev = resource->data;
5162 + if (!mc_adev)
5163 + goto error;
5164 +
5165 + mc_adev->consumer_link = device_link_add(&mc_dev->dev,
5166 + &mc_adev->dev,
5167 + DL_FLAG_AUTOREMOVE_CONSUMER);
5168 + if (!mc_adev->consumer_link) {
5169 + error = -EINVAL;
5170 + goto error;
5171 + }
5172 +
5173 + *new_mc_adev = mc_adev;
5174 + return 0;
5175 +error:
5176 + if (resource)
5177 + fsl_mc_resource_free(resource);
5178 +
5179 + return error;
5180 +}
5181 +EXPORT_SYMBOL_GPL(fsl_mc_object_allocate);
5182 +
5183 +/**
5184 + * fsl_mc_object_free - Returns an fsl-mc object to the resource
5185 + * pool where it came from.
5186 + * @mc_adev: Pointer to the fsl-mc device
5187 + */
5188 +void fsl_mc_object_free(struct fsl_mc_device *mc_adev)
5189 +{
5190 + struct fsl_mc_resource *resource;
5191 +
5192 + resource = mc_adev->resource;
5193 + if (resource->type == FSL_MC_POOL_DPMCP)
5194 + return;
5195 + if (resource->data != mc_adev)
5196 + return;
5197 +
5198 + fsl_mc_resource_free(resource);
5199 +
5200 + device_link_del(mc_adev->consumer_link);
5201 + mc_adev->consumer_link = NULL;
5202 +}
5203 +EXPORT_SYMBOL_GPL(fsl_mc_object_free);
5204 +
5205 +/*
5206 + * A DPRC and the devices in the DPRC all share the same GIC-ITS device
5207 + * ID. A block of IRQs is pre-allocated and maintained in a pool
5208 + * from which devices can allocate them when needed.
5209 + */
5210 +
5211 +/*
5212 + * Initialize the interrupt pool associated with an fsl-mc bus.
5213 + * It allocates a block of IRQs from the GIC-ITS.
5214 + */
5215 +int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
5216 + unsigned int irq_count)
5217 +{
5218 + unsigned int i;
5219 + struct msi_desc *msi_desc;
5220 + struct fsl_mc_device_irq *irq_resources;
5221 + struct fsl_mc_device_irq *mc_dev_irq;
5222 + int error;
5223 + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
5224 + struct fsl_mc_resource_pool *res_pool =
5225 + &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
5226 +
5227 + if (irq_count == 0 ||
5228 + irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS)
5229 + return -EINVAL;
5230 +
5231 + error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count);
5232 + if (error < 0)
5233 + return error;
5234 +
5235 + irq_resources = devm_kzalloc(&mc_bus_dev->dev,
5236 + sizeof(*irq_resources) * irq_count,
5237 + GFP_KERNEL);
5238 + if (!irq_resources) {
5239 + error = -ENOMEM;
5240 + goto cleanup_msi_irqs;
5241 + }
5242 +
5243 + for (i = 0; i < irq_count; i++) {
5244 + mc_dev_irq = &irq_resources[i];
5245 +
5246 + /*
5247 + * NOTE: This mc_dev_irq's MSI addr/value pair will be set
5248 + * by the fsl_mc_msi_write_msg() callback
5249 + */
5250 + mc_dev_irq->resource.type = res_pool->type;
5251 + mc_dev_irq->resource.data = mc_dev_irq;
5252 + mc_dev_irq->resource.parent_pool = res_pool;
5253 + INIT_LIST_HEAD(&mc_dev_irq->resource.node);
5254 + list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list);
5255 + }
5256 +
5257 + for_each_msi_entry(msi_desc, &mc_bus_dev->dev) {
5258 + mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index];
5259 + mc_dev_irq->msi_desc = msi_desc;
5260 + mc_dev_irq->resource.id = msi_desc->irq;
5261 + }
5262 +
5263 + res_pool->max_count = irq_count;
5264 + res_pool->free_count = irq_count;
5265 + mc_bus->irq_resources = irq_resources;
5266 + return 0;
5267 +
5268 +cleanup_msi_irqs:
5269 + fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
5270 + return error;
5271 +}
5272 +EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool);
5273 +
5274 +/**
5275 + * Teardown the interrupt pool associated with an fsl-mc bus.
5276 + * It frees the IRQs that were allocated to the pool, back to the GIC-ITS.
5277 + */
5278 +void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus)
5279 +{
5280 + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
5281 + struct fsl_mc_resource_pool *res_pool =
5282 + &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
5283 +
5284 + if (!mc_bus->irq_resources)
5285 + return;
5286 +
5287 + if (res_pool->max_count == 0)
5288 + return;
5289 +
5290 + if (res_pool->free_count != res_pool->max_count)
5291 + return;
5292 +
5293 + INIT_LIST_HEAD(&res_pool->free_list);
5294 + res_pool->max_count = 0;
5295 + res_pool->free_count = 0;
5296 + mc_bus->irq_resources = NULL;
5297 + fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
5298 +}
5299 +EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool);
5300 +
5301 +/**
5302 + * Allocate the IRQs required by a given fsl-mc device.
5303 + */
5304 +int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev)
5305 +{
5306 + int i;
5307 + int irq_count;
5308 + int res_allocated_count = 0;
5309 + int error = -EINVAL;
5310 + struct fsl_mc_device_irq **irqs = NULL;
5311 + struct fsl_mc_bus *mc_bus;
5312 + struct fsl_mc_resource_pool *res_pool;
5313 +
5314 + if (mc_dev->irqs)
5315 + return -EINVAL;
5316 +
5317 + irq_count = mc_dev->obj_desc.irq_count;
5318 + if (irq_count == 0)
5319 + return -EINVAL;
5320 +
5321 + if (is_fsl_mc_bus_dprc(mc_dev))
5322 + mc_bus = to_fsl_mc_bus(mc_dev);
5323 + else
5324 + mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
5325 +
5326 + if (!mc_bus->irq_resources)
5327 + return -EINVAL;
5328 +
5329 + res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
5330 + if (res_pool->free_count < irq_count) {
5331 + dev_err(&mc_dev->dev,
5332 + "Not able to allocate %u irqs for device\n", irq_count);
5333 + return -ENOSPC;
5334 + }
5335 +
5336 + irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]),
5337 + GFP_KERNEL);
5338 + if (!irqs)
5339 + return -ENOMEM;
5340 +
5341 + for (i = 0; i < irq_count; i++) {
5342 + struct fsl_mc_resource *resource;
5343 +
5344 + error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ,
5345 + &resource);
5346 + if (error < 0)
5347 + goto error_resource_alloc;
5348 +
5349 + irqs[i] = to_fsl_mc_irq(resource);
5350 + res_allocated_count++;
5351 +
5352 + irqs[i]->mc_dev = mc_dev;
5353 + irqs[i]->dev_irq_index = i;
5354 + }
5355 +
5356 + mc_dev->irqs = irqs;
5357 + return 0;
5358 +
5359 +error_resource_alloc:
5360 + for (i = 0; i < res_allocated_count; i++) {
5361 + irqs[i]->mc_dev = NULL;
5362 + fsl_mc_resource_free(&irqs[i]->resource);
5363 + }
5364 +
5365 + return error;
5366 +}
5367 +EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs);
5368 +
5369 +/*
5370 + * Frees the IRQs that were allocated for an fsl-mc device.
5371 + */
5372 +void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev)
5373 +{
5374 + int i;
5375 + int irq_count;
5376 + struct fsl_mc_bus *mc_bus;
5377 + struct fsl_mc_device_irq **irqs = mc_dev->irqs;
5378 +
5379 + if (!irqs)
5380 + return;
5381 +
5382 + irq_count = mc_dev->obj_desc.irq_count;
5383 +
5384 + if (is_fsl_mc_bus_dprc(mc_dev))
5385 + mc_bus = to_fsl_mc_bus(mc_dev);
5386 + else
5387 + mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
5388 +
5389 + if (!mc_bus->irq_resources)
5390 + return;
5391 +
5392 + for (i = 0; i < irq_count; i++) {
5393 + irqs[i]->mc_dev = NULL;
5394 + fsl_mc_resource_free(&irqs[i]->resource);
5395 + }
5396 +
5397 + mc_dev->irqs = NULL;
5398 +}
5399 +EXPORT_SYMBOL_GPL(fsl_mc_free_irqs);
5400 +
5401 +void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
5402 +{
5403 + int pool_type;
5404 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
5405 +
5406 + for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) {
5407 + struct fsl_mc_resource_pool *res_pool =
5408 + &mc_bus->resource_pools[pool_type];
5409 +
5410 + res_pool->type = pool_type;
5411 + res_pool->max_count = 0;
5412 + res_pool->free_count = 0;
5413 + res_pool->mc_bus = mc_bus;
5414 + INIT_LIST_HEAD(&res_pool->free_list);
5415 + mutex_init(&res_pool->mutex);
5416 + }
5417 +}
5418 +EXPORT_SYMBOL_GPL(fsl_mc_init_all_resource_pools);
5419 +
5420 +static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev,
5421 + enum fsl_mc_pool_type pool_type)
5422 +{
5423 + struct fsl_mc_resource *resource;
5424 + struct fsl_mc_resource *next;
5425 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
5426 + struct fsl_mc_resource_pool *res_pool =
5427 + &mc_bus->resource_pools[pool_type];
5428 + int free_count = 0;
5429 +
5430 + list_for_each_entry_safe(resource, next, &res_pool->free_list, node) {
5431 + free_count++;
5432 + devm_kfree(&mc_bus_dev->dev, resource);
5433 + }
5434 +}
5435 +
5436 +void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
5437 +{
5438 + int pool_type;
5439 +
5440 + for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++)
5441 + fsl_mc_cleanup_resource_pool(mc_bus_dev, pool_type);
5442 +}
5443 +EXPORT_SYMBOL_GPL(fsl_mc_cleanup_all_resource_pools);
5444 +
5445 +/**
5446 + * fsl_mc_allocator_probe - callback invoked when an allocatable device is
5447 + * being added to the system
5448 + */
5449 +static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev)
5450 +{
5451 + enum fsl_mc_pool_type pool_type;
5452 + struct fsl_mc_device *mc_bus_dev;
5453 + struct fsl_mc_bus *mc_bus;
5454 + int error;
5455 +
5456 + if (!fsl_mc_is_allocatable(mc_dev))
5457 + return -EINVAL;
5458 +
5459 + mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
5460 + if (!dev_is_fsl_mc(&mc_bus_dev->dev))
5461 + return -EINVAL;
5462 +
5463 + mc_bus = to_fsl_mc_bus(mc_bus_dev);
5464 + error = object_type_to_pool_type(mc_dev->obj_desc.type, &pool_type);
5465 + if (error < 0)
5466 + return error;
5467 +
5468 + error = fsl_mc_resource_pool_add_device(mc_bus, pool_type, mc_dev);
5469 + if (error < 0)
5470 + return error;
5471 +
5472 + dev_dbg(&mc_dev->dev,
5473 + "Allocatable fsl-mc device bound to fsl_mc_allocator driver");
5474 + return 0;
5475 +}
5476 +
5477 +/**
5478 + * fsl_mc_allocator_remove - callback invoked when an allocatable device is
5479 + * being removed from the system
5480 + */
5481 +static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev)
5482 +{
5483 + int error;
5484 +
5485 + if (!fsl_mc_is_allocatable(mc_dev))
5486 + return -EINVAL;
5487 +
5488 + if (mc_dev->resource) {
5489 + error = fsl_mc_resource_pool_remove_device(mc_dev);
5490 + if (error < 0)
5491 + return error;
5492 + }
5493 +
5494 + dev_dbg(&mc_dev->dev,
5495 + "Allocatable fsl-mc device unbound from fsl_mc_allocator driver");
5496 + return 0;
5497 +}
5498 +
5499 +static const struct fsl_mc_device_id match_id_table[] = {
5500 + {
5501 + .vendor = FSL_MC_VENDOR_FREESCALE,
5502 + .obj_type = "dpbp",
5503 + },
5504 + {
5505 + .vendor = FSL_MC_VENDOR_FREESCALE,
5506 + .obj_type = "dpmcp",
5507 + },
5508 + {
5509 + .vendor = FSL_MC_VENDOR_FREESCALE,
5510 + .obj_type = "dpcon",
5511 + },
5512 + {.vendor = 0x0},
5513 +};
5514 +
5515 +static struct fsl_mc_driver fsl_mc_allocator_driver = {
5516 + .driver = {
5517 + .name = "fsl_mc_allocator",
5518 + .pm = NULL,
5519 + },
5520 + .match_id_table = match_id_table,
5521 + .probe = fsl_mc_allocator_probe,
5522 + .remove = fsl_mc_allocator_remove,
5523 +};
5524 +
5525 +int __init fsl_mc_allocator_driver_init(void)
5526 +{
5527 + return fsl_mc_driver_register(&fsl_mc_allocator_driver);
5528 +}
5529 +
5530 +void fsl_mc_allocator_driver_exit(void)
5531 +{
5532 + fsl_mc_driver_unregister(&fsl_mc_allocator_driver);
5533 +}
5534 --- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c
5535 +++ /dev/null
5536 @@ -1,900 +0,0 @@
5537 -// SPDX-License-Identifier: GPL-2.0
5538 -/*
5539 - * Freescale Management Complex (MC) bus driver
5540 - *
5541 - * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
5542 - * Author: German Rivera <German.Rivera@freescale.com>
5543 - *
5544 - */
5545 -
5546 -#define pr_fmt(fmt) "fsl-mc: " fmt
5547 -
5548 -#include <linux/module.h>
5549 -#include <linux/of_device.h>
5550 -#include <linux/of_address.h>
5551 -#include <linux/ioport.h>
5552 -#include <linux/slab.h>
5553 -#include <linux/limits.h>
5554 -#include <linux/bitops.h>
5555 -#include <linux/msi.h>
5556 -#include <linux/dma-mapping.h>
5557 -
5558 -#include "fsl-mc-private.h"
5559 -#include "dprc-cmd.h"
5560 -#include "dpmng-cmd.h"
5561 -
5562 -/**
5563 - * Default DMA mask for devices on a fsl-mc bus
5564 - */
5565 -#define FSL_MC_DEFAULT_DMA_MASK (~0ULL)
5566 -
5567 -/**
5568 - * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device
5569 - * @root_mc_bus_dev: fsl-mc device representing the root DPRC
5570 - * @num_translation_ranges: number of entries in addr_translation_ranges
5571 - * @translation_ranges: array of bus to system address translation ranges
5572 - */
5573 -struct fsl_mc {
5574 - struct fsl_mc_device *root_mc_bus_dev;
5575 - u8 num_translation_ranges;
5576 - struct fsl_mc_addr_translation_range *translation_ranges;
5577 -};
5578 -
5579 -/**
5580 - * struct fsl_mc_addr_translation_range - bus to system address translation
5581 - * range
5582 - * @mc_region_type: Type of MC region for the range being translated
5583 - * @start_mc_offset: Start MC offset of the range being translated
5584 - * @end_mc_offset: MC offset of the first byte after the range (last MC
5585 - * offset of the range is end_mc_offset - 1)
5586 - * @start_phys_addr: system physical address corresponding to start_mc_addr
5587 - */
5588 -struct fsl_mc_addr_translation_range {
5589 - enum dprc_region_type mc_region_type;
5590 - u64 start_mc_offset;
5591 - u64 end_mc_offset;
5592 - phys_addr_t start_phys_addr;
5593 -};
5594 -
5595 -/**
5596 - * struct mc_version
5597 - * @major: Major version number: incremented on API compatibility changes
5598 - * @minor: Minor version number: incremented on API additions (that are
5599 - * backward compatible); reset when major version is incremented
5600 - * @revision: Internal revision number: incremented on implementation changes
5601 - * and/or bug fixes that have no impact on API
5602 - */
5603 -struct mc_version {
5604 - u32 major;
5605 - u32 minor;
5606 - u32 revision;
5607 -};
5608 -
5609 -/**
5610 - * fsl_mc_bus_match - device to driver matching callback
5611 - * @dev: the fsl-mc device to match against
5612 - * @drv: the device driver to search for matching fsl-mc object type
5613 - * structures
5614 - *
5615 - * Returns 1 on success, 0 otherwise.
5616 - */
5617 -static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv)
5618 -{
5619 - const struct fsl_mc_device_id *id;
5620 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
5621 - struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv);
5622 - bool found = false;
5623 -
5624 - if (!mc_drv->match_id_table)
5625 - goto out;
5626 -
5627 - /*
5628 - * If the object is not 'plugged' don't match.
5629 - * Only exception is the root DPRC, which is a special case.
5630 - */
5631 - if ((mc_dev->obj_desc.state & FSL_MC_OBJ_STATE_PLUGGED) == 0 &&
5632 - !fsl_mc_is_root_dprc(&mc_dev->dev))
5633 - goto out;
5634 -
5635 - /*
5636 - * Traverse the match_id table of the given driver, trying to find
5637 - * a matching for the given device.
5638 - */
5639 - for (id = mc_drv->match_id_table; id->vendor != 0x0; id++) {
5640 - if (id->vendor == mc_dev->obj_desc.vendor &&
5641 - strcmp(id->obj_type, mc_dev->obj_desc.type) == 0) {
5642 - found = true;
5643 -
5644 - break;
5645 - }
5646 - }
5647 -
5648 -out:
5649 - dev_dbg(dev, "%smatched\n", found ? "" : "not ");
5650 - return found;
5651 -}
5652 -
5653 -/**
5654 - * fsl_mc_bus_uevent - callback invoked when a device is added
5655 - */
5656 -static int fsl_mc_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
5657 -{
5658 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
5659 -
5660 - if (add_uevent_var(env, "MODALIAS=fsl-mc:v%08Xd%s",
5661 - mc_dev->obj_desc.vendor,
5662 - mc_dev->obj_desc.type))
5663 - return -ENOMEM;
5664 -
5665 - return 0;
5666 -}
5667 -
5668 -static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
5669 - char *buf)
5670 -{
5671 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
5672 -
5673 - return sprintf(buf, "fsl-mc:v%08Xd%s\n", mc_dev->obj_desc.vendor,
5674 - mc_dev->obj_desc.type);
5675 -}
5676 -static DEVICE_ATTR_RO(modalias);
5677 -
5678 -static struct attribute *fsl_mc_dev_attrs[] = {
5679 - &dev_attr_modalias.attr,
5680 - NULL,
5681 -};
5682 -
5683 -ATTRIBUTE_GROUPS(fsl_mc_dev);
5684 -
5685 -struct bus_type fsl_mc_bus_type = {
5686 - .name = "fsl-mc",
5687 - .match = fsl_mc_bus_match,
5688 - .uevent = fsl_mc_bus_uevent,
5689 - .dev_groups = fsl_mc_dev_groups,
5690 -};
5691 -EXPORT_SYMBOL_GPL(fsl_mc_bus_type);
5692 -
5693 -static int fsl_mc_driver_probe(struct device *dev)
5694 -{
5695 - struct fsl_mc_driver *mc_drv;
5696 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
5697 - int error;
5698 -
5699 - if (WARN_ON(!dev->driver))
5700 - return -EINVAL;
5701 -
5702 - mc_drv = to_fsl_mc_driver(dev->driver);
5703 - if (WARN_ON(!mc_drv->probe))
5704 - return -EINVAL;
5705 -
5706 - error = mc_drv->probe(mc_dev);
5707 - if (error < 0) {
5708 - dev_err(dev, "%s failed: %d\n", __func__, error);
5709 - return error;
5710 - }
5711 -
5712 - return 0;
5713 -}
5714 -
5715 -static int fsl_mc_driver_remove(struct device *dev)
5716 -{
5717 - struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver);
5718 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
5719 - int error;
5720 -
5721 - if (WARN_ON(!dev->driver))
5722 - return -EINVAL;
5723 -
5724 - error = mc_drv->remove(mc_dev);
5725 - if (error < 0) {
5726 - dev_err(dev, "%s failed: %d\n", __func__, error);
5727 - return error;
5728 - }
5729 -
5730 - return 0;
5731 -}
5732 -
5733 -static void fsl_mc_driver_shutdown(struct device *dev)
5734 -{
5735 - struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver);
5736 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
5737 -
5738 - mc_drv->shutdown(mc_dev);
5739 -}
5740 -
5741 -/**
5742 - * __fsl_mc_driver_register - registers a child device driver with the
5743 - * MC bus
5744 - *
5745 - * This function is implicitly invoked from the registration function of
5746 - * fsl_mc device drivers, which is generated by the
5747 - * module_fsl_mc_driver() macro.
5748 - */
5749 -int __fsl_mc_driver_register(struct fsl_mc_driver *mc_driver,
5750 - struct module *owner)
5751 -{
5752 - int error;
5753 -
5754 - mc_driver->driver.owner = owner;
5755 - mc_driver->driver.bus = &fsl_mc_bus_type;
5756 -
5757 - if (mc_driver->probe)
5758 - mc_driver->driver.probe = fsl_mc_driver_probe;
5759 -
5760 - if (mc_driver->remove)
5761 - mc_driver->driver.remove = fsl_mc_driver_remove;
5762 -
5763 - if (mc_driver->shutdown)
5764 - mc_driver->driver.shutdown = fsl_mc_driver_shutdown;
5765 -
5766 - error = driver_register(&mc_driver->driver);
5767 - if (error < 0) {
5768 - pr_err("driver_register() failed for %s: %d\n",
5769 - mc_driver->driver.name, error);
5770 - return error;
5771 - }
5772 -
5773 - return 0;
5774 -}
5775 -EXPORT_SYMBOL_GPL(__fsl_mc_driver_register);
5776 -
5777 -/**
5778 - * fsl_mc_driver_unregister - unregisters a device driver from the
5779 - * MC bus
5780 - */
5781 -void fsl_mc_driver_unregister(struct fsl_mc_driver *mc_driver)
5782 -{
5783 - driver_unregister(&mc_driver->driver);
5784 -}
5785 -EXPORT_SYMBOL_GPL(fsl_mc_driver_unregister);
5786 -
5787 -/**
5788 - * mc_get_version() - Retrieves the Management Complex firmware
5789 - * version information
5790 - * @mc_io: Pointer to opaque I/O object
5791 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
5792 - * @mc_ver_info: Returned version information structure
5793 - *
5794 - * Return: '0' on Success; Error code otherwise.
5795 - */
5796 -static int mc_get_version(struct fsl_mc_io *mc_io,
5797 - u32 cmd_flags,
5798 - struct mc_version *mc_ver_info)
5799 -{
5800 - struct mc_command cmd = { 0 };
5801 - struct dpmng_rsp_get_version *rsp_params;
5802 - int err;
5803 -
5804 - /* prepare command */
5805 - cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_VERSION,
5806 - cmd_flags,
5807 - 0);
5808 -
5809 - /* send command to mc*/
5810 - err = mc_send_command(mc_io, &cmd);
5811 - if (err)
5812 - return err;
5813 -
5814 - /* retrieve response parameters */
5815 - rsp_params = (struct dpmng_rsp_get_version *)cmd.params;
5816 - mc_ver_info->revision = le32_to_cpu(rsp_params->revision);
5817 - mc_ver_info->major = le32_to_cpu(rsp_params->version_major);
5818 - mc_ver_info->minor = le32_to_cpu(rsp_params->version_minor);
5819 -
5820 - return 0;
5821 -}
5822 -
5823 -/**
5824 - * fsl_mc_get_root_dprc - function to traverse to the root dprc
5825 - */
5826 -static void fsl_mc_get_root_dprc(struct device *dev,
5827 - struct device **root_dprc_dev)
5828 -{
5829 - if (WARN_ON(!dev)) {
5830 - *root_dprc_dev = NULL;
5831 - } else if (WARN_ON(!dev_is_fsl_mc(dev))) {
5832 - *root_dprc_dev = NULL;
5833 - } else {
5834 - *root_dprc_dev = dev;
5835 - while (dev_is_fsl_mc((*root_dprc_dev)->parent))
5836 - *root_dprc_dev = (*root_dprc_dev)->parent;
5837 - }
5838 -}
5839 -
5840 -static int get_dprc_attr(struct fsl_mc_io *mc_io,
5841 - int container_id, struct dprc_attributes *attr)
5842 -{
5843 - u16 dprc_handle;
5844 - int error;
5845 -
5846 - error = dprc_open(mc_io, 0, container_id, &dprc_handle);
5847 - if (error < 0) {
5848 - dev_err(mc_io->dev, "dprc_open() failed: %d\n", error);
5849 - return error;
5850 - }
5851 -
5852 - memset(attr, 0, sizeof(struct dprc_attributes));
5853 - error = dprc_get_attributes(mc_io, 0, dprc_handle, attr);
5854 - if (error < 0) {
5855 - dev_err(mc_io->dev, "dprc_get_attributes() failed: %d\n",
5856 - error);
5857 - goto common_cleanup;
5858 - }
5859 -
5860 - error = 0;
5861 -
5862 -common_cleanup:
5863 - (void)dprc_close(mc_io, 0, dprc_handle);
5864 - return error;
5865 -}
5866 -
5867 -static int get_dprc_icid(struct fsl_mc_io *mc_io,
5868 - int container_id, u16 *icid)
5869 -{
5870 - struct dprc_attributes attr;
5871 - int error;
5872 -
5873 - error = get_dprc_attr(mc_io, container_id, &attr);
5874 - if (error == 0)
5875 - *icid = attr.icid;
5876 -
5877 - return error;
5878 -}
5879 -
5880 -static int translate_mc_addr(struct fsl_mc_device *mc_dev,
5881 - enum dprc_region_type mc_region_type,
5882 - u64 mc_offset, phys_addr_t *phys_addr)
5883 -{
5884 - int i;
5885 - struct device *root_dprc_dev;
5886 - struct fsl_mc *mc;
5887 -
5888 - fsl_mc_get_root_dprc(&mc_dev->dev, &root_dprc_dev);
5889 - if (WARN_ON(!root_dprc_dev))
5890 - return -EINVAL;
5891 - mc = dev_get_drvdata(root_dprc_dev->parent);
5892 -
5893 - if (mc->num_translation_ranges == 0) {
5894 - /*
5895 - * Do identity mapping:
5896 - */
5897 - *phys_addr = mc_offset;
5898 - return 0;
5899 - }
5900 -
5901 - for (i = 0; i < mc->num_translation_ranges; i++) {
5902 - struct fsl_mc_addr_translation_range *range =
5903 - &mc->translation_ranges[i];
5904 -
5905 - if (mc_region_type == range->mc_region_type &&
5906 - mc_offset >= range->start_mc_offset &&
5907 - mc_offset < range->end_mc_offset) {
5908 - *phys_addr = range->start_phys_addr +
5909 - (mc_offset - range->start_mc_offset);
5910 - return 0;
5911 - }
5912 - }
5913 -
5914 - return -EFAULT;
5915 -}
5916 -
5917 -static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev,
5918 - struct fsl_mc_device *mc_bus_dev)
5919 -{
5920 - int i;
5921 - int error;
5922 - struct resource *regions;
5923 - struct fsl_mc_obj_desc *obj_desc = &mc_dev->obj_desc;
5924 - struct device *parent_dev = mc_dev->dev.parent;
5925 - enum dprc_region_type mc_region_type;
5926 -
5927 - if (strcmp(obj_desc->type, "dprc") == 0 ||
5928 - strcmp(obj_desc->type, "dpmcp") == 0) {
5929 - mc_region_type = DPRC_REGION_TYPE_MC_PORTAL;
5930 - } else if (strcmp(obj_desc->type, "dpio") == 0) {
5931 - mc_region_type = DPRC_REGION_TYPE_QBMAN_PORTAL;
5932 - } else {
5933 - /*
5934 - * This function should not have been called for this MC object
5935 - * type, as this object type is not supposed to have MMIO
5936 - * regions
5937 - */
5938 - WARN_ON(true);
5939 - return -EINVAL;
5940 - }
5941 -
5942 - regions = kmalloc_array(obj_desc->region_count,
5943 - sizeof(regions[0]), GFP_KERNEL);
5944 - if (!regions)
5945 - return -ENOMEM;
5946 -
5947 - for (i = 0; i < obj_desc->region_count; i++) {
5948 - struct dprc_region_desc region_desc;
5949 -
5950 - error = dprc_get_obj_region(mc_bus_dev->mc_io,
5951 - 0,
5952 - mc_bus_dev->mc_handle,
5953 - obj_desc->type,
5954 - obj_desc->id, i, &region_desc);
5955 - if (error < 0) {
5956 - dev_err(parent_dev,
5957 - "dprc_get_obj_region() failed: %d\n", error);
5958 - goto error_cleanup_regions;
5959 - }
5960 -
5961 - WARN_ON(region_desc.size == 0);
5962 - error = translate_mc_addr(mc_dev, mc_region_type,
5963 - region_desc.base_offset,
5964 - &regions[i].start);
5965 - if (error < 0) {
5966 - dev_err(parent_dev,
5967 - "Invalid MC offset: %#x (for %s.%d\'s region %d)\n",
5968 - region_desc.base_offset,
5969 - obj_desc->type, obj_desc->id, i);
5970 - goto error_cleanup_regions;
5971 - }
5972 -
5973 - regions[i].end = regions[i].start + region_desc.size - 1;
5974 - regions[i].name = "fsl-mc object MMIO region";
5975 - regions[i].flags = IORESOURCE_IO;
5976 - if (region_desc.flags & DPRC_REGION_CACHEABLE)
5977 - regions[i].flags |= IORESOURCE_CACHEABLE;
5978 - }
5979 -
5980 - mc_dev->regions = regions;
5981 - return 0;
5982 -
5983 -error_cleanup_regions:
5984 - kfree(regions);
5985 - return error;
5986 -}
5987 -
5988 -/**
5989 - * fsl_mc_is_root_dprc - function to check if a given device is a root dprc
5990 - */
5991 -bool fsl_mc_is_root_dprc(struct device *dev)
5992 -{
5993 - struct device *root_dprc_dev;
5994 -
5995 - fsl_mc_get_root_dprc(dev, &root_dprc_dev);
5996 - if (!root_dprc_dev)
5997 - return false;
5998 - return dev == root_dprc_dev;
5999 -}
6000 -
6001 -static void fsl_mc_device_release(struct device *dev)
6002 -{
6003 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6004 -
6005 - kfree(mc_dev->regions);
6006 -
6007 - if (strcmp(mc_dev->obj_desc.type, "dprc") == 0)
6008 - kfree(to_fsl_mc_bus(mc_dev));
6009 - else
6010 - kfree(mc_dev);
6011 -}
6012 -
6013 -/**
6014 - * Add a newly discovered fsl-mc device to be visible in Linux
6015 - */
6016 -int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc,
6017 - struct fsl_mc_io *mc_io,
6018 - struct device *parent_dev,
6019 - struct fsl_mc_device **new_mc_dev)
6020 -{
6021 - int error;
6022 - struct fsl_mc_device *mc_dev = NULL;
6023 - struct fsl_mc_bus *mc_bus = NULL;
6024 - struct fsl_mc_device *parent_mc_dev;
6025 -
6026 - if (dev_is_fsl_mc(parent_dev))
6027 - parent_mc_dev = to_fsl_mc_device(parent_dev);
6028 - else
6029 - parent_mc_dev = NULL;
6030 -
6031 - if (strcmp(obj_desc->type, "dprc") == 0) {
6032 - /*
6033 - * Allocate an MC bus device object:
6034 - */
6035 - mc_bus = kzalloc(sizeof(*mc_bus), GFP_KERNEL);
6036 - if (!mc_bus)
6037 - return -ENOMEM;
6038 -
6039 - mc_dev = &mc_bus->mc_dev;
6040 - } else {
6041 - /*
6042 - * Allocate a regular fsl_mc_device object:
6043 - */
6044 - mc_dev = kzalloc(sizeof(*mc_dev), GFP_KERNEL);
6045 - if (!mc_dev)
6046 - return -ENOMEM;
6047 - }
6048 -
6049 - mc_dev->obj_desc = *obj_desc;
6050 - mc_dev->mc_io = mc_io;
6051 - device_initialize(&mc_dev->dev);
6052 - mc_dev->dev.parent = parent_dev;
6053 - mc_dev->dev.bus = &fsl_mc_bus_type;
6054 - mc_dev->dev.release = fsl_mc_device_release;
6055 - dev_set_name(&mc_dev->dev, "%s.%d", obj_desc->type, obj_desc->id);
6056 -
6057 - if (strcmp(obj_desc->type, "dprc") == 0) {
6058 - struct fsl_mc_io *mc_io2;
6059 -
6060 - mc_dev->flags |= FSL_MC_IS_DPRC;
6061 -
6062 - /*
6063 - * To get the DPRC's ICID, we need to open the DPRC
6064 - * in get_dprc_icid(). For child DPRCs, we do so using the
6065 - * parent DPRC's MC portal instead of the child DPRC's MC
6066 - * portal, in case the child DPRC is already opened with
6067 - * its own portal (e.g., the DPRC used by AIOP).
6068 - *
6069 - * NOTE: There cannot be more than one active open for a
6070 - * given MC object, using the same MC portal.
6071 - */
6072 - if (parent_mc_dev) {
6073 - /*
6074 - * device being added is a child DPRC device
6075 - */
6076 - mc_io2 = parent_mc_dev->mc_io;
6077 - } else {
6078 - /*
6079 - * device being added is the root DPRC device
6080 - */
6081 - if (WARN_ON(!mc_io)) {
6082 - error = -EINVAL;
6083 - goto error_cleanup_dev;
6084 - }
6085 -
6086 - mc_io2 = mc_io;
6087 - }
6088 -
6089 - error = get_dprc_icid(mc_io2, obj_desc->id, &mc_dev->icid);
6090 - if (error < 0)
6091 - goto error_cleanup_dev;
6092 - } else {
6093 - /*
6094 - * A non-DPRC object has to be a child of a DPRC, use the
6095 - * parent's ICID and interrupt domain.
6096 - */
6097 - mc_dev->icid = parent_mc_dev->icid;
6098 - mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK;
6099 - mc_dev->dev.dma_mask = &mc_dev->dma_mask;
6100 - dev_set_msi_domain(&mc_dev->dev,
6101 - dev_get_msi_domain(&parent_mc_dev->dev));
6102 - }
6103 -
6104 - /*
6105 - * Get MMIO regions for the device from the MC:
6106 - *
6107 - * NOTE: the root DPRC is a special case as its MMIO region is
6108 - * obtained from the device tree
6109 - */
6110 - if (parent_mc_dev && obj_desc->region_count != 0) {
6111 - error = fsl_mc_device_get_mmio_regions(mc_dev,
6112 - parent_mc_dev);
6113 - if (error < 0)
6114 - goto error_cleanup_dev;
6115 - }
6116 -
6117 - /* Objects are coherent, unless 'no shareability' flag set. */
6118 - if (!(obj_desc->flags & FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY))
6119 - arch_setup_dma_ops(&mc_dev->dev, 0, 0, NULL, true);
6120 -
6121 - /*
6122 - * The device-specific probe callback will get invoked by device_add()
6123 - */
6124 - error = device_add(&mc_dev->dev);
6125 - if (error < 0) {
6126 - dev_err(parent_dev,
6127 - "device_add() failed for device %s: %d\n",
6128 - dev_name(&mc_dev->dev), error);
6129 - goto error_cleanup_dev;
6130 - }
6131 -
6132 - dev_dbg(parent_dev, "added %s\n", dev_name(&mc_dev->dev));
6133 -
6134 - *new_mc_dev = mc_dev;
6135 - return 0;
6136 -
6137 -error_cleanup_dev:
6138 - kfree(mc_dev->regions);
6139 - kfree(mc_bus);
6140 - kfree(mc_dev);
6141 -
6142 - return error;
6143 -}
6144 -EXPORT_SYMBOL_GPL(fsl_mc_device_add);
6145 -
6146 -/**
6147 - * fsl_mc_device_remove - Remove an fsl-mc device from being visible to
6148 - * Linux
6149 - *
6150 - * @mc_dev: Pointer to an fsl-mc device
6151 - */
6152 -void fsl_mc_device_remove(struct fsl_mc_device *mc_dev)
6153 -{
6154 - /*
6155 - * The device-specific remove callback will get invoked by device_del()
6156 - */
6157 - device_del(&mc_dev->dev);
6158 - put_device(&mc_dev->dev);
6159 -}
6160 -EXPORT_SYMBOL_GPL(fsl_mc_device_remove);
6161 -
6162 -static int parse_mc_ranges(struct device *dev,
6163 - int *paddr_cells,
6164 - int *mc_addr_cells,
6165 - int *mc_size_cells,
6166 - const __be32 **ranges_start)
6167 -{
6168 - const __be32 *prop;
6169 - int range_tuple_cell_count;
6170 - int ranges_len;
6171 - int tuple_len;
6172 - struct device_node *mc_node = dev->of_node;
6173 -
6174 - *ranges_start = of_get_property(mc_node, "ranges", &ranges_len);
6175 - if (!(*ranges_start) || !ranges_len) {
6176 - dev_warn(dev,
6177 - "missing or empty ranges property for device tree node '%s'\n",
6178 - mc_node->name);
6179 - return 0;
6180 - }
6181 -
6182 - *paddr_cells = of_n_addr_cells(mc_node);
6183 -
6184 - prop = of_get_property(mc_node, "#address-cells", NULL);
6185 - if (prop)
6186 - *mc_addr_cells = be32_to_cpup(prop);
6187 - else
6188 - *mc_addr_cells = *paddr_cells;
6189 -
6190 - prop = of_get_property(mc_node, "#size-cells", NULL);
6191 - if (prop)
6192 - *mc_size_cells = be32_to_cpup(prop);
6193 - else
6194 - *mc_size_cells = of_n_size_cells(mc_node);
6195 -
6196 - range_tuple_cell_count = *paddr_cells + *mc_addr_cells +
6197 - *mc_size_cells;
6198 -
6199 - tuple_len = range_tuple_cell_count * sizeof(__be32);
6200 - if (ranges_len % tuple_len != 0) {
6201 - dev_err(dev, "malformed ranges property '%s'\n", mc_node->name);
6202 - return -EINVAL;
6203 - }
6204 -
6205 - return ranges_len / tuple_len;
6206 -}
6207 -
6208 -static int get_mc_addr_translation_ranges(struct device *dev,
6209 - struct fsl_mc_addr_translation_range
6210 - **ranges,
6211 - u8 *num_ranges)
6212 -{
6213 - int ret;
6214 - int paddr_cells;
6215 - int mc_addr_cells;
6216 - int mc_size_cells;
6217 - int i;
6218 - const __be32 *ranges_start;
6219 - const __be32 *cell;
6220 -
6221 - ret = parse_mc_ranges(dev,
6222 - &paddr_cells,
6223 - &mc_addr_cells,
6224 - &mc_size_cells,
6225 - &ranges_start);
6226 - if (ret < 0)
6227 - return ret;
6228 -
6229 - *num_ranges = ret;
6230 - if (!ret) {
6231 - /*
6232 - * Missing or empty ranges property ("ranges;") for the
6233 - * 'fsl,qoriq-mc' node. In this case, identity mapping
6234 - * will be used.
6235 - */
6236 - *ranges = NULL;
6237 - return 0;
6238 - }
6239 -
6240 - *ranges = devm_kcalloc(dev, *num_ranges,
6241 - sizeof(struct fsl_mc_addr_translation_range),
6242 - GFP_KERNEL);
6243 - if (!(*ranges))
6244 - return -ENOMEM;
6245 -
6246 - cell = ranges_start;
6247 - for (i = 0; i < *num_ranges; ++i) {
6248 - struct fsl_mc_addr_translation_range *range = &(*ranges)[i];
6249 -
6250 - range->mc_region_type = of_read_number(cell, 1);
6251 - range->start_mc_offset = of_read_number(cell + 1,
6252 - mc_addr_cells - 1);
6253 - cell += mc_addr_cells;
6254 - range->start_phys_addr = of_read_number(cell, paddr_cells);
6255 - cell += paddr_cells;
6256 - range->end_mc_offset = range->start_mc_offset +
6257 - of_read_number(cell, mc_size_cells);
6258 -
6259 - cell += mc_size_cells;
6260 - }
6261 -
6262 - return 0;
6263 -}
6264 -
6265 -/**
6266 - * fsl_mc_bus_probe - callback invoked when the root MC bus is being
6267 - * added
6268 - */
6269 -static int fsl_mc_bus_probe(struct platform_device *pdev)
6270 -{
6271 - struct fsl_mc_obj_desc obj_desc;
6272 - int error;
6273 - struct fsl_mc *mc;
6274 - struct fsl_mc_device *mc_bus_dev = NULL;
6275 - struct fsl_mc_io *mc_io = NULL;
6276 - int container_id;
6277 - phys_addr_t mc_portal_phys_addr;
6278 - u32 mc_portal_size;
6279 - struct mc_version mc_version;
6280 - struct resource res;
6281 -
6282 - mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL);
6283 - if (!mc)
6284 - return -ENOMEM;
6285 -
6286 - platform_set_drvdata(pdev, mc);
6287 -
6288 - /*
6289 - * Get physical address of MC portal for the root DPRC:
6290 - */
6291 - error = of_address_to_resource(pdev->dev.of_node, 0, &res);
6292 - if (error < 0) {
6293 - dev_err(&pdev->dev,
6294 - "of_address_to_resource() failed for %pOF\n",
6295 - pdev->dev.of_node);
6296 - return error;
6297 - }
6298 -
6299 - mc_portal_phys_addr = res.start;
6300 - mc_portal_size = resource_size(&res);
6301 - error = fsl_create_mc_io(&pdev->dev, mc_portal_phys_addr,
6302 - mc_portal_size, NULL,
6303 - FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, &mc_io);
6304 - if (error < 0)
6305 - return error;
6306 -
6307 - error = mc_get_version(mc_io, 0, &mc_version);
6308 - if (error != 0) {
6309 - dev_err(&pdev->dev,
6310 - "mc_get_version() failed with error %d\n", error);
6311 - goto error_cleanup_mc_io;
6312 - }
6313 -
6314 - dev_info(&pdev->dev, "MC firmware version: %u.%u.%u\n",
6315 - mc_version.major, mc_version.minor, mc_version.revision);
6316 -
6317 - error = get_mc_addr_translation_ranges(&pdev->dev,
6318 - &mc->translation_ranges,
6319 - &mc->num_translation_ranges);
6320 - if (error < 0)
6321 - goto error_cleanup_mc_io;
6322 -
6323 - error = dprc_get_container_id(mc_io, 0, &container_id);
6324 - if (error < 0) {
6325 - dev_err(&pdev->dev,
6326 - "dprc_get_container_id() failed: %d\n", error);
6327 - goto error_cleanup_mc_io;
6328 - }
6329 -
6330 - memset(&obj_desc, 0, sizeof(struct fsl_mc_obj_desc));
6331 - error = dprc_get_api_version(mc_io, 0,
6332 - &obj_desc.ver_major,
6333 - &obj_desc.ver_minor);
6334 - if (error < 0)
6335 - goto error_cleanup_mc_io;
6336 -
6337 - obj_desc.vendor = FSL_MC_VENDOR_FREESCALE;
6338 - strcpy(obj_desc.type, "dprc");
6339 - obj_desc.id = container_id;
6340 - obj_desc.irq_count = 1;
6341 - obj_desc.region_count = 0;
6342 -
6343 - error = fsl_mc_device_add(&obj_desc, mc_io, &pdev->dev, &mc_bus_dev);
6344 - if (error < 0)
6345 - goto error_cleanup_mc_io;
6346 -
6347 - mc->root_mc_bus_dev = mc_bus_dev;
6348 - return 0;
6349 -
6350 -error_cleanup_mc_io:
6351 - fsl_destroy_mc_io(mc_io);
6352 - return error;
6353 -}
6354 -
6355 -/**
6356 - * fsl_mc_bus_remove - callback invoked when the root MC bus is being
6357 - * removed
6358 - */
6359 -static int fsl_mc_bus_remove(struct platform_device *pdev)
6360 -{
6361 - struct fsl_mc *mc = platform_get_drvdata(pdev);
6362 -
6363 - if (WARN_ON(!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev)))
6364 - return -EINVAL;
6365 -
6366 - fsl_mc_device_remove(mc->root_mc_bus_dev);
6367 -
6368 - fsl_destroy_mc_io(mc->root_mc_bus_dev->mc_io);
6369 - mc->root_mc_bus_dev->mc_io = NULL;
6370 -
6371 - return 0;
6372 -}
6373 -
6374 -static const struct of_device_id fsl_mc_bus_match_table[] = {
6375 - {.compatible = "fsl,qoriq-mc",},
6376 - {},
6377 -};
6378 -
6379 -MODULE_DEVICE_TABLE(of, fsl_mc_bus_match_table);
6380 -
6381 -static struct platform_driver fsl_mc_bus_driver = {
6382 - .driver = {
6383 - .name = "fsl_mc_bus",
6384 - .pm = NULL,
6385 - .of_match_table = fsl_mc_bus_match_table,
6386 - },
6387 - .probe = fsl_mc_bus_probe,
6388 - .remove = fsl_mc_bus_remove,
6389 -};
6390 -
6391 -static int __init fsl_mc_bus_driver_init(void)
6392 -{
6393 - int error;
6394 -
6395 - error = bus_register(&fsl_mc_bus_type);
6396 - if (error < 0) {
6397 - pr_err("bus type registration failed: %d\n", error);
6398 - goto error_cleanup_cache;
6399 - }
6400 -
6401 - error = platform_driver_register(&fsl_mc_bus_driver);
6402 - if (error < 0) {
6403 - pr_err("platform_driver_register() failed: %d\n", error);
6404 - goto error_cleanup_bus;
6405 - }
6406 -
6407 - error = dprc_driver_init();
6408 - if (error < 0)
6409 - goto error_cleanup_driver;
6410 -
6411 - error = fsl_mc_allocator_driver_init();
6412 - if (error < 0)
6413 - goto error_cleanup_dprc_driver;
6414 -
6415 - error = its_fsl_mc_msi_init();
6416 - if (error < 0)
6417 - goto error_cleanup_mc_allocator;
6418 -
6419 - return 0;
6420 -
6421 -error_cleanup_mc_allocator:
6422 - fsl_mc_allocator_driver_exit();
6423 -
6424 -error_cleanup_dprc_driver:
6425 - dprc_driver_exit();
6426 -
6427 -error_cleanup_driver:
6428 - platform_driver_unregister(&fsl_mc_bus_driver);
6429 -
6430 -error_cleanup_bus:
6431 - bus_unregister(&fsl_mc_bus_type);
6432 -
6433 -error_cleanup_cache:
6434 - return error;
6435 -}
6436 -postcore_initcall(fsl_mc_bus_driver_init);
6437 --- /dev/null
6438 +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
6439 @@ -0,0 +1,1148 @@
6440 +// SPDX-License-Identifier: GPL-2.0
6441 +/*
6442 + * Freescale Management Complex (MC) bus driver
6443 + *
6444 + * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
6445 + * Author: German Rivera <German.Rivera@freescale.com>
6446 + *
6447 + */
6448 +
6449 +#define pr_fmt(fmt) "fsl-mc: " fmt
6450 +
6451 +#include <linux/module.h>
6452 +#include <linux/of_device.h>
6453 +#include <linux/of_address.h>
6454 +#include <linux/ioport.h>
6455 +#include <linux/slab.h>
6456 +#include <linux/limits.h>
6457 +#include <linux/bitops.h>
6458 +#include <linux/msi.h>
6459 +#include <linux/dma-mapping.h>
6460 +
6461 +#include "fsl-mc-private.h"
6462 +
6463 +/**
6464 + * Default DMA mask for devices on a fsl-mc bus
6465 + */
6466 +#define FSL_MC_DEFAULT_DMA_MASK (~0ULL)
6467 +
6468 +/**
6469 + * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device
6470 + * @root_mc_bus_dev: fsl-mc device representing the root DPRC
6471 + * @num_translation_ranges: number of entries in addr_translation_ranges
6472 + * @translation_ranges: array of bus to system address translation ranges
6473 + */
6474 +struct fsl_mc {
6475 + struct fsl_mc_device *root_mc_bus_dev;
6476 + u8 num_translation_ranges;
6477 + struct fsl_mc_addr_translation_range *translation_ranges;
6478 +};
6479 +
6480 +/**
6481 + * struct fsl_mc_addr_translation_range - bus to system address translation
6482 + * range
6483 + * @mc_region_type: Type of MC region for the range being translated
6484 + * @start_mc_offset: Start MC offset of the range being translated
6485 + * @end_mc_offset: MC offset of the first byte after the range (last MC
6486 + * offset of the range is end_mc_offset - 1)
6487 + * @start_phys_addr: system physical address corresponding to start_mc_addr
6488 + */
6489 +struct fsl_mc_addr_translation_range {
6490 + enum dprc_region_type mc_region_type;
6491 + u64 start_mc_offset;
6492 + u64 end_mc_offset;
6493 + phys_addr_t start_phys_addr;
6494 +};
6495 +
6496 +/**
6497 + * struct mc_version
6498 + * @major: Major version number: incremented on API compatibility changes
6499 + * @minor: Minor version number: incremented on API additions (that are
6500 + * backward compatible); reset when major version is incremented
6501 + * @revision: Internal revision number: incremented on implementation changes
6502 + * and/or bug fixes that have no impact on API
6503 + */
6504 +struct mc_version {
6505 + u32 major;
6506 + u32 minor;
6507 + u32 revision;
6508 +};
6509 +
6510 +/**
6511 + * fsl_mc_bus_match - device to driver matching callback
6512 + * @dev: the fsl-mc device to match against
6513 + * @drv: the device driver to search for matching fsl-mc object type
6514 + * structures
6515 + *
6516 + * Returns 1 on success, 0 otherwise.
6517 + */
6518 +static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv)
6519 +{
6520 + const struct fsl_mc_device_id *id;
6521 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6522 + struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv);
6523 + bool found = false;
6524 +
6525 + /* When driver_override is set, only bind to the matching driver */
6526 + if (mc_dev->driver_override) {
6527 + found = !strcmp(mc_dev->driver_override, mc_drv->driver.name);
6528 + goto out;
6529 + }
6530 +
6531 + if (!mc_drv->match_id_table)
6532 + goto out;
6533 +
6534 + /*
6535 + * If the object is not 'plugged' don't match.
6536 + * Only exception is the root DPRC, which is a special case.
6537 + */
6538 + if ((mc_dev->obj_desc.state & FSL_MC_OBJ_STATE_PLUGGED) == 0 &&
6539 + !fsl_mc_is_root_dprc(&mc_dev->dev))
6540 + goto out;
6541 +
6542 + /*
6543 + * Traverse the match_id table of the given driver, trying to find
6544 + * a matching for the given device.
6545 + */
6546 + for (id = mc_drv->match_id_table; id->vendor != 0x0; id++) {
6547 + if (id->vendor == mc_dev->obj_desc.vendor &&
6548 + strcmp(id->obj_type, mc_dev->obj_desc.type) == 0) {
6549 + found = true;
6550 +
6551 + break;
6552 + }
6553 + }
6554 +
6555 +out:
6556 + dev_dbg(dev, "%smatched\n", found ? "" : "not ");
6557 + return found;
6558 +}
6559 +
6560 +/**
6561 + * fsl_mc_bus_uevent - callback invoked when a device is added
6562 + */
6563 +static int fsl_mc_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
6564 +{
6565 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6566 +
6567 + if (add_uevent_var(env, "MODALIAS=fsl-mc:v%08Xd%s",
6568 + mc_dev->obj_desc.vendor,
6569 + mc_dev->obj_desc.type))
6570 + return -ENOMEM;
6571 +
6572 + return 0;
6573 +}
6574 +
6575 +static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
6576 + char *buf)
6577 +{
6578 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6579 +
6580 + return sprintf(buf, "fsl-mc:v%08Xd%s\n", mc_dev->obj_desc.vendor,
6581 + mc_dev->obj_desc.type);
6582 +}
6583 +static DEVICE_ATTR_RO(modalias);
6584 +
6585 +static ssize_t rescan_store(struct device *dev,
6586 + struct device_attribute *attr,
6587 + const char *buf, size_t count)
6588 +{
6589 + struct fsl_mc_device *root_mc_dev;
6590 + struct fsl_mc_bus *root_mc_bus;
6591 + unsigned long val;
6592 +
6593 + if (!fsl_mc_is_root_dprc(dev))
6594 + return -EINVAL;
6595 +
6596 + root_mc_dev = to_fsl_mc_device(dev);
6597 + root_mc_bus = to_fsl_mc_bus(root_mc_dev);
6598 +
6599 + if (kstrtoul(buf, 0, &val) < 0)
6600 + return -EINVAL;
6601 +
6602 + if (val) {
6603 + mutex_lock(&root_mc_bus->scan_mutex);
6604 + dprc_scan_objects(root_mc_dev, NULL, NULL);
6605 + mutex_unlock(&root_mc_bus->scan_mutex);
6606 + }
6607 +
6608 + return count;
6609 +}
6610 +static DEVICE_ATTR_WO(rescan);
6611 +
6612 +static ssize_t driver_override_store(struct device *dev,
6613 + struct device_attribute *attr,
6614 + const char *buf, size_t count)
6615 +{
6616 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6617 + const char *driver_override, *old = mc_dev->driver_override;
6618 + char *cp;
6619 +
6620 + if (WARN_ON(dev->bus != &fsl_mc_bus_type))
6621 + return -EINVAL;
6622 +
6623 + if (count >= (PAGE_SIZE - 1))
6624 + return -EINVAL;
6625 +
6626 + driver_override = kstrndup(buf, count, GFP_KERNEL);
6627 + if (!driver_override)
6628 + return -ENOMEM;
6629 +
6630 + cp = strchr(driver_override, '\n');
6631 + if (cp)
6632 + *cp = '\0';
6633 +
6634 + if (strlen(driver_override)) {
6635 + mc_dev->driver_override = driver_override;
6636 + } else {
6637 + kfree(driver_override);
6638 + mc_dev->driver_override = NULL;
6639 + }
6640 +
6641 + kfree(old);
6642 +
6643 + return count;
6644 +}
6645 +
6646 +static ssize_t driver_override_show(struct device *dev,
6647 + struct device_attribute *attr, char *buf)
6648 +{
6649 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6650 +
6651 + return snprintf(buf, PAGE_SIZE, "%s\n", mc_dev->driver_override);
6652 +}
6653 +static DEVICE_ATTR_RW(driver_override);
6654 +
6655 +static struct attribute *fsl_mc_dev_attrs[] = {
6656 + &dev_attr_modalias.attr,
6657 + &dev_attr_rescan.attr,
6658 + &dev_attr_driver_override.attr,
6659 + NULL,
6660 +};
6661 +
6662 +ATTRIBUTE_GROUPS(fsl_mc_dev);
6663 +
6664 +static int scan_fsl_mc_bus(struct device *dev, void *data)
6665 +{
6666 + struct fsl_mc_device *root_mc_dev;
6667 + struct fsl_mc_bus *root_mc_bus;
6668 +
6669 + if (!fsl_mc_is_root_dprc(dev))
6670 + goto exit;
6671 +
6672 + root_mc_dev = to_fsl_mc_device(dev);
6673 + root_mc_bus = to_fsl_mc_bus(root_mc_dev);
6674 + mutex_lock(&root_mc_bus->scan_mutex);
6675 + dprc_scan_objects(root_mc_dev, NULL, NULL);
6676 + mutex_unlock(&root_mc_bus->scan_mutex);
6677 +
6678 +exit:
6679 + return 0;
6680 +}
6681 +
6682 +static ssize_t bus_rescan_store(struct bus_type *bus,
6683 + const char *buf, size_t count)
6684 +{
6685 + unsigned long val;
6686 +
6687 + if (kstrtoul(buf, 0, &val) < 0)
6688 + return -EINVAL;
6689 +
6690 + if (val)
6691 + bus_for_each_dev(bus, NULL, NULL, scan_fsl_mc_bus);
6692 +
6693 + return count;
6694 +}
6695 +static BUS_ATTR(rescan, 0220, NULL, bus_rescan_store);
6696 +
6697 +static struct attribute *fsl_mc_bus_attrs[] = {
6698 + &bus_attr_rescan.attr,
6699 + NULL,
6700 +};
6701 +
6702 +static const struct attribute_group fsl_mc_bus_group = {
6703 + .attrs = fsl_mc_bus_attrs,
6704 +};
6705 +
6706 +static const struct attribute_group *fsl_mc_bus_groups[] = {
6707 + &fsl_mc_bus_group,
6708 + NULL,
6709 +};
6710 +
6711 +struct bus_type fsl_mc_bus_type = {
6712 + .name = "fsl-mc",
6713 + .match = fsl_mc_bus_match,
6714 + .uevent = fsl_mc_bus_uevent,
6715 + .dev_groups = fsl_mc_dev_groups,
6716 + .bus_groups = fsl_mc_bus_groups,
6717 +};
6718 +EXPORT_SYMBOL_GPL(fsl_mc_bus_type);
6719 +
6720 +struct device_type fsl_mc_bus_dprc_type = {
6721 + .name = "fsl_mc_bus_dprc"
6722 +};
6723 +
6724 +struct device_type fsl_mc_bus_dpni_type = {
6725 + .name = "fsl_mc_bus_dpni"
6726 +};
6727 +
6728 +struct device_type fsl_mc_bus_dpio_type = {
6729 + .name = "fsl_mc_bus_dpio"
6730 +};
6731 +
6732 +struct device_type fsl_mc_bus_dpsw_type = {
6733 + .name = "fsl_mc_bus_dpsw"
6734 +};
6735 +
6736 +struct device_type fsl_mc_bus_dpdmux_type = {
6737 + .name = "fsl_mc_bus_dpdmux"
6738 +};
6739 +
6740 +struct device_type fsl_mc_bus_dpbp_type = {
6741 + .name = "fsl_mc_bus_dpbp"
6742 +};
6743 +
6744 +struct device_type fsl_mc_bus_dpcon_type = {
6745 + .name = "fsl_mc_bus_dpcon"
6746 +};
6747 +
6748 +struct device_type fsl_mc_bus_dpmcp_type = {
6749 + .name = "fsl_mc_bus_dpmcp"
6750 +};
6751 +
6752 +struct device_type fsl_mc_bus_dpmac_type = {
6753 + .name = "fsl_mc_bus_dpmac"
6754 +};
6755 +
6756 +struct device_type fsl_mc_bus_dprtc_type = {
6757 + .name = "fsl_mc_bus_dprtc"
6758 +};
6759 +
6760 +struct device_type fsl_mc_bus_dpseci_type = {
6761 + .name = "fsl_mc_bus_dpseci"
6762 +};
6763 +
6764 +struct device_type fsl_mc_bus_dpdcei_type = {
6765 + .name = "fsl_mc_bus_dpdcei"
6766 +};
6767 +
6768 +struct device_type fsl_mc_bus_dpaiop_type = {
6769 + .name = "fsl_mc_bus_dpaiop"
6770 +};
6771 +
6772 +struct device_type fsl_mc_bus_dpci_type = {
6773 + .name = "fsl_mc_bus_dpci"
6774 +};
6775 +
6776 +struct device_type fsl_mc_bus_dpdmai_type = {
6777 + .name = "fsl_mc_bus_dpdmai"
6778 +};
6779 +
6780 +static struct device_type *fsl_mc_get_device_type(const char *type)
6781 +{
6782 + static const struct {
6783 + struct device_type *dev_type;
6784 + const char *type;
6785 + } dev_types[] = {
6786 + { &fsl_mc_bus_dprc_type, "dprc" },
6787 + { &fsl_mc_bus_dpni_type, "dpni" },
6788 + { &fsl_mc_bus_dpio_type, "dpio" },
6789 + { &fsl_mc_bus_dpsw_type, "dpsw" },
6790 + { &fsl_mc_bus_dpdmux_type, "dpdmux" },
6791 + { &fsl_mc_bus_dpbp_type, "dpbp" },
6792 + { &fsl_mc_bus_dpcon_type, "dpcon" },
6793 + { &fsl_mc_bus_dpmcp_type, "dpmcp" },
6794 + { &fsl_mc_bus_dpmac_type, "dpmac" },
6795 + { &fsl_mc_bus_dprtc_type, "dprtc" },
6796 + { &fsl_mc_bus_dpseci_type, "dpseci" },
6797 + { &fsl_mc_bus_dpdcei_type, "dpdcei" },
6798 + { &fsl_mc_bus_dpaiop_type, "dpaiop" },
6799 + { &fsl_mc_bus_dpci_type, "dpci" },
6800 + { &fsl_mc_bus_dpdmai_type, "dpdmai" },
6801 + { NULL, NULL }
6802 + };
6803 + int i;
6804 +
6805 + for (i = 0; dev_types[i].dev_type; i++)
6806 + if (!strcmp(dev_types[i].type, type))
6807 + return dev_types[i].dev_type;
6808 +
6809 + return NULL;
6810 +}
6811 +
6812 +static int fsl_mc_driver_probe(struct device *dev)
6813 +{
6814 + struct fsl_mc_driver *mc_drv;
6815 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6816 + int error;
6817 +
6818 + mc_drv = to_fsl_mc_driver(dev->driver);
6819 +
6820 + error = mc_drv->probe(mc_dev);
6821 + if (error < 0) {
6822 + if (error != -EPROBE_DEFER)
6823 + dev_err(dev, "%s failed: %d\n", __func__, error);
6824 + return error;
6825 + }
6826 +
6827 + return 0;
6828 +}
6829 +
6830 +static int fsl_mc_driver_remove(struct device *dev)
6831 +{
6832 + struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver);
6833 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6834 + int error;
6835 +
6836 + error = mc_drv->remove(mc_dev);
6837 + if (error < 0) {
6838 + dev_err(dev, "%s failed: %d\n", __func__, error);
6839 + return error;
6840 + }
6841 +
6842 + return 0;
6843 +}
6844 +
6845 +static void fsl_mc_driver_shutdown(struct device *dev)
6846 +{
6847 + struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver);
6848 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6849 +
6850 + mc_drv->shutdown(mc_dev);
6851 +}
6852 +
6853 +/**
6854 + * __fsl_mc_driver_register - registers a child device driver with the
6855 + * MC bus
6856 + *
6857 + * This function is implicitly invoked from the registration function of
6858 + * fsl_mc device drivers, which is generated by the
6859 + * module_fsl_mc_driver() macro.
6860 + */
6861 +int __fsl_mc_driver_register(struct fsl_mc_driver *mc_driver,
6862 + struct module *owner)
6863 +{
6864 + int error;
6865 +
6866 + mc_driver->driver.owner = owner;
6867 + mc_driver->driver.bus = &fsl_mc_bus_type;
6868 +
6869 + if (mc_driver->probe)
6870 + mc_driver->driver.probe = fsl_mc_driver_probe;
6871 +
6872 + if (mc_driver->remove)
6873 + mc_driver->driver.remove = fsl_mc_driver_remove;
6874 +
6875 + if (mc_driver->shutdown)
6876 + mc_driver->driver.shutdown = fsl_mc_driver_shutdown;
6877 +
6878 + error = driver_register(&mc_driver->driver);
6879 + if (error < 0) {
6880 + pr_err("driver_register() failed for %s: %d\n",
6881 + mc_driver->driver.name, error);
6882 + return error;
6883 + }
6884 +
6885 + return 0;
6886 +}
6887 +EXPORT_SYMBOL_GPL(__fsl_mc_driver_register);
6888 +
6889 +/**
6890 + * fsl_mc_driver_unregister - unregisters a device driver from the
6891 + * MC bus
6892 + */
6893 +void fsl_mc_driver_unregister(struct fsl_mc_driver *mc_driver)
6894 +{
6895 + driver_unregister(&mc_driver->driver);
6896 +}
6897 +EXPORT_SYMBOL_GPL(fsl_mc_driver_unregister);
6898 +
6899 +/**
6900 + * mc_get_version() - Retrieves the Management Complex firmware
6901 + * version information
6902 + * @mc_io: Pointer to opaque I/O object
6903 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
6904 + * @mc_ver_info: Returned version information structure
6905 + *
6906 + * Return: '0' on Success; Error code otherwise.
6907 + */
6908 +static int mc_get_version(struct fsl_mc_io *mc_io,
6909 + u32 cmd_flags,
6910 + struct mc_version *mc_ver_info)
6911 +{
6912 + struct fsl_mc_command cmd = { 0 };
6913 + struct dpmng_rsp_get_version *rsp_params;
6914 + int err;
6915 +
6916 + /* prepare command */
6917 + cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_VERSION,
6918 + cmd_flags,
6919 + 0);
6920 +
6921 + /* send command to mc*/
6922 + err = mc_send_command(mc_io, &cmd);
6923 + if (err)
6924 + return err;
6925 +
6926 + /* retrieve response parameters */
6927 + rsp_params = (struct dpmng_rsp_get_version *)cmd.params;
6928 + mc_ver_info->revision = le32_to_cpu(rsp_params->revision);
6929 + mc_ver_info->major = le32_to_cpu(rsp_params->version_major);
6930 + mc_ver_info->minor = le32_to_cpu(rsp_params->version_minor);
6931 +
6932 + return 0;
6933 +}
6934 +
6935 +/**
6936 + * fsl_mc_get_root_dprc - function to traverse to the root dprc
6937 + */
6938 +void fsl_mc_get_root_dprc(struct device *dev,
6939 + struct device **root_dprc_dev)
6940 +{
6941 + if (!dev) {
6942 + *root_dprc_dev = NULL;
6943 + } else if (!dev_is_fsl_mc(dev)) {
6944 + *root_dprc_dev = NULL;
6945 + } else {
6946 + *root_dprc_dev = dev;
6947 + while (dev_is_fsl_mc((*root_dprc_dev)->parent))
6948 + *root_dprc_dev = (*root_dprc_dev)->parent;
6949 + }
6950 +}
6951 +EXPORT_SYMBOL_GPL(fsl_mc_get_root_dprc);
6952 +
6953 +static int get_dprc_attr(struct fsl_mc_io *mc_io,
6954 + int container_id, struct dprc_attributes *attr)
6955 +{
6956 + u16 dprc_handle;
6957 + int error;
6958 +
6959 + error = dprc_open(mc_io, 0, container_id, &dprc_handle);
6960 + if (error < 0) {
6961 + dev_err(mc_io->dev, "dprc_open() failed: %d\n", error);
6962 + return error;
6963 + }
6964 +
6965 + memset(attr, 0, sizeof(struct dprc_attributes));
6966 + error = dprc_get_attributes(mc_io, 0, dprc_handle, attr);
6967 + if (error < 0) {
6968 + dev_err(mc_io->dev, "dprc_get_attributes() failed: %d\n",
6969 + error);
6970 + goto common_cleanup;
6971 + }
6972 +
6973 + error = 0;
6974 +
6975 +common_cleanup:
6976 + (void)dprc_close(mc_io, 0, dprc_handle);
6977 + return error;
6978 +}
6979 +
6980 +static int get_dprc_icid(struct fsl_mc_io *mc_io,
6981 + int container_id, u32 *icid)
6982 +{
6983 + struct dprc_attributes attr;
6984 + int error;
6985 +
6986 + error = get_dprc_attr(mc_io, container_id, &attr);
6987 + if (error == 0)
6988 + *icid = attr.icid;
6989 +
6990 + return error;
6991 +}
6992 +
6993 +static int translate_mc_addr(struct fsl_mc_device *mc_dev,
6994 + enum dprc_region_type mc_region_type,
6995 + u64 mc_offset, phys_addr_t *phys_addr)
6996 +{
6997 + int i;
6998 + struct device *root_dprc_dev;
6999 + struct fsl_mc *mc;
7000 +
7001 + fsl_mc_get_root_dprc(&mc_dev->dev, &root_dprc_dev);
7002 + mc = dev_get_drvdata(root_dprc_dev->parent);
7003 +
7004 + if (mc->num_translation_ranges == 0) {
7005 + /*
7006 + * Do identity mapping:
7007 + */
7008 + *phys_addr = mc_offset;
7009 + return 0;
7010 + }
7011 +
7012 + for (i = 0; i < mc->num_translation_ranges; i++) {
7013 + struct fsl_mc_addr_translation_range *range =
7014 + &mc->translation_ranges[i];
7015 +
7016 + if (mc_region_type == range->mc_region_type &&
7017 + mc_offset >= range->start_mc_offset &&
7018 + mc_offset < range->end_mc_offset) {
7019 + *phys_addr = range->start_phys_addr +
7020 + (mc_offset - range->start_mc_offset);
7021 + return 0;
7022 + }
7023 + }
7024 +
7025 + return -EFAULT;
7026 +}
7027 +
7028 +static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev,
7029 + struct fsl_mc_device *mc_bus_dev)
7030 +{
7031 + int i;
7032 + int error;
7033 + struct resource *regions;
7034 + struct fsl_mc_obj_desc *obj_desc = &mc_dev->obj_desc;
7035 + struct device *parent_dev = mc_dev->dev.parent;
7036 + enum dprc_region_type mc_region_type;
7037 +
7038 + if (is_fsl_mc_bus_dprc(mc_dev) ||
7039 + is_fsl_mc_bus_dpmcp(mc_dev)) {
7040 + mc_region_type = DPRC_REGION_TYPE_MC_PORTAL;
7041 + } else if (is_fsl_mc_bus_dpio(mc_dev)) {
7042 + mc_region_type = DPRC_REGION_TYPE_QBMAN_PORTAL;
7043 + } else {
7044 + /*
7045 + * This function should not have been called for this MC object
7046 + * type, as this object type is not supposed to have MMIO
7047 + * regions
7048 + */
7049 + return -EINVAL;
7050 + }
7051 +
7052 + regions = kmalloc_array(obj_desc->region_count,
7053 + sizeof(regions[0]), GFP_KERNEL);
7054 + if (!regions)
7055 + return -ENOMEM;
7056 +
7057 + for (i = 0; i < obj_desc->region_count; i++) {
7058 + struct dprc_region_desc region_desc;
7059 +
7060 + error = dprc_get_obj_region(mc_bus_dev->mc_io,
7061 + 0,
7062 + mc_bus_dev->mc_handle,
7063 + obj_desc->type,
7064 + obj_desc->id, i, &region_desc);
7065 + if (error < 0) {
7066 + dev_err(parent_dev,
7067 + "dprc_get_obj_region() failed: %d\n", error);
7068 + goto error_cleanup_regions;
7069 + }
7070 + /* Older MC only returned region offset and no base address
7071 + * If base address is in the region_desc use it otherwise
7072 + * revert to old mechanism
7073 + */
7074 + if (region_desc.base_address)
7075 + regions[i].start = region_desc.base_address +
7076 + region_desc.base_offset;
7077 + else
7078 + error = translate_mc_addr(mc_dev, mc_region_type,
7079 + region_desc.base_offset,
7080 + &regions[i].start);
7081 + if (error < 0) {
7082 + dev_err(parent_dev,
7083 + "Invalid MC offset: %#x (for %s.%d\'s region %d)\n",
7084 + region_desc.base_offset,
7085 + obj_desc->type, obj_desc->id, i);
7086 + goto error_cleanup_regions;
7087 + }
7088 +
7089 + regions[i].end = regions[i].start + region_desc.size - 1;
7090 + regions[i].name = "fsl-mc object MMIO region";
7091 + regions[i].flags = IORESOURCE_IO;
7092 + if (region_desc.flags & DPRC_REGION_CACHEABLE)
7093 + regions[i].flags |= IORESOURCE_CACHEABLE;
7094 + if (region_desc.flags & DPRC_REGION_SHAREABLE)
7095 + regions[i].flags |= IORESOURCE_MEM;
7096 + }
7097 +
7098 + mc_dev->regions = regions;
7099 + return 0;
7100 +
7101 +error_cleanup_regions:
7102 + kfree(regions);
7103 + return error;
7104 +}
7105 +
7106 +/**
7107 + * fsl_mc_is_root_dprc - function to check if a given device is a root dprc
7108 + */
7109 +bool fsl_mc_is_root_dprc(struct device *dev)
7110 +{
7111 + struct device *root_dprc_dev;
7112 +
7113 + fsl_mc_get_root_dprc(dev, &root_dprc_dev);
7114 + if (!root_dprc_dev)
7115 + return false;
7116 + return dev == root_dprc_dev;
7117 +}
7118 +
7119 +static void fsl_mc_device_release(struct device *dev)
7120 +{
7121 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
7122 +
7123 + kfree(mc_dev->regions);
7124 +
7125 + if (is_fsl_mc_bus_dprc(mc_dev))
7126 + kfree(to_fsl_mc_bus(mc_dev));
7127 + else
7128 + kfree(mc_dev);
7129 +}
7130 +
7131 +/**
7132 + * Add a newly discovered fsl-mc device to be visible in Linux
7133 + */
7134 +int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc,
7135 + struct fsl_mc_io *mc_io,
7136 + struct device *parent_dev,
7137 + const char *driver_override,
7138 + struct fsl_mc_device **new_mc_dev)
7139 +{
7140 + int error;
7141 + struct fsl_mc_device *mc_dev = NULL;
7142 + struct fsl_mc_bus *mc_bus = NULL;
7143 + struct fsl_mc_device *parent_mc_dev;
7144 +
7145 + if (dev_is_fsl_mc(parent_dev))
7146 + parent_mc_dev = to_fsl_mc_device(parent_dev);
7147 + else
7148 + parent_mc_dev = NULL;
7149 +
7150 + if (strcmp(obj_desc->type, "dprc") == 0) {
7151 + /*
7152 + * Allocate an MC bus device object:
7153 + */
7154 + mc_bus = kzalloc(sizeof(*mc_bus), GFP_KERNEL);
7155 + if (!mc_bus)
7156 + return -ENOMEM;
7157 +
7158 + mc_dev = &mc_bus->mc_dev;
7159 + } else {
7160 + /*
7161 + * Allocate a regular fsl_mc_device object:
7162 + */
7163 + mc_dev = kzalloc(sizeof(*mc_dev), GFP_KERNEL);
7164 + if (!mc_dev)
7165 + return -ENOMEM;
7166 + }
7167 +
7168 + mc_dev->obj_desc = *obj_desc;
7169 + mc_dev->mc_io = mc_io;
7170 +
7171 + if (driver_override) {
7172 + /*
7173 + * We trust driver_override, so we don't need to use
7174 + * kstrndup() here
7175 + */
7176 + mc_dev->driver_override = kstrdup(driver_override, GFP_KERNEL);
7177 + if (!mc_dev->driver_override) {
7178 + error = -ENOMEM;
7179 + goto error_cleanup_dev;
7180 + }
7181 + }
7182 +
7183 + device_initialize(&mc_dev->dev);
7184 + mc_dev->dev.parent = parent_dev;
7185 + mc_dev->dev.bus = &fsl_mc_bus_type;
7186 + mc_dev->dev.release = fsl_mc_device_release;
7187 + mc_dev->dev.type = fsl_mc_get_device_type(obj_desc->type);
7188 + if (!mc_dev->dev.type) {
7189 + error = -ENODEV;
7190 + dev_err(parent_dev, "unknown device type %s\n", obj_desc->type);
7191 + goto error_cleanup_dev;
7192 + }
7193 + dev_set_name(&mc_dev->dev, "%s.%d", obj_desc->type, obj_desc->id);
7194 +
7195 + if (strcmp(obj_desc->type, "dprc") == 0) {
7196 + struct fsl_mc_io *mc_io2;
7197 +
7198 + mc_dev->flags |= FSL_MC_IS_DPRC;
7199 +
7200 + /*
7201 + * To get the DPRC's ICID, we need to open the DPRC
7202 + * in get_dprc_icid(). For child DPRCs, we do so using the
7203 + * parent DPRC's MC portal instead of the child DPRC's MC
7204 + * portal, in case the child DPRC is already opened with
7205 + * its own portal (e.g., the DPRC used by AIOP).
7206 + *
7207 + * NOTE: There cannot be more than one active open for a
7208 + * given MC object, using the same MC portal.
7209 + */
7210 + if (parent_mc_dev) {
7211 + /*
7212 + * device being added is a child DPRC device
7213 + */
7214 + mc_io2 = parent_mc_dev->mc_io;
7215 + } else {
7216 + /*
7217 + * device being added is the root DPRC device
7218 + */
7219 + if (!mc_io) {
7220 + error = -EINVAL;
7221 + goto error_cleanup_dev;
7222 + }
7223 +
7224 + mc_io2 = mc_io;
7225 + }
7226 +
7227 + error = get_dprc_icid(mc_io2, obj_desc->id, &mc_dev->icid);
7228 + if (error < 0)
7229 + goto error_cleanup_dev;
7230 + } else {
7231 + /*
7232 + * A non-DPRC object has to be a child of a DPRC, use the
7233 + * parent's ICID and interrupt domain.
7234 + */
7235 + mc_dev->icid = parent_mc_dev->icid;
7236 + mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK;
7237 + mc_dev->dev.dma_mask = &mc_dev->dma_mask;
7238 + mc_dev->dev.coherent_dma_mask = mc_dev->dma_mask;
7239 + dev_set_msi_domain(&mc_dev->dev,
7240 + dev_get_msi_domain(&parent_mc_dev->dev));
7241 + }
7242 +
7243 + /*
7244 + * Get MMIO regions for the device from the MC:
7245 + *
7246 + * NOTE: the root DPRC is a special case as its MMIO region is
7247 + * obtained from the device tree
7248 + */
7249 + if (parent_mc_dev && obj_desc->region_count != 0) {
7250 + error = fsl_mc_device_get_mmio_regions(mc_dev,
7251 + parent_mc_dev);
7252 + if (error < 0)
7253 + goto error_cleanup_dev;
7254 + }
7255 +
7256 + /*
7257 + * The device-specific probe callback will get invoked by device_add()
7258 + */
7259 + error = device_add(&mc_dev->dev);
7260 + if (error < 0) {
7261 + dev_err(parent_dev,
7262 + "device_add() failed for device %s: %d\n",
7263 + dev_name(&mc_dev->dev), error);
7264 + goto error_cleanup_dev;
7265 + }
7266 +
7267 + dev_dbg(parent_dev, "added %s\n", dev_name(&mc_dev->dev));
7268 +
7269 + *new_mc_dev = mc_dev;
7270 + return 0;
7271 +
7272 +error_cleanup_dev:
7273 + kfree(mc_dev->regions);
7274 + kfree(mc_bus);
7275 + kfree(mc_dev);
7276 +
7277 + return error;
7278 +}
7279 +EXPORT_SYMBOL_GPL(fsl_mc_device_add);
7280 +
7281 +/**
7282 + * fsl_mc_device_remove - Remove an fsl-mc device from being visible to
7283 + * Linux
7284 + *
7285 + * @mc_dev: Pointer to an fsl-mc device
7286 + */
7287 +void fsl_mc_device_remove(struct fsl_mc_device *mc_dev)
7288 +{
7289 + kfree(mc_dev->driver_override);
7290 + mc_dev->driver_override = NULL;
7291 +
7292 + /*
7293 + * The device-specific remove callback will get invoked by device_del()
7294 + */
7295 + device_del(&mc_dev->dev);
7296 + put_device(&mc_dev->dev);
7297 +}
7298 +EXPORT_SYMBOL_GPL(fsl_mc_device_remove);
7299 +
7300 +static int parse_mc_ranges(struct device *dev,
7301 + int *paddr_cells,
7302 + int *mc_addr_cells,
7303 + int *mc_size_cells,
7304 + const __be32 **ranges_start)
7305 +{
7306 + const __be32 *prop;
7307 + int range_tuple_cell_count;
7308 + int ranges_len;
7309 + int tuple_len;
7310 + struct device_node *mc_node = dev->of_node;
7311 +
7312 + *ranges_start = of_get_property(mc_node, "ranges", &ranges_len);
7313 + if (!(*ranges_start) || !ranges_len) {
7314 + dev_warn(dev,
7315 + "missing or empty ranges property for device tree node '%s'\n",
7316 + mc_node->name);
7317 + return 0;
7318 + }
7319 +
7320 + *paddr_cells = of_n_addr_cells(mc_node);
7321 +
7322 + prop = of_get_property(mc_node, "#address-cells", NULL);
7323 + if (prop)
7324 + *mc_addr_cells = be32_to_cpup(prop);
7325 + else
7326 + *mc_addr_cells = *paddr_cells;
7327 +
7328 + prop = of_get_property(mc_node, "#size-cells", NULL);
7329 + if (prop)
7330 + *mc_size_cells = be32_to_cpup(prop);
7331 + else
7332 + *mc_size_cells = of_n_size_cells(mc_node);
7333 +
7334 + range_tuple_cell_count = *paddr_cells + *mc_addr_cells +
7335 + *mc_size_cells;
7336 +
7337 + tuple_len = range_tuple_cell_count * sizeof(__be32);
7338 + if (ranges_len % tuple_len != 0) {
7339 + dev_err(dev, "malformed ranges property '%s'\n", mc_node->name);
7340 + return -EINVAL;
7341 + }
7342 +
7343 + return ranges_len / tuple_len;
7344 +}
7345 +
7346 +static int get_mc_addr_translation_ranges(struct device *dev,
7347 + struct fsl_mc_addr_translation_range
7348 + **ranges,
7349 + u8 *num_ranges)
7350 +{
7351 + int ret;
7352 + int paddr_cells;
7353 + int mc_addr_cells;
7354 + int mc_size_cells;
7355 + int i;
7356 + const __be32 *ranges_start;
7357 + const __be32 *cell;
7358 +
7359 + ret = parse_mc_ranges(dev,
7360 + &paddr_cells,
7361 + &mc_addr_cells,
7362 + &mc_size_cells,
7363 + &ranges_start);
7364 + if (ret < 0)
7365 + return ret;
7366 +
7367 + *num_ranges = ret;
7368 + if (!ret) {
7369 + /*
7370 + * Missing or empty ranges property ("ranges;") for the
7371 + * 'fsl,qoriq-mc' node. In this case, identity mapping
7372 + * will be used.
7373 + */
7374 + *ranges = NULL;
7375 + return 0;
7376 + }
7377 +
7378 + *ranges = devm_kcalloc(dev, *num_ranges,
7379 + sizeof(struct fsl_mc_addr_translation_range),
7380 + GFP_KERNEL);
7381 + if (!(*ranges))
7382 + return -ENOMEM;
7383 +
7384 + cell = ranges_start;
7385 + for (i = 0; i < *num_ranges; ++i) {
7386 + struct fsl_mc_addr_translation_range *range = &(*ranges)[i];
7387 +
7388 + range->mc_region_type = of_read_number(cell, 1);
7389 + range->start_mc_offset = of_read_number(cell + 1,
7390 + mc_addr_cells - 1);
7391 + cell += mc_addr_cells;
7392 + range->start_phys_addr = of_read_number(cell, paddr_cells);
7393 + cell += paddr_cells;
7394 + range->end_mc_offset = range->start_mc_offset +
7395 + of_read_number(cell, mc_size_cells);
7396 +
7397 + cell += mc_size_cells;
7398 + }
7399 +
7400 + return 0;
7401 +}
7402 +
7403 +/**
7404 + * fsl_mc_bus_probe - callback invoked when the root MC bus is being
7405 + * added
7406 + */
7407 +static int fsl_mc_bus_probe(struct platform_device *pdev)
7408 +{
7409 + struct fsl_mc_obj_desc obj_desc;
7410 + int error;
7411 + struct fsl_mc *mc;
7412 + struct fsl_mc_device *mc_bus_dev = NULL;
7413 + struct fsl_mc_io *mc_io = NULL;
7414 + struct fsl_mc_bus *mc_bus = NULL;
7415 + int container_id;
7416 + phys_addr_t mc_portal_phys_addr;
7417 + u32 mc_portal_size;
7418 + struct mc_version mc_version;
7419 + struct resource res;
7420 +
7421 + mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL);
7422 + if (!mc)
7423 + return -ENOMEM;
7424 +
7425 + platform_set_drvdata(pdev, mc);
7426 +
7427 + /*
7428 + * Get physical address of MC portal for the root DPRC:
7429 + */
7430 + error = of_address_to_resource(pdev->dev.of_node, 0, &res);
7431 + if (error < 0) {
7432 + dev_err(&pdev->dev,
7433 + "of_address_to_resource() failed for %pOF\n",
7434 + pdev->dev.of_node);
7435 + return error;
7436 + }
7437 +
7438 + mc_portal_phys_addr = res.start;
7439 + mc_portal_size = resource_size(&res);
7440 + error = fsl_create_mc_io(&pdev->dev, mc_portal_phys_addr,
7441 + mc_portal_size, NULL,
7442 + FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, &mc_io);
7443 + if (error < 0)
7444 + return error;
7445 +
7446 + error = mc_get_version(mc_io, 0, &mc_version);
7447 + if (error != 0) {
7448 + dev_err(&pdev->dev,
7449 + "mc_get_version() failed with error %d\n", error);
7450 + goto error_cleanup_mc_io;
7451 + }
7452 +
7453 + dev_info(&pdev->dev, "MC firmware version: %u.%u.%u\n",
7454 + mc_version.major, mc_version.minor, mc_version.revision);
7455 +
7456 + error = get_mc_addr_translation_ranges(&pdev->dev,
7457 + &mc->translation_ranges,
7458 + &mc->num_translation_ranges);
7459 + if (error < 0)
7460 + goto error_cleanup_mc_io;
7461 +
7462 + error = dprc_get_container_id(mc_io, 0, &container_id);
7463 + if (error < 0) {
7464 + dev_err(&pdev->dev,
7465 + "dprc_get_container_id() failed: %d\n", error);
7466 + goto error_cleanup_mc_io;
7467 + }
7468 +
7469 + memset(&obj_desc, 0, sizeof(struct fsl_mc_obj_desc));
7470 + error = dprc_get_api_version(mc_io, 0,
7471 + &obj_desc.ver_major,
7472 + &obj_desc.ver_minor);
7473 + if (error < 0)
7474 + goto error_cleanup_mc_io;
7475 +
7476 + obj_desc.vendor = FSL_MC_VENDOR_FREESCALE;
7477 + strcpy(obj_desc.type, "dprc");
7478 + obj_desc.id = container_id;
7479 + obj_desc.irq_count = 1;
7480 + obj_desc.region_count = 0;
7481 +
7482 + error = fsl_mc_device_add(&obj_desc, mc_io, &pdev->dev, NULL,
7483 + &mc_bus_dev);
7484 + if (error < 0)
7485 + goto error_cleanup_mc_io;
7486 +
7487 + mc_bus = to_fsl_mc_bus(mc_bus_dev);
7488 + error = fsl_mc_restool_create_device_file(mc_bus);
7489 + if (error < 0)
7490 + goto error_cleanup_device;
7491 +
7492 + mc->root_mc_bus_dev = mc_bus_dev;
7493 +
7494 + return 0;
7495 +
7496 +error_cleanup_device:
7497 + fsl_mc_device_remove(mc_bus_dev);
7498 +
7499 +error_cleanup_mc_io:
7500 + fsl_destroy_mc_io(mc_io);
7501 + return error;
7502 +}
7503 +
7504 +/**
7505 + * fsl_mc_bus_remove - callback invoked when the root MC bus is being
7506 + * removed
7507 + */
7508 +static int fsl_mc_bus_remove(struct platform_device *pdev)
7509 +{
7510 + struct fsl_mc *mc = platform_get_drvdata(pdev);
7511 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc->root_mc_bus_dev);
7512 +
7513 + if (!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev))
7514 + return -EINVAL;
7515 +
7516 + fsl_mc_restool_remove_device_file(mc_bus);
7517 + fsl_mc_device_remove(mc->root_mc_bus_dev);
7518 +
7519 + fsl_destroy_mc_io(mc->root_mc_bus_dev->mc_io);
7520 + mc->root_mc_bus_dev->mc_io = NULL;
7521 +
7522 + return 0;
7523 +}
7524 +
7525 +static const struct of_device_id fsl_mc_bus_match_table[] = {
7526 + {.compatible = "fsl,qoriq-mc",},
7527 + {},
7528 +};
7529 +
7530 +MODULE_DEVICE_TABLE(of, fsl_mc_bus_match_table);
7531 +
7532 +static struct platform_driver fsl_mc_bus_driver = {
7533 + .driver = {
7534 + .name = "fsl_mc_bus",
7535 + .pm = NULL,
7536 + .of_match_table = fsl_mc_bus_match_table,
7537 + },
7538 + .probe = fsl_mc_bus_probe,
7539 + .remove = fsl_mc_bus_remove,
7540 +};
7541 +
7542 +static int __init fsl_mc_bus_driver_init(void)
7543 +{
7544 + int error;
7545 +
7546 + error = bus_register(&fsl_mc_bus_type);
7547 + if (error < 0) {
7548 + pr_err("bus type registration failed: %d\n", error);
7549 + goto error_cleanup_cache;
7550 + }
7551 +
7552 + error = platform_driver_register(&fsl_mc_bus_driver);
7553 + if (error < 0) {
7554 + pr_err("platform_driver_register() failed: %d\n", error);
7555 + goto error_cleanup_bus;
7556 + }
7557 +
7558 + error = dprc_driver_init();
7559 + if (error < 0)
7560 + goto error_cleanup_driver;
7561 +
7562 + error = fsl_mc_allocator_driver_init();
7563 + if (error < 0)
7564 + goto error_cleanup_dprc_driver;
7565 +
7566 + error = fsl_mc_restool_init();
7567 + if (error < 0)
7568 + goto error_cleanup_mc_allocator;
7569 +
7570 + return 0;
7571 +
7572 +error_cleanup_mc_allocator:
7573 + fsl_mc_allocator_driver_exit();
7574 +
7575 +error_cleanup_dprc_driver:
7576 + dprc_driver_exit();
7577 +
7578 +error_cleanup_driver:
7579 + platform_driver_unregister(&fsl_mc_bus_driver);
7580 +
7581 +error_cleanup_bus:
7582 + bus_unregister(&fsl_mc_bus_type);
7583 +
7584 +error_cleanup_cache:
7585 + return error;
7586 +}
7587 +postcore_initcall(fsl_mc_bus_driver_init);
7588 --- a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c
7589 +++ /dev/null
7590 @@ -1,285 +0,0 @@
7591 -// SPDX-License-Identifier: GPL-2.0
7592 -/*
7593 - * Freescale Management Complex (MC) bus driver MSI support
7594 - *
7595 - * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
7596 - * Author: German Rivera <German.Rivera@freescale.com>
7597 - *
7598 - */
7599 -
7600 -#include <linux/of_device.h>
7601 -#include <linux/of_address.h>
7602 -#include <linux/of_irq.h>
7603 -#include <linux/irq.h>
7604 -#include <linux/irqdomain.h>
7605 -#include <linux/msi.h>
7606 -#include "fsl-mc-private.h"
7607 -
7608 -#ifdef GENERIC_MSI_DOMAIN_OPS
7609 -/*
7610 - * Generate a unique ID identifying the interrupt (only used within the MSI
7611 - * irqdomain. Combine the icid with the interrupt index.
7612 - */
7613 -static irq_hw_number_t fsl_mc_domain_calc_hwirq(struct fsl_mc_device *dev,
7614 - struct msi_desc *desc)
7615 -{
7616 - /*
7617 - * Make the base hwirq value for ICID*10000 so it is readable
7618 - * as a decimal value in /proc/interrupts.
7619 - */
7620 - return (irq_hw_number_t)(desc->fsl_mc.msi_index + (dev->icid * 10000));
7621 -}
7622 -
7623 -static void fsl_mc_msi_set_desc(msi_alloc_info_t *arg,
7624 - struct msi_desc *desc)
7625 -{
7626 - arg->desc = desc;
7627 - arg->hwirq = fsl_mc_domain_calc_hwirq(to_fsl_mc_device(desc->dev),
7628 - desc);
7629 -}
7630 -#else
7631 -#define fsl_mc_msi_set_desc NULL
7632 -#endif
7633 -
7634 -static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info)
7635 -{
7636 - struct msi_domain_ops *ops = info->ops;
7637 -
7638 - if (WARN_ON(!ops))
7639 - return;
7640 -
7641 - /*
7642 - * set_desc should not be set by the caller
7643 - */
7644 - if (!ops->set_desc)
7645 - ops->set_desc = fsl_mc_msi_set_desc;
7646 -}
7647 -
7648 -static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev,
7649 - struct fsl_mc_device_irq *mc_dev_irq)
7650 -{
7651 - int error;
7652 - struct fsl_mc_device *owner_mc_dev = mc_dev_irq->mc_dev;
7653 - struct msi_desc *msi_desc = mc_dev_irq->msi_desc;
7654 - struct dprc_irq_cfg irq_cfg;
7655 -
7656 - /*
7657 - * msi_desc->msg.address is 0x0 when this function is invoked in
7658 - * the free_irq() code path. In this case, for the MC, we don't
7659 - * really need to "unprogram" the MSI, so we just return.
7660 - */
7661 - if (msi_desc->msg.address_lo == 0x0 && msi_desc->msg.address_hi == 0x0)
7662 - return;
7663 -
7664 - if (WARN_ON(!owner_mc_dev))
7665 - return;
7666 -
7667 - irq_cfg.paddr = ((u64)msi_desc->msg.address_hi << 32) |
7668 - msi_desc->msg.address_lo;
7669 - irq_cfg.val = msi_desc->msg.data;
7670 - irq_cfg.irq_num = msi_desc->irq;
7671 -
7672 - if (owner_mc_dev == mc_bus_dev) {
7673 - /*
7674 - * IRQ is for the mc_bus_dev's DPRC itself
7675 - */
7676 - error = dprc_set_irq(mc_bus_dev->mc_io,
7677 - MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI,
7678 - mc_bus_dev->mc_handle,
7679 - mc_dev_irq->dev_irq_index,
7680 - &irq_cfg);
7681 - if (error < 0) {
7682 - dev_err(&owner_mc_dev->dev,
7683 - "dprc_set_irq() failed: %d\n", error);
7684 - }
7685 - } else {
7686 - /*
7687 - * IRQ is for for a child device of mc_bus_dev
7688 - */
7689 - error = dprc_set_obj_irq(mc_bus_dev->mc_io,
7690 - MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI,
7691 - mc_bus_dev->mc_handle,
7692 - owner_mc_dev->obj_desc.type,
7693 - owner_mc_dev->obj_desc.id,
7694 - mc_dev_irq->dev_irq_index,
7695 - &irq_cfg);
7696 - if (error < 0) {
7697 - dev_err(&owner_mc_dev->dev,
7698 - "dprc_obj_set_irq() failed: %d\n", error);
7699 - }
7700 - }
7701 -}
7702 -
7703 -/*
7704 - * NOTE: This function is invoked with interrupts disabled
7705 - */
7706 -static void fsl_mc_msi_write_msg(struct irq_data *irq_data,
7707 - struct msi_msg *msg)
7708 -{
7709 - struct msi_desc *msi_desc = irq_data_get_msi_desc(irq_data);
7710 - struct fsl_mc_device *mc_bus_dev = to_fsl_mc_device(msi_desc->dev);
7711 - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
7712 - struct fsl_mc_device_irq *mc_dev_irq =
7713 - &mc_bus->irq_resources[msi_desc->fsl_mc.msi_index];
7714 -
7715 - WARN_ON(mc_dev_irq->msi_desc != msi_desc);
7716 - msi_desc->msg = *msg;
7717 -
7718 - /*
7719 - * Program the MSI (paddr, value) pair in the device:
7720 - */
7721 - __fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq);
7722 -}
7723 -
7724 -static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info)
7725 -{
7726 - struct irq_chip *chip = info->chip;
7727 -
7728 - if (WARN_ON((!chip)))
7729 - return;
7730 -
7731 - /*
7732 - * irq_write_msi_msg should not be set by the caller
7733 - */
7734 - if (!chip->irq_write_msi_msg)
7735 - chip->irq_write_msi_msg = fsl_mc_msi_write_msg;
7736 -}
7737 -
7738 -/**
7739 - * fsl_mc_msi_create_irq_domain - Create a fsl-mc MSI interrupt domain
7740 - * @np: Optional device-tree node of the interrupt controller
7741 - * @info: MSI domain info
7742 - * @parent: Parent irq domain
7743 - *
7744 - * Updates the domain and chip ops and creates a fsl-mc MSI
7745 - * interrupt domain.
7746 - *
7747 - * Returns:
7748 - * A domain pointer or NULL in case of failure.
7749 - */
7750 -struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode,
7751 - struct msi_domain_info *info,
7752 - struct irq_domain *parent)
7753 -{
7754 - struct irq_domain *domain;
7755 -
7756 - if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS)
7757 - fsl_mc_msi_update_dom_ops(info);
7758 - if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
7759 - fsl_mc_msi_update_chip_ops(info);
7760 -
7761 - domain = msi_create_irq_domain(fwnode, info, parent);
7762 - if (domain)
7763 - irq_domain_update_bus_token(domain, DOMAIN_BUS_FSL_MC_MSI);
7764 -
7765 - return domain;
7766 -}
7767 -
7768 -int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
7769 - struct irq_domain **mc_msi_domain)
7770 -{
7771 - struct irq_domain *msi_domain;
7772 - struct device_node *mc_of_node = mc_platform_dev->of_node;
7773 -
7774 - msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node,
7775 - DOMAIN_BUS_FSL_MC_MSI);
7776 - if (!msi_domain) {
7777 - pr_err("Unable to find fsl-mc MSI domain for %pOF\n",
7778 - mc_of_node);
7779 -
7780 - return -ENOENT;
7781 - }
7782 -
7783 - *mc_msi_domain = msi_domain;
7784 - return 0;
7785 -}
7786 -
7787 -static void fsl_mc_msi_free_descs(struct device *dev)
7788 -{
7789 - struct msi_desc *desc, *tmp;
7790 -
7791 - list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) {
7792 - list_del(&desc->list);
7793 - free_msi_entry(desc);
7794 - }
7795 -}
7796 -
7797 -static int fsl_mc_msi_alloc_descs(struct device *dev, unsigned int irq_count)
7798 -
7799 -{
7800 - unsigned int i;
7801 - int error;
7802 - struct msi_desc *msi_desc;
7803 -
7804 - for (i = 0; i < irq_count; i++) {
7805 - msi_desc = alloc_msi_entry(dev, 1, NULL);
7806 - if (!msi_desc) {
7807 - dev_err(dev, "Failed to allocate msi entry\n");
7808 - error = -ENOMEM;
7809 - goto cleanup_msi_descs;
7810 - }
7811 -
7812 - msi_desc->fsl_mc.msi_index = i;
7813 - INIT_LIST_HEAD(&msi_desc->list);
7814 - list_add_tail(&msi_desc->list, dev_to_msi_list(dev));
7815 - }
7816 -
7817 - return 0;
7818 -
7819 -cleanup_msi_descs:
7820 - fsl_mc_msi_free_descs(dev);
7821 - return error;
7822 -}
7823 -
7824 -int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
7825 - unsigned int irq_count)
7826 -{
7827 - struct irq_domain *msi_domain;
7828 - int error;
7829 -
7830 - if (WARN_ON(!list_empty(dev_to_msi_list(dev))))
7831 - return -EINVAL;
7832 -
7833 - error = fsl_mc_msi_alloc_descs(dev, irq_count);
7834 - if (error < 0)
7835 - return error;
7836 -
7837 - msi_domain = dev_get_msi_domain(dev);
7838 - if (WARN_ON(!msi_domain)) {
7839 - error = -EINVAL;
7840 - goto cleanup_msi_descs;
7841 - }
7842 -
7843 - /*
7844 - * NOTE: Calling this function will trigger the invocation of the
7845 - * its_fsl_mc_msi_prepare() callback
7846 - */
7847 - error = msi_domain_alloc_irqs(msi_domain, dev, irq_count);
7848 -
7849 - if (error) {
7850 - dev_err(dev, "Failed to allocate IRQs\n");
7851 - goto cleanup_msi_descs;
7852 - }
7853 -
7854 - return 0;
7855 -
7856 -cleanup_msi_descs:
7857 - fsl_mc_msi_free_descs(dev);
7858 - return error;
7859 -}
7860 -
7861 -void fsl_mc_msi_domain_free_irqs(struct device *dev)
7862 -{
7863 - struct irq_domain *msi_domain;
7864 -
7865 - msi_domain = dev_get_msi_domain(dev);
7866 - if (WARN_ON(!msi_domain))
7867 - return;
7868 -
7869 - msi_domain_free_irqs(msi_domain, dev);
7870 -
7871 - if (WARN_ON(list_empty(dev_to_msi_list(dev))))
7872 - return;
7873 -
7874 - fsl_mc_msi_free_descs(dev);
7875 -}
7876 --- /dev/null
7877 +++ b/drivers/bus/fsl-mc/fsl-mc-msi.c
7878 @@ -0,0 +1,285 @@
7879 +// SPDX-License-Identifier: GPL-2.0
7880 +/*
7881 + * Freescale Management Complex (MC) bus driver MSI support
7882 + *
7883 + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
7884 + * Author: German Rivera <German.Rivera@freescale.com>
7885 + *
7886 + */
7887 +
7888 +#include <linux/of_device.h>
7889 +#include <linux/of_address.h>
7890 +#include <linux/of_irq.h>
7891 +#include <linux/irq.h>
7892 +#include <linux/irqdomain.h>
7893 +#include <linux/msi.h>
7894 +
7895 +#include "fsl-mc-private.h"
7896 +
7897 +#ifdef GENERIC_MSI_DOMAIN_OPS
7898 +/*
7899 + * Generate a unique ID identifying the interrupt (only used within the MSI
7900 + * irqdomain. Combine the icid with the interrupt index.
7901 + */
7902 +static irq_hw_number_t fsl_mc_domain_calc_hwirq(struct fsl_mc_device *dev,
7903 + struct msi_desc *desc)
7904 +{
7905 + /*
7906 + * Make the base hwirq value for ICID*10000 so it is readable
7907 + * as a decimal value in /proc/interrupts.
7908 + */
7909 + return (irq_hw_number_t)(desc->fsl_mc.msi_index + (dev->icid * 10000));
7910 +}
7911 +
7912 +static void fsl_mc_msi_set_desc(msi_alloc_info_t *arg,
7913 + struct msi_desc *desc)
7914 +{
7915 + arg->desc = desc;
7916 + arg->hwirq = fsl_mc_domain_calc_hwirq(to_fsl_mc_device(desc->dev),
7917 + desc);
7918 +}
7919 +#else
7920 +#define fsl_mc_msi_set_desc NULL
7921 +#endif
7922 +
7923 +static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info)
7924 +{
7925 + struct msi_domain_ops *ops = info->ops;
7926 +
7927 + if (!ops)
7928 + return;
7929 +
7930 + /*
7931 + * set_desc should not be set by the caller
7932 + */
7933 + if (!ops->set_desc)
7934 + ops->set_desc = fsl_mc_msi_set_desc;
7935 +}
7936 +
7937 +static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev,
7938 + struct fsl_mc_device_irq *mc_dev_irq)
7939 +{
7940 + int error;
7941 + struct fsl_mc_device *owner_mc_dev = mc_dev_irq->mc_dev;
7942 + struct msi_desc *msi_desc = mc_dev_irq->msi_desc;
7943 + struct dprc_irq_cfg irq_cfg;
7944 +
7945 + /*
7946 + * msi_desc->msg.address is 0x0 when this function is invoked in
7947 + * the free_irq() code path. In this case, for the MC, we don't
7948 + * really need to "unprogram" the MSI, so we just return.
7949 + */
7950 + if (msi_desc->msg.address_lo == 0x0 && msi_desc->msg.address_hi == 0x0)
7951 + return;
7952 +
7953 + if (!owner_mc_dev)
7954 + return;
7955 +
7956 + irq_cfg.paddr = ((u64)msi_desc->msg.address_hi << 32) |
7957 + msi_desc->msg.address_lo;
7958 + irq_cfg.val = msi_desc->msg.data;
7959 + irq_cfg.irq_num = msi_desc->irq;
7960 +
7961 + if (owner_mc_dev == mc_bus_dev) {
7962 + /*
7963 + * IRQ is for the mc_bus_dev's DPRC itself
7964 + */
7965 + error = dprc_set_irq(mc_bus_dev->mc_io,
7966 + MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI,
7967 + mc_bus_dev->mc_handle,
7968 + mc_dev_irq->dev_irq_index,
7969 + &irq_cfg);
7970 + if (error < 0) {
7971 + dev_err(&owner_mc_dev->dev,
7972 + "dprc_set_irq() failed: %d\n", error);
7973 + }
7974 + } else {
7975 + /*
7976 + * IRQ is for for a child device of mc_bus_dev
7977 + */
7978 + error = dprc_set_obj_irq(mc_bus_dev->mc_io,
7979 + MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI,
7980 + mc_bus_dev->mc_handle,
7981 + owner_mc_dev->obj_desc.type,
7982 + owner_mc_dev->obj_desc.id,
7983 + mc_dev_irq->dev_irq_index,
7984 + &irq_cfg);
7985 + if (error < 0) {
7986 + dev_err(&owner_mc_dev->dev,
7987 + "dprc_obj_set_irq() failed: %d\n", error);
7988 + }
7989 + }
7990 +}
7991 +
7992 +/*
7993 + * NOTE: This function is invoked with interrupts disabled
7994 + */
7995 +static void fsl_mc_msi_write_msg(struct irq_data *irq_data,
7996 + struct msi_msg *msg)
7997 +{
7998 + struct msi_desc *msi_desc = irq_data_get_msi_desc(irq_data);
7999 + struct fsl_mc_device *mc_bus_dev = to_fsl_mc_device(msi_desc->dev);
8000 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
8001 + struct fsl_mc_device_irq *mc_dev_irq =
8002 + &mc_bus->irq_resources[msi_desc->fsl_mc.msi_index];
8003 +
8004 + msi_desc->msg = *msg;
8005 +
8006 + /*
8007 + * Program the MSI (paddr, value) pair in the device:
8008 + */
8009 + __fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq);
8010 +}
8011 +
8012 +static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info)
8013 +{
8014 + struct irq_chip *chip = info->chip;
8015 +
8016 + if (!chip)
8017 + return;
8018 +
8019 + /*
8020 + * irq_write_msi_msg should not be set by the caller
8021 + */
8022 + if (!chip->irq_write_msi_msg)
8023 + chip->irq_write_msi_msg = fsl_mc_msi_write_msg;
8024 +}
8025 +
8026 +/**
8027 + * fsl_mc_msi_create_irq_domain - Create a fsl-mc MSI interrupt domain
8028 + * @np: Optional device-tree node of the interrupt controller
8029 + * @info: MSI domain info
8030 + * @parent: Parent irq domain
8031 + *
8032 + * Updates the domain and chip ops and creates a fsl-mc MSI
8033 + * interrupt domain.
8034 + *
8035 + * Returns:
8036 + * A domain pointer or NULL in case of failure.
8037 + */
8038 +struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode,
8039 + struct msi_domain_info *info,
8040 + struct irq_domain *parent)
8041 +{
8042 + struct irq_domain *domain;
8043 +
8044 + if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS)
8045 + fsl_mc_msi_update_dom_ops(info);
8046 + if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
8047 + fsl_mc_msi_update_chip_ops(info);
8048 +
8049 + domain = msi_create_irq_domain(fwnode, info, parent);
8050 + if (domain)
8051 + irq_domain_update_bus_token(domain, DOMAIN_BUS_FSL_MC_MSI);
8052 +
8053 + return domain;
8054 +}
8055 +
8056 +int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
8057 + struct irq_domain **mc_msi_domain)
8058 +{
8059 + struct irq_domain *msi_domain;
8060 + struct device_node *mc_of_node = mc_platform_dev->of_node;
8061 +
8062 + msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node,
8063 + DOMAIN_BUS_FSL_MC_MSI);
8064 + if (!msi_domain) {
8065 + pr_err("Unable to find fsl-mc MSI domain for %pOF\n",
8066 + mc_of_node);
8067 +
8068 + return -ENOENT;
8069 + }
8070 +
8071 + *mc_msi_domain = msi_domain;
8072 + return 0;
8073 +}
8074 +
8075 +static void fsl_mc_msi_free_descs(struct device *dev)
8076 +{
8077 + struct msi_desc *desc, *tmp;
8078 +
8079 + list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) {
8080 + list_del(&desc->list);
8081 + free_msi_entry(desc);
8082 + }
8083 +}
8084 +
8085 +static int fsl_mc_msi_alloc_descs(struct device *dev, unsigned int irq_count)
8086 +
8087 +{
8088 + unsigned int i;
8089 + int error;
8090 + struct msi_desc *msi_desc;
8091 +
8092 + for (i = 0; i < irq_count; i++) {
8093 + msi_desc = alloc_msi_entry(dev, 1, NULL);
8094 + if (!msi_desc) {
8095 + dev_err(dev, "Failed to allocate msi entry\n");
8096 + error = -ENOMEM;
8097 + goto cleanup_msi_descs;
8098 + }
8099 +
8100 + msi_desc->fsl_mc.msi_index = i;
8101 + INIT_LIST_HEAD(&msi_desc->list);
8102 + list_add_tail(&msi_desc->list, dev_to_msi_list(dev));
8103 + }
8104 +
8105 + return 0;
8106 +
8107 +cleanup_msi_descs:
8108 + fsl_mc_msi_free_descs(dev);
8109 + return error;
8110 +}
8111 +
8112 +int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
8113 + unsigned int irq_count)
8114 +{
8115 + struct irq_domain *msi_domain;
8116 + int error;
8117 +
8118 + if (!list_empty(dev_to_msi_list(dev)))
8119 + return -EINVAL;
8120 +
8121 + error = fsl_mc_msi_alloc_descs(dev, irq_count);
8122 + if (error < 0)
8123 + return error;
8124 +
8125 + msi_domain = dev_get_msi_domain(dev);
8126 + if (!msi_domain) {
8127 + error = -EINVAL;
8128 + goto cleanup_msi_descs;
8129 + }
8130 +
8131 + /*
8132 + * NOTE: Calling this function will trigger the invocation of the
8133 + * its_fsl_mc_msi_prepare() callback
8134 + */
8135 + error = msi_domain_alloc_irqs(msi_domain, dev, irq_count);
8136 +
8137 + if (error) {
8138 + dev_err(dev, "Failed to allocate IRQs\n");
8139 + goto cleanup_msi_descs;
8140 + }
8141 +
8142 + return 0;
8143 +
8144 +cleanup_msi_descs:
8145 + fsl_mc_msi_free_descs(dev);
8146 + return error;
8147 +}
8148 +
8149 +void fsl_mc_msi_domain_free_irqs(struct device *dev)
8150 +{
8151 + struct irq_domain *msi_domain;
8152 +
8153 + msi_domain = dev_get_msi_domain(dev);
8154 + if (!msi_domain)
8155 + return;
8156 +
8157 + msi_domain_free_irqs(msi_domain, dev);
8158 +
8159 + if (list_empty(dev_to_msi_list(dev)))
8160 + return;
8161 +
8162 + fsl_mc_msi_free_descs(dev);
8163 +}
8164 --- /dev/null
8165 +++ b/drivers/bus/fsl-mc/fsl-mc-private.h
8166 @@ -0,0 +1,223 @@
8167 +/* SPDX-License-Identifier: GPL-2.0 */
8168 +/*
8169 + * Freescale Management Complex (MC) bus private declarations
8170 + *
8171 + * Copyright (C) 2016 Freescale Semiconductor, Inc.
8172 + *
8173 + */
8174 +#ifndef _FSL_MC_PRIVATE_H_
8175 +#define _FSL_MC_PRIVATE_H_
8176 +
8177 +#include <linux/fsl/mc.h>
8178 +#include <linux/mutex.h>
8179 +#include <linux/cdev.h>
8180 +#include <linux/ioctl.h>
8181 +
8182 +/*
8183 + * Data Path Management Complex (DPMNG) General API
8184 + */
8185 +
8186 +/* DPMNG command versioning */
8187 +#define DPMNG_CMD_BASE_VERSION 1
8188 +#define DPMNG_CMD_ID_OFFSET 4
8189 +
8190 +#define DPMNG_CMD(id) (((id) << DPMNG_CMD_ID_OFFSET) | DPMNG_CMD_BASE_VERSION)
8191 +
8192 +/* DPMNG command IDs */
8193 +#define DPMNG_CMDID_GET_VERSION DPMNG_CMD(0x831)
8194 +
8195 +struct dpmng_rsp_get_version {
8196 + __le32 revision;
8197 + __le32 version_major;
8198 + __le32 version_minor;
8199 +};
8200 +
8201 +/*
8202 + * Data Path Management Command Portal (DPMCP) API
8203 + */
8204 +
8205 +/* Minimal supported DPMCP Version */
8206 +#define DPMCP_MIN_VER_MAJOR 3
8207 +#define DPMCP_MIN_VER_MINOR 0
8208 +
8209 +/* DPMCP command versioning */
8210 +#define DPMCP_CMD_BASE_VERSION 1
8211 +#define DPMCP_CMD_ID_OFFSET 4
8212 +
8213 +#define DPMCP_CMD(id) (((id) << DPMCP_CMD_ID_OFFSET) | DPMCP_CMD_BASE_VERSION)
8214 +
8215 +/* DPMCP command IDs */
8216 +#define DPMCP_CMDID_CLOSE DPMCP_CMD(0x800)
8217 +#define DPMCP_CMDID_OPEN DPMCP_CMD(0x80b)
8218 +#define DPMCP_CMDID_RESET DPMCP_CMD(0x005)
8219 +
8220 +struct dpmcp_cmd_open {
8221 + __le32 dpmcp_id;
8222 +};
8223 +
8224 +/*
8225 + * Initialization and runtime control APIs for DPMCP
8226 + */
8227 +int dpmcp_open(struct fsl_mc_io *mc_io,
8228 + u32 cmd_flags,
8229 + int dpmcp_id,
8230 + u16 *token);
8231 +
8232 +int dpmcp_close(struct fsl_mc_io *mc_io,
8233 + u32 cmd_flags,
8234 + u16 token);
8235 +
8236 +int dpmcp_reset(struct fsl_mc_io *mc_io,
8237 + u32 cmd_flags,
8238 + u16 token);
8239 +
8240 +/*
8241 + * Data Path Buffer Pool (DPBP) API
8242 + */
8243 +
8244 +/* DPBP Version */
8245 +#define DPBP_VER_MAJOR 3
8246 +#define DPBP_VER_MINOR 2
8247 +
8248 +/* Command versioning */
8249 +#define DPBP_CMD_BASE_VERSION 1
8250 +#define DPBP_CMD_ID_OFFSET 4
8251 +
8252 +#define DPBP_CMD(id) (((id) << DPBP_CMD_ID_OFFSET) | DPBP_CMD_BASE_VERSION)
8253 +
8254 +/* Command IDs */
8255 +#define DPBP_CMDID_CLOSE DPBP_CMD(0x800)
8256 +#define DPBP_CMDID_OPEN DPBP_CMD(0x804)
8257 +
8258 +#define DPBP_CMDID_ENABLE DPBP_CMD(0x002)
8259 +#define DPBP_CMDID_DISABLE DPBP_CMD(0x003)
8260 +#define DPBP_CMDID_GET_ATTR DPBP_CMD(0x004)
8261 +#define DPBP_CMDID_RESET DPBP_CMD(0x005)
8262 +
8263 +struct dpbp_cmd_open {
8264 + __le32 dpbp_id;
8265 +};
8266 +
8267 +#define DPBP_ENABLE 0x1
8268 +
8269 +struct dpbp_rsp_get_attributes {
8270 + /* response word 0 */
8271 + __le16 pad;
8272 + __le16 bpid;
8273 + __le32 id;
8274 + /* response word 1 */
8275 + __le16 version_major;
8276 + __le16 version_minor;
8277 +};
8278 +
8279 +/*
8280 + * Data Path Concentrator (DPCON) API
8281 + */
8282 +
8283 +/* DPCON Version */
8284 +#define DPCON_VER_MAJOR 3
8285 +#define DPCON_VER_MINOR 2
8286 +
8287 +/* Command versioning */
8288 +#define DPCON_CMD_BASE_VERSION 1
8289 +#define DPCON_CMD_ID_OFFSET 4
8290 +
8291 +#define DPCON_CMD(id) (((id) << DPCON_CMD_ID_OFFSET) | DPCON_CMD_BASE_VERSION)
8292 +
8293 +/* Command IDs */
8294 +#define DPCON_CMDID_CLOSE DPCON_CMD(0x800)
8295 +#define DPCON_CMDID_OPEN DPCON_CMD(0x808)
8296 +
8297 +#define DPCON_CMDID_ENABLE DPCON_CMD(0x002)
8298 +#define DPCON_CMDID_DISABLE DPCON_CMD(0x003)
8299 +#define DPCON_CMDID_GET_ATTR DPCON_CMD(0x004)
8300 +#define DPCON_CMDID_RESET DPCON_CMD(0x005)
8301 +
8302 +#define DPCON_CMDID_SET_NOTIFICATION DPCON_CMD(0x100)
8303 +
8304 +struct dpcon_cmd_open {
8305 + __le32 dpcon_id;
8306 +};
8307 +
8308 +#define DPCON_ENABLE 1
8309 +
8310 +struct dpcon_rsp_get_attr {
8311 + /* response word 0 */
8312 + __le32 id;
8313 + __le16 qbman_ch_id;
8314 + u8 num_priorities;
8315 + u8 pad;
8316 +};
8317 +
8318 +struct dpcon_cmd_set_notification {
8319 + /* cmd word 0 */
8320 + __le32 dpio_id;
8321 + u8 priority;
8322 + u8 pad[3];
8323 + /* cmd word 1 */
8324 + __le64 user_ctx;
8325 +};
8326 +
8327 +int __must_check fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc,
8328 + struct fsl_mc_io *mc_io,
8329 + struct device *parent_dev,
8330 + const char *driver_override,
8331 + struct fsl_mc_device **new_mc_dev);
8332 +
8333 +int __init dprc_driver_init(void);
8334 +
8335 +void dprc_driver_exit(void);
8336 +
8337 +int __init fsl_mc_allocator_driver_init(void);
8338 +
8339 +void fsl_mc_allocator_driver_exit(void);
8340 +
8341 +int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus,
8342 + enum fsl_mc_pool_type pool_type,
8343 + struct fsl_mc_resource
8344 + **new_resource);
8345 +
8346 +void fsl_mc_resource_free(struct fsl_mc_resource *resource);
8347 +
8348 +int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
8349 + unsigned int irq_count);
8350 +
8351 +void fsl_mc_msi_domain_free_irqs(struct device *dev);
8352 +
8353 +int __must_check fsl_create_mc_io(struct device *dev,
8354 + phys_addr_t mc_portal_phys_addr,
8355 + u32 mc_portal_size,
8356 + struct fsl_mc_device *dpmcp_dev,
8357 + u32 flags, struct fsl_mc_io **new_mc_io);
8358 +
8359 +void fsl_destroy_mc_io(struct fsl_mc_io *mc_io);
8360 +
8361 +bool fsl_mc_is_root_dprc(struct device *dev);
8362 +
8363 +#ifdef CONFIG_FSL_MC_RESTOOL
8364 +
8365 +int fsl_mc_restool_create_device_file(struct fsl_mc_bus *mc_bus);
8366 +
8367 +void fsl_mc_restool_remove_device_file(struct fsl_mc_bus *mc_bus);
8368 +
8369 +int fsl_mc_restool_init(void);
8370 +
8371 +#else
8372 +
8373 +static inline int fsl_mc_restool_create_device_file(struct fsl_mc_bus *mc_bus)
8374 +{
8375 + return 0;
8376 +}
8377 +
8378 +static inline void fsl_mc_restool_remove_device_file(struct fsl_mc_bus *mc_bus)
8379 +{
8380 +}
8381 +
8382 +static inline int fsl_mc_restool_init(void)
8383 +{
8384 + return 0;
8385 +}
8386 +
8387 +#endif
8388 +
8389 +#endif /* _FSL_MC_PRIVATE_H_ */
8390 --- /dev/null
8391 +++ b/drivers/bus/fsl-mc/fsl-mc-restool.c
8392 @@ -0,0 +1,219 @@
8393 +// SPDX-License-Identifier: GPL-2.0
8394 +/*
8395 + * Management Complex (MC) restool support
8396 + *
8397 + * Copyright 2018 NXP
8398 + *
8399 + */
8400 +
8401 +#include <linux/slab.h>
8402 +#include <linux/cdev.h>
8403 +#include <linux/fs.h>
8404 +#include <linux/uaccess.h>
8405 +
8406 +#include "fsl-mc-private.h"
8407 +
8408 +#define FSL_MC_BUS_MAX_MINORS 1
8409 +
8410 +static struct class *fsl_mc_bus_class;
8411 +static int fsl_mc_bus_major;
8412 +
8413 +static int fsl_mc_restool_send_command(unsigned long arg,
8414 + struct fsl_mc_io *mc_io)
8415 +{
8416 + struct fsl_mc_command mc_cmd;
8417 + int error;
8418 +
8419 + error = copy_from_user(&mc_cmd, (void __user *)arg, sizeof(mc_cmd));
8420 + if (error)
8421 + return -EFAULT;
8422 +
8423 + error = mc_send_command(mc_io, &mc_cmd);
8424 + if (error)
8425 + return error;
8426 +
8427 + error = copy_to_user((void __user *)arg, &mc_cmd, sizeof(mc_cmd));
8428 + if (error)
8429 + return -EFAULT;
8430 +
8431 + return 0;
8432 +}
8433 +
8434 +int fsl_mc_restool_init(void)
8435 +{
8436 + dev_t dev;
8437 + int error;
8438 +
8439 + fsl_mc_bus_class = class_create(THIS_MODULE, "fsl_mc_bus");
8440 + if (IS_ERR(fsl_mc_bus_class)) {
8441 + error = PTR_ERR(fsl_mc_bus_class);
8442 + return error;
8443 + }
8444 +
8445 + error = alloc_chrdev_region(&dev, 0,
8446 + FSL_MC_BUS_MAX_MINORS,
8447 + "fsl_mc_bus");
8448 + if (error < 0)
8449 + return error;
8450 +
8451 + fsl_mc_bus_major = MAJOR(dev);
8452 +
8453 + return 0;
8454 +}
8455 +
8456 +static int fsl_mc_restool_dev_open(struct inode *inode, struct file *filep)
8457 +{
8458 + struct fsl_mc_device *root_mc_device;
8459 + struct fsl_mc_restool *mc_restool;
8460 + struct fsl_mc_bus *mc_bus;
8461 + struct fsl_mc_io *dynamic_mc_io;
8462 + int error;
8463 +
8464 + mc_restool = container_of(inode->i_cdev, struct fsl_mc_restool, cdev);
8465 + mc_bus = container_of(mc_restool, struct fsl_mc_bus, restool_misc);
8466 + root_mc_device = &mc_bus->mc_dev;
8467 +
8468 + mutex_lock(&mc_restool->mutex);
8469 +
8470 + if (!mc_restool->local_instance_in_use) {
8471 + filep->private_data = root_mc_device->mc_io;
8472 + mc_restool->local_instance_in_use = true;
8473 + } else {
8474 + dynamic_mc_io = kzalloc(sizeof(*dynamic_mc_io), GFP_KERNEL);
8475 + if (!dynamic_mc_io) {
8476 + error = -ENOMEM;
8477 + goto error_alloc_mc_io;
8478 + }
8479 +
8480 + error = fsl_mc_portal_allocate(root_mc_device, 0,
8481 + &dynamic_mc_io);
8482 + if (error) {
8483 + pr_err("Could not allocate MC portal\n");
8484 + goto error_portal_allocate;
8485 + }
8486 +
8487 + mc_restool->dynamic_instance_count++;
8488 + filep->private_data = dynamic_mc_io;
8489 + }
8490 +
8491 + mutex_unlock(&mc_restool->mutex);
8492 +
8493 + return 0;
8494 +
8495 +error_portal_allocate:
8496 + kfree(dynamic_mc_io);
8497 +
8498 +error_alloc_mc_io:
8499 + mutex_unlock(&mc_restool->mutex);
8500 +
8501 + return error;
8502 +}
8503 +
8504 +static int fsl_mc_restool_dev_release(struct inode *inode, struct file *filep)
8505 +{
8506 + struct fsl_mc_device *root_mc_device;
8507 + struct fsl_mc_restool *mc_restool;
8508 + struct fsl_mc_bus *mc_bus;
8509 + struct fsl_mc_io *mc_io;
8510 +
8511 + mc_restool = container_of(inode->i_cdev, struct fsl_mc_restool, cdev);
8512 + mc_bus = container_of(mc_restool, struct fsl_mc_bus, restool_misc);
8513 + root_mc_device = &mc_bus->mc_dev;
8514 + mc_io = filep->private_data;
8515 +
8516 + mutex_lock(&mc_restool->mutex);
8517 +
8518 + if (WARN_ON(!mc_restool->local_instance_in_use &&
8519 + mc_restool->dynamic_instance_count == 0)) {
8520 + mutex_unlock(&mc_restool->mutex);
8521 + return -EINVAL;
8522 + }
8523 +
8524 + if (filep->private_data == root_mc_device->mc_io) {
8525 + mc_restool->local_instance_in_use = false;
8526 + } else {
8527 + fsl_mc_portal_free(mc_io);
8528 + kfree(mc_io);
8529 + mc_restool->dynamic_instance_count--;
8530 + }
8531 +
8532 + filep->private_data = NULL;
8533 + mutex_unlock(&mc_restool->mutex);
8534 +
8535 + return 0;
8536 +}
8537 +
8538 +static long fsl_mc_restool_dev_ioctl(struct file *file,
8539 + unsigned int cmd,
8540 + unsigned long arg)
8541 +{
8542 + int error;
8543 +
8544 + switch (cmd) {
8545 + case RESTOOL_SEND_MC_COMMAND:
8546 + error = fsl_mc_restool_send_command(arg, file->private_data);
8547 + break;
8548 + default:
8549 + pr_err("%s: unexpected ioctl call number\n", __func__);
8550 + error = -EINVAL;
8551 + }
8552 +
8553 + return error;
8554 +}
8555 +
8556 +static const struct file_operations fsl_mc_restool_dev_fops = {
8557 + .owner = THIS_MODULE,
8558 + .open = fsl_mc_restool_dev_open,
8559 + .release = fsl_mc_restool_dev_release,
8560 + .unlocked_ioctl = fsl_mc_restool_dev_ioctl,
8561 +};
8562 +
8563 +int fsl_mc_restool_create_device_file(struct fsl_mc_bus *mc_bus)
8564 +{
8565 + struct fsl_mc_device *mc_dev = &mc_bus->mc_dev;
8566 + struct fsl_mc_restool *mc_restool = &mc_bus->restool_misc;
8567 + int error;
8568 +
8569 + mc_restool = &mc_bus->restool_misc;
8570 + mc_restool->dev = MKDEV(fsl_mc_bus_major, 0);
8571 + cdev_init(&mc_restool->cdev, &fsl_mc_restool_dev_fops);
8572 +
8573 + error = cdev_add(&mc_restool->cdev,
8574 + mc_restool->dev,
8575 + FSL_MC_BUS_MAX_MINORS);
8576 + if (error)
8577 + return error;
8578 +
8579 + mc_restool->device = device_create(fsl_mc_bus_class,
8580 + NULL,
8581 + mc_restool->dev,
8582 + NULL,
8583 + "%s",
8584 + dev_name(&mc_dev->dev));
8585 + if (IS_ERR(mc_restool->device)) {
8586 + error = PTR_ERR(mc_restool->device);
8587 + goto error_device_create;
8588 + }
8589 +
8590 + mutex_init(&mc_restool->mutex);
8591 +
8592 + return 0;
8593 +
8594 +error_device_create:
8595 + cdev_del(&mc_restool->cdev);
8596 +
8597 + return error;
8598 +}
8599 +
8600 +void fsl_mc_restool_remove_device_file(struct fsl_mc_bus *mc_bus)
8601 +{
8602 + struct fsl_mc_restool *mc_restool = &mc_bus->restool_misc;
8603 +
8604 + if (WARN_ON(mc_restool->local_instance_in_use))
8605 + return;
8606 +
8607 + if (WARN_ON(mc_restool->dynamic_instance_count != 0))
8608 + return;
8609 +
8610 + cdev_del(&mc_restool->cdev);
8611 +}
8612 --- a/drivers/staging/fsl-mc/bus/mc-io.c
8613 +++ /dev/null
8614 @@ -1,297 +0,0 @@
8615 -// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
8616 -/*
8617 - * Copyright 2013-2016 Freescale Semiconductor Inc.
8618 - *
8619 - */
8620 -
8621 -#include <linux/io.h>
8622 -#include "../include/mc.h"
8623 -
8624 -#include "fsl-mc-private.h"
8625 -#include "dpmcp.h"
8626 -#include "dpmcp-cmd.h"
8627 -
8628 -static int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io,
8629 - struct fsl_mc_device *dpmcp_dev)
8630 -{
8631 - int error;
8632 -
8633 - if (WARN_ON(!dpmcp_dev))
8634 - return -EINVAL;
8635 -
8636 - if (WARN_ON(mc_io->dpmcp_dev))
8637 - return -EINVAL;
8638 -
8639 - if (WARN_ON(dpmcp_dev->mc_io))
8640 - return -EINVAL;
8641 -
8642 - error = dpmcp_open(mc_io,
8643 - 0,
8644 - dpmcp_dev->obj_desc.id,
8645 - &dpmcp_dev->mc_handle);
8646 - if (error < 0)
8647 - return error;
8648 -
8649 - mc_io->dpmcp_dev = dpmcp_dev;
8650 - dpmcp_dev->mc_io = mc_io;
8651 - return 0;
8652 -}
8653 -
8654 -static void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io)
8655 -{
8656 - int error;
8657 - struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
8658 -
8659 - if (WARN_ON(!dpmcp_dev))
8660 - return;
8661 -
8662 - if (WARN_ON(dpmcp_dev->mc_io != mc_io))
8663 - return;
8664 -
8665 - error = dpmcp_close(mc_io,
8666 - 0,
8667 - dpmcp_dev->mc_handle);
8668 - if (error < 0) {
8669 - dev_err(&dpmcp_dev->dev, "dpmcp_close() failed: %d\n",
8670 - error);
8671 - }
8672 -
8673 - mc_io->dpmcp_dev = NULL;
8674 - dpmcp_dev->mc_io = NULL;
8675 -}
8676 -
8677 -/**
8678 - * Creates an MC I/O object
8679 - *
8680 - * @dev: device to be associated with the MC I/O object
8681 - * @mc_portal_phys_addr: physical address of the MC portal to use
8682 - * @mc_portal_size: size in bytes of the MC portal
8683 - * @dpmcp-dev: Pointer to the DPMCP object associated with this MC I/O
8684 - * object or NULL if none.
8685 - * @flags: flags for the new MC I/O object
8686 - * @new_mc_io: Area to return pointer to newly created MC I/O object
8687 - *
8688 - * Returns '0' on Success; Error code otherwise.
8689 - */
8690 -int __must_check fsl_create_mc_io(struct device *dev,
8691 - phys_addr_t mc_portal_phys_addr,
8692 - u32 mc_portal_size,
8693 - struct fsl_mc_device *dpmcp_dev,
8694 - u32 flags, struct fsl_mc_io **new_mc_io)
8695 -{
8696 - int error;
8697 - struct fsl_mc_io *mc_io;
8698 - void __iomem *mc_portal_virt_addr;
8699 - struct resource *res;
8700 -
8701 - mc_io = devm_kzalloc(dev, sizeof(*mc_io), GFP_KERNEL);
8702 - if (!mc_io)
8703 - return -ENOMEM;
8704 -
8705 - mc_io->dev = dev;
8706 - mc_io->flags = flags;
8707 - mc_io->portal_phys_addr = mc_portal_phys_addr;
8708 - mc_io->portal_size = mc_portal_size;
8709 - if (flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
8710 - spin_lock_init(&mc_io->spinlock);
8711 - else
8712 - mutex_init(&mc_io->mutex);
8713 -
8714 - res = devm_request_mem_region(dev,
8715 - mc_portal_phys_addr,
8716 - mc_portal_size,
8717 - "mc_portal");
8718 - if (!res) {
8719 - dev_err(dev,
8720 - "devm_request_mem_region failed for MC portal %pa\n",
8721 - &mc_portal_phys_addr);
8722 - return -EBUSY;
8723 - }
8724 -
8725 - mc_portal_virt_addr = devm_ioremap_nocache(dev,
8726 - mc_portal_phys_addr,
8727 - mc_portal_size);
8728 - if (!mc_portal_virt_addr) {
8729 - dev_err(dev,
8730 - "devm_ioremap_nocache failed for MC portal %pa\n",
8731 - &mc_portal_phys_addr);
8732 - return -ENXIO;
8733 - }
8734 -
8735 - mc_io->portal_virt_addr = mc_portal_virt_addr;
8736 - if (dpmcp_dev) {
8737 - error = fsl_mc_io_set_dpmcp(mc_io, dpmcp_dev);
8738 - if (error < 0)
8739 - goto error_destroy_mc_io;
8740 - }
8741 -
8742 - *new_mc_io = mc_io;
8743 - return 0;
8744 -
8745 -error_destroy_mc_io:
8746 - fsl_destroy_mc_io(mc_io);
8747 - return error;
8748 -}
8749 -
8750 -/**
8751 - * Destroys an MC I/O object
8752 - *
8753 - * @mc_io: MC I/O object to destroy
8754 - */
8755 -void fsl_destroy_mc_io(struct fsl_mc_io *mc_io)
8756 -{
8757 - struct fsl_mc_device *dpmcp_dev;
8758 -
8759 - if (!mc_io)
8760 - return;
8761 -
8762 - dpmcp_dev = mc_io->dpmcp_dev;
8763 -
8764 - if (dpmcp_dev)
8765 - fsl_mc_io_unset_dpmcp(mc_io);
8766 -
8767 - devm_iounmap(mc_io->dev, mc_io->portal_virt_addr);
8768 - devm_release_mem_region(mc_io->dev,
8769 - mc_io->portal_phys_addr,
8770 - mc_io->portal_size);
8771 -
8772 - mc_io->portal_virt_addr = NULL;
8773 - devm_kfree(mc_io->dev, mc_io);
8774 -}
8775 -
8776 -/**
8777 - * fsl_mc_portal_allocate - Allocates an MC portal
8778 - *
8779 - * @mc_dev: MC device for which the MC portal is to be allocated
8780 - * @mc_io_flags: Flags for the fsl_mc_io object that wraps the allocated
8781 - * MC portal.
8782 - * @new_mc_io: Pointer to area where the pointer to the fsl_mc_io object
8783 - * that wraps the allocated MC portal is to be returned
8784 - *
8785 - * This function allocates an MC portal from the device's parent DPRC,
8786 - * from the corresponding MC bus' pool of MC portals and wraps
8787 - * it in a new fsl_mc_io object. If 'mc_dev' is a DPRC itself, the
8788 - * portal is allocated from its own MC bus.
8789 - */
8790 -int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
8791 - u16 mc_io_flags,
8792 - struct fsl_mc_io **new_mc_io)
8793 -{
8794 - struct fsl_mc_device *mc_bus_dev;
8795 - struct fsl_mc_bus *mc_bus;
8796 - phys_addr_t mc_portal_phys_addr;
8797 - size_t mc_portal_size;
8798 - struct fsl_mc_device *dpmcp_dev;
8799 - int error = -EINVAL;
8800 - struct fsl_mc_resource *resource = NULL;
8801 - struct fsl_mc_io *mc_io = NULL;
8802 -
8803 - if (mc_dev->flags & FSL_MC_IS_DPRC) {
8804 - mc_bus_dev = mc_dev;
8805 - } else {
8806 - if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent)))
8807 - return error;
8808 -
8809 - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
8810 - }
8811 -
8812 - mc_bus = to_fsl_mc_bus(mc_bus_dev);
8813 - *new_mc_io = NULL;
8814 - error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_DPMCP, &resource);
8815 - if (error < 0)
8816 - return error;
8817 -
8818 - error = -EINVAL;
8819 - dpmcp_dev = resource->data;
8820 - if (WARN_ON(!dpmcp_dev))
8821 - goto error_cleanup_resource;
8822 -
8823 - if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR ||
8824 - (dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR &&
8825 - dpmcp_dev->obj_desc.ver_minor < DPMCP_MIN_VER_MINOR)) {
8826 - dev_err(&dpmcp_dev->dev,
8827 - "ERROR: Version %d.%d of DPMCP not supported.\n",
8828 - dpmcp_dev->obj_desc.ver_major,
8829 - dpmcp_dev->obj_desc.ver_minor);
8830 - error = -ENOTSUPP;
8831 - goto error_cleanup_resource;
8832 - }
8833 -
8834 - if (WARN_ON(dpmcp_dev->obj_desc.region_count == 0))
8835 - goto error_cleanup_resource;
8836 -
8837 - mc_portal_phys_addr = dpmcp_dev->regions[0].start;
8838 - mc_portal_size = resource_size(dpmcp_dev->regions);
8839 -
8840 - if (WARN_ON(mc_portal_size != mc_bus_dev->mc_io->portal_size))
8841 - goto error_cleanup_resource;
8842 -
8843 - error = fsl_create_mc_io(&mc_bus_dev->dev,
8844 - mc_portal_phys_addr,
8845 - mc_portal_size, dpmcp_dev,
8846 - mc_io_flags, &mc_io);
8847 - if (error < 0)
8848 - goto error_cleanup_resource;
8849 -
8850 - *new_mc_io = mc_io;
8851 - return 0;
8852 -
8853 -error_cleanup_resource:
8854 - fsl_mc_resource_free(resource);
8855 - return error;
8856 -}
8857 -EXPORT_SYMBOL_GPL(fsl_mc_portal_allocate);
8858 -
8859 -/**
8860 - * fsl_mc_portal_free - Returns an MC portal to the pool of free MC portals
8861 - * of a given MC bus
8862 - *
8863 - * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free
8864 - */
8865 -void fsl_mc_portal_free(struct fsl_mc_io *mc_io)
8866 -{
8867 - struct fsl_mc_device *dpmcp_dev;
8868 - struct fsl_mc_resource *resource;
8869 -
8870 - /*
8871 - * Every mc_io obtained by calling fsl_mc_portal_allocate() is supposed
8872 - * to have a DPMCP object associated with.
8873 - */
8874 - dpmcp_dev = mc_io->dpmcp_dev;
8875 - if (WARN_ON(!dpmcp_dev))
8876 - return;
8877 -
8878 - resource = dpmcp_dev->resource;
8879 - if (WARN_ON(!resource || resource->type != FSL_MC_POOL_DPMCP))
8880 - return;
8881 -
8882 - if (WARN_ON(resource->data != dpmcp_dev))
8883 - return;
8884 -
8885 - fsl_destroy_mc_io(mc_io);
8886 - fsl_mc_resource_free(resource);
8887 -}
8888 -EXPORT_SYMBOL_GPL(fsl_mc_portal_free);
8889 -
8890 -/**
8891 - * fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object
8892 - *
8893 - * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free
8894 - */
8895 -int fsl_mc_portal_reset(struct fsl_mc_io *mc_io)
8896 -{
8897 - int error;
8898 - struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
8899 -
8900 - if (WARN_ON(!dpmcp_dev))
8901 - return -EINVAL;
8902 -
8903 - error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle);
8904 - if (error < 0) {
8905 - dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error);
8906 - return error;
8907 - }
8908 -
8909 - return 0;
8910 -}
8911 -EXPORT_SYMBOL_GPL(fsl_mc_portal_reset);
8912 --- /dev/null
8913 +++ b/drivers/bus/fsl-mc/mc-io.c
8914 @@ -0,0 +1,281 @@
8915 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
8916 +/*
8917 + * Copyright 2013-2016 Freescale Semiconductor Inc.
8918 + *
8919 + */
8920 +
8921 +#include <linux/io.h>
8922 +#include <linux/fsl/mc.h>
8923 +
8924 +#include "fsl-mc-private.h"
8925 +
8926 +static int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io,
8927 + struct fsl_mc_device *dpmcp_dev)
8928 +{
8929 + int error;
8930 +
8931 + if (mc_io->dpmcp_dev)
8932 + return -EINVAL;
8933 +
8934 + if (dpmcp_dev->mc_io)
8935 + return -EINVAL;
8936 +
8937 + error = dpmcp_open(mc_io,
8938 + 0,
8939 + dpmcp_dev->obj_desc.id,
8940 + &dpmcp_dev->mc_handle);
8941 + if (error < 0)
8942 + return error;
8943 +
8944 + mc_io->dpmcp_dev = dpmcp_dev;
8945 + dpmcp_dev->mc_io = mc_io;
8946 + return 0;
8947 +}
8948 +
8949 +static void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io)
8950 +{
8951 + int error;
8952 + struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
8953 +
8954 + error = dpmcp_close(mc_io,
8955 + 0,
8956 + dpmcp_dev->mc_handle);
8957 + if (error < 0) {
8958 + dev_err(&dpmcp_dev->dev, "dpmcp_close() failed: %d\n",
8959 + error);
8960 + }
8961 +
8962 + mc_io->dpmcp_dev = NULL;
8963 + dpmcp_dev->mc_io = NULL;
8964 +}
8965 +
8966 +/**
8967 + * Creates an MC I/O object
8968 + *
8969 + * @dev: device to be associated with the MC I/O object
8970 + * @mc_portal_phys_addr: physical address of the MC portal to use
8971 + * @mc_portal_size: size in bytes of the MC portal
8972 + * @dpmcp-dev: Pointer to the DPMCP object associated with this MC I/O
8973 + * object or NULL if none.
8974 + * @flags: flags for the new MC I/O object
8975 + * @new_mc_io: Area to return pointer to newly created MC I/O object
8976 + *
8977 + * Returns '0' on Success; Error code otherwise.
8978 + */
8979 +int __must_check fsl_create_mc_io(struct device *dev,
8980 + phys_addr_t mc_portal_phys_addr,
8981 + u32 mc_portal_size,
8982 + struct fsl_mc_device *dpmcp_dev,
8983 + u32 flags, struct fsl_mc_io **new_mc_io)
8984 +{
8985 + int error;
8986 + struct fsl_mc_io *mc_io;
8987 + void __iomem *mc_portal_virt_addr;
8988 + struct resource *res;
8989 +
8990 + mc_io = devm_kzalloc(dev, sizeof(*mc_io), GFP_KERNEL);
8991 + if (!mc_io)
8992 + return -ENOMEM;
8993 +
8994 + mc_io->dev = dev;
8995 + mc_io->flags = flags;
8996 + mc_io->portal_phys_addr = mc_portal_phys_addr;
8997 + mc_io->portal_size = mc_portal_size;
8998 + if (flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
8999 + spin_lock_init(&mc_io->spinlock);
9000 + else
9001 + mutex_init(&mc_io->mutex);
9002 +
9003 + res = devm_request_mem_region(dev,
9004 + mc_portal_phys_addr,
9005 + mc_portal_size,
9006 + "mc_portal");
9007 + if (!res) {
9008 + dev_err(dev,
9009 + "devm_request_mem_region failed for MC portal %pa\n",
9010 + &mc_portal_phys_addr);
9011 + return -EBUSY;
9012 + }
9013 +
9014 + mc_portal_virt_addr = devm_ioremap_nocache(dev,
9015 + mc_portal_phys_addr,
9016 + mc_portal_size);
9017 + if (!mc_portal_virt_addr) {
9018 + dev_err(dev,
9019 + "devm_ioremap_nocache failed for MC portal %pa\n",
9020 + &mc_portal_phys_addr);
9021 + return -ENXIO;
9022 + }
9023 +
9024 + mc_io->portal_virt_addr = mc_portal_virt_addr;
9025 + if (dpmcp_dev) {
9026 + error = fsl_mc_io_set_dpmcp(mc_io, dpmcp_dev);
9027 + if (error < 0)
9028 + goto error_destroy_mc_io;
9029 + }
9030 +
9031 + *new_mc_io = mc_io;
9032 + return 0;
9033 +
9034 +error_destroy_mc_io:
9035 + fsl_destroy_mc_io(mc_io);
9036 + return error;
9037 +}
9038 +
9039 +/**
9040 + * Destroys an MC I/O object
9041 + *
9042 + * @mc_io: MC I/O object to destroy
9043 + */
9044 +void fsl_destroy_mc_io(struct fsl_mc_io *mc_io)
9045 +{
9046 + struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
9047 +
9048 + if (dpmcp_dev)
9049 + fsl_mc_io_unset_dpmcp(mc_io);
9050 +
9051 + devm_iounmap(mc_io->dev, mc_io->portal_virt_addr);
9052 + devm_release_mem_region(mc_io->dev,
9053 + mc_io->portal_phys_addr,
9054 + mc_io->portal_size);
9055 +
9056 + mc_io->portal_virt_addr = NULL;
9057 + devm_kfree(mc_io->dev, mc_io);
9058 +}
9059 +
9060 +/**
9061 + * fsl_mc_portal_allocate - Allocates an MC portal
9062 + *
9063 + * @mc_dev: MC device for which the MC portal is to be allocated
9064 + * @mc_io_flags: Flags for the fsl_mc_io object that wraps the allocated
9065 + * MC portal.
9066 + * @new_mc_io: Pointer to area where the pointer to the fsl_mc_io object
9067 + * that wraps the allocated MC portal is to be returned
9068 + *
9069 + * This function allocates an MC portal from the device's parent DPRC,
9070 + * from the corresponding MC bus' pool of MC portals and wraps
9071 + * it in a new fsl_mc_io object. If 'mc_dev' is a DPRC itself, the
9072 + * portal is allocated from its own MC bus.
9073 + */
9074 +int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
9075 + u16 mc_io_flags,
9076 + struct fsl_mc_io **new_mc_io)
9077 +{
9078 + struct fsl_mc_device *mc_bus_dev;
9079 + struct fsl_mc_bus *mc_bus;
9080 + phys_addr_t mc_portal_phys_addr;
9081 + size_t mc_portal_size;
9082 + struct fsl_mc_device *dpmcp_dev;
9083 + int error = -EINVAL;
9084 + struct fsl_mc_resource *resource = NULL;
9085 + struct fsl_mc_io *mc_io = NULL;
9086 +
9087 + if (fsl_mc_is_root_dprc(&mc_dev->dev)) {
9088 + mc_bus_dev = mc_dev;
9089 + } else {
9090 + if (!dev_is_fsl_mc(mc_dev->dev.parent))
9091 + return error;
9092 +
9093 + mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
9094 + }
9095 +
9096 + mc_bus = to_fsl_mc_bus(mc_bus_dev);
9097 + *new_mc_io = NULL;
9098 + error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_DPMCP, &resource);
9099 + if (error < 0)
9100 + return error;
9101 +
9102 + error = -EINVAL;
9103 + dpmcp_dev = resource->data;
9104 +
9105 + if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR ||
9106 + (dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR &&
9107 + dpmcp_dev->obj_desc.ver_minor < DPMCP_MIN_VER_MINOR)) {
9108 + dev_err(&dpmcp_dev->dev,
9109 + "ERROR: Version %d.%d of DPMCP not supported.\n",
9110 + dpmcp_dev->obj_desc.ver_major,
9111 + dpmcp_dev->obj_desc.ver_minor);
9112 + error = -ENOTSUPP;
9113 + goto error_cleanup_resource;
9114 + }
9115 +
9116 + mc_portal_phys_addr = dpmcp_dev->regions[0].start;
9117 + mc_portal_size = resource_size(dpmcp_dev->regions);
9118 +
9119 + error = fsl_create_mc_io(&mc_bus_dev->dev,
9120 + mc_portal_phys_addr,
9121 + mc_portal_size, dpmcp_dev,
9122 + mc_io_flags, &mc_io);
9123 + if (error < 0)
9124 + goto error_cleanup_resource;
9125 +
9126 + dpmcp_dev->consumer_link = device_link_add(&mc_dev->dev,
9127 + &dpmcp_dev->dev,
9128 + DL_FLAG_AUTOREMOVE_CONSUMER);
9129 + if (!dpmcp_dev->consumer_link) {
9130 + error = -EINVAL;
9131 + goto error_cleanup_mc_io;
9132 + }
9133 +
9134 + *new_mc_io = mc_io;
9135 + return 0;
9136 +
9137 +error_cleanup_mc_io:
9138 + fsl_destroy_mc_io(mc_io);
9139 +error_cleanup_resource:
9140 + fsl_mc_resource_free(resource);
9141 + return error;
9142 +}
9143 +EXPORT_SYMBOL_GPL(fsl_mc_portal_allocate);
9144 +
9145 +/**
9146 + * fsl_mc_portal_free - Returns an MC portal to the pool of free MC portals
9147 + * of a given MC bus
9148 + *
9149 + * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free
9150 + */
9151 +void fsl_mc_portal_free(struct fsl_mc_io *mc_io)
9152 +{
9153 + struct fsl_mc_device *dpmcp_dev;
9154 + struct fsl_mc_resource *resource;
9155 +
9156 + /*
9157 + * Every mc_io obtained by calling fsl_mc_portal_allocate() is supposed
9158 + * to have a DPMCP object associated with.
9159 + */
9160 + dpmcp_dev = mc_io->dpmcp_dev;
9161 +
9162 + resource = dpmcp_dev->resource;
9163 + if (!resource || resource->type != FSL_MC_POOL_DPMCP)
9164 + return;
9165 +
9166 + if (resource->data != dpmcp_dev)
9167 + return;
9168 +
9169 + fsl_destroy_mc_io(mc_io);
9170 + fsl_mc_resource_free(resource);
9171 +
9172 + device_link_del(dpmcp_dev->consumer_link);
9173 + dpmcp_dev->consumer_link = NULL;
9174 +}
9175 +EXPORT_SYMBOL_GPL(fsl_mc_portal_free);
9176 +
9177 +/**
9178 + * fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object
9179 + *
9180 + * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free
9181 + */
9182 +int fsl_mc_portal_reset(struct fsl_mc_io *mc_io)
9183 +{
9184 + int error;
9185 + struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
9186 +
9187 + error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle);
9188 + if (error < 0) {
9189 + dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error);
9190 + return error;
9191 + }
9192 +
9193 + return 0;
9194 +}
9195 +EXPORT_SYMBOL_GPL(fsl_mc_portal_reset);
9196 --- a/drivers/staging/fsl-mc/bus/mc-sys.c
9197 +++ /dev/null
9198 @@ -1,297 +0,0 @@
9199 -// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
9200 -/*
9201 - * Copyright 2013-2016 Freescale Semiconductor Inc.
9202 - *
9203 - * I/O services to send MC commands to the MC hardware
9204 - *
9205 - */
9206 -
9207 -#include <linux/delay.h>
9208 -#include <linux/slab.h>
9209 -#include <linux/ioport.h>
9210 -#include <linux/device.h>
9211 -#include <linux/io.h>
9212 -#include <linux/io-64-nonatomic-hi-lo.h>
9213 -#include "../include/mc.h"
9214 -
9215 -#include "dpmcp.h"
9216 -
9217 -/**
9218 - * Timeout in milliseconds to wait for the completion of an MC command
9219 - */
9220 -#define MC_CMD_COMPLETION_TIMEOUT_MS 500
9221 -
9222 -/*
9223 - * usleep_range() min and max values used to throttle down polling
9224 - * iterations while waiting for MC command completion
9225 - */
9226 -#define MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS 10
9227 -#define MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS 500
9228 -
9229 -static enum mc_cmd_status mc_cmd_hdr_read_status(struct mc_command *cmd)
9230 -{
9231 - struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
9232 -
9233 - return (enum mc_cmd_status)hdr->status;
9234 -}
9235 -
9236 -static u16 mc_cmd_hdr_read_cmdid(struct mc_command *cmd)
9237 -{
9238 - struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
9239 - u16 cmd_id = le16_to_cpu(hdr->cmd_id);
9240 -
9241 - return cmd_id;
9242 -}
9243 -
9244 -static int mc_status_to_error(enum mc_cmd_status status)
9245 -{
9246 - static const int mc_status_to_error_map[] = {
9247 - [MC_CMD_STATUS_OK] = 0,
9248 - [MC_CMD_STATUS_AUTH_ERR] = -EACCES,
9249 - [MC_CMD_STATUS_NO_PRIVILEGE] = -EPERM,
9250 - [MC_CMD_STATUS_DMA_ERR] = -EIO,
9251 - [MC_CMD_STATUS_CONFIG_ERR] = -ENXIO,
9252 - [MC_CMD_STATUS_TIMEOUT] = -ETIMEDOUT,
9253 - [MC_CMD_STATUS_NO_RESOURCE] = -ENAVAIL,
9254 - [MC_CMD_STATUS_NO_MEMORY] = -ENOMEM,
9255 - [MC_CMD_STATUS_BUSY] = -EBUSY,
9256 - [MC_CMD_STATUS_UNSUPPORTED_OP] = -ENOTSUPP,
9257 - [MC_CMD_STATUS_INVALID_STATE] = -ENODEV,
9258 - };
9259 -
9260 - if (WARN_ON((u32)status >= ARRAY_SIZE(mc_status_to_error_map)))
9261 - return -EINVAL;
9262 -
9263 - return mc_status_to_error_map[status];
9264 -}
9265 -
9266 -static const char *mc_status_to_string(enum mc_cmd_status status)
9267 -{
9268 - static const char *const status_strings[] = {
9269 - [MC_CMD_STATUS_OK] = "Command completed successfully",
9270 - [MC_CMD_STATUS_READY] = "Command ready to be processed",
9271 - [MC_CMD_STATUS_AUTH_ERR] = "Authentication error",
9272 - [MC_CMD_STATUS_NO_PRIVILEGE] = "No privilege",
9273 - [MC_CMD_STATUS_DMA_ERR] = "DMA or I/O error",
9274 - [MC_CMD_STATUS_CONFIG_ERR] = "Configuration error",
9275 - [MC_CMD_STATUS_TIMEOUT] = "Operation timed out",
9276 - [MC_CMD_STATUS_NO_RESOURCE] = "No resources",
9277 - [MC_CMD_STATUS_NO_MEMORY] = "No memory available",
9278 - [MC_CMD_STATUS_BUSY] = "Device is busy",
9279 - [MC_CMD_STATUS_UNSUPPORTED_OP] = "Unsupported operation",
9280 - [MC_CMD_STATUS_INVALID_STATE] = "Invalid state"
9281 - };
9282 -
9283 - if ((unsigned int)status >= ARRAY_SIZE(status_strings))
9284 - return "Unknown MC error";
9285 -
9286 - return status_strings[status];
9287 -}
9288 -
9289 -/**
9290 - * mc_write_command - writes a command to a Management Complex (MC) portal
9291 - *
9292 - * @portal: pointer to an MC portal
9293 - * @cmd: pointer to a filled command
9294 - */
9295 -static inline void mc_write_command(struct mc_command __iomem *portal,
9296 - struct mc_command *cmd)
9297 -{
9298 - int i;
9299 -
9300 - /* copy command parameters into the portal */
9301 - for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++)
9302 - /*
9303 - * Data is already in the expected LE byte-order. Do an
9304 - * extra LE -> CPU conversion so that the CPU -> LE done in
9305 - * the device io write api puts it back in the right order.
9306 - */
9307 - writeq_relaxed(le64_to_cpu(cmd->params[i]), &portal->params[i]);
9308 -
9309 - /* submit the command by writing the header */
9310 - writeq(le64_to_cpu(cmd->header), &portal->header);
9311 -}
9312 -
9313 -/**
9314 - * mc_read_response - reads the response for the last MC command from a
9315 - * Management Complex (MC) portal
9316 - *
9317 - * @portal: pointer to an MC portal
9318 - * @resp: pointer to command response buffer
9319 - *
9320 - * Returns MC_CMD_STATUS_OK on Success; Error code otherwise.
9321 - */
9322 -static inline enum mc_cmd_status mc_read_response(struct mc_command __iomem *
9323 - portal,
9324 - struct mc_command *resp)
9325 -{
9326 - int i;
9327 - enum mc_cmd_status status;
9328 -
9329 - /* Copy command response header from MC portal: */
9330 - resp->header = cpu_to_le64(readq_relaxed(&portal->header));
9331 - status = mc_cmd_hdr_read_status(resp);
9332 - if (status != MC_CMD_STATUS_OK)
9333 - return status;
9334 -
9335 - /* Copy command response data from MC portal: */
9336 - for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++)
9337 - /*
9338 - * Data is expected to be in LE byte-order. Do an
9339 - * extra CPU -> LE to revert the LE -> CPU done in
9340 - * the device io read api.
9341 - */
9342 - resp->params[i] =
9343 - cpu_to_le64(readq_relaxed(&portal->params[i]));
9344 -
9345 - return status;
9346 -}
9347 -
9348 -/**
9349 - * Waits for the completion of an MC command doing preemptible polling.
9350 - * uslepp_range() is called between polling iterations.
9351 - *
9352 - * @mc_io: MC I/O object to be used
9353 - * @cmd: command buffer to receive MC response
9354 - * @mc_status: MC command completion status
9355 - */
9356 -static int mc_polling_wait_preemptible(struct fsl_mc_io *mc_io,
9357 - struct mc_command *cmd,
9358 - enum mc_cmd_status *mc_status)
9359 -{
9360 - enum mc_cmd_status status;
9361 - unsigned long jiffies_until_timeout =
9362 - jiffies + msecs_to_jiffies(MC_CMD_COMPLETION_TIMEOUT_MS);
9363 -
9364 - /*
9365 - * Wait for response from the MC hardware:
9366 - */
9367 - for (;;) {
9368 - status = mc_read_response(mc_io->portal_virt_addr, cmd);
9369 - if (status != MC_CMD_STATUS_READY)
9370 - break;
9371 -
9372 - /*
9373 - * TODO: When MC command completion interrupts are supported
9374 - * call wait function here instead of usleep_range()
9375 - */
9376 - usleep_range(MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS,
9377 - MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
9378 -
9379 - if (time_after_eq(jiffies, jiffies_until_timeout)) {
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 - * Waits for the completion of an MC command doing atomic polling.
9396 - * udelay() is called between polling iterations.
9397 - *
9398 - * @mc_io: MC I/O object to be used
9399 - * @cmd: command buffer to receive MC response
9400 - * @mc_status: MC command completion status
9401 - */
9402 -static int mc_polling_wait_atomic(struct fsl_mc_io *mc_io,
9403 - struct mc_command *cmd,
9404 - enum mc_cmd_status *mc_status)
9405 -{
9406 - enum mc_cmd_status status;
9407 - unsigned long timeout_usecs = MC_CMD_COMPLETION_TIMEOUT_MS * 1000;
9408 -
9409 - BUILD_BUG_ON((MC_CMD_COMPLETION_TIMEOUT_MS * 1000) %
9410 - MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS != 0);
9411 -
9412 - for (;;) {
9413 - status = mc_read_response(mc_io->portal_virt_addr, cmd);
9414 - if (status != MC_CMD_STATUS_READY)
9415 - break;
9416 -
9417 - udelay(MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
9418 - timeout_usecs -= MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS;
9419 - if (timeout_usecs == 0) {
9420 - dev_dbg(mc_io->dev,
9421 - "MC command timed out (portal: %pa, dprc handle: %#x, command: %#x)\n",
9422 - &mc_io->portal_phys_addr,
9423 - (unsigned int)mc_cmd_hdr_read_token(cmd),
9424 - (unsigned int)mc_cmd_hdr_read_cmdid(cmd));
9425 -
9426 - return -ETIMEDOUT;
9427 - }
9428 - }
9429 -
9430 - *mc_status = status;
9431 - return 0;
9432 -}
9433 -
9434 -/**
9435 - * Sends a command to the MC device using the given MC I/O object
9436 - *
9437 - * @mc_io: MC I/O object to be used
9438 - * @cmd: command to be sent
9439 - *
9440 - * Returns '0' on Success; Error code otherwise.
9441 - */
9442 -int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd)
9443 -{
9444 - int error;
9445 - enum mc_cmd_status status;
9446 - unsigned long irq_flags = 0;
9447 -
9448 - if (WARN_ON(in_irq() &&
9449 - !(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)))
9450 - return -EINVAL;
9451 -
9452 - if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
9453 - spin_lock_irqsave(&mc_io->spinlock, irq_flags);
9454 - else
9455 - mutex_lock(&mc_io->mutex);
9456 -
9457 - /*
9458 - * Send command to the MC hardware:
9459 - */
9460 - mc_write_command(mc_io->portal_virt_addr, cmd);
9461 -
9462 - /*
9463 - * Wait for response from the MC hardware:
9464 - */
9465 - if (!(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL))
9466 - error = mc_polling_wait_preemptible(mc_io, cmd, &status);
9467 - else
9468 - error = mc_polling_wait_atomic(mc_io, cmd, &status);
9469 -
9470 - if (error < 0)
9471 - goto common_exit;
9472 -
9473 - if (status != MC_CMD_STATUS_OK) {
9474 - dev_dbg(mc_io->dev,
9475 - "MC command failed: portal: %pa, dprc handle: %#x, command: %#x, status: %s (%#x)\n",
9476 - &mc_io->portal_phys_addr,
9477 - (unsigned int)mc_cmd_hdr_read_token(cmd),
9478 - (unsigned int)mc_cmd_hdr_read_cmdid(cmd),
9479 - mc_status_to_string(status),
9480 - (unsigned int)status);
9481 -
9482 - error = mc_status_to_error(status);
9483 - goto common_exit;
9484 - }
9485 -
9486 - error = 0;
9487 -common_exit:
9488 - if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
9489 - spin_unlock_irqrestore(&mc_io->spinlock, irq_flags);
9490 - else
9491 - mutex_unlock(&mc_io->mutex);
9492 -
9493 - return error;
9494 -}
9495 -EXPORT_SYMBOL(mc_send_command);
9496 --- /dev/null
9497 +++ b/drivers/bus/fsl-mc/mc-sys.c
9498 @@ -0,0 +1,296 @@
9499 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
9500 +/*
9501 + * Copyright 2013-2016 Freescale Semiconductor Inc.
9502 + *
9503 + * I/O services to send MC commands to the MC hardware
9504 + *
9505 + */
9506 +
9507 +#include <linux/delay.h>
9508 +#include <linux/slab.h>
9509 +#include <linux/ioport.h>
9510 +#include <linux/device.h>
9511 +#include <linux/io.h>
9512 +#include <linux/io-64-nonatomic-hi-lo.h>
9513 +#include <linux/fsl/mc.h>
9514 +
9515 +#include "fsl-mc-private.h"
9516 +
9517 +/**
9518 + * Timeout in milliseconds to wait for the completion of an MC command
9519 + */
9520 +#define MC_CMD_COMPLETION_TIMEOUT_MS 15000
9521 +
9522 +/*
9523 + * usleep_range() min and max values used to throttle down polling
9524 + * iterations while waiting for MC command completion
9525 + */
9526 +#define MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS 10
9527 +#define MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS 500
9528 +
9529 +static enum mc_cmd_status mc_cmd_hdr_read_status(struct fsl_mc_command *cmd)
9530 +{
9531 + struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
9532 +
9533 + return (enum mc_cmd_status)hdr->status;
9534 +}
9535 +
9536 +static u16 mc_cmd_hdr_read_cmdid(struct fsl_mc_command *cmd)
9537 +{
9538 + struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
9539 + u16 cmd_id = le16_to_cpu(hdr->cmd_id);
9540 +
9541 + return cmd_id;
9542 +}
9543 +
9544 +static int mc_status_to_error(enum mc_cmd_status status)
9545 +{
9546 + static const int mc_status_to_error_map[] = {
9547 + [MC_CMD_STATUS_OK] = 0,
9548 + [MC_CMD_STATUS_AUTH_ERR] = -EACCES,
9549 + [MC_CMD_STATUS_NO_PRIVILEGE] = -EPERM,
9550 + [MC_CMD_STATUS_DMA_ERR] = -EIO,
9551 + [MC_CMD_STATUS_CONFIG_ERR] = -ENXIO,
9552 + [MC_CMD_STATUS_TIMEOUT] = -ETIMEDOUT,
9553 + [MC_CMD_STATUS_NO_RESOURCE] = -ENAVAIL,
9554 + [MC_CMD_STATUS_NO_MEMORY] = -ENOMEM,
9555 + [MC_CMD_STATUS_BUSY] = -EBUSY,
9556 + [MC_CMD_STATUS_UNSUPPORTED_OP] = -ENOTSUPP,
9557 + [MC_CMD_STATUS_INVALID_STATE] = -ENODEV,
9558 + };
9559 +
9560 + if ((u32)status >= ARRAY_SIZE(mc_status_to_error_map))
9561 + return -EINVAL;
9562 +
9563 + return mc_status_to_error_map[status];
9564 +}
9565 +
9566 +static const char *mc_status_to_string(enum mc_cmd_status status)
9567 +{
9568 + static const char *const status_strings[] = {
9569 + [MC_CMD_STATUS_OK] = "Command completed successfully",
9570 + [MC_CMD_STATUS_READY] = "Command ready to be processed",
9571 + [MC_CMD_STATUS_AUTH_ERR] = "Authentication error",
9572 + [MC_CMD_STATUS_NO_PRIVILEGE] = "No privilege",
9573 + [MC_CMD_STATUS_DMA_ERR] = "DMA or I/O error",
9574 + [MC_CMD_STATUS_CONFIG_ERR] = "Configuration error",
9575 + [MC_CMD_STATUS_TIMEOUT] = "Operation timed out",
9576 + [MC_CMD_STATUS_NO_RESOURCE] = "No resources",
9577 + [MC_CMD_STATUS_NO_MEMORY] = "No memory available",
9578 + [MC_CMD_STATUS_BUSY] = "Device is busy",
9579 + [MC_CMD_STATUS_UNSUPPORTED_OP] = "Unsupported operation",
9580 + [MC_CMD_STATUS_INVALID_STATE] = "Invalid state"
9581 + };
9582 +
9583 + if ((unsigned int)status >= ARRAY_SIZE(status_strings))
9584 + return "Unknown MC error";
9585 +
9586 + return status_strings[status];
9587 +}
9588 +
9589 +/**
9590 + * mc_write_command - writes a command to a Management Complex (MC) portal
9591 + *
9592 + * @portal: pointer to an MC portal
9593 + * @cmd: pointer to a filled command
9594 + */
9595 +static inline void mc_write_command(struct fsl_mc_command __iomem *portal,
9596 + struct fsl_mc_command *cmd)
9597 +{
9598 + int i;
9599 +
9600 + /* copy command parameters into the portal */
9601 + for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++)
9602 + /*
9603 + * Data is already in the expected LE byte-order. Do an
9604 + * extra LE -> CPU conversion so that the CPU -> LE done in
9605 + * the device io write api puts it back in the right order.
9606 + */
9607 + writeq_relaxed(le64_to_cpu(cmd->params[i]), &portal->params[i]);
9608 +
9609 + /* submit the command by writing the header */
9610 + writeq(le64_to_cpu(cmd->header), &portal->header);
9611 +}
9612 +
9613 +/**
9614 + * mc_read_response - reads the response for the last MC command from a
9615 + * Management Complex (MC) portal
9616 + *
9617 + * @portal: pointer to an MC portal
9618 + * @resp: pointer to command response buffer
9619 + *
9620 + * Returns MC_CMD_STATUS_OK on Success; Error code otherwise.
9621 + */
9622 +static inline enum mc_cmd_status mc_read_response(struct fsl_mc_command __iomem
9623 + *portal,
9624 + struct fsl_mc_command *resp)
9625 +{
9626 + int i;
9627 + enum mc_cmd_status status;
9628 +
9629 + /* Copy command response header from MC portal: */
9630 + resp->header = cpu_to_le64(readq_relaxed(&portal->header));
9631 + status = mc_cmd_hdr_read_status(resp);
9632 + if (status != MC_CMD_STATUS_OK)
9633 + return status;
9634 +
9635 + /* Copy command response data from MC portal: */
9636 + for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++)
9637 + /*
9638 + * Data is expected to be in LE byte-order. Do an
9639 + * extra CPU -> LE to revert the LE -> CPU done in
9640 + * the device io read api.
9641 + */
9642 + resp->params[i] =
9643 + cpu_to_le64(readq_relaxed(&portal->params[i]));
9644 +
9645 + return status;
9646 +}
9647 +
9648 +/**
9649 + * Waits for the completion of an MC command doing preemptible polling.
9650 + * uslepp_range() is called between polling iterations.
9651 + *
9652 + * @mc_io: MC I/O object to be used
9653 + * @cmd: command buffer to receive MC response
9654 + * @mc_status: MC command completion status
9655 + */
9656 +static int mc_polling_wait_preemptible(struct fsl_mc_io *mc_io,
9657 + struct fsl_mc_command *cmd,
9658 + enum mc_cmd_status *mc_status)
9659 +{
9660 + enum mc_cmd_status status;
9661 + unsigned long jiffies_until_timeout =
9662 + jiffies + msecs_to_jiffies(MC_CMD_COMPLETION_TIMEOUT_MS);
9663 +
9664 + /*
9665 + * Wait for response from the MC hardware:
9666 + */
9667 + for (;;) {
9668 + status = mc_read_response(mc_io->portal_virt_addr, cmd);
9669 + if (status != MC_CMD_STATUS_READY)
9670 + break;
9671 +
9672 + /*
9673 + * TODO: When MC command completion interrupts are supported
9674 + * call wait function here instead of usleep_range()
9675 + */
9676 + usleep_range(MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS,
9677 + MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
9678 +
9679 + if (time_after_eq(jiffies, jiffies_until_timeout)) {
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 + * Waits for the completion of an MC command doing atomic polling.
9696 + * udelay() is called between polling iterations.
9697 + *
9698 + * @mc_io: MC I/O object to be used
9699 + * @cmd: command buffer to receive MC response
9700 + * @mc_status: MC command completion status
9701 + */
9702 +static int mc_polling_wait_atomic(struct fsl_mc_io *mc_io,
9703 + struct fsl_mc_command *cmd,
9704 + enum mc_cmd_status *mc_status)
9705 +{
9706 + enum mc_cmd_status status;
9707 + unsigned long timeout_usecs = MC_CMD_COMPLETION_TIMEOUT_MS * 1000;
9708 +
9709 + BUILD_BUG_ON((MC_CMD_COMPLETION_TIMEOUT_MS * 1000) %
9710 + MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS != 0);
9711 +
9712 + for (;;) {
9713 + status = mc_read_response(mc_io->portal_virt_addr, cmd);
9714 + if (status != MC_CMD_STATUS_READY)
9715 + break;
9716 +
9717 + udelay(MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
9718 + timeout_usecs -= MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS;
9719 + if (timeout_usecs == 0) {
9720 + dev_dbg(mc_io->dev,
9721 + "MC command timed out (portal: %pa, dprc handle: %#x, command: %#x)\n",
9722 + &mc_io->portal_phys_addr,
9723 + (unsigned int)mc_cmd_hdr_read_token(cmd),
9724 + (unsigned int)mc_cmd_hdr_read_cmdid(cmd));
9725 +
9726 + return -ETIMEDOUT;
9727 + }
9728 + }
9729 +
9730 + *mc_status = status;
9731 + return 0;
9732 +}
9733 +
9734 +/**
9735 + * Sends a command to the MC device using the given MC I/O object
9736 + *
9737 + * @mc_io: MC I/O object to be used
9738 + * @cmd: command to be sent
9739 + *
9740 + * Returns '0' on Success; Error code otherwise.
9741 + */
9742 +int mc_send_command(struct fsl_mc_io *mc_io, struct fsl_mc_command *cmd)
9743 +{
9744 + int error;
9745 + enum mc_cmd_status status;
9746 + unsigned long irq_flags = 0;
9747 +
9748 + if (in_irq() && !(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL))
9749 + return -EINVAL;
9750 +
9751 + if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
9752 + spin_lock_irqsave(&mc_io->spinlock, irq_flags);
9753 + else
9754 + mutex_lock(&mc_io->mutex);
9755 +
9756 + /*
9757 + * Send command to the MC hardware:
9758 + */
9759 + mc_write_command(mc_io->portal_virt_addr, cmd);
9760 +
9761 + /*
9762 + * Wait for response from the MC hardware:
9763 + */
9764 + if (!(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL))
9765 + error = mc_polling_wait_preemptible(mc_io, cmd, &status);
9766 + else
9767 + error = mc_polling_wait_atomic(mc_io, cmd, &status);
9768 +
9769 + if (error < 0)
9770 + goto common_exit;
9771 +
9772 + if (status != MC_CMD_STATUS_OK) {
9773 + dev_dbg(mc_io->dev,
9774 + "MC command failed: portal: %pa, dprc handle: %#x, command: %#x, status: %s (%#x)\n",
9775 + &mc_io->portal_phys_addr,
9776 + (unsigned int)mc_cmd_hdr_read_token(cmd),
9777 + (unsigned int)mc_cmd_hdr_read_cmdid(cmd),
9778 + mc_status_to_string(status),
9779 + (unsigned int)status);
9780 +
9781 + error = mc_status_to_error(status);
9782 + goto common_exit;
9783 + }
9784 +
9785 + error = 0;
9786 +common_exit:
9787 + if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
9788 + spin_unlock_irqrestore(&mc_io->spinlock, irq_flags);
9789 + else
9790 + mutex_unlock(&mc_io->mutex);
9791 +
9792 + return error;
9793 +}
9794 +EXPORT_SYMBOL_GPL(mc_send_command);
9795 --- a/drivers/irqchip/Kconfig
9796 +++ b/drivers/irqchip/Kconfig
9797 @@ -42,6 +42,12 @@ config ARM_GIC_V3_ITS
9798 depends on PCI
9799 depends on PCI_MSI
9800
9801 +config ARM_GIC_V3_ITS_FSL_MC
9802 + bool
9803 + depends on ARM_GIC_V3_ITS
9804 + depends on FSL_MC_BUS
9805 + default ARM_GIC_V3_ITS
9806 +
9807 config ARM_NVIC
9808 bool
9809 select IRQ_DOMAIN
9810 --- a/drivers/irqchip/Makefile
9811 +++ b/drivers/irqchip/Makefile
9812 @@ -30,6 +30,7 @@ obj-$(CONFIG_ARCH_REALVIEW) += irq-gic-
9813 obj-$(CONFIG_ARM_GIC_V2M) += irq-gic-v2m.o
9814 obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-common.o
9815 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
9816 +obj-$(CONFIG_ARM_GIC_V3_ITS_FSL_MC) += irq-gic-v3-its-fsl-mc-msi.o
9817 obj-$(CONFIG_PARTITION_PERCPU) += irq-partition-percpu.o
9818 obj-$(CONFIG_HISILICON_IRQ_MBIGEN) += irq-mbigen.o
9819 obj-$(CONFIG_ARM_NVIC) += irq-nvic.o
9820 --- /dev/null
9821 +++ b/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c
9822 @@ -0,0 +1,98 @@
9823 +// SPDX-License-Identifier: GPL-2.0
9824 +/*
9825 + * Freescale Management Complex (MC) bus driver MSI support
9826 + *
9827 + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
9828 + * Author: German Rivera <German.Rivera@freescale.com>
9829 + *
9830 + */
9831 +
9832 +#include <linux/of_device.h>
9833 +#include <linux/of_address.h>
9834 +#include <linux/irq.h>
9835 +#include <linux/msi.h>
9836 +#include <linux/of.h>
9837 +#include <linux/of_irq.h>
9838 +#include <linux/fsl/mc.h>
9839 +
9840 +static struct irq_chip its_msi_irq_chip = {
9841 + .name = "ITS-fMSI",
9842 + .irq_mask = irq_chip_mask_parent,
9843 + .irq_unmask = irq_chip_unmask_parent,
9844 + .irq_eoi = irq_chip_eoi_parent,
9845 + .irq_set_affinity = msi_domain_set_affinity
9846 +};
9847 +
9848 +static int its_fsl_mc_msi_prepare(struct irq_domain *msi_domain,
9849 + struct device *dev,
9850 + int nvec, msi_alloc_info_t *info)
9851 +{
9852 + struct fsl_mc_device *mc_bus_dev;
9853 + struct msi_domain_info *msi_info;
9854 +
9855 + if (!dev_is_fsl_mc(dev))
9856 + return -EINVAL;
9857 +
9858 + mc_bus_dev = to_fsl_mc_device(dev);
9859 + if (!(mc_bus_dev->flags & FSL_MC_IS_DPRC))
9860 + return -EINVAL;
9861 +
9862 + /*
9863 + * Set the device Id to be passed to the GIC-ITS:
9864 + *
9865 + * NOTE: This device id corresponds to the IOMMU stream ID
9866 + * associated with the DPRC object (ICID).
9867 + */
9868 + info->scratchpad[0].ul = mc_bus_dev->icid;
9869 + msi_info = msi_get_domain_info(msi_domain->parent);
9870 + return msi_info->ops->msi_prepare(msi_domain->parent, dev, nvec, info);
9871 +}
9872 +
9873 +static struct msi_domain_ops its_fsl_mc_msi_ops __ro_after_init = {
9874 + .msi_prepare = its_fsl_mc_msi_prepare,
9875 +};
9876 +
9877 +static struct msi_domain_info its_fsl_mc_msi_domain_info = {
9878 + .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS),
9879 + .ops = &its_fsl_mc_msi_ops,
9880 + .chip = &its_msi_irq_chip,
9881 +};
9882 +
9883 +static const struct of_device_id its_device_id[] = {
9884 + { .compatible = "arm,gic-v3-its", },
9885 + {},
9886 +};
9887 +
9888 +static int __init its_fsl_mc_msi_init(void)
9889 +{
9890 + struct device_node *np;
9891 + struct irq_domain *parent;
9892 + struct irq_domain *mc_msi_domain;
9893 +
9894 + for (np = of_find_matching_node(NULL, its_device_id); np;
9895 + np = of_find_matching_node(np, its_device_id)) {
9896 + if (!of_property_read_bool(np, "msi-controller"))
9897 + continue;
9898 +
9899 + parent = irq_find_matching_host(np, DOMAIN_BUS_NEXUS);
9900 + if (!parent || !msi_get_domain_info(parent)) {
9901 + pr_err("%pOF: unable to locate ITS domain\n", np);
9902 + continue;
9903 + }
9904 +
9905 + mc_msi_domain = fsl_mc_msi_create_irq_domain(
9906 + of_node_to_fwnode(np),
9907 + &its_fsl_mc_msi_domain_info,
9908 + parent);
9909 + if (!mc_msi_domain) {
9910 + pr_err("%pOF: unable to create fsl-mc domain\n", np);
9911 + continue;
9912 + }
9913 +
9914 + pr_info("fsl-mc MSI: %pOF domain created\n", np);
9915 + }
9916 +
9917 + return 0;
9918 +}
9919 +
9920 +early_initcall(its_fsl_mc_msi_init);
9921 --- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
9922 +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
9923 @@ -16,7 +16,7 @@
9924 #include <linux/filter.h>
9925 #include <linux/atomic.h>
9926 #include <net/sock.h>
9927 -#include "../../fsl-mc/include/mc.h"
9928 +#include <linux/fsl/mc.h>
9929 #include "dpaa2-eth.h"
9930 #include "dpaa2-eth-ceetm.h"
9931
9932 --- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
9933 +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
9934 @@ -9,12 +9,11 @@
9935 #include <linux/dcbnl.h>
9936 #include <linux/netdevice.h>
9937 #include <linux/if_vlan.h>
9938 +#include <linux/fsl/mc.h>
9939 #include <linux/filter.h>
9940
9941 #include "../../fsl-mc/include/dpaa2-io.h"
9942 #include "../../fsl-mc/include/dpaa2-fd.h"
9943 -#include "../../fsl-mc/include/dpbp.h"
9944 -#include "../../fsl-mc/include/dpcon.h"
9945 #include "dpni.h"
9946 #include "dpni-cmd.h"
9947
9948 --- a/drivers/staging/fsl-dpaa2/ethernet/dpni.c
9949 +++ b/drivers/staging/fsl-dpaa2/ethernet/dpni.c
9950 @@ -4,7 +4,7 @@
9951 */
9952 #include <linux/kernel.h>
9953 #include <linux/errno.h>
9954 -#include "../../fsl-mc/include/mc.h"
9955 +#include <linux/fsl/mc.h>
9956 #include "dpni.h"
9957 #include "dpni-cmd.h"
9958
9959 --- a/drivers/staging/fsl-mc/bus/Kconfig
9960 +++ b/drivers/staging/fsl-mc/bus/Kconfig
9961 @@ -5,15 +5,6 @@
9962 # Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
9963 #
9964
9965 -config FSL_MC_BUS
9966 - bool "QorIQ DPAA2 fsl-mc bus driver"
9967 - depends on OF && (ARCH_LAYERSCAPE || (COMPILE_TEST && (ARM || ARM64 || X86_LOCAL_APIC || PPC)))
9968 - select GENERIC_MSI_IRQ_DOMAIN
9969 - help
9970 - Driver to enable the bus infrastructure for the QorIQ DPAA2
9971 - architecture. The fsl-mc bus driver handles discovery of
9972 - DPAA2 objects (which are represented as Linux devices) and
9973 - binding objects to drivers.
9974
9975 config FSL_MC_DPIO
9976 tristate "QorIQ DPAA2 DPIO driver"
9977 @@ -24,3 +15,9 @@ config FSL_MC_DPIO
9978 other DPAA2 objects. This driver does not expose the DPIO
9979 objects individually, but groups them under a service layer
9980 API.
9981 +
9982 +config FSL_QBMAN_DEBUG
9983 + tristate "Freescale QBMAN Debug APIs"
9984 + depends on FSL_MC_DPIO
9985 + help
9986 + QBMan debug assistant APIs.
9987 --- a/drivers/staging/fsl-mc/bus/Makefile
9988 +++ b/drivers/staging/fsl-mc/bus/Makefile
9989 @@ -4,19 +4,6 @@
9990 #
9991 # Copyright (C) 2014 Freescale Semiconductor, Inc.
9992 #
9993 -obj-$(CONFIG_FSL_MC_BUS) += mc-bus-driver.o
9994 -
9995 -mc-bus-driver-objs := fsl-mc-bus.o \
9996 - mc-sys.o \
9997 - mc-io.o \
9998 - dprc.o \
9999 - dprc-driver.o \
10000 - fsl-mc-allocator.o \
10001 - fsl-mc-msi.o \
10002 - irq-gic-v3-its-fsl-mc-msi.o \
10003 - dpmcp.o \
10004 - dpbp.o \
10005 - dpcon.o
10006
10007 # MC DPIO driver
10008 obj-$(CONFIG_FSL_MC_DPIO) += dpio/
10009 --- a/drivers/staging/fsl-mc/bus/dpio/dpio-driver.c
10010 +++ b/drivers/staging/fsl-mc/bus/dpio/dpio-driver.c
10011 @@ -15,7 +15,7 @@
10012 #include <linux/delay.h>
10013 #include <linux/io.h>
10014
10015 -#include "../../include/mc.h"
10016 +#include <linux/fsl/mc.h>
10017 #include "../../include/dpaa2-io.h"
10018
10019 #include "qbman-portal.h"
10020 --- a/drivers/staging/fsl-mc/bus/dpio/dpio-service.c
10021 +++ b/drivers/staging/fsl-mc/bus/dpio/dpio-service.c
10022 @@ -5,7 +5,7 @@
10023 *
10024 */
10025 #include <linux/types.h>
10026 -#include "../../include/mc.h"
10027 +#include <linux/fsl/mc.h>
10028 #include "../../include/dpaa2-io.h"
10029 #include <linux/init.h>
10030 #include <linux/module.h>
10031 --- a/drivers/staging/fsl-mc/bus/dpio/dpio.c
10032 +++ b/drivers/staging/fsl-mc/bus/dpio/dpio.c
10033 @@ -5,7 +5,7 @@
10034 *
10035 */
10036 #include <linux/kernel.h>
10037 -#include "../../include/mc.h"
10038 +#include <linux/fsl/mc.h>
10039
10040 #include "dpio.h"
10041 #include "dpio-cmd.h"
10042 @@ -37,7 +37,7 @@ int dpio_open(struct fsl_mc_io *mc_io,
10043 int dpio_id,
10044 u16 *token)
10045 {
10046 - struct mc_command cmd = { 0 };
10047 + struct fsl_mc_command cmd = { 0 };
10048 struct dpio_cmd_open *dpio_cmd;
10049 int err;
10050
10051 @@ -70,7 +70,7 @@ int dpio_close(struct fsl_mc_io *mc_io,
10052 u32 cmd_flags,
10053 u16 token)
10054 {
10055 - struct mc_command cmd = { 0 };
10056 + struct fsl_mc_command cmd = { 0 };
10057
10058 /* prepare command */
10059 cmd.header = mc_encode_cmd_header(DPIO_CMDID_CLOSE,
10060 @@ -92,7 +92,7 @@ int dpio_enable(struct fsl_mc_io *mc_io,
10061 u32 cmd_flags,
10062 u16 token)
10063 {
10064 - struct mc_command cmd = { 0 };
10065 + struct fsl_mc_command cmd = { 0 };
10066
10067 /* prepare command */
10068 cmd.header = mc_encode_cmd_header(DPIO_CMDID_ENABLE,
10069 @@ -114,7 +114,7 @@ int dpio_disable(struct fsl_mc_io *mc_io
10070 u32 cmd_flags,
10071 u16 token)
10072 {
10073 - struct mc_command cmd = { 0 };
10074 + struct fsl_mc_command cmd = { 0 };
10075
10076 /* prepare command */
10077 cmd.header = mc_encode_cmd_header(DPIO_CMDID_DISABLE,
10078 @@ -138,7 +138,7 @@ int dpio_get_attributes(struct fsl_mc_io
10079 u16 token,
10080 struct dpio_attr *attr)
10081 {
10082 - struct mc_command cmd = { 0 };
10083 + struct fsl_mc_command cmd = { 0 };
10084 struct dpio_rsp_get_attr *dpio_rsp;
10085 int err;
10086
10087 @@ -180,7 +180,7 @@ int dpio_get_api_version(struct fsl_mc_i
10088 u16 *major_ver,
10089 u16 *minor_ver)
10090 {
10091 - struct mc_command cmd = { 0 };
10092 + struct fsl_mc_command cmd = { 0 };
10093 int err;
10094
10095 /* prepare command */
10096 --- a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h
10097 +++ /dev/null
10098 @@ -1,56 +0,0 @@
10099 -/*
10100 - * Copyright 2013-2016 Freescale Semiconductor Inc.
10101 - *
10102 - * Redistribution and use in source and binary forms, with or without
10103 - * modification, are permitted provided that the following conditions are met:
10104 - * * Redistributions of source code must retain the above copyright
10105 - * notice, this list of conditions and the following disclaimer.
10106 - * * Redistributions in binary form must reproduce the above copyright
10107 - * notice, this list of conditions and the following disclaimer in the
10108 - * documentation and/or other materials provided with the distribution.
10109 - * * Neither the name of the above-listed copyright holders nor the
10110 - * names of any contributors may be used to endorse or promote products
10111 - * derived from this software without specific prior written permission.
10112 - *
10113 - * ALTERNATIVELY, this software may be distributed under the terms of the
10114 - * GNU General Public License ("GPL") as published by the Free Software
10115 - * Foundation, either version 2 of that License or (at your option) any
10116 - * later version.
10117 - *
10118 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
10119 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10120 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10121 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
10122 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
10123 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
10124 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
10125 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
10126 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
10127 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
10128 - * POSSIBILITY OF SUCH DAMAGE.
10129 - */
10130 -#ifndef _FSL_DPMCP_CMD_H
10131 -#define _FSL_DPMCP_CMD_H
10132 -
10133 -/* Minimal supported DPMCP Version */
10134 -#define DPMCP_MIN_VER_MAJOR 3
10135 -#define DPMCP_MIN_VER_MINOR 0
10136 -
10137 -/* Command versioning */
10138 -#define DPMCP_CMD_BASE_VERSION 1
10139 -#define DPMCP_CMD_ID_OFFSET 4
10140 -
10141 -#define DPMCP_CMD(id) (((id) << DPMCP_CMD_ID_OFFSET) | DPMCP_CMD_BASE_VERSION)
10142 -
10143 -/* Command IDs */
10144 -#define DPMCP_CMDID_CLOSE DPMCP_CMD(0x800)
10145 -#define DPMCP_CMDID_OPEN DPMCP_CMD(0x80b)
10146 -#define DPMCP_CMDID_GET_API_VERSION DPMCP_CMD(0xa0b)
10147 -
10148 -#define DPMCP_CMDID_RESET DPMCP_CMD(0x005)
10149 -
10150 -struct dpmcp_cmd_open {
10151 - __le32 dpmcp_id;
10152 -};
10153 -
10154 -#endif /* _FSL_DPMCP_CMD_H */
10155 --- a/drivers/staging/fsl-mc/bus/dpmcp.h
10156 +++ /dev/null
10157 @@ -1,60 +0,0 @@
10158 -/*
10159 - * Copyright 2013-2016 Freescale Semiconductor Inc.
10160 - *
10161 - * Redistribution and use in source and binary forms, with or without
10162 - * modification, are permitted provided that the following conditions are met:
10163 - * * Redistributions of source code must retain the above copyright
10164 - * notice, this list of conditions and the following disclaimer.
10165 - * * Redistributions in binary form must reproduce the above copyright
10166 - * notice, this list of conditions and the following disclaimer in the
10167 - * documentation and/or other materials provided with the distribution.
10168 - * * Neither the name of the above-listed copyright holders nor the
10169 - * names of any contributors may be used to endorse or promote products
10170 - * derived from this software without specific prior written permission.
10171 - *
10172 - * ALTERNATIVELY, this software may be distributed under the terms of the
10173 - * GNU General Public License ("GPL") as published by the Free Software
10174 - * Foundation, either version 2 of that License or (at your option) any
10175 - * later version.
10176 - *
10177 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
10178 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10179 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10180 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
10181 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
10182 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
10183 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
10184 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
10185 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
10186 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
10187 - * POSSIBILITY OF SUCH DAMAGE.
10188 - */
10189 -#ifndef __FSL_DPMCP_H
10190 -#define __FSL_DPMCP_H
10191 -
10192 -/*
10193 - * Data Path Management Command Portal API
10194 - * Contains initialization APIs and runtime control APIs for DPMCP
10195 - */
10196 -
10197 -struct fsl_mc_io;
10198 -
10199 -int dpmcp_open(struct fsl_mc_io *mc_io,
10200 - u32 cmd_flags,
10201 - int dpmcp_id,
10202 - u16 *token);
10203 -
10204 -int dpmcp_close(struct fsl_mc_io *mc_io,
10205 - u32 cmd_flags,
10206 - u16 token);
10207 -
10208 -int dpmcp_get_api_version(struct fsl_mc_io *mc_io,
10209 - u32 cmd_flags,
10210 - u16 *major_ver,
10211 - u16 *minor_ver);
10212 -
10213 -int dpmcp_reset(struct fsl_mc_io *mc_io,
10214 - u32 cmd_flags,
10215 - u16 token);
10216 -
10217 -#endif /* __FSL_DPMCP_H */
10218 --- a/drivers/staging/fsl-mc/bus/dpmng-cmd.h
10219 +++ /dev/null
10220 @@ -1,58 +0,0 @@
10221 -/*
10222 - * Copyright 2013-2016 Freescale Semiconductor Inc.
10223 - *
10224 - * Redistribution and use in source and binary forms, with or without
10225 - * modification, are permitted provided that the following conditions are met:
10226 - * * Redistributions of source code must retain the above copyright
10227 - * notice, this list of conditions and the following disclaimer.
10228 - * * Redistributions in binary form must reproduce the above copyright
10229 - * notice, this list of conditions and the following disclaimer in the
10230 - * documentation and/or other materials provided with the distribution.
10231 - * * Neither the name of the above-listed copyright holders nor the
10232 - * names of any contributors may be used to endorse or promote products
10233 - * derived from this software without specific prior written permission.
10234 - *
10235 - * ALTERNATIVELY, this software may be distributed under the terms of the
10236 - * GNU General Public License ("GPL") as published by the Free Software
10237 - * Foundation, either version 2 of that License or (at your option) any
10238 - * later version.
10239 - *
10240 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
10241 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10242 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10243 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
10244 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
10245 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
10246 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
10247 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
10248 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
10249 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
10250 - * POSSIBILITY OF SUCH DAMAGE.
10251 - */
10252 -
10253 -/*
10254 - * dpmng-cmd.h
10255 - *
10256 - * defines portal commands
10257 - *
10258 - */
10259 -
10260 -#ifndef __FSL_DPMNG_CMD_H
10261 -#define __FSL_DPMNG_CMD_H
10262 -
10263 -/* Command versioning */
10264 -#define DPMNG_CMD_BASE_VERSION 1
10265 -#define DPMNG_CMD_ID_OFFSET 4
10266 -
10267 -#define DPMNG_CMD(id) (((id) << DPMNG_CMD_ID_OFFSET) | DPMNG_CMD_BASE_VERSION)
10268 -
10269 -/* Command IDs */
10270 -#define DPMNG_CMDID_GET_VERSION DPMNG_CMD(0x831)
10271 -
10272 -struct dpmng_rsp_get_version {
10273 - __le32 revision;
10274 - __le32 version_major;
10275 - __le32 version_minor;
10276 -};
10277 -
10278 -#endif /* __FSL_DPMNG_CMD_H */
10279 --- a/drivers/staging/fsl-mc/bus/dprc-cmd.h
10280 +++ /dev/null
10281 @@ -1,451 +0,0 @@
10282 -/*
10283 - * Copyright 2013-2016 Freescale Semiconductor Inc.
10284 - *
10285 - * Redistribution and use in source and binary forms, with or without
10286 - * modification, are permitted provided that the following conditions are met:
10287 - * * Redistributions of source code must retain the above copyright
10288 - * notice, this list of conditions and the following disclaimer.
10289 - * * Redistributions in binary form must reproduce the above copyright
10290 - * notice, this list of conditions and the following disclaimer in the
10291 - * documentation and/or other materials provided with the distribution.
10292 - * * Neither the name of the above-listed copyright holders nor the
10293 - * names of any contributors may be used to endorse or promote products
10294 - * derived from this software without specific prior written permission.
10295 - *
10296 - * ALTERNATIVELY, this software may be distributed under the terms of the
10297 - * GNU General Public License ("GPL") as published by the Free Software
10298 - * Foundation, either version 2 of that License or (at your option) any
10299 - * later version.
10300 - *
10301 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
10302 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10303 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10304 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
10305 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
10306 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
10307 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
10308 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
10309 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
10310 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
10311 - * POSSIBILITY OF SUCH DAMAGE.
10312 - */
10313 -
10314 -/*
10315 - * dprc-cmd.h
10316 - *
10317 - * defines dprc portal commands
10318 - *
10319 - */
10320 -
10321 -#ifndef _FSL_DPRC_CMD_H
10322 -#define _FSL_DPRC_CMD_H
10323 -
10324 -/* Minimal supported DPRC Version */
10325 -#define DPRC_MIN_VER_MAJOR 6
10326 -#define DPRC_MIN_VER_MINOR 0
10327 -
10328 -/* Command versioning */
10329 -#define DPRC_CMD_BASE_VERSION 1
10330 -#define DPRC_CMD_ID_OFFSET 4
10331 -
10332 -#define DPRC_CMD(id) (((id) << DPRC_CMD_ID_OFFSET) | DPRC_CMD_BASE_VERSION)
10333 -
10334 -/* Command IDs */
10335 -#define DPRC_CMDID_CLOSE DPRC_CMD(0x800)
10336 -#define DPRC_CMDID_OPEN DPRC_CMD(0x805)
10337 -#define DPRC_CMDID_GET_API_VERSION DPRC_CMD(0xa05)
10338 -
10339 -#define DPRC_CMDID_GET_ATTR DPRC_CMD(0x004)
10340 -
10341 -#define DPRC_CMDID_SET_IRQ DPRC_CMD(0x010)
10342 -#define DPRC_CMDID_GET_IRQ DPRC_CMD(0x011)
10343 -#define DPRC_CMDID_SET_IRQ_ENABLE DPRC_CMD(0x012)
10344 -#define DPRC_CMDID_GET_IRQ_ENABLE DPRC_CMD(0x013)
10345 -#define DPRC_CMDID_SET_IRQ_MASK DPRC_CMD(0x014)
10346 -#define DPRC_CMDID_GET_IRQ_MASK DPRC_CMD(0x015)
10347 -#define DPRC_CMDID_GET_IRQ_STATUS DPRC_CMD(0x016)
10348 -#define DPRC_CMDID_CLEAR_IRQ_STATUS DPRC_CMD(0x017)
10349 -
10350 -#define DPRC_CMDID_GET_CONT_ID DPRC_CMD(0x830)
10351 -#define DPRC_CMDID_GET_OBJ_COUNT DPRC_CMD(0x159)
10352 -#define DPRC_CMDID_GET_OBJ DPRC_CMD(0x15A)
10353 -#define DPRC_CMDID_GET_RES_COUNT DPRC_CMD(0x15B)
10354 -#define DPRC_CMDID_GET_OBJ_REG DPRC_CMD(0x15E)
10355 -#define DPRC_CMDID_SET_OBJ_IRQ DPRC_CMD(0x15F)
10356 -#define DPRC_CMDID_GET_OBJ_IRQ DPRC_CMD(0x160)
10357 -
10358 -struct dprc_cmd_open {
10359 - __le32 container_id;
10360 -};
10361 -
10362 -struct dprc_cmd_create_container {
10363 - /* cmd word 0 */
10364 - __le32 options;
10365 - __le16 icid;
10366 - __le16 pad0;
10367 - /* cmd word 1 */
10368 - __le32 pad1;
10369 - __le32 portal_id;
10370 - /* cmd words 2-3 */
10371 - u8 label[16];
10372 -};
10373 -
10374 -struct dprc_rsp_create_container {
10375 - /* response word 0 */
10376 - __le64 pad0;
10377 - /* response word 1 */
10378 - __le32 child_container_id;
10379 - __le32 pad1;
10380 - /* response word 2 */
10381 - __le64 child_portal_addr;
10382 -};
10383 -
10384 -struct dprc_cmd_destroy_container {
10385 - __le32 child_container_id;
10386 -};
10387 -
10388 -struct dprc_cmd_reset_container {
10389 - __le32 child_container_id;
10390 -};
10391 -
10392 -struct dprc_cmd_set_irq {
10393 - /* cmd word 0 */
10394 - __le32 irq_val;
10395 - u8 irq_index;
10396 - u8 pad[3];
10397 - /* cmd word 1 */
10398 - __le64 irq_addr;
10399 - /* cmd word 2 */
10400 - __le32 irq_num;
10401 -};
10402 -
10403 -struct dprc_cmd_get_irq {
10404 - __le32 pad;
10405 - u8 irq_index;
10406 -};
10407 -
10408 -struct dprc_rsp_get_irq {
10409 - /* response word 0 */
10410 - __le32 irq_val;
10411 - __le32 pad;
10412 - /* response word 1 */
10413 - __le64 irq_addr;
10414 - /* response word 2 */
10415 - __le32 irq_num;
10416 - __le32 type;
10417 -};
10418 -
10419 -#define DPRC_ENABLE 0x1
10420 -
10421 -struct dprc_cmd_set_irq_enable {
10422 - u8 enable;
10423 - u8 pad[3];
10424 - u8 irq_index;
10425 -};
10426 -
10427 -struct dprc_cmd_get_irq_enable {
10428 - __le32 pad;
10429 - u8 irq_index;
10430 -};
10431 -
10432 -struct dprc_rsp_get_irq_enable {
10433 - u8 enabled;
10434 -};
10435 -
10436 -struct dprc_cmd_set_irq_mask {
10437 - __le32 mask;
10438 - u8 irq_index;
10439 -};
10440 -
10441 -struct dprc_cmd_get_irq_mask {
10442 - __le32 pad;
10443 - u8 irq_index;
10444 -};
10445 -
10446 -struct dprc_rsp_get_irq_mask {
10447 - __le32 mask;
10448 -};
10449 -
10450 -struct dprc_cmd_get_irq_status {
10451 - __le32 status;
10452 - u8 irq_index;
10453 -};
10454 -
10455 -struct dprc_rsp_get_irq_status {
10456 - __le32 status;
10457 -};
10458 -
10459 -struct dprc_cmd_clear_irq_status {
10460 - __le32 status;
10461 - u8 irq_index;
10462 -};
10463 -
10464 -struct dprc_rsp_get_attributes {
10465 - /* response word 0 */
10466 - __le32 container_id;
10467 - __le16 icid;
10468 - __le16 pad;
10469 - /* response word 1 */
10470 - __le32 options;
10471 - __le32 portal_id;
10472 -};
10473 -
10474 -struct dprc_cmd_set_res_quota {
10475 - /* cmd word 0 */
10476 - __le32 child_container_id;
10477 - __le16 quota;
10478 - __le16 pad;
10479 - /* cmd words 1-2 */
10480 - u8 type[16];
10481 -};
10482 -
10483 -struct dprc_cmd_get_res_quota {
10484 - /* cmd word 0 */
10485 - __le32 child_container_id;
10486 - __le32 pad;
10487 - /* cmd word 1-2 */
10488 - u8 type[16];
10489 -};
10490 -
10491 -struct dprc_rsp_get_res_quota {
10492 - __le32 pad;
10493 - __le16 quota;
10494 -};
10495 -
10496 -struct dprc_cmd_assign {
10497 - /* cmd word 0 */
10498 - __le32 container_id;
10499 - __le32 options;
10500 - /* cmd word 1 */
10501 - __le32 num;
10502 - __le32 id_base_align;
10503 - /* cmd word 2-3 */
10504 - u8 type[16];
10505 -};
10506 -
10507 -struct dprc_cmd_unassign {
10508 - /* cmd word 0 */
10509 - __le32 child_container_id;
10510 - __le32 options;
10511 - /* cmd word 1 */
10512 - __le32 num;
10513 - __le32 id_base_align;
10514 - /* cmd word 2-3 */
10515 - u8 type[16];
10516 -};
10517 -
10518 -struct dprc_rsp_get_pool_count {
10519 - __le32 pool_count;
10520 -};
10521 -
10522 -struct dprc_cmd_get_pool {
10523 - __le32 pool_index;
10524 -};
10525 -
10526 -struct dprc_rsp_get_pool {
10527 - /* response word 0 */
10528 - __le64 pad;
10529 - /* response word 1-2 */
10530 - u8 type[16];
10531 -};
10532 -
10533 -struct dprc_rsp_get_obj_count {
10534 - __le32 pad;
10535 - __le32 obj_count;
10536 -};
10537 -
10538 -struct dprc_cmd_get_obj {
10539 - __le32 obj_index;
10540 -};
10541 -
10542 -struct dprc_rsp_get_obj {
10543 - /* response word 0 */
10544 - __le32 pad0;
10545 - __le32 id;
10546 - /* response word 1 */
10547 - __le16 vendor;
10548 - u8 irq_count;
10549 - u8 region_count;
10550 - __le32 state;
10551 - /* response word 2 */
10552 - __le16 version_major;
10553 - __le16 version_minor;
10554 - __le16 flags;
10555 - __le16 pad1;
10556 - /* response word 3-4 */
10557 - u8 type[16];
10558 - /* response word 5-6 */
10559 - u8 label[16];
10560 -};
10561 -
10562 -struct dprc_cmd_get_obj_desc {
10563 - /* cmd word 0 */
10564 - __le32 obj_id;
10565 - __le32 pad;
10566 - /* cmd word 1-2 */
10567 - u8 type[16];
10568 -};
10569 -
10570 -struct dprc_rsp_get_obj_desc {
10571 - /* response word 0 */
10572 - __le32 pad0;
10573 - __le32 id;
10574 - /* response word 1 */
10575 - __le16 vendor;
10576 - u8 irq_count;
10577 - u8 region_count;
10578 - __le32 state;
10579 - /* response word 2 */
10580 - __le16 version_major;
10581 - __le16 version_minor;
10582 - __le16 flags;
10583 - __le16 pad1;
10584 - /* response word 3-4 */
10585 - u8 type[16];
10586 - /* response word 5-6 */
10587 - u8 label[16];
10588 -};
10589 -
10590 -struct dprc_cmd_get_res_count {
10591 - /* cmd word 0 */
10592 - __le64 pad;
10593 - /* cmd word 1-2 */
10594 - u8 type[16];
10595 -};
10596 -
10597 -struct dprc_rsp_get_res_count {
10598 - __le32 res_count;
10599 -};
10600 -
10601 -struct dprc_cmd_get_res_ids {
10602 - /* cmd word 0 */
10603 - u8 pad0[5];
10604 - u8 iter_status;
10605 - __le16 pad1;
10606 - /* cmd word 1 */
10607 - __le32 base_id;
10608 - __le32 last_id;
10609 - /* cmd word 2-3 */
10610 - u8 type[16];
10611 -};
10612 -
10613 -struct dprc_rsp_get_res_ids {
10614 - /* response word 0 */
10615 - u8 pad0[5];
10616 - u8 iter_status;
10617 - __le16 pad1;
10618 - /* response word 1 */
10619 - __le32 base_id;
10620 - __le32 last_id;
10621 -};
10622 -
10623 -struct dprc_cmd_get_obj_region {
10624 - /* cmd word 0 */
10625 - __le32 obj_id;
10626 - __le16 pad0;
10627 - u8 region_index;
10628 - u8 pad1;
10629 - /* cmd word 1-2 */
10630 - __le64 pad2[2];
10631 - /* cmd word 3-4 */
10632 - u8 obj_type[16];
10633 -};
10634 -
10635 -struct dprc_rsp_get_obj_region {
10636 - /* response word 0 */
10637 - __le64 pad;
10638 - /* response word 1 */
10639 - __le64 base_addr;
10640 - /* response word 2 */
10641 - __le32 size;
10642 -};
10643 -
10644 -struct dprc_cmd_set_obj_label {
10645 - /* cmd word 0 */
10646 - __le32 obj_id;
10647 - __le32 pad;
10648 - /* cmd word 1-2 */
10649 - u8 label[16];
10650 - /* cmd word 3-4 */
10651 - u8 obj_type[16];
10652 -};
10653 -
10654 -struct dprc_cmd_set_obj_irq {
10655 - /* cmd word 0 */
10656 - __le32 irq_val;
10657 - u8 irq_index;
10658 - u8 pad[3];
10659 - /* cmd word 1 */
10660 - __le64 irq_addr;
10661 - /* cmd word 2 */
10662 - __le32 irq_num;
10663 - __le32 obj_id;
10664 - /* cmd word 3-4 */
10665 - u8 obj_type[16];
10666 -};
10667 -
10668 -struct dprc_cmd_get_obj_irq {
10669 - /* cmd word 0 */
10670 - __le32 obj_id;
10671 - u8 irq_index;
10672 - u8 pad[3];
10673 - /* cmd word 1-2 */
10674 - u8 obj_type[16];
10675 -};
10676 -
10677 -struct dprc_rsp_get_obj_irq {
10678 - /* response word 0 */
10679 - __le32 irq_val;
10680 - __le32 pad;
10681 - /* response word 1 */
10682 - __le64 irq_addr;
10683 - /* response word 2 */
10684 - __le32 irq_num;
10685 - __le32 type;
10686 -};
10687 -
10688 -struct dprc_cmd_connect {
10689 - /* cmd word 0 */
10690 - __le32 ep1_id;
10691 - __le32 ep1_interface_id;
10692 - /* cmd word 1 */
10693 - __le32 ep2_id;
10694 - __le32 ep2_interface_id;
10695 - /* cmd word 2-3 */
10696 - u8 ep1_type[16];
10697 - /* cmd word 4 */
10698 - __le32 max_rate;
10699 - __le32 committed_rate;
10700 - /* cmd word 5-6 */
10701 - u8 ep2_type[16];
10702 -};
10703 -
10704 -struct dprc_cmd_disconnect {
10705 - /* cmd word 0 */
10706 - __le32 id;
10707 - __le32 interface_id;
10708 - /* cmd word 1-2 */
10709 - u8 type[16];
10710 -};
10711 -
10712 -struct dprc_cmd_get_connection {
10713 - /* cmd word 0 */
10714 - __le32 ep1_id;
10715 - __le32 ep1_interface_id;
10716 - /* cmd word 1-2 */
10717 - u8 ep1_type[16];
10718 -};
10719 -
10720 -struct dprc_rsp_get_connection {
10721 - /* response word 0-2 */
10722 - __le64 pad[3];
10723 - /* response word 3 */
10724 - __le32 ep2_id;
10725 - __le32 ep2_interface_id;
10726 - /* response word 4-5 */
10727 - u8 ep2_type[16];
10728 - /* response word 6 */
10729 - __le32 state;
10730 -};
10731 -
10732 -#endif /* _FSL_DPRC_CMD_H */
10733 --- a/drivers/staging/fsl-mc/bus/dprc.h
10734 +++ /dev/null
10735 @@ -1,268 +0,0 @@
10736 -/*
10737 - * Copyright 2013-2016 Freescale Semiconductor Inc.
10738 - *
10739 - * Redistribution and use in source and binary forms, with or without
10740 - * modification, are permitted provided that the following conditions are met:
10741 - * * Redistributions of source code must retain the above copyright
10742 - * notice, this list of conditions and the following disclaimer.
10743 - * * Redistributions in binary form must reproduce the above copyright
10744 - * notice, this list of conditions and the following disclaimer in the
10745 - * documentation and/or other materials provided with the distribution.
10746 - * * Neither the name of the above-listed copyright holders nor the
10747 - * names of any contributors may be used to endorse or promote products
10748 - * derived from this software without specific prior written permission.
10749 - *
10750 - *
10751 - * ALTERNATIVELY, this software may be distributed under the terms of the
10752 - * GNU General Public License ("GPL") as published by the Free Software
10753 - * Foundation, either version 2 of that License or (at your option) any
10754 - * later version.
10755 - *
10756 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
10757 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10758 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10759 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
10760 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
10761 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
10762 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
10763 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
10764 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
10765 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
10766 - * POSSIBILITY OF SUCH DAMAGE.
10767 - */
10768 -#ifndef _FSL_DPRC_H
10769 -#define _FSL_DPRC_H
10770 -
10771 -/*
10772 - * Data Path Resource Container API
10773 - * Contains DPRC API for managing and querying DPAA resources
10774 - */
10775 -
10776 -struct fsl_mc_io;
10777 -struct fsl_mc_obj_desc;
10778 -
10779 -int dprc_open(struct fsl_mc_io *mc_io,
10780 - u32 cmd_flags,
10781 - int container_id,
10782 - u16 *token);
10783 -
10784 -int dprc_close(struct fsl_mc_io *mc_io,
10785 - u32 cmd_flags,
10786 - u16 token);
10787 -
10788 -/* IRQ */
10789 -
10790 -/* IRQ index */
10791 -#define DPRC_IRQ_INDEX 0
10792 -
10793 -/* Number of dprc's IRQs */
10794 -#define DPRC_NUM_OF_IRQS 1
10795 -
10796 -/* DPRC IRQ events */
10797 -
10798 -/* IRQ event - Indicates that a new object added to the container */
10799 -#define DPRC_IRQ_EVENT_OBJ_ADDED 0x00000001
10800 -/* IRQ event - Indicates that an object was removed from the container */
10801 -#define DPRC_IRQ_EVENT_OBJ_REMOVED 0x00000002
10802 -/* IRQ event - Indicates that resources added to the container */
10803 -#define DPRC_IRQ_EVENT_RES_ADDED 0x00000004
10804 -/* IRQ event - Indicates that resources removed from the container */
10805 -#define DPRC_IRQ_EVENT_RES_REMOVED 0x00000008
10806 -/*
10807 - * IRQ event - Indicates that one of the descendant containers that opened by
10808 - * this container is destroyed
10809 - */
10810 -#define DPRC_IRQ_EVENT_CONTAINER_DESTROYED 0x00000010
10811 -
10812 -/*
10813 - * IRQ event - Indicates that on one of the container's opened object is
10814 - * destroyed
10815 - */
10816 -#define DPRC_IRQ_EVENT_OBJ_DESTROYED 0x00000020
10817 -
10818 -/* Irq event - Indicates that object is created at the container */
10819 -#define DPRC_IRQ_EVENT_OBJ_CREATED 0x00000040
10820 -
10821 -/**
10822 - * struct dprc_irq_cfg - IRQ configuration
10823 - * @paddr: Address that must be written to signal a message-based interrupt
10824 - * @val: Value to write into irq_addr address
10825 - * @irq_num: A user defined number associated with this IRQ
10826 - */
10827 -struct dprc_irq_cfg {
10828 - phys_addr_t paddr;
10829 - u32 val;
10830 - int irq_num;
10831 -};
10832 -
10833 -int dprc_set_irq(struct fsl_mc_io *mc_io,
10834 - u32 cmd_flags,
10835 - u16 token,
10836 - u8 irq_index,
10837 - struct dprc_irq_cfg *irq_cfg);
10838 -
10839 -int dprc_get_irq(struct fsl_mc_io *mc_io,
10840 - u32 cmd_flags,
10841 - u16 token,
10842 - u8 irq_index,
10843 - int *type,
10844 - struct dprc_irq_cfg *irq_cfg);
10845 -
10846 -int dprc_set_irq_enable(struct fsl_mc_io *mc_io,
10847 - u32 cmd_flags,
10848 - u16 token,
10849 - u8 irq_index,
10850 - u8 en);
10851 -
10852 -int dprc_get_irq_enable(struct fsl_mc_io *mc_io,
10853 - u32 cmd_flags,
10854 - u16 token,
10855 - u8 irq_index,
10856 - u8 *en);
10857 -
10858 -int dprc_set_irq_mask(struct fsl_mc_io *mc_io,
10859 - u32 cmd_flags,
10860 - u16 token,
10861 - u8 irq_index,
10862 - u32 mask);
10863 -
10864 -int dprc_get_irq_mask(struct fsl_mc_io *mc_io,
10865 - u32 cmd_flags,
10866 - u16 token,
10867 - u8 irq_index,
10868 - u32 *mask);
10869 -
10870 -int dprc_get_irq_status(struct fsl_mc_io *mc_io,
10871 - u32 cmd_flags,
10872 - u16 token,
10873 - u8 irq_index,
10874 - u32 *status);
10875 -
10876 -int dprc_clear_irq_status(struct fsl_mc_io *mc_io,
10877 - u32 cmd_flags,
10878 - u16 token,
10879 - u8 irq_index,
10880 - u32 status);
10881 -
10882 -/**
10883 - * struct dprc_attributes - Container attributes
10884 - * @container_id: Container's ID
10885 - * @icid: Container's ICID
10886 - * @portal_id: Container's portal ID
10887 - * @options: Container's options as set at container's creation
10888 - */
10889 -struct dprc_attributes {
10890 - int container_id;
10891 - u16 icid;
10892 - int portal_id;
10893 - u64 options;
10894 -};
10895 -
10896 -int dprc_get_attributes(struct fsl_mc_io *mc_io,
10897 - u32 cmd_flags,
10898 - u16 token,
10899 - struct dprc_attributes *attributes);
10900 -
10901 -int dprc_get_obj_count(struct fsl_mc_io *mc_io,
10902 - u32 cmd_flags,
10903 - u16 token,
10904 - int *obj_count);
10905 -
10906 -int dprc_get_obj(struct fsl_mc_io *mc_io,
10907 - u32 cmd_flags,
10908 - u16 token,
10909 - int obj_index,
10910 - struct fsl_mc_obj_desc *obj_desc);
10911 -
10912 -int dprc_get_obj_desc(struct fsl_mc_io *mc_io,
10913 - u32 cmd_flags,
10914 - u16 token,
10915 - char *obj_type,
10916 - int obj_id,
10917 - struct fsl_mc_obj_desc *obj_desc);
10918 -
10919 -int dprc_set_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 - struct dprc_irq_cfg *irq_cfg);
10926 -
10927 -int dprc_get_obj_irq(struct fsl_mc_io *mc_io,
10928 - u32 cmd_flags,
10929 - u16 token,
10930 - char *obj_type,
10931 - int obj_id,
10932 - u8 irq_index,
10933 - int *type,
10934 - struct dprc_irq_cfg *irq_cfg);
10935 -
10936 -int dprc_get_res_count(struct fsl_mc_io *mc_io,
10937 - u32 cmd_flags,
10938 - u16 token,
10939 - char *type,
10940 - int *res_count);
10941 -
10942 -/**
10943 - * enum dprc_iter_status - Iteration status
10944 - * @DPRC_ITER_STATUS_FIRST: Perform first iteration
10945 - * @DPRC_ITER_STATUS_MORE: Indicates more/next iteration is needed
10946 - * @DPRC_ITER_STATUS_LAST: Indicates last iteration
10947 - */
10948 -enum dprc_iter_status {
10949 - DPRC_ITER_STATUS_FIRST = 0,
10950 - DPRC_ITER_STATUS_MORE = 1,
10951 - DPRC_ITER_STATUS_LAST = 2
10952 -};
10953 -
10954 -/* Region flags */
10955 -/* Cacheable - Indicates that region should be mapped as cacheable */
10956 -#define DPRC_REGION_CACHEABLE 0x00000001
10957 -
10958 -/**
10959 - * enum dprc_region_type - Region type
10960 - * @DPRC_REGION_TYPE_MC_PORTAL: MC portal region
10961 - * @DPRC_REGION_TYPE_QBMAN_PORTAL: Qbman portal region
10962 - */
10963 -enum dprc_region_type {
10964 - DPRC_REGION_TYPE_MC_PORTAL,
10965 - DPRC_REGION_TYPE_QBMAN_PORTAL
10966 -};
10967 -
10968 -/**
10969 - * struct dprc_region_desc - Mappable region descriptor
10970 - * @base_offset: Region offset from region's base address.
10971 - * For DPMCP and DPRC objects, region base is offset from SoC MC portals
10972 - * base address; For DPIO, region base is offset from SoC QMan portals
10973 - * base address
10974 - * @size: Region size (in bytes)
10975 - * @flags: Region attributes
10976 - * @type: Portal region type
10977 - */
10978 -struct dprc_region_desc {
10979 - u32 base_offset;
10980 - u32 size;
10981 - u32 flags;
10982 - enum dprc_region_type type;
10983 -};
10984 -
10985 -int dprc_get_obj_region(struct fsl_mc_io *mc_io,
10986 - u32 cmd_flags,
10987 - u16 token,
10988 - char *obj_type,
10989 - int obj_id,
10990 - u8 region_index,
10991 - struct dprc_region_desc *region_desc);
10992 -
10993 -int dprc_get_api_version(struct fsl_mc_io *mc_io,
10994 - u32 cmd_flags,
10995 - u16 *major_ver,
10996 - u16 *minor_ver);
10997 -
10998 -int dprc_get_container_id(struct fsl_mc_io *mc_io,
10999 - u32 cmd_flags,
11000 - int *container_id);
11001 -
11002 -#endif /* _FSL_DPRC_H */
11003 -
11004 --- a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c
11005 +++ b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c
11006 @@ -13,6 +13,7 @@
11007 #include <linux/msi.h>
11008 #include <linux/of.h>
11009 #include <linux/of_irq.h>
11010 +#include <linux/fsl/mc.h>
11011 #include "fsl-mc-private.h"
11012
11013 static struct irq_chip its_msi_irq_chip = {
11014 --- /dev/null
11015 +++ b/include/linux/fsl/mc.h
11016 @@ -0,0 +1,1029 @@
11017 +/* SPDX-License-Identifier: GPL-2.0 */
11018 +/*
11019 + * Freescale Management Complex (MC) bus public interface
11020 + *
11021 + * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
11022 + * Author: German Rivera <German.Rivera@freescale.com>
11023 + *
11024 + */
11025 +#ifndef _FSL_MC_H_
11026 +#define _FSL_MC_H_
11027 +
11028 +#include <linux/device.h>
11029 +#include <linux/mod_devicetable.h>
11030 +#include <linux/interrupt.h>
11031 +#include <linux/cdev.h>
11032 +#include <uapi/linux/fsl_mc.h>
11033 +
11034 +#define FSL_MC_VENDOR_FREESCALE 0x1957
11035 +
11036 +struct irq_domain;
11037 +struct msi_domain_info;
11038 +
11039 +struct fsl_mc_device;
11040 +struct fsl_mc_io;
11041 +
11042 +/**
11043 + * struct fsl_mc_driver - MC object device driver object
11044 + * @driver: Generic device driver
11045 + * @match_id_table: table of supported device matching Ids
11046 + * @probe: Function called when a device is added
11047 + * @remove: Function called when a device is removed
11048 + * @shutdown: Function called at shutdown time to quiesce the device
11049 + * @suspend: Function called when a device is stopped
11050 + * @resume: Function called when a device is resumed
11051 + *
11052 + * Generic DPAA device driver object for device drivers that are registered
11053 + * with a DPRC bus. This structure is to be embedded in each device-specific
11054 + * driver structure.
11055 + */
11056 +struct fsl_mc_driver {
11057 + struct device_driver driver;
11058 + const struct fsl_mc_device_id *match_id_table;
11059 + int (*probe)(struct fsl_mc_device *dev);
11060 + int (*remove)(struct fsl_mc_device *dev);
11061 + void (*shutdown)(struct fsl_mc_device *dev);
11062 + int (*suspend)(struct fsl_mc_device *dev, pm_message_t state);
11063 + int (*resume)(struct fsl_mc_device *dev);
11064 +};
11065 +
11066 +#define to_fsl_mc_driver(_drv) \
11067 + container_of(_drv, struct fsl_mc_driver, driver)
11068 +
11069 +#define to_fsl_mc_bus(_mc_dev) \
11070 + container_of(_mc_dev, struct fsl_mc_bus, mc_dev)
11071 +
11072 +/**
11073 + * enum fsl_mc_pool_type - Types of allocatable MC bus resources
11074 + *
11075 + * Entries in these enum are used as indices in the array of resource
11076 + * pools of an fsl_mc_bus object.
11077 + */
11078 +enum fsl_mc_pool_type {
11079 + FSL_MC_POOL_DPMCP = 0x0, /* corresponds to "dpmcp" in the MC */
11080 + FSL_MC_POOL_DPBP, /* corresponds to "dpbp" in the MC */
11081 + FSL_MC_POOL_DPCON, /* corresponds to "dpcon" in the MC */
11082 + FSL_MC_POOL_IRQ,
11083 +
11084 + /*
11085 + * NOTE: New resource pool types must be added before this entry
11086 + */
11087 + FSL_MC_NUM_POOL_TYPES
11088 +};
11089 +
11090 +/**
11091 + * struct fsl_mc_resource - MC generic resource
11092 + * @type: type of resource
11093 + * @id: unique MC resource Id within the resources of the same type
11094 + * @data: pointer to resource-specific data if the resource is currently
11095 + * allocated, or NULL if the resource is not currently allocated.
11096 + * @parent_pool: pointer to the parent resource pool from which this
11097 + * resource is allocated from.
11098 + * @node: Node in the free list of the corresponding resource pool
11099 + *
11100 + * NOTE: This structure is to be embedded as a field of specific
11101 + * MC resource structures.
11102 + */
11103 +struct fsl_mc_resource {
11104 + enum fsl_mc_pool_type type;
11105 + s32 id;
11106 + void *data;
11107 + struct fsl_mc_resource_pool *parent_pool;
11108 + struct list_head node;
11109 +};
11110 +
11111 +/**
11112 + * struct fsl_mc_device_irq - MC object device message-based interrupt
11113 + * @msi_desc: pointer to MSI descriptor allocated by fsl_mc_msi_alloc_descs()
11114 + * @mc_dev: MC object device that owns this interrupt
11115 + * @dev_irq_index: device-relative IRQ index
11116 + * @resource: MC generic resource associated with the interrupt
11117 + */
11118 +struct fsl_mc_device_irq {
11119 + struct msi_desc *msi_desc;
11120 + struct fsl_mc_device *mc_dev;
11121 + u8 dev_irq_index;
11122 + struct fsl_mc_resource resource;
11123 +};
11124 +
11125 +#define to_fsl_mc_irq(_mc_resource) \
11126 + container_of(_mc_resource, struct fsl_mc_device_irq, resource)
11127 +
11128 +/* Opened state - Indicates that an object is open by at least one owner */
11129 +#define FSL_MC_OBJ_STATE_OPEN 0x00000001
11130 +/* Plugged state - Indicates that the object is plugged */
11131 +#define FSL_MC_OBJ_STATE_PLUGGED 0x00000002
11132 +
11133 +/**
11134 + * Shareability flag - Object flag indicating no memory shareability.
11135 + * the object generates memory accesses that are non coherent with other
11136 + * masters;
11137 + * user is responsible for proper memory handling through IOMMU configuration.
11138 + */
11139 +#define FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY 0x0001
11140 +
11141 +/**
11142 + * struct fsl_mc_obj_desc - Object descriptor
11143 + * @type: Type of object: NULL terminated string
11144 + * @id: ID of logical object resource
11145 + * @vendor: Object vendor identifier
11146 + * @ver_major: Major version number
11147 + * @ver_minor: Minor version number
11148 + * @irq_count: Number of interrupts supported by the object
11149 + * @region_count: Number of mappable regions supported by the object
11150 + * @state: Object state: combination of FSL_MC_OBJ_STATE_ states
11151 + * @label: Object label: NULL terminated string
11152 + * @flags: Object's flags
11153 + */
11154 +struct fsl_mc_obj_desc {
11155 + char type[16];
11156 + int id;
11157 + u16 vendor;
11158 + u16 ver_major;
11159 + u16 ver_minor;
11160 + u8 irq_count;
11161 + u8 region_count;
11162 + u32 state;
11163 + char label[16];
11164 + u16 flags;
11165 +};
11166 +
11167 +/**
11168 + * Bit masks for a MC object device (struct fsl_mc_device) flags
11169 + */
11170 +#define FSL_MC_IS_DPRC 0x0001
11171 +
11172 +/**
11173 + * struct fsl_mc_device - MC object device object
11174 + * @dev: Linux driver model device object
11175 + * @dma_mask: Default DMA mask
11176 + * @flags: MC object device flags
11177 + * @icid: Isolation context ID for the device
11178 + * @mc_handle: MC handle for the corresponding MC object opened
11179 + * @mc_io: Pointer to MC IO object assigned to this device or
11180 + * NULL if none.
11181 + * @obj_desc: MC description of the DPAA device
11182 + * @regions: pointer to array of MMIO region entries
11183 + * @irqs: pointer to array of pointers to interrupts allocated to this device
11184 + * @resource: generic resource associated with this MC object device, if any.
11185 + * @driver_override: Driver name to force a match
11186 + *
11187 + * Generic device object for MC object devices that are "attached" to a
11188 + * MC bus.
11189 + *
11190 + * NOTES:
11191 + * - For a non-DPRC object its icid is the same as its parent DPRC's icid.
11192 + * - The SMMU notifier callback gets invoked after device_add() has been
11193 + * called for an MC object device, but before the device-specific probe
11194 + * callback gets called.
11195 + * - DP_OBJ_DPRC objects are the only MC objects that have built-in MC
11196 + * portals. For all other MC objects, their device drivers are responsible for
11197 + * allocating MC portals for them by calling fsl_mc_portal_allocate().
11198 + * - Some types of MC objects (e.g., DP_OBJ_DPBP, DP_OBJ_DPCON) are
11199 + * treated as resources that can be allocated/deallocated from the
11200 + * corresponding resource pool in the object's parent DPRC, using the
11201 + * fsl_mc_object_allocate()/fsl_mc_object_free() functions. These MC objects
11202 + * are known as "allocatable" objects. For them, the corresponding
11203 + * fsl_mc_device's 'resource' points to the associated resource object.
11204 + * For MC objects that are not allocatable (e.g., DP_OBJ_DPRC, DP_OBJ_DPNI),
11205 + * 'resource' is NULL.
11206 + */
11207 +struct fsl_mc_device {
11208 + struct device dev;
11209 + u64 dma_mask;
11210 + u16 flags;
11211 + u32 icid;
11212 + u16 mc_handle;
11213 + struct fsl_mc_io *mc_io;
11214 + struct fsl_mc_obj_desc obj_desc;
11215 + struct resource *regions;
11216 + struct fsl_mc_device_irq **irqs;
11217 + struct fsl_mc_resource *resource;
11218 + const char *driver_override;
11219 + struct device_link *consumer_link;
11220 +};
11221 +
11222 +#define to_fsl_mc_device(_dev) \
11223 + container_of(_dev, struct fsl_mc_device, dev)
11224 +
11225 +struct mc_cmd_header {
11226 + u8 src_id;
11227 + u8 flags_hw;
11228 + u8 status;
11229 + u8 flags_sw;
11230 + __le16 token;
11231 + __le16 cmd_id;
11232 +};
11233 +
11234 +enum mc_cmd_status {
11235 + MC_CMD_STATUS_OK = 0x0, /* Completed successfully */
11236 + MC_CMD_STATUS_READY = 0x1, /* Ready to be processed */
11237 + MC_CMD_STATUS_AUTH_ERR = 0x3, /* Authentication error */
11238 + MC_CMD_STATUS_NO_PRIVILEGE = 0x4, /* No privilege */
11239 + MC_CMD_STATUS_DMA_ERR = 0x5, /* DMA or I/O error */
11240 + MC_CMD_STATUS_CONFIG_ERR = 0x6, /* Configuration error */
11241 + MC_CMD_STATUS_TIMEOUT = 0x7, /* Operation timed out */
11242 + MC_CMD_STATUS_NO_RESOURCE = 0x8, /* No resources */
11243 + MC_CMD_STATUS_NO_MEMORY = 0x9, /* No memory available */
11244 + MC_CMD_STATUS_BUSY = 0xA, /* Device is busy */
11245 + MC_CMD_STATUS_UNSUPPORTED_OP = 0xB, /* Unsupported operation */
11246 + MC_CMD_STATUS_INVALID_STATE = 0xC /* Invalid state */
11247 +};
11248 +
11249 +/*
11250 + * MC command flags
11251 + */
11252 +
11253 +/* High priority flag */
11254 +#define MC_CMD_FLAG_PRI 0x80
11255 +/* Command completion flag */
11256 +#define MC_CMD_FLAG_INTR_DIS 0x01
11257 +
11258 +static inline u64 mc_encode_cmd_header(u16 cmd_id,
11259 + u32 cmd_flags,
11260 + u16 token)
11261 +{
11262 + u64 header = 0;
11263 + struct mc_cmd_header *hdr = (struct mc_cmd_header *)&header;
11264 +
11265 + hdr->cmd_id = cpu_to_le16(cmd_id);
11266 + hdr->token = cpu_to_le16(token);
11267 + hdr->status = MC_CMD_STATUS_READY;
11268 + if (cmd_flags & MC_CMD_FLAG_PRI)
11269 + hdr->flags_hw = MC_CMD_FLAG_PRI;
11270 + if (cmd_flags & MC_CMD_FLAG_INTR_DIS)
11271 + hdr->flags_sw = MC_CMD_FLAG_INTR_DIS;
11272 +
11273 + return header;
11274 +}
11275 +
11276 +static inline u16 mc_cmd_hdr_read_token(struct fsl_mc_command *cmd)
11277 +{
11278 + struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
11279 + u16 token = le16_to_cpu(hdr->token);
11280 +
11281 + return token;
11282 +}
11283 +
11284 +struct mc_rsp_create {
11285 + __le32 object_id;
11286 +};
11287 +
11288 +struct mc_rsp_api_ver {
11289 + __le16 major_ver;
11290 + __le16 minor_ver;
11291 +};
11292 +
11293 +static inline u32 mc_cmd_read_object_id(struct fsl_mc_command *cmd)
11294 +{
11295 + struct mc_rsp_create *rsp_params;
11296 +
11297 + rsp_params = (struct mc_rsp_create *)cmd->params;
11298 + return le32_to_cpu(rsp_params->object_id);
11299 +}
11300 +
11301 +static inline void mc_cmd_read_api_version(struct fsl_mc_command *cmd,
11302 + u16 *major_ver,
11303 + u16 *minor_ver)
11304 +{
11305 + struct mc_rsp_api_ver *rsp_params;
11306 +
11307 + rsp_params = (struct mc_rsp_api_ver *)cmd->params;
11308 + *major_ver = le16_to_cpu(rsp_params->major_ver);
11309 + *minor_ver = le16_to_cpu(rsp_params->minor_ver);
11310 +}
11311 +
11312 +/**
11313 + * Bit masks for a MC I/O object (struct fsl_mc_io) flags
11314 + */
11315 +#define FSL_MC_IO_ATOMIC_CONTEXT_PORTAL 0x0001
11316 +
11317 +/**
11318 + * struct fsl_mc_io - MC I/O object to be passed-in to mc_send_command()
11319 + * @dev: device associated with this Mc I/O object
11320 + * @flags: flags for mc_send_command()
11321 + * @portal_size: MC command portal size in bytes
11322 + * @portal_phys_addr: MC command portal physical address
11323 + * @portal_virt_addr: MC command portal virtual address
11324 + * @dpmcp_dev: pointer to the DPMCP device associated with the MC portal.
11325 + *
11326 + * Fields are only meaningful if the FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is not
11327 + * set:
11328 + * @mutex: Mutex to serialize mc_send_command() calls that use the same MC
11329 + * portal, if the fsl_mc_io object was created with the
11330 + * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag off. mc_send_command() calls for this
11331 + * fsl_mc_io object must be made only from non-atomic context.
11332 + *
11333 + * Fields are only meaningful if the FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is
11334 + * set:
11335 + * @spinlock: Spinlock to serialize mc_send_command() calls that use the same MC
11336 + * portal, if the fsl_mc_io object was created with the
11337 + * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag on. mc_send_command() calls for this
11338 + * fsl_mc_io object can be made from atomic or non-atomic context.
11339 + */
11340 +struct fsl_mc_io {
11341 + struct device *dev;
11342 + u16 flags;
11343 + u32 portal_size;
11344 + phys_addr_t portal_phys_addr;
11345 + void __iomem *portal_virt_addr;
11346 + struct fsl_mc_device *dpmcp_dev;
11347 + union {
11348 + /*
11349 + * This field is only meaningful if the
11350 + * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is not set
11351 + */
11352 + struct mutex mutex; /* serializes mc_send_command() */
11353 +
11354 + /*
11355 + * This field is only meaningful if the
11356 + * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is set
11357 + */
11358 + spinlock_t spinlock; /* serializes mc_send_command() */
11359 + };
11360 +};
11361 +
11362 +int mc_send_command(struct fsl_mc_io *mc_io, struct fsl_mc_command *cmd);
11363 +
11364 +#ifdef CONFIG_FSL_MC_BUS
11365 +#define dev_is_fsl_mc(_dev) ((_dev)->bus == &fsl_mc_bus_type)
11366 +#else
11367 +/* If fsl-mc bus is not present device cannot belong to fsl-mc bus */
11368 +#define dev_is_fsl_mc(_dev) (0)
11369 +#endif
11370 +
11371 +/* Macro to check if a device is a container device */
11372 +#define fsl_mc_is_cont_dev(_dev) (to_fsl_mc_device(_dev)->flags & \
11373 + FSL_MC_IS_DPRC)
11374 +
11375 +/* Macro to get the container device of a MC device */
11376 +#define fsl_mc_cont_dev(_dev) (fsl_mc_is_cont_dev(_dev) ? \
11377 + (_dev) : (_dev)->parent)
11378 +
11379 +#define fsl_mc_is_dev_coherent(_dev) \
11380 + (!((to_fsl_mc_device(_dev))->obj_desc.flags & \
11381 + FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY))
11382 +
11383 +/*
11384 + * module_fsl_mc_driver() - Helper macro for drivers that don't do
11385 + * anything special in module init/exit. This eliminates a lot of
11386 + * boilerplate. Each module may only use this macro once, and
11387 + * calling it replaces module_init() and module_exit()
11388 + */
11389 +#define module_fsl_mc_driver(__fsl_mc_driver) \
11390 + module_driver(__fsl_mc_driver, fsl_mc_driver_register, \
11391 + fsl_mc_driver_unregister)
11392 +
11393 +void fsl_mc_device_remove(struct fsl_mc_device *mc_dev);
11394 +
11395 +/*
11396 + * Macro to avoid include chaining to get THIS_MODULE
11397 + */
11398 +#define fsl_mc_driver_register(drv) \
11399 + __fsl_mc_driver_register(drv, THIS_MODULE)
11400 +
11401 +int __must_check __fsl_mc_driver_register(struct fsl_mc_driver *fsl_mc_driver,
11402 + struct module *owner);
11403 +
11404 +void fsl_mc_driver_unregister(struct fsl_mc_driver *driver);
11405 +
11406 +int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
11407 + u16 mc_io_flags,
11408 + struct fsl_mc_io **new_mc_io);
11409 +
11410 +void fsl_mc_portal_free(struct fsl_mc_io *mc_io);
11411 +
11412 +int fsl_mc_portal_reset(struct fsl_mc_io *mc_io);
11413 +
11414 +int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
11415 + enum fsl_mc_pool_type pool_type,
11416 + struct fsl_mc_device **new_mc_adev);
11417 +
11418 +void fsl_mc_object_free(struct fsl_mc_device *mc_adev);
11419 +
11420 +struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode,
11421 + struct msi_domain_info *info,
11422 + struct irq_domain *parent);
11423 +
11424 +int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev);
11425 +
11426 +void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev);
11427 +
11428 +extern struct bus_type fsl_mc_bus_type;
11429 +
11430 +extern struct device_type fsl_mc_bus_dprc_type;
11431 +extern struct device_type fsl_mc_bus_dpni_type;
11432 +extern struct device_type fsl_mc_bus_dpio_type;
11433 +extern struct device_type fsl_mc_bus_dpsw_type;
11434 +extern struct device_type fsl_mc_bus_dpdmux_type;
11435 +extern struct device_type fsl_mc_bus_dpbp_type;
11436 +extern struct device_type fsl_mc_bus_dpcon_type;
11437 +extern struct device_type fsl_mc_bus_dpmcp_type;
11438 +extern struct device_type fsl_mc_bus_dpmac_type;
11439 +extern struct device_type fsl_mc_bus_dprtc_type;
11440 +extern struct device_type fsl_mc_bus_dpseci_type;
11441 +extern struct device_type fsl_mc_bus_dpdcei_type;
11442 +extern struct device_type fsl_mc_bus_dpaiop_type;
11443 +extern struct device_type fsl_mc_bus_dpci_type;
11444 +extern struct device_type fsl_mc_bus_dpdmai_type;
11445 +
11446 +static inline bool is_fsl_mc_bus_dprc(const struct fsl_mc_device *mc_dev)
11447 +{
11448 + return mc_dev->dev.type == &fsl_mc_bus_dprc_type;
11449 +}
11450 +
11451 +static inline bool is_fsl_mc_bus_dpni(const struct fsl_mc_device *mc_dev)
11452 +{
11453 + return mc_dev->dev.type == &fsl_mc_bus_dpni_type;
11454 +}
11455 +
11456 +static inline bool is_fsl_mc_bus_dpio(const struct fsl_mc_device *mc_dev)
11457 +{
11458 + return mc_dev->dev.type == &fsl_mc_bus_dpio_type;
11459 +}
11460 +
11461 +static inline bool is_fsl_mc_bus_dpsw(const struct fsl_mc_device *mc_dev)
11462 +{
11463 + return mc_dev->dev.type == &fsl_mc_bus_dpsw_type;
11464 +}
11465 +
11466 +static inline bool is_fsl_mc_bus_dpdmux(const struct fsl_mc_device *mc_dev)
11467 +{
11468 + return mc_dev->dev.type == &fsl_mc_bus_dpdmux_type;
11469 +}
11470 +
11471 +static inline bool is_fsl_mc_bus_dpbp(const struct fsl_mc_device *mc_dev)
11472 +{
11473 + return mc_dev->dev.type == &fsl_mc_bus_dpbp_type;
11474 +}
11475 +
11476 +static inline bool is_fsl_mc_bus_dpcon(const struct fsl_mc_device *mc_dev)
11477 +{
11478 + return mc_dev->dev.type == &fsl_mc_bus_dpcon_type;
11479 +}
11480 +
11481 +static inline bool is_fsl_mc_bus_dpmcp(const struct fsl_mc_device *mc_dev)
11482 +{
11483 + return mc_dev->dev.type == &fsl_mc_bus_dpmcp_type;
11484 +}
11485 +
11486 +static inline bool is_fsl_mc_bus_dpmac(const struct fsl_mc_device *mc_dev)
11487 +{
11488 + return mc_dev->dev.type == &fsl_mc_bus_dpmac_type;
11489 +}
11490 +
11491 +static inline bool is_fsl_mc_bus_dprtc(const struct fsl_mc_device *mc_dev)
11492 +{
11493 + return mc_dev->dev.type == &fsl_mc_bus_dprtc_type;
11494 +}
11495 +
11496 +static inline bool is_fsl_mc_bus_dpseci(const struct fsl_mc_device *mc_dev)
11497 +{
11498 + return mc_dev->dev.type == &fsl_mc_bus_dpseci_type;
11499 +}
11500 +
11501 +static inline bool is_fsl_mc_bus_dpdcei(const struct fsl_mc_device *mc_dev)
11502 +{
11503 + return mc_dev->dev.type == &fsl_mc_bus_dpdcei_type;
11504 +}
11505 +
11506 +static inline bool is_fsl_mc_bus_dpaiop(const struct fsl_mc_device *mc_dev)
11507 +{
11508 + return mc_dev->dev.type == &fsl_mc_bus_dpaiop_type;
11509 +}
11510 +
11511 +static inline bool is_fsl_mc_bus_dpci(const struct fsl_mc_device *mc_dev)
11512 +{
11513 + return mc_dev->dev.type == &fsl_mc_bus_dpci_type;
11514 +}
11515 +
11516 +static inline bool is_fsl_mc_bus_dpdmai(const struct fsl_mc_device *mc_dev)
11517 +{
11518 + return mc_dev->dev.type == &fsl_mc_bus_dpdmai_type;
11519 +}
11520 +
11521 +/*
11522 + * Data Path Resource Container (DPRC) API
11523 + */
11524 +
11525 +/* Minimal supported DPRC Version */
11526 +#define DPRC_MIN_VER_MAJOR 6
11527 +#define DPRC_MIN_VER_MINOR 0
11528 +
11529 +/* DPRC command versioning */
11530 +#define DPRC_CMD_BASE_VERSION 1
11531 +#define DPRC_CMD_2ND_VERSION 2
11532 +#define DPRC_CMD_ID_OFFSET 4
11533 +
11534 +#define DPRC_CMD(id) (((id) << DPRC_CMD_ID_OFFSET) | DPRC_CMD_BASE_VERSION)
11535 +#define DPRC_CMD_V2(id) (((id) << DPRC_CMD_ID_OFFSET) | DPRC_CMD_2ND_VERSION)
11536 +
11537 +/* DPRC command IDs */
11538 +#define DPRC_CMDID_CLOSE DPRC_CMD(0x800)
11539 +#define DPRC_CMDID_OPEN DPRC_CMD(0x805)
11540 +#define DPRC_CMDID_GET_API_VERSION DPRC_CMD(0xa05)
11541 +
11542 +#define DPRC_CMDID_GET_ATTR DPRC_CMD(0x004)
11543 +#define DPRC_CMDID_RESET_CONT DPRC_CMD(0x005)
11544 +
11545 +#define DPRC_CMDID_SET_IRQ DPRC_CMD(0x010)
11546 +#define DPRC_CMDID_SET_IRQ_ENABLE DPRC_CMD(0x012)
11547 +#define DPRC_CMDID_SET_IRQ_MASK DPRC_CMD(0x014)
11548 +#define DPRC_CMDID_GET_IRQ_STATUS DPRC_CMD(0x016)
11549 +#define DPRC_CMDID_CLEAR_IRQ_STATUS DPRC_CMD(0x017)
11550 +
11551 +#define DPRC_CMDID_GET_CONT_ID DPRC_CMD(0x830)
11552 +#define DPRC_CMDID_GET_OBJ_COUNT DPRC_CMD(0x159)
11553 +#define DPRC_CMDID_GET_OBJ DPRC_CMD(0x15A)
11554 +#define DPRC_CMDID_GET_OBJ_REG DPRC_CMD_V2(0x15E)
11555 +#define DPRC_CMDID_SET_OBJ_IRQ DPRC_CMD(0x15F)
11556 +
11557 +struct dprc_cmd_open {
11558 + __le32 container_id;
11559 +};
11560 +
11561 +struct dprc_cmd_reset_container {
11562 + __le32 child_container_id;
11563 +};
11564 +
11565 +struct dprc_cmd_set_irq {
11566 + /* cmd word 0 */
11567 + __le32 irq_val;
11568 + u8 irq_index;
11569 + u8 pad[3];
11570 + /* cmd word 1 */
11571 + __le64 irq_addr;
11572 + /* cmd word 2 */
11573 + __le32 irq_num;
11574 +};
11575 +
11576 +#define DPRC_ENABLE 0x1
11577 +
11578 +struct dprc_cmd_set_irq_enable {
11579 + u8 enable;
11580 + u8 pad[3];
11581 + u8 irq_index;
11582 +};
11583 +
11584 +struct dprc_cmd_set_irq_mask {
11585 + __le32 mask;
11586 + u8 irq_index;
11587 +};
11588 +
11589 +struct dprc_cmd_get_irq_status {
11590 + __le32 status;
11591 + u8 irq_index;
11592 +};
11593 +
11594 +struct dprc_rsp_get_irq_status {
11595 + __le32 status;
11596 +};
11597 +
11598 +struct dprc_cmd_clear_irq_status {
11599 + __le32 status;
11600 + u8 irq_index;
11601 +};
11602 +
11603 +struct dprc_rsp_get_attributes {
11604 + /* response word 0 */
11605 + __le32 container_id;
11606 + __le32 icid;
11607 + /* response word 1 */
11608 + __le32 options;
11609 + __le32 portal_id;
11610 +};
11611 +
11612 +struct dprc_rsp_get_obj_count {
11613 + __le32 pad;
11614 + __le32 obj_count;
11615 +};
11616 +
11617 +struct dprc_cmd_get_obj {
11618 + __le32 obj_index;
11619 +};
11620 +
11621 +struct dprc_rsp_get_obj {
11622 + /* response word 0 */
11623 + __le32 pad0;
11624 + __le32 id;
11625 + /* response word 1 */
11626 + __le16 vendor;
11627 + u8 irq_count;
11628 + u8 region_count;
11629 + __le32 state;
11630 + /* response word 2 */
11631 + __le16 version_major;
11632 + __le16 version_minor;
11633 + __le16 flags;
11634 + __le16 pad1;
11635 + /* response word 3-4 */
11636 + u8 type[16];
11637 + /* response word 5-6 */
11638 + u8 label[16];
11639 +};
11640 +
11641 +struct dprc_cmd_get_obj_region {
11642 + /* cmd word 0 */
11643 + __le32 obj_id;
11644 + __le16 pad0;
11645 + u8 region_index;
11646 + u8 pad1;
11647 + /* cmd word 1-2 */
11648 + __le64 pad2[2];
11649 + /* cmd word 3-4 */
11650 + u8 obj_type[16];
11651 +};
11652 +
11653 +struct dprc_rsp_get_obj_region {
11654 + /* response word 0 */
11655 + __le64 pad0;
11656 + /* response word 1 */
11657 + __le32 base_offset;
11658 + __le32 pad1;
11659 + /* response word 2 */
11660 + __le32 size;
11661 + u8 type;
11662 + u8 pad2[3];
11663 + /* response word 3 */
11664 + __le32 flags;
11665 + __le32 pad3;
11666 + /* response word 4 */
11667 + __le64 base_addr;
11668 +};
11669 +
11670 +struct dprc_cmd_set_obj_irq {
11671 + /* cmd word 0 */
11672 + __le32 irq_val;
11673 + u8 irq_index;
11674 + u8 pad[3];
11675 + /* cmd word 1 */
11676 + __le64 irq_addr;
11677 + /* cmd word 2 */
11678 + __le32 irq_num;
11679 + __le32 obj_id;
11680 + /* cmd word 3-4 */
11681 + u8 obj_type[16];
11682 +};
11683 +
11684 +/*
11685 + * DPRC API for managing and querying DPAA resources
11686 + */
11687 +int dprc_open(struct fsl_mc_io *mc_io,
11688 + u32 cmd_flags,
11689 + int container_id,
11690 + u16 *token);
11691 +
11692 +int dprc_close(struct fsl_mc_io *mc_io,
11693 + u32 cmd_flags,
11694 + u16 token);
11695 +
11696 +/* DPRC IRQ events */
11697 +
11698 +/* IRQ event - Indicates that a new object added to the container */
11699 +#define DPRC_IRQ_EVENT_OBJ_ADDED 0x00000001
11700 +/* IRQ event - Indicates that an object was removed from the container */
11701 +#define DPRC_IRQ_EVENT_OBJ_REMOVED 0x00000002
11702 +/*
11703 + * IRQ event - Indicates that one of the descendant containers that opened by
11704 + * this container is destroyed
11705 + */
11706 +#define DPRC_IRQ_EVENT_CONTAINER_DESTROYED 0x00000010
11707 +
11708 +/*
11709 + * IRQ event - Indicates that on one of the container's opened object is
11710 + * destroyed
11711 + */
11712 +#define DPRC_IRQ_EVENT_OBJ_DESTROYED 0x00000020
11713 +
11714 +/* Irq event - Indicates that object is created at the container */
11715 +#define DPRC_IRQ_EVENT_OBJ_CREATED 0x00000040
11716 +
11717 +/**
11718 + * struct dprc_irq_cfg - IRQ configuration
11719 + * @paddr: Address that must be written to signal a message-based interrupt
11720 + * @val: Value to write into irq_addr address
11721 + * @irq_num: A user defined number associated with this IRQ
11722 + */
11723 +struct dprc_irq_cfg {
11724 + phys_addr_t paddr;
11725 + u32 val;
11726 + int irq_num;
11727 +};
11728 +
11729 +int dprc_set_irq(struct fsl_mc_io *mc_io,
11730 + u32 cmd_flags,
11731 + u16 token,
11732 + u8 irq_index,
11733 + struct dprc_irq_cfg *irq_cfg);
11734 +
11735 +int dprc_set_irq_enable(struct fsl_mc_io *mc_io,
11736 + u32 cmd_flags,
11737 + u16 token,
11738 + u8 irq_index,
11739 + u8 en);
11740 +
11741 +int dprc_set_irq_mask(struct fsl_mc_io *mc_io,
11742 + u32 cmd_flags,
11743 + u16 token,
11744 + u8 irq_index,
11745 + u32 mask);
11746 +
11747 +int dprc_get_irq_status(struct fsl_mc_io *mc_io,
11748 + u32 cmd_flags,
11749 + u16 token,
11750 + u8 irq_index,
11751 + u32 *status);
11752 +
11753 +int dprc_clear_irq_status(struct fsl_mc_io *mc_io,
11754 + u32 cmd_flags,
11755 + u16 token,
11756 + u8 irq_index,
11757 + u32 status);
11758 +
11759 +/**
11760 + * struct dprc_attributes - Container attributes
11761 + * @container_id: Container's ID
11762 + * @icid: Container's ICID
11763 + * @portal_id: Container's portal ID
11764 + * @options: Container's options as set at container's creation
11765 + */
11766 +struct dprc_attributes {
11767 + int container_id;
11768 + u32 icid;
11769 + int portal_id;
11770 + u64 options;
11771 +};
11772 +
11773 +int dprc_get_attributes(struct fsl_mc_io *mc_io,
11774 + u32 cmd_flags,
11775 + u16 token,
11776 + struct dprc_attributes *attributes);
11777 +
11778 +int dprc_get_obj_count(struct fsl_mc_io *mc_io,
11779 + u32 cmd_flags,
11780 + u16 token,
11781 + int *obj_count);
11782 +
11783 +int dprc_get_obj(struct fsl_mc_io *mc_io,
11784 + u32 cmd_flags,
11785 + u16 token,
11786 + int obj_index,
11787 + struct fsl_mc_obj_desc *obj_desc);
11788 +
11789 +int dprc_set_obj_irq(struct fsl_mc_io *mc_io,
11790 + u32 cmd_flags,
11791 + u16 token,
11792 + char *obj_type,
11793 + int obj_id,
11794 + u8 irq_index,
11795 + struct dprc_irq_cfg *irq_cfg);
11796 +
11797 +/* Region flags */
11798 +/* Cacheable - Indicates that region should be mapped as cacheable */
11799 +#define DPRC_REGION_CACHEABLE 0x00000001
11800 +#define DPRC_REGION_SHAREABLE 0x00000002
11801 +
11802 +/**
11803 + * enum dprc_region_type - Region type
11804 + * @DPRC_REGION_TYPE_MC_PORTAL: MC portal region
11805 + * @DPRC_REGION_TYPE_QBMAN_PORTAL: Qbman portal region
11806 + */
11807 +enum dprc_region_type {
11808 + DPRC_REGION_TYPE_MC_PORTAL,
11809 + DPRC_REGION_TYPE_QBMAN_PORTAL,
11810 + DPRC_REGION_TYPE_QBMAN_MEM_BACKED_PORTAL
11811 +};
11812 +
11813 +/**
11814 + * struct dprc_region_desc - Mappable region descriptor
11815 + * @base_offset: Region offset from region's base address.
11816 + * For DPMCP and DPRC objects, region base is offset from SoC MC portals
11817 + * base address; For DPIO, region base is offset from SoC QMan portals
11818 + * base address
11819 + * @size: Region size (in bytes)
11820 + * @flags: Region attributes
11821 + * @type: Portal region type
11822 + */
11823 +struct dprc_region_desc {
11824 + u32 base_offset;
11825 + u32 size;
11826 + u32 flags;
11827 + enum dprc_region_type type;
11828 + u64 base_address;
11829 +};
11830 +
11831 +int dprc_get_obj_region(struct fsl_mc_io *mc_io,
11832 + u32 cmd_flags,
11833 + u16 token,
11834 + char *obj_type,
11835 + int obj_id,
11836 + u8 region_index,
11837 + struct dprc_region_desc *region_desc);
11838 +
11839 +int dprc_get_api_version(struct fsl_mc_io *mc_io,
11840 + u32 cmd_flags,
11841 + u16 *major_ver,
11842 + u16 *minor_ver);
11843 +
11844 +int dprc_get_container_id(struct fsl_mc_io *mc_io,
11845 + u32 cmd_flags,
11846 + int *container_id);
11847 +
11848 +int dprc_reset_container(struct fsl_mc_io *mc_io,
11849 + u32 cmd_flags,
11850 + u16 token,
11851 + int child_container_id);
11852 +
11853 +/*
11854 + * Data Path Buffer Pool (DPBP) API
11855 + * Contains initialization APIs and runtime control APIs for DPBP
11856 + */
11857 +
11858 +int dpbp_open(struct fsl_mc_io *mc_io,
11859 + u32 cmd_flags,
11860 + int dpbp_id,
11861 + u16 *token);
11862 +
11863 +int dpbp_close(struct fsl_mc_io *mc_io,
11864 + u32 cmd_flags,
11865 + u16 token);
11866 +
11867 +int dpbp_enable(struct fsl_mc_io *mc_io,
11868 + u32 cmd_flags,
11869 + u16 token);
11870 +
11871 +int dpbp_disable(struct fsl_mc_io *mc_io,
11872 + u32 cmd_flags,
11873 + u16 token);
11874 +
11875 +int dpbp_reset(struct fsl_mc_io *mc_io,
11876 + u32 cmd_flags,
11877 + u16 token);
11878 +
11879 +/**
11880 + * struct dpbp_attr - Structure representing DPBP attributes
11881 + * @id: DPBP object ID
11882 + * @bpid: Hardware buffer pool ID; should be used as an argument in
11883 + * acquire/release operations on buffers
11884 + */
11885 +struct dpbp_attr {
11886 + int id;
11887 + u16 bpid;
11888 +};
11889 +
11890 +int dpbp_get_attributes(struct fsl_mc_io *mc_io,
11891 + u32 cmd_flags,
11892 + u16 token,
11893 + struct dpbp_attr *attr);
11894 +
11895 +/* Data Path Concentrator (DPCON) API
11896 + * Contains initialization APIs and runtime control APIs for DPCON
11897 + */
11898 +
11899 +/**
11900 + * Use it to disable notifications; see dpcon_set_notification()
11901 + */
11902 +#define DPCON_INVALID_DPIO_ID (int)(-1)
11903 +
11904 +int dpcon_open(struct fsl_mc_io *mc_io,
11905 + u32 cmd_flags,
11906 + int dpcon_id,
11907 + u16 *token);
11908 +
11909 +int dpcon_close(struct fsl_mc_io *mc_io,
11910 + u32 cmd_flags,
11911 + u16 token);
11912 +
11913 +int dpcon_enable(struct fsl_mc_io *mc_io,
11914 + u32 cmd_flags,
11915 + u16 token);
11916 +
11917 +int dpcon_disable(struct fsl_mc_io *mc_io,
11918 + u32 cmd_flags,
11919 + u16 token);
11920 +
11921 +int dpcon_reset(struct fsl_mc_io *mc_io,
11922 + u32 cmd_flags,
11923 + u16 token);
11924 +
11925 +/**
11926 + * struct dpcon_attr - Structure representing DPCON attributes
11927 + * @id: DPCON object ID
11928 + * @qbman_ch_id: Channel ID to be used by dequeue operation
11929 + * @num_priorities: Number of priorities for the DPCON channel (1-8)
11930 + */
11931 +struct dpcon_attr {
11932 + int id;
11933 + u16 qbman_ch_id;
11934 + u8 num_priorities;
11935 +};
11936 +
11937 +int dpcon_get_attributes(struct fsl_mc_io *mc_io,
11938 + u32 cmd_flags,
11939 + u16 token,
11940 + struct dpcon_attr *attr);
11941 +
11942 +/**
11943 + * struct dpcon_notification_cfg - Structure representing notification params
11944 + * @dpio_id: DPIO object ID; must be configured with a notification channel;
11945 + * to disable notifications set it to 'DPCON_INVALID_DPIO_ID';
11946 + * @priority: Priority selection within the DPIO channel; valid values
11947 + * are 0-7, depending on the number of priorities in that channel
11948 + * @user_ctx: User context value provided with each CDAN message
11949 + */
11950 +struct dpcon_notification_cfg {
11951 + int dpio_id;
11952 + u8 priority;
11953 + u64 user_ctx;
11954 +};
11955 +
11956 +int dpcon_set_notification(struct fsl_mc_io *mc_io,
11957 + u32 cmd_flags,
11958 + u16 token,
11959 + struct dpcon_notification_cfg *cfg);
11960 +
11961 +struct irq_domain;
11962 +struct msi_domain_info;
11963 +
11964 +/**
11965 + * Maximum number of total IRQs that can be pre-allocated for an MC bus'
11966 + * IRQ pool
11967 + */
11968 +#define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256
11969 +
11970 +/**
11971 + * struct fsl_mc_resource_pool - Pool of MC resources of a given
11972 + * type
11973 + * @type: type of resources in the pool
11974 + * @max_count: maximum number of resources in the pool
11975 + * @free_count: number of free resources in the pool
11976 + * @mutex: mutex to serialize access to the pool's free list
11977 + * @free_list: anchor node of list of free resources in the pool
11978 + * @mc_bus: pointer to the MC bus that owns this resource pool
11979 + */
11980 +struct fsl_mc_resource_pool {
11981 + enum fsl_mc_pool_type type;
11982 + int max_count;
11983 + int free_count;
11984 + struct mutex mutex; /* serializes access to free_list */
11985 + struct list_head free_list;
11986 + struct fsl_mc_bus *mc_bus;
11987 +};
11988 +
11989 +/**
11990 + * struct fsl_mc_restool - information associated with a restool device file
11991 + * @cdev: struct char device linked to the root dprc
11992 + * @dev: dev_t for the char device to be added
11993 + * @device: newly created device in /dev
11994 + * @mutex: mutex lock to serialize the open/release operations
11995 + * @local_instance_in_use: local MC I/O instance in use or not
11996 + * @dynamic_instance_count: number of dynamically created MC I/O instances
11997 + */
11998 +struct fsl_mc_restool {
11999 + struct cdev cdev;
12000 + dev_t dev;
12001 + struct device *device;
12002 + struct mutex mutex; /* serialize open/release operations */
12003 + bool local_instance_in_use;
12004 + u32 dynamic_instance_count;
12005 +};
12006 +
12007 +/**
12008 + * struct fsl_mc_bus - logical bus that corresponds to a physical DPRC
12009 + * @mc_dev: fsl-mc device for the bus device itself.
12010 + * @resource_pools: array of resource pools (one pool per resource type)
12011 + * for this MC bus. These resources represent allocatable entities
12012 + * from the physical DPRC.
12013 + * @irq_resources: Pointer to array of IRQ objects for the IRQ pool
12014 + * @scan_mutex: Serializes bus scanning
12015 + * @dprc_attr: DPRC attributes
12016 + * @restool_misc: struct that abstracts the interaction with userspace restool
12017 + */
12018 +struct fsl_mc_bus {
12019 + struct fsl_mc_device mc_dev;
12020 + struct fsl_mc_resource_pool resource_pools[FSL_MC_NUM_POOL_TYPES];
12021 + struct fsl_mc_device_irq *irq_resources;
12022 + struct mutex scan_mutex; /* serializes bus scanning */
12023 + struct dprc_attributes dprc_attr;
12024 + struct fsl_mc_restool restool_misc;
12025 +};
12026 +
12027 +int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
12028 + const char *driver_override,
12029 + unsigned int *total_irq_count);
12030 +
12031 +int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
12032 + struct irq_domain **mc_msi_domain);
12033 +
12034 +int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
12035 + unsigned int irq_count);
12036 +
12037 +void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus);
12038 +
12039 +void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev);
12040 +
12041 +void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev);
12042 +
12043 +void fsl_mc_get_root_dprc(struct device *dev, struct device **root_dprc_dev);
12044 +
12045 +#endif /* _FSL_MC_H_ */
12046 --- /dev/null
12047 +++ b/include/uapi/linux/fsl_mc.h
12048 @@ -0,0 +1,31 @@
12049 +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
12050 +/*
12051 + * Management Complex (MC) userspace public interface
12052 + *
12053 + * Copyright 2018 NXP
12054 + *
12055 + */
12056 +#ifndef _UAPI_FSL_MC_H_
12057 +#define _UAPI_FSL_MC_H_
12058 +
12059 +#define MC_CMD_NUM_OF_PARAMS 7
12060 +
12061 +/**
12062 + * struct fsl_mc_command - Management Complex (MC) command structure
12063 + * @header: MC command header
12064 + * @params: MC command parameters
12065 + *
12066 + * Used by RESTOOL_SEND_MC_COMMAND
12067 + */
12068 +struct fsl_mc_command {
12069 + __u64 header;
12070 + __u64 params[MC_CMD_NUM_OF_PARAMS];
12071 +};
12072 +
12073 +#define RESTOOL_IOCTL_TYPE 'R'
12074 +#define RESTOOL_IOCTL_SEQ 0xE0
12075 +
12076 +#define RESTOOL_SEND_MC_COMMAND \
12077 + _IOWR(RESTOOL_IOCTL_TYPE, RESTOOL_IOCTL_SEQ, struct fsl_mc_command)
12078 +
12079 +#endif /* _UAPI_FSL_MC_H_ */