layerscape: define ls-append function
[openwrt/openwrt.git] / target / linux / layerscape / patches-4.9 / 704-fsl-mc-layerscape-support.patch
1 From ab7b47676f9334bb55f80e0ac096c7aa289810e2 Mon Sep 17 00:00:00 2001
2 From: Yangbo Lu <yangbo.lu@nxp.com>
3 Date: Thu, 5 Jul 2018 16:44:34 +0800
4 Subject: [PATCH 10/32] fsl-mc: layerscape support
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 for layerscape mc-bus support.
10
11 Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>
12 Signed-off-by: Bharat Bhushan <Bharat.Bhushan@nxp.com>
13 Signed-off-by: Arnd Bergmann <arnd@arndb.de>
14 Signed-off-by: Laurentiu Tudor <laurentiu.tudor@nxp.com>
15 Signed-off-by: Roy Pledge <roy.pledge@nxp.com>
16 Signed-off-by: Shiva Kerdel <shiva@exdev.nl>
17 Signed-off-by: Nipun Gupta <nipun.gupta@nxp.com>
18 Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
19 Signed-off-by: Horia Geantă <horia.geanta@nxp.com>
20 Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
21 ---
22 Documentation/ABI/stable/sysfs-bus-fsl-mc | 13 +
23 Documentation/ioctl/ioctl-number.txt | 1 +
24 Documentation/networking/dpaa2/index.rst | 8 +
25 Documentation/networking/dpaa2/overview.rst | 408 +++++
26 MAINTAINERS | 11 +-
27 drivers/bus/Kconfig | 3 +
28 drivers/bus/Makefile | 4 +
29 drivers/bus/fsl-mc/Kconfig | 23 +
30 drivers/bus/fsl-mc/Makefile | 22 +
31 drivers/bus/fsl-mc/dpbp.c | 186 +++
32 drivers/bus/fsl-mc/dpcon.c | 222 +++
33 drivers/bus/fsl-mc/dpmcp.c | 99 ++
34 .../fsl-mc/bus => bus/fsl-mc}/dprc-driver.c | 180 ++-
35 drivers/bus/fsl-mc/dprc.c | 575 +++++++
36 .../bus => bus/fsl-mc}/fsl-mc-allocator.c | 195 ++-
37 .../fsl-mc/bus => bus/fsl-mc}/fsl-mc-bus.c | 523 +++++--
38 drivers/bus/fsl-mc/fsl-mc-iommu.c | 78 +
39 .../fsl-mc/bus => bus/fsl-mc}/fsl-mc-msi.c | 34 +-
40 drivers/bus/fsl-mc/fsl-mc-private.h | 223 +++
41 drivers/bus/fsl-mc/fsl-mc-restool.c | 219 +++
42 .../fsl-mc/bus => bus/fsl-mc}/mc-io.c | 80 +-
43 .../fsl-mc/bus => bus/fsl-mc}/mc-sys.c | 105 +-
44 drivers/irqchip/Kconfig | 6 +
45 drivers/irqchip/Makefile | 1 +
46 .../irq-gic-v3-its-fsl-mc-msi.c | 52 +-
47 drivers/staging/fsl-mc/Kconfig | 1 +
48 drivers/staging/fsl-mc/Makefile | 1 +
49 drivers/staging/fsl-mc/TODO | 18 -
50 drivers/staging/fsl-mc/bus/Kconfig | 37 +-
51 drivers/staging/fsl-mc/bus/Makefile | 17 +-
52 drivers/staging/fsl-mc/bus/dpbp.c | 691 --------
53 drivers/staging/fsl-mc/bus/dpio/Makefile | 8 +
54 drivers/staging/fsl-mc/bus/dpio/dpio-cmd.h | 50 +
55 drivers/staging/fsl-mc/bus/dpio/dpio-driver.c | 278 ++++
56 .../staging/fsl-mc/bus/dpio/dpio-service.c | 780 +++++++++
57 drivers/staging/fsl-mc/bus/dpio/dpio.c | 221 +++
58 drivers/staging/fsl-mc/bus/dpio/dpio.h | 87 ++
59 .../staging/fsl-mc/bus/dpio/qbman-portal.c | 1164 ++++++++++++++
60 .../staging/fsl-mc/bus/dpio/qbman-portal.h | 505 ++++++
61 drivers/staging/fsl-mc/bus/dpmcp-cmd.h | 140 --
62 drivers/staging/fsl-mc/bus/dpmcp.c | 504 ------
63 drivers/staging/fsl-mc/bus/dpmcp.h | 159 --
64 drivers/staging/fsl-mc/bus/dpmng-cmd.h | 58 -
65 drivers/staging/fsl-mc/bus/dpmng.c | 107 --
66 drivers/staging/fsl-mc/bus/dprc-cmd.h | 465 ------
67 drivers/staging/fsl-mc/bus/dprc.c | 1388 -----------------
68 drivers/staging/fsl-mc/bus/fsl-mc-private.h | 52 -
69 drivers/staging/fsl-mc/include/dpaa2-fd.h | 681 ++++++++
70 drivers/staging/fsl-mc/include/dpaa2-global.h | 177 +++
71 drivers/staging/fsl-mc/include/dpaa2-io.h | 178 +++
72 drivers/staging/fsl-mc/include/dpbp-cmd.h | 185 ---
73 drivers/staging/fsl-mc/include/dpbp.h | 220 ---
74 drivers/staging/fsl-mc/include/dpcon-cmd.h | 62 -
75 drivers/staging/fsl-mc/include/dpmng.h | 69 -
76 drivers/staging/fsl-mc/include/dpopr.h | 112 ++
77 drivers/staging/fsl-mc/include/dprc.h | 544 -------
78 drivers/staging/fsl-mc/include/mc-bus.h | 111 --
79 drivers/staging/fsl-mc/include/mc-cmd.h | 108 --
80 drivers/staging/fsl-mc/include/mc-sys.h | 98 --
81 drivers/staging/fsl-mc/include/mc.h | 201 ---
82 include/linux/fsl/mc.h | 1025 ++++++++++++
83 include/uapi/linux/fsl_mc.h | 31 +
84 62 files changed, 8068 insertions(+), 5736 deletions(-)
85 create mode 100644 Documentation/ABI/stable/sysfs-bus-fsl-mc
86 create mode 100644 Documentation/networking/dpaa2/index.rst
87 create mode 100644 Documentation/networking/dpaa2/overview.rst
88 create mode 100644 drivers/bus/fsl-mc/Kconfig
89 create mode 100644 drivers/bus/fsl-mc/Makefile
90 create mode 100644 drivers/bus/fsl-mc/dpbp.c
91 create mode 100644 drivers/bus/fsl-mc/dpcon.c
92 create mode 100644 drivers/bus/fsl-mc/dpmcp.c
93 rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dprc-driver.c (84%)
94 create mode 100644 drivers/bus/fsl-mc/dprc.c
95 rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-allocator.c (71%)
96 rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-bus.c (64%)
97 create mode 100644 drivers/bus/fsl-mc/fsl-mc-iommu.c
98 rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-msi.c (89%)
99 create mode 100644 drivers/bus/fsl-mc/fsl-mc-private.h
100 create mode 100644 drivers/bus/fsl-mc/fsl-mc-restool.c
101 rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/mc-io.c (68%)
102 rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/mc-sys.c (66%)
103 rename drivers/{staging/fsl-mc/bus => irqchip}/irq-gic-v3-its-fsl-mc-msi.c (60%)
104 delete mode 100644 drivers/staging/fsl-mc/TODO
105 delete mode 100644 drivers/staging/fsl-mc/bus/dpbp.c
106 create mode 100644 drivers/staging/fsl-mc/bus/dpio/Makefile
107 create mode 100644 drivers/staging/fsl-mc/bus/dpio/dpio-cmd.h
108 create mode 100644 drivers/staging/fsl-mc/bus/dpio/dpio-driver.c
109 create mode 100644 drivers/staging/fsl-mc/bus/dpio/dpio-service.c
110 create mode 100644 drivers/staging/fsl-mc/bus/dpio/dpio.c
111 create mode 100644 drivers/staging/fsl-mc/bus/dpio/dpio.h
112 create mode 100644 drivers/staging/fsl-mc/bus/dpio/qbman-portal.c
113 create mode 100644 drivers/staging/fsl-mc/bus/dpio/qbman-portal.h
114 delete mode 100644 drivers/staging/fsl-mc/bus/dpmcp-cmd.h
115 delete mode 100644 drivers/staging/fsl-mc/bus/dpmcp.c
116 delete mode 100644 drivers/staging/fsl-mc/bus/dpmcp.h
117 delete mode 100644 drivers/staging/fsl-mc/bus/dpmng-cmd.h
118 delete mode 100644 drivers/staging/fsl-mc/bus/dpmng.c
119 delete mode 100644 drivers/staging/fsl-mc/bus/dprc-cmd.h
120 delete mode 100644 drivers/staging/fsl-mc/bus/dprc.c
121 delete mode 100644 drivers/staging/fsl-mc/bus/fsl-mc-private.h
122 create mode 100644 drivers/staging/fsl-mc/include/dpaa2-fd.h
123 create mode 100644 drivers/staging/fsl-mc/include/dpaa2-global.h
124 create mode 100644 drivers/staging/fsl-mc/include/dpaa2-io.h
125 delete mode 100644 drivers/staging/fsl-mc/include/dpbp-cmd.h
126 delete mode 100644 drivers/staging/fsl-mc/include/dpbp.h
127 delete mode 100644 drivers/staging/fsl-mc/include/dpcon-cmd.h
128 delete mode 100644 drivers/staging/fsl-mc/include/dpmng.h
129 create mode 100644 drivers/staging/fsl-mc/include/dpopr.h
130 delete mode 100644 drivers/staging/fsl-mc/include/dprc.h
131 delete mode 100644 drivers/staging/fsl-mc/include/mc-bus.h
132 delete mode 100644 drivers/staging/fsl-mc/include/mc-cmd.h
133 delete mode 100644 drivers/staging/fsl-mc/include/mc-sys.h
134 delete mode 100644 drivers/staging/fsl-mc/include/mc.h
135 create mode 100644 include/linux/fsl/mc.h
136 create mode 100644 include/uapi/linux/fsl_mc.h
137
138 --- /dev/null
139 +++ b/Documentation/ABI/stable/sysfs-bus-fsl-mc
140 @@ -0,0 +1,13 @@
141 +What: /sys/bus/fsl-mc/devices/dprc.*/rescan
142 +Date: March. 2018
143 +KernelVersion: 4.16
144 +Contact: Ioana Ciornei <ioana.ciornei@nxp.com>
145 +Description: Root dprc rescan attribute
146 +Users: Userspace drivers and management tools
147 +
148 +What: /sys/bus/fsl-mc/rescan
149 +Date: March. 2018
150 +KernelVersion: 4.16
151 +Contact: Ioana Ciornei <ioana.ciornei@nxp.com>
152 +Description: Bus rescan attribute
153 +Users: Userspace drivers and management tools
154 --- a/Documentation/ioctl/ioctl-number.txt
155 +++ b/Documentation/ioctl/ioctl-number.txt
156 @@ -170,6 +170,7 @@ Code Seq#(hex) Include File Comments
157 'R' 00-1F linux/random.h conflict!
158 'R' 01 linux/rfkill.h conflict!
159 'R' C0-DF net/bluetooth/rfcomm.h
160 +'R' E0 uapi/linux/fsl_mc.h
161 'S' all linux/cdrom.h conflict!
162 'S' 80-81 scsi/scsi_ioctl.h conflict!
163 'S' 82-FF scsi/scsi.h conflict!
164 --- /dev/null
165 +++ b/Documentation/networking/dpaa2/index.rst
166 @@ -0,0 +1,8 @@
167 +===================
168 +DPAA2 Documentation
169 +===================
170 +
171 +.. toctree::
172 + :maxdepth: 1
173 +
174 + overview
175 --- /dev/null
176 +++ b/Documentation/networking/dpaa2/overview.rst
177 @@ -0,0 +1,408 @@
178 +.. include:: <isonum.txt>
179 +
180 +DPAA2 (Data Path Acceleration Architecture Gen2) Overview
181 +=========================================================
182 +
183 +:Copyright: |copy| 2015 Freescale Semiconductor Inc.
184 +:Copyright: |copy| 2018 NXP
185 +
186 +This document provides an overview of the Freescale DPAA2 architecture
187 +and how it is integrated into the Linux kernel.
188 +
189 +Introduction
190 +============
191 +
192 +DPAA2 is a hardware architecture designed for high-speeed network
193 +packet processing. DPAA2 consists of sophisticated mechanisms for
194 +processing Ethernet packets, queue management, buffer management,
195 +autonomous L2 switching, virtual Ethernet bridging, and accelerator
196 +(e.g. crypto) sharing.
197 +
198 +A DPAA2 hardware component called the Management Complex (or MC) manages the
199 +DPAA2 hardware resources. The MC provides an object-based abstraction for
200 +software drivers to use the DPAA2 hardware.
201 +The MC uses DPAA2 hardware resources such as queues, buffer pools, and
202 +network ports to create functional objects/devices such as network
203 +interfaces, an L2 switch, or accelerator instances.
204 +The MC provides memory-mapped I/O command interfaces (MC portals)
205 +which DPAA2 software drivers use to operate on DPAA2 objects.
206 +
207 +The diagram below shows an overview of the DPAA2 resource management
208 +architecture::
209 +
210 + +--------------------------------------+
211 + | OS |
212 + | DPAA2 drivers |
213 + | | |
214 + +-----------------------------|--------+
215 + |
216 + | (create,discover,connect
217 + | config,use,destroy)
218 + |
219 + DPAA2 |
220 + +------------------------| mc portal |-+
221 + | | |
222 + | +- - - - - - - - - - - - -V- - -+ |
223 + | | | |
224 + | | Management Complex (MC) | |
225 + | | | |
226 + | +- - - - - - - - - - - - - - - -+ |
227 + | |
228 + | Hardware Hardware |
229 + | Resources Objects |
230 + | --------- ------- |
231 + | -queues -DPRC |
232 + | -buffer pools -DPMCP |
233 + | -Eth MACs/ports -DPIO |
234 + | -network interface -DPNI |
235 + | profiles -DPMAC |
236 + | -queue portals -DPBP |
237 + | -MC portals ... |
238 + | ... |
239 + | |
240 + +--------------------------------------+
241 +
242 +
243 +The MC mediates operations such as create, discover,
244 +connect, configuration, and destroy. Fast-path operations
245 +on data, such as packet transmit/receive, are not mediated by
246 +the MC and are done directly using memory mapped regions in
247 +DPIO objects.
248 +
249 +Overview of DPAA2 Objects
250 +=========================
251 +
252 +The section provides a brief overview of some key DPAA2 objects.
253 +A simple scenario is described illustrating the objects involved
254 +in creating a network interfaces.
255 +
256 +DPRC (Datapath Resource Container)
257 +----------------------------------
258 +
259 +A DPRC is a container object that holds all the other
260 +types of DPAA2 objects. In the example diagram below there
261 +are 8 objects of 5 types (DPMCP, DPIO, DPBP, DPNI, and DPMAC)
262 +in the container.
263 +
264 +::
265 +
266 + +---------------------------------------------------------+
267 + | DPRC |
268 + | |
269 + | +-------+ +-------+ +-------+ +-------+ +-------+ |
270 + | | DPMCP | | DPIO | | DPBP | | DPNI | | DPMAC | |
271 + | +-------+ +-------+ +-------+ +---+---+ +---+---+ |
272 + | | DPMCP | | DPIO | |
273 + | +-------+ +-------+ |
274 + | | DPMCP | |
275 + | +-------+ |
276 + | |
277 + +---------------------------------------------------------+
278 +
279 +From the point of view of an OS, a DPRC behaves similar to a plug and
280 +play bus, like PCI. DPRC commands can be used to enumerate the contents
281 +of the DPRC, discover the hardware objects present (including mappable
282 +regions and interrupts).
283 +
284 +::
285 +
286 + DPRC.1 (bus)
287 + |
288 + +--+--------+-------+-------+-------+
289 + | | | | |
290 + DPMCP.1 DPIO.1 DPBP.1 DPNI.1 DPMAC.1
291 + DPMCP.2 DPIO.2
292 + DPMCP.3
293 +
294 +Hardware objects can be created and destroyed dynamically, providing
295 +the ability to hot plug/unplug objects in and out of the DPRC.
296 +
297 +A DPRC has a mappable MMIO region (an MC portal) that can be used
298 +to send MC commands. It has an interrupt for status events (like
299 +hotplug).
300 +All objects in a container share the same hardware "isolation context".
301 +This means that with respect to an IOMMU the isolation granularity
302 +is at the DPRC (container) level, not at the individual object
303 +level.
304 +
305 +DPRCs can be defined statically and populated with objects
306 +via a config file passed to the MC when firmware starts it.
307 +There is also a Linux user space tool called "restool" that can be
308 +used to create/destroy containers and objects dynamically. The latest
309 +version of restool can be found at:
310 + https://github.com/qoriq-open-source/restool
311 +
312 +DPAA2 Objects for an Ethernet Network Interface
313 +-----------------------------------------------
314 +
315 +A typical Ethernet NIC is monolithic-- the NIC device contains TX/RX
316 +queuing mechanisms, configuration mechanisms, buffer management,
317 +physical ports, and interrupts. DPAA2 uses a more granular approach
318 +utilizing multiple hardware objects. Each object provides specialized
319 +functions. Groups of these objects are used by software to provide
320 +Ethernet network interface functionality. This approach provides
321 +efficient use of finite hardware resources, flexibility, and
322 +performance advantages.
323 +
324 +The diagram below shows the objects needed for a simple
325 +network interface configuration on a system with 2 CPUs.
326 +
327 +::
328 +
329 + +---+---+ +---+---+
330 + CPU0 CPU1
331 + +---+---+ +---+---+
332 + | |
333 + +---+---+ +---+---+
334 + DPIO DPIO
335 + +---+---+ +---+---+
336 + \ /
337 + \ /
338 + \ /
339 + +---+---+
340 + DPNI --- DPBP,DPMCP
341 + +---+---+
342 + |
343 + |
344 + +---+---+
345 + DPMAC
346 + +---+---+
347 + |
348 + port/PHY
349 +
350 +Below the objects are described. For each object a brief description
351 +is provided along with a summary of the kinds of operations the object
352 +supports and a summary of key resources of the object (MMIO regions
353 +and IRQs).
354 +
355 +DPMAC (Datapath Ethernet MAC)
356 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
357 +Represents an Ethernet MAC, a hardware device that connects to an Ethernet
358 +PHY and allows physical transmission and reception of Ethernet frames.
359 +
360 +- MMIO regions: none
361 +- IRQs: DPNI link change
362 +- commands: set link up/down, link config, get stats,
363 + IRQ config, enable, reset
364 +
365 +DPNI (Datapath Network Interface)
366 +Contains TX/RX queues, network interface configuration, and RX buffer pool
367 +configuration mechanisms. The TX/RX queues are in memory and are identified
368 +by queue number.
369 +
370 +- MMIO regions: none
371 +- IRQs: link state
372 +- commands: port config, offload config, queue config,
373 + parse/classify config, IRQ config, enable, reset
374 +
375 +DPIO (Datapath I/O)
376 +~~~~~~~~~~~~~~~~~~~
377 +Provides interfaces to enqueue and dequeue
378 +packets and do hardware buffer pool management operations. The DPAA2
379 +architecture separates the mechanism to access queues (the DPIO object)
380 +from the queues themselves. The DPIO provides an MMIO interface to
381 +enqueue/dequeue packets. To enqueue something a descriptor is written
382 +to the DPIO MMIO region, which includes the target queue number.
383 +There will typically be one DPIO assigned to each CPU. This allows all
384 +CPUs to simultaneously perform enqueue/dequeued operations. DPIOs are
385 +expected to be shared by different DPAA2 drivers.
386 +
387 +- MMIO regions: queue operations, buffer management
388 +- IRQs: data availability, congestion notification, buffer
389 + pool depletion
390 +- commands: IRQ config, enable, reset
391 +
392 +DPBP (Datapath Buffer Pool)
393 +~~~~~~~~~~~~~~~~~~~~~~~~~~~
394 +Represents a hardware buffer pool.
395 +
396 +- MMIO regions: none
397 +- IRQs: none
398 +- commands: enable, reset
399 +
400 +DPMCP (Datapath MC Portal)
401 +~~~~~~~~~~~~~~~~~~~~~~~~~~
402 +Provides an MC command portal.
403 +Used by drivers to send commands to the MC to manage
404 +objects.
405 +
406 +- MMIO regions: MC command portal
407 +- IRQs: command completion
408 +- commands: IRQ config, enable, reset
409 +
410 +Object Connections
411 +==================
412 +Some objects have explicit relationships that must
413 +be configured:
414 +
415 +- DPNI <--> DPMAC
416 +- DPNI <--> DPNI
417 +- DPNI <--> L2-switch-port
418 +
419 + A DPNI must be connected to something such as a DPMAC,
420 + another DPNI, or L2 switch port. The DPNI connection
421 + is made via a DPRC command.
422 +
423 +::
424 +
425 + +-------+ +-------+
426 + | DPNI | | DPMAC |
427 + +---+---+ +---+---+
428 + | |
429 + +==========+
430 +
431 +- DPNI <--> DPBP
432 +
433 + A network interface requires a 'buffer pool' (DPBP
434 + object) which provides a list of pointers to memory
435 + where received Ethernet data is to be copied. The
436 + Ethernet driver configures the DPBPs associated with
437 + the network interface.
438 +
439 +Interrupts
440 +==========
441 +All interrupts generated by DPAA2 objects are message
442 +interrupts. At the hardware level message interrupts
443 +generated by devices will normally have 3 components--
444 +1) a non-spoofable 'device-id' expressed on the hardware
445 +bus, 2) an address, 3) a data value.
446 +
447 +In the case of DPAA2 devices/objects, all objects in the
448 +same container/DPRC share the same 'device-id'.
449 +For ARM-based SoC this is the same as the stream ID.
450 +
451 +
452 +DPAA2 Linux Drivers Overview
453 +============================
454 +
455 +This section provides an overview of the Linux kernel drivers for
456 +DPAA2-- 1) the bus driver and associated "DPAA2 infrastructure"
457 +drivers and 2) functional object drivers (such as Ethernet).
458 +
459 +As described previously, a DPRC is a container that holds the other
460 +types of DPAA2 objects. It is functionally similar to a plug-and-play
461 +bus controller.
462 +Each object in the DPRC is a Linux "device" and is bound to a driver.
463 +The diagram below shows the Linux drivers involved in a networking
464 +scenario and the objects bound to each driver. A brief description
465 +of each driver follows.
466 +
467 +::
468 +
469 + +------------+
470 + | OS Network |
471 + | Stack |
472 + +------------+ +------------+
473 + | Allocator |. . . . . . . | Ethernet |
474 + |(DPMCP,DPBP)| | (DPNI) |
475 + +-.----------+ +---+---+----+
476 + . . ^ |
477 + . . <data avail, | | <enqueue,
478 + . . tx confirm> | | dequeue>
479 + +-------------+ . | |
480 + | DPRC driver | . +---+---V----+ +---------+
481 + | (DPRC) | . . . . . .| DPIO driver| | MAC |
482 + +----------+--+ | (DPIO) | | (DPMAC) |
483 + | +------+-----+ +-----+---+
484 + |<dev add/remove> | |
485 + | | |
486 + +--------+----------+ | +--+---+
487 + | MC-bus driver | | | PHY |
488 + | | | |driver|
489 + | /bus/fsl-mc | | +--+---+
490 + +-------------------+ | |
491 + | |
492 + ========================= HARDWARE =========|=================|======
493 + DPIO |
494 + | |
495 + DPNI---DPBP |
496 + | |
497 + DPMAC |
498 + | |
499 + PHY ---------------+
500 + ============================================|========================
501 +
502 +A brief description of each driver is provided below.
503 +
504 +MC-bus driver
505 +-------------
506 +The MC-bus driver is a platform driver and is probed from a
507 +node in the device tree (compatible "fsl,qoriq-mc") passed in by boot
508 +firmware. It is responsible for bootstrapping the DPAA2 kernel
509 +infrastructure.
510 +Key functions include:
511 +
512 +- registering a new bus type named "fsl-mc" with the kernel,
513 + and implementing bus call-backs (e.g. match/uevent/dev_groups)
514 +- implementing APIs for DPAA2 driver registration and for device
515 + add/remove
516 +- creates an MSI IRQ domain
517 +- doing a 'device add' to expose the 'root' DPRC, in turn triggering
518 + a bind of the root DPRC to the DPRC driver
519 +
520 +The binding for the MC-bus device-tree node can be consulted at
521 +*Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt*.
522 +The sysfs bind/unbind interfaces for the MC-bus can be consulted at
523 +*Documentation/ABI/testing/sysfs-bus-fsl-mc*.
524 +
525 +DPRC driver
526 +-----------
527 +The DPRC driver is bound to DPRC objects and does runtime management
528 +of a bus instance. It performs the initial bus scan of the DPRC
529 +and handles interrupts for container events such as hot plug by
530 +re-scanning the DPRC.
531 +
532 +Allocator
533 +---------
534 +Certain objects such as DPMCP and DPBP are generic and fungible,
535 +and are intended to be used by other drivers. For example,
536 +the DPAA2 Ethernet driver needs:
537 +
538 +- DPMCPs to send MC commands, to configure network interfaces
539 +- DPBPs for network buffer pools
540 +
541 +The allocator driver registers for these allocatable object types
542 +and those objects are bound to the allocator when the bus is probed.
543 +The allocator maintains a pool of objects that are available for
544 +allocation by other DPAA2 drivers.
545 +
546 +DPIO driver
547 +-----------
548 +The DPIO driver is bound to DPIO objects and provides services that allow
549 +other drivers such as the Ethernet driver to enqueue and dequeue data for
550 +their respective objects.
551 +Key services include:
552 +
553 +- data availability notifications
554 +- hardware queuing operations (enqueue and dequeue of data)
555 +- hardware buffer pool management
556 +
557 +To transmit a packet the Ethernet driver puts data on a queue and
558 +invokes a DPIO API. For receive, the Ethernet driver registers
559 +a data availability notification callback. To dequeue a packet
560 +a DPIO API is used.
561 +There is typically one DPIO object per physical CPU for optimum
562 +performance, allowing different CPUs to simultaneously enqueue
563 +and dequeue data.
564 +
565 +The DPIO driver operates on behalf of all DPAA2 drivers
566 +active in the kernel-- Ethernet, crypto, compression,
567 +etc.
568 +
569 +Ethernet driver
570 +---------------
571 +The Ethernet driver is bound to a DPNI and implements the kernel
572 +interfaces needed to connect the DPAA2 network interface to
573 +the network stack.
574 +Each DPNI corresponds to a Linux network interface.
575 +
576 +MAC driver
577 +----------
578 +An Ethernet PHY is an off-chip, board specific component and is managed
579 +by the appropriate PHY driver via an mdio bus. The MAC driver
580 +plays a role of being a proxy between the PHY driver and the
581 +MC. It does this proxy via the MC commands to a DPMAC object.
582 +If the PHY driver signals a link change, the MAC driver notifies
583 +the MC via a DPMAC command. If a network interface is brought
584 +up or down, the MC notifies the DPMAC driver via an interrupt and
585 +the driver can take appropriate action.
586 --- a/MAINTAINERS
587 +++ b/MAINTAINERS
588 @@ -3980,6 +3980,12 @@ S: Maintained
589 F: drivers/char/dtlk.c
590 F: include/linux/dtlk.h
591
592 +DPAA2 DATAPATH I/O (DPIO) DRIVER
593 +M: Roy Pledge <Roy.Pledge@nxp.com>
594 +L: linux-kernel@vger.kernel.org
595 +S: Maintained
596 +F: drivers/staging/fsl-mc/bus/dpio
597 +
598 DPT_I2O SCSI RAID DRIVER
599 M: Adaptec OEM Raid Solutions <aacraid@adaptec.com>
600 L: linux-scsi@vger.kernel.org
601 @@ -5110,7 +5116,10 @@ M: "J. German Rivera" <German.Rivera@fre
602 M: Stuart Yoder <stuart.yoder@nxp.com>
603 L: linux-kernel@vger.kernel.org
604 S: Maintained
605 -F: drivers/staging/fsl-mc/
606 +F: drivers/bus/fsl-mc/
607 +F: Documentation/networking/dpaa2/overview.rst
608 +F: include/uapi/linux/fsl_mc.h
609 +F: Documentation/ABI/stable/sysfs-bus-fsl-mc
610
611 FREEVXFS FILESYSTEM
612 M: Christoph Hellwig <hch@infradead.org>
613 --- a/drivers/bus/Kconfig
614 +++ b/drivers/bus/Kconfig
615 @@ -167,4 +167,7 @@ config VEXPRESS_CONFIG
616 help
617 Platform configuration infrastructure for the ARM Ltd.
618 Versatile Express.
619 +
620 +source "drivers/bus/fsl-mc/Kconfig"
621 +
622 endmenu
623 --- a/drivers/bus/Makefile
624 +++ b/drivers/bus/Makefile
625 @@ -7,6 +7,10 @@ obj-$(CONFIG_ARM_CCI) += arm-cci.o
626 obj-$(CONFIG_ARM_CCN) += arm-ccn.o
627
628 obj-$(CONFIG_BRCMSTB_GISB_ARB) += brcmstb_gisb.o
629 +
630 +# DPAA2 fsl-mc bus
631 +obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/
632 +
633 obj-$(CONFIG_IMX_WEIM) += imx-weim.o
634 obj-$(CONFIG_MIPS_CDMM) += mips_cdmm.o
635 obj-$(CONFIG_MVEBU_MBUS) += mvebu-mbus.o
636 --- /dev/null
637 +++ b/drivers/bus/fsl-mc/Kconfig
638 @@ -0,0 +1,23 @@
639 +# SPDX-License-Identifier: GPL-2.0
640 +#
641 +# DPAA2 fsl-mc bus
642 +#
643 +# Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
644 +#
645 +
646 +config FSL_MC_BUS
647 + bool "QorIQ DPAA2 fsl-mc bus driver"
648 + depends on OF && (ARCH_LAYERSCAPE || (COMPILE_TEST && (ARM || ARM64 || X86 || PPC)))
649 + select GENERIC_MSI_IRQ_DOMAIN
650 + help
651 + Driver to enable the bus infrastructure for the QorIQ DPAA2
652 + architecture. The fsl-mc bus driver handles discovery of
653 + DPAA2 objects (which are represented as Linux devices) and
654 + binding objects to drivers.
655 +
656 +config FSL_MC_RESTOOL
657 + bool "Management Complex (MC) restool support"
658 + depends on FSL_MC_BUS
659 + help
660 + Provides kernel support for the Management Complex resource
661 + manager user-space tool - restool.
662 --- /dev/null
663 +++ b/drivers/bus/fsl-mc/Makefile
664 @@ -0,0 +1,22 @@
665 +# SPDX-License-Identifier: GPL-2.0
666 +#
667 +# Freescale Management Complex (MC) bus drivers
668 +#
669 +# Copyright (C) 2014 Freescale Semiconductor, Inc.
670 +#
671 +obj-$(CONFIG_FSL_MC_BUS) += mc-bus-driver.o
672 +
673 +mc-bus-driver-objs := fsl-mc-bus.o \
674 + mc-sys.o \
675 + mc-io.o \
676 + dpbp.o \
677 + dpcon.o \
678 + dprc.o \
679 + dprc-driver.o \
680 + fsl-mc-allocator.o \
681 + fsl-mc-msi.o \
682 + dpmcp.o \
683 + fsl-mc-iommu.o
684 +
685 +# MC restool kernel support
686 +obj-$(CONFIG_FSL_MC_RESTOOL) += fsl-mc-restool.o
687 --- /dev/null
688 +++ b/drivers/bus/fsl-mc/dpbp.c
689 @@ -0,0 +1,186 @@
690 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
691 +/*
692 + * Copyright 2013-2016 Freescale Semiconductor Inc.
693 + *
694 + */
695 +#include <linux/kernel.h>
696 +#include <linux/fsl/mc.h>
697 +#include <linux/fsl/mc.h>
698 +
699 +#include "fsl-mc-private.h"
700 +
701 +/**
702 + * dpbp_open() - Open a control session for the specified object.
703 + * @mc_io: Pointer to MC portal's I/O object
704 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
705 + * @dpbp_id: DPBP unique ID
706 + * @token: Returned token; use in subsequent API calls
707 + *
708 + * This function can be used to open a control session for an
709 + * already created object; an object may have been declared in
710 + * the DPL or by calling the dpbp_create function.
711 + * This function returns a unique authentication token,
712 + * associated with the specific object ID and the specific MC
713 + * portal; this token must be used in all subsequent commands for
714 + * this specific object
715 + *
716 + * Return: '0' on Success; Error code otherwise.
717 + */
718 +int dpbp_open(struct fsl_mc_io *mc_io,
719 + u32 cmd_flags,
720 + int dpbp_id,
721 + u16 *token)
722 +{
723 + struct fsl_mc_command cmd = { 0 };
724 + struct dpbp_cmd_open *cmd_params;
725 + int err;
726 +
727 + /* prepare command */
728 + cmd.header = mc_encode_cmd_header(DPBP_CMDID_OPEN,
729 + cmd_flags, 0);
730 + cmd_params = (struct dpbp_cmd_open *)cmd.params;
731 + cmd_params->dpbp_id = cpu_to_le32(dpbp_id);
732 +
733 + /* send command to mc*/
734 + err = mc_send_command(mc_io, &cmd);
735 + if (err)
736 + return err;
737 +
738 + /* retrieve response parameters */
739 + *token = mc_cmd_hdr_read_token(&cmd);
740 +
741 + return err;
742 +}
743 +EXPORT_SYMBOL_GPL(dpbp_open);
744 +
745 +/**
746 + * dpbp_close() - Close the control session of the object
747 + * @mc_io: Pointer to MC portal's I/O object
748 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
749 + * @token: Token of DPBP object
750 + *
751 + * After this function is called, no further operations are
752 + * allowed on the object without opening a new control session.
753 + *
754 + * Return: '0' on Success; Error code otherwise.
755 + */
756 +int dpbp_close(struct fsl_mc_io *mc_io,
757 + u32 cmd_flags,
758 + u16 token)
759 +{
760 + struct fsl_mc_command cmd = { 0 };
761 +
762 + /* prepare command */
763 + cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLOSE, cmd_flags,
764 + token);
765 +
766 + /* send command to mc*/
767 + return mc_send_command(mc_io, &cmd);
768 +}
769 +EXPORT_SYMBOL_GPL(dpbp_close);
770 +
771 +/**
772 + * dpbp_enable() - Enable the DPBP.
773 + * @mc_io: Pointer to MC portal's I/O object
774 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
775 + * @token: Token of DPBP object
776 + *
777 + * Return: '0' on Success; Error code otherwise.
778 + */
779 +int dpbp_enable(struct fsl_mc_io *mc_io,
780 + u32 cmd_flags,
781 + u16 token)
782 +{
783 + struct fsl_mc_command cmd = { 0 };
784 +
785 + /* prepare command */
786 + cmd.header = mc_encode_cmd_header(DPBP_CMDID_ENABLE, cmd_flags,
787 + token);
788 +
789 + /* send command to mc*/
790 + return mc_send_command(mc_io, &cmd);
791 +}
792 +EXPORT_SYMBOL_GPL(dpbp_enable);
793 +
794 +/**
795 + * dpbp_disable() - Disable the DPBP.
796 + * @mc_io: Pointer to MC portal's I/O object
797 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
798 + * @token: Token of DPBP object
799 + *
800 + * Return: '0' on Success; Error code otherwise.
801 + */
802 +int dpbp_disable(struct fsl_mc_io *mc_io,
803 + u32 cmd_flags,
804 + u16 token)
805 +{
806 + struct fsl_mc_command cmd = { 0 };
807 +
808 + /* prepare command */
809 + cmd.header = mc_encode_cmd_header(DPBP_CMDID_DISABLE,
810 + cmd_flags, token);
811 +
812 + /* send command to mc*/
813 + return mc_send_command(mc_io, &cmd);
814 +}
815 +EXPORT_SYMBOL_GPL(dpbp_disable);
816 +
817 +/**
818 + * dpbp_reset() - Reset the DPBP, returns the object to initial state.
819 + * @mc_io: Pointer to MC portal's I/O object
820 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
821 + * @token: Token of DPBP object
822 + *
823 + * Return: '0' on Success; Error code otherwise.
824 + */
825 +int dpbp_reset(struct fsl_mc_io *mc_io,
826 + u32 cmd_flags,
827 + u16 token)
828 +{
829 + struct fsl_mc_command cmd = { 0 };
830 +
831 + /* prepare command */
832 + cmd.header = mc_encode_cmd_header(DPBP_CMDID_RESET,
833 + cmd_flags, token);
834 +
835 + /* send command to mc*/
836 + return mc_send_command(mc_io, &cmd);
837 +}
838 +EXPORT_SYMBOL_GPL(dpbp_reset);
839 +
840 +/**
841 + * dpbp_get_attributes - Retrieve DPBP attributes.
842 + *
843 + * @mc_io: Pointer to MC portal's I/O object
844 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
845 + * @token: Token of DPBP object
846 + * @attr: Returned object's attributes
847 + *
848 + * Return: '0' on Success; Error code otherwise.
849 + */
850 +int dpbp_get_attributes(struct fsl_mc_io *mc_io,
851 + u32 cmd_flags,
852 + u16 token,
853 + struct dpbp_attr *attr)
854 +{
855 + struct fsl_mc_command cmd = { 0 };
856 + struct dpbp_rsp_get_attributes *rsp_params;
857 + int err;
858 +
859 + /* prepare command */
860 + cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_ATTR,
861 + cmd_flags, token);
862 +
863 + /* send command to mc*/
864 + err = mc_send_command(mc_io, &cmd);
865 + if (err)
866 + return err;
867 +
868 + /* retrieve response parameters */
869 + rsp_params = (struct dpbp_rsp_get_attributes *)cmd.params;
870 + attr->bpid = le16_to_cpu(rsp_params->bpid);
871 + attr->id = le32_to_cpu(rsp_params->id);
872 +
873 + return 0;
874 +}
875 +EXPORT_SYMBOL_GPL(dpbp_get_attributes);
876 --- /dev/null
877 +++ b/drivers/bus/fsl-mc/dpcon.c
878 @@ -0,0 +1,222 @@
879 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
880 +/*
881 + * Copyright 2013-2016 Freescale Semiconductor Inc.
882 + *
883 + */
884 +#include <linux/kernel.h>
885 +#include <linux/fsl/mc.h>
886 +#include <linux/fsl/mc.h>
887 +
888 +#include "fsl-mc-private.h"
889 +
890 +/**
891 + * dpcon_open() - Open a control session for the specified object
892 + * @mc_io: Pointer to MC portal's I/O object
893 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
894 + * @dpcon_id: DPCON unique ID
895 + * @token: Returned token; use in subsequent API calls
896 + *
897 + * This function can be used to open a control session for an
898 + * already created object; an object may have been declared in
899 + * the DPL or by calling the dpcon_create() function.
900 + * This function returns a unique authentication token,
901 + * associated with the specific object ID and the specific MC
902 + * portal; this token must be used in all subsequent commands for
903 + * this specific object.
904 + *
905 + * Return: '0' on Success; Error code otherwise.
906 + */
907 +int dpcon_open(struct fsl_mc_io *mc_io,
908 + u32 cmd_flags,
909 + int dpcon_id,
910 + u16 *token)
911 +{
912 + struct fsl_mc_command cmd = { 0 };
913 + struct dpcon_cmd_open *dpcon_cmd;
914 + int err;
915 +
916 + /* prepare command */
917 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_OPEN,
918 + cmd_flags,
919 + 0);
920 + dpcon_cmd = (struct dpcon_cmd_open *)cmd.params;
921 + dpcon_cmd->dpcon_id = cpu_to_le32(dpcon_id);
922 +
923 + /* send command to mc*/
924 + err = mc_send_command(mc_io, &cmd);
925 + if (err)
926 + return err;
927 +
928 + /* retrieve response parameters */
929 + *token = mc_cmd_hdr_read_token(&cmd);
930 +
931 + return 0;
932 +}
933 +EXPORT_SYMBOL_GPL(dpcon_open);
934 +
935 +/**
936 + * dpcon_close() - Close the control session of the object
937 + * @mc_io: Pointer to MC portal's I/O object
938 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
939 + * @token: Token of DPCON object
940 + *
941 + * After this function is called, no further operations are
942 + * allowed on the object without opening a new control session.
943 + *
944 + * Return: '0' on Success; Error code otherwise.
945 + */
946 +int dpcon_close(struct fsl_mc_io *mc_io,
947 + u32 cmd_flags,
948 + u16 token)
949 +{
950 + struct fsl_mc_command cmd = { 0 };
951 +
952 + /* prepare command */
953 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_CLOSE,
954 + cmd_flags,
955 + token);
956 +
957 + /* send command to mc*/
958 + return mc_send_command(mc_io, &cmd);
959 +}
960 +EXPORT_SYMBOL_GPL(dpcon_close);
961 +
962 +/**
963 + * dpcon_enable() - Enable the DPCON
964 + * @mc_io: Pointer to MC portal's I/O object
965 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
966 + * @token: Token of DPCON object
967 + *
968 + * Return: '0' on Success; Error code otherwise
969 + */
970 +int dpcon_enable(struct fsl_mc_io *mc_io,
971 + u32 cmd_flags,
972 + u16 token)
973 +{
974 + struct fsl_mc_command cmd = { 0 };
975 +
976 + /* prepare command */
977 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_ENABLE,
978 + cmd_flags,
979 + token);
980 +
981 + /* send command to mc*/
982 + return mc_send_command(mc_io, &cmd);
983 +}
984 +EXPORT_SYMBOL_GPL(dpcon_enable);
985 +
986 +/**
987 + * dpcon_disable() - Disable the DPCON
988 + * @mc_io: Pointer to MC portal's I/O object
989 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
990 + * @token: Token of DPCON object
991 + *
992 + * Return: '0' on Success; Error code otherwise
993 + */
994 +int dpcon_disable(struct fsl_mc_io *mc_io,
995 + u32 cmd_flags,
996 + u16 token)
997 +{
998 + struct fsl_mc_command cmd = { 0 };
999 +
1000 + /* prepare command */
1001 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_DISABLE,
1002 + cmd_flags,
1003 + token);
1004 +
1005 + /* send command to mc*/
1006 + return mc_send_command(mc_io, &cmd);
1007 +}
1008 +EXPORT_SYMBOL_GPL(dpcon_disable);
1009 +
1010 +/**
1011 + * dpcon_reset() - Reset the DPCON, returns the object to initial state.
1012 + * @mc_io: Pointer to MC portal's I/O object
1013 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1014 + * @token: Token of DPCON object
1015 + *
1016 + * Return: '0' on Success; Error code otherwise.
1017 + */
1018 +int dpcon_reset(struct fsl_mc_io *mc_io,
1019 + u32 cmd_flags,
1020 + u16 token)
1021 +{
1022 + struct fsl_mc_command cmd = { 0 };
1023 +
1024 + /* prepare command */
1025 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_RESET,
1026 + cmd_flags, token);
1027 +
1028 + /* send command to mc*/
1029 + return mc_send_command(mc_io, &cmd);
1030 +}
1031 +EXPORT_SYMBOL_GPL(dpcon_reset);
1032 +
1033 +/**
1034 + * dpcon_get_attributes() - Retrieve DPCON attributes.
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 + * @attr: Object's attributes
1039 + *
1040 + * Return: '0' on Success; Error code otherwise.
1041 + */
1042 +int dpcon_get_attributes(struct fsl_mc_io *mc_io,
1043 + u32 cmd_flags,
1044 + u16 token,
1045 + struct dpcon_attr *attr)
1046 +{
1047 + struct fsl_mc_command cmd = { 0 };
1048 + struct dpcon_rsp_get_attr *dpcon_rsp;
1049 + int err;
1050 +
1051 + /* prepare command */
1052 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_ATTR,
1053 + cmd_flags,
1054 + token);
1055 +
1056 + /* send command to mc*/
1057 + err = mc_send_command(mc_io, &cmd);
1058 + if (err)
1059 + return err;
1060 +
1061 + /* retrieve response parameters */
1062 + dpcon_rsp = (struct dpcon_rsp_get_attr *)cmd.params;
1063 + attr->id = le32_to_cpu(dpcon_rsp->id);
1064 + attr->qbman_ch_id = le16_to_cpu(dpcon_rsp->qbman_ch_id);
1065 + attr->num_priorities = dpcon_rsp->num_priorities;
1066 +
1067 + return 0;
1068 +}
1069 +EXPORT_SYMBOL_GPL(dpcon_get_attributes);
1070 +
1071 +/**
1072 + * dpcon_set_notification() - Set DPCON notification destination
1073 + * @mc_io: Pointer to MC portal's I/O object
1074 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1075 + * @token: Token of DPCON object
1076 + * @cfg: Notification parameters
1077 + *
1078 + * Return: '0' on Success; Error code otherwise
1079 + */
1080 +int dpcon_set_notification(struct fsl_mc_io *mc_io,
1081 + u32 cmd_flags,
1082 + u16 token,
1083 + struct dpcon_notification_cfg *cfg)
1084 +{
1085 + struct fsl_mc_command cmd = { 0 };
1086 + struct dpcon_cmd_set_notification *dpcon_cmd;
1087 +
1088 + /* prepare command */
1089 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_SET_NOTIFICATION,
1090 + cmd_flags,
1091 + token);
1092 + dpcon_cmd = (struct dpcon_cmd_set_notification *)cmd.params;
1093 + dpcon_cmd->dpio_id = cpu_to_le32(cfg->dpio_id);
1094 + dpcon_cmd->priority = cfg->priority;
1095 + dpcon_cmd->user_ctx = cpu_to_le64(cfg->user_ctx);
1096 +
1097 + /* send command to mc*/
1098 + return mc_send_command(mc_io, &cmd);
1099 +}
1100 +EXPORT_SYMBOL_GPL(dpcon_set_notification);
1101 --- /dev/null
1102 +++ b/drivers/bus/fsl-mc/dpmcp.c
1103 @@ -0,0 +1,99 @@
1104 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
1105 +/*
1106 + * Copyright 2013-2016 Freescale Semiconductor Inc.
1107 + *
1108 + */
1109 +#include <linux/kernel.h>
1110 +#include <linux/fsl/mc.h>
1111 +
1112 +#include "fsl-mc-private.h"
1113 +
1114 +/**
1115 + * dpmcp_open() - Open a control session for the specified object.
1116 + * @mc_io: Pointer to MC portal's I/O object
1117 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1118 + * @dpmcp_id: DPMCP unique ID
1119 + * @token: Returned token; use in subsequent API calls
1120 + *
1121 + * This function can be used to open a control session for an
1122 + * already created object; an object may have been declared in
1123 + * the DPL or by calling the dpmcp_create function.
1124 + * This function returns a unique authentication token,
1125 + * associated with the specific object ID and the specific MC
1126 + * portal; this token must be used in all subsequent commands for
1127 + * this specific object
1128 + *
1129 + * Return: '0' on Success; Error code otherwise.
1130 + */
1131 +int dpmcp_open(struct fsl_mc_io *mc_io,
1132 + u32 cmd_flags,
1133 + int dpmcp_id,
1134 + u16 *token)
1135 +{
1136 + struct fsl_mc_command cmd = { 0 };
1137 + struct dpmcp_cmd_open *cmd_params;
1138 + int err;
1139 +
1140 + /* prepare command */
1141 + cmd.header = mc_encode_cmd_header(DPMCP_CMDID_OPEN,
1142 + cmd_flags, 0);
1143 + cmd_params = (struct dpmcp_cmd_open *)cmd.params;
1144 + cmd_params->dpmcp_id = cpu_to_le32(dpmcp_id);
1145 +
1146 + /* send command to mc*/
1147 + err = mc_send_command(mc_io, &cmd);
1148 + if (err)
1149 + return err;
1150 +
1151 + /* retrieve response parameters */
1152 + *token = mc_cmd_hdr_read_token(&cmd);
1153 +
1154 + return err;
1155 +}
1156 +
1157 +/**
1158 + * dpmcp_close() - Close the control session of the object
1159 + * @mc_io: Pointer to MC portal's I/O object
1160 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1161 + * @token: Token of DPMCP object
1162 + *
1163 + * After this function is called, no further operations are
1164 + * allowed on the object without opening a new control session.
1165 + *
1166 + * Return: '0' on Success; Error code otherwise.
1167 + */
1168 +int dpmcp_close(struct fsl_mc_io *mc_io,
1169 + u32 cmd_flags,
1170 + u16 token)
1171 +{
1172 + struct fsl_mc_command cmd = { 0 };
1173 +
1174 + /* prepare command */
1175 + cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CLOSE,
1176 + cmd_flags, token);
1177 +
1178 + /* send command to mc*/
1179 + return mc_send_command(mc_io, &cmd);
1180 +}
1181 +
1182 +/**
1183 + * dpmcp_reset() - Reset the DPMCP, returns the object to initial state.
1184 + * @mc_io: Pointer to MC portal's I/O object
1185 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1186 + * @token: Token of DPMCP object
1187 + *
1188 + * Return: '0' on Success; Error code otherwise.
1189 + */
1190 +int dpmcp_reset(struct fsl_mc_io *mc_io,
1191 + u32 cmd_flags,
1192 + u16 token)
1193 +{
1194 + struct fsl_mc_command cmd = { 0 };
1195 +
1196 + /* prepare command */
1197 + cmd.header = mc_encode_cmd_header(DPMCP_CMDID_RESET,
1198 + cmd_flags, token);
1199 +
1200 + /* send command to mc*/
1201 + return mc_send_command(mc_io, &cmd);
1202 +}
1203 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c
1204 +++ /dev/null
1205 @@ -1,805 +0,0 @@
1206 -/*
1207 - * Freescale data path resource container (DPRC) driver
1208 - *
1209 - * Copyright (C) 2014 Freescale Semiconductor, Inc.
1210 - * Author: German Rivera <German.Rivera@freescale.com>
1211 - *
1212 - * This file is licensed under the terms of the GNU General Public
1213 - * License version 2. This program is licensed "as is" without any
1214 - * warranty of any kind, whether express or implied.
1215 - */
1216 -
1217 -#include <linux/module.h>
1218 -#include <linux/slab.h>
1219 -#include <linux/interrupt.h>
1220 -#include <linux/msi.h>
1221 -#include "../include/mc-bus.h"
1222 -#include "../include/mc-sys.h"
1223 -
1224 -#include "dprc-cmd.h"
1225 -#include "fsl-mc-private.h"
1226 -
1227 -#define FSL_MC_DPRC_DRIVER_NAME "fsl_mc_dprc"
1228 -
1229 -#define FSL_MC_DEVICE_MATCH(_mc_dev, _obj_desc) \
1230 - (strcmp((_mc_dev)->obj_desc.type, (_obj_desc)->type) == 0 && \
1231 - (_mc_dev)->obj_desc.id == (_obj_desc)->id)
1232 -
1233 -struct dprc_child_objs {
1234 - int child_count;
1235 - struct dprc_obj_desc *child_array;
1236 -};
1237 -
1238 -static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data)
1239 -{
1240 - int i;
1241 - struct dprc_child_objs *objs;
1242 - struct fsl_mc_device *mc_dev;
1243 -
1244 - WARN_ON(!dev);
1245 - WARN_ON(!data);
1246 - mc_dev = to_fsl_mc_device(dev);
1247 - objs = data;
1248 -
1249 - for (i = 0; i < objs->child_count; i++) {
1250 - struct dprc_obj_desc *obj_desc = &objs->child_array[i];
1251 -
1252 - if (strlen(obj_desc->type) != 0 &&
1253 - FSL_MC_DEVICE_MATCH(mc_dev, obj_desc))
1254 - break;
1255 - }
1256 -
1257 - if (i == objs->child_count)
1258 - fsl_mc_device_remove(mc_dev);
1259 -
1260 - return 0;
1261 -}
1262 -
1263 -static int __fsl_mc_device_remove(struct device *dev, void *data)
1264 -{
1265 - WARN_ON(!dev);
1266 - WARN_ON(data);
1267 - fsl_mc_device_remove(to_fsl_mc_device(dev));
1268 - return 0;
1269 -}
1270 -
1271 -/**
1272 - * dprc_remove_devices - Removes devices for objects removed from a DPRC
1273 - *
1274 - * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
1275 - * @obj_desc_array: array of object descriptors for child objects currently
1276 - * present in the DPRC in the MC.
1277 - * @num_child_objects_in_mc: number of entries in obj_desc_array
1278 - *
1279 - * Synchronizes the state of the Linux bus driver with the actual state of
1280 - * the MC by removing devices that represent MC objects that have
1281 - * been dynamically removed in the physical DPRC.
1282 - */
1283 -static void dprc_remove_devices(struct fsl_mc_device *mc_bus_dev,
1284 - struct dprc_obj_desc *obj_desc_array,
1285 - int num_child_objects_in_mc)
1286 -{
1287 - if (num_child_objects_in_mc != 0) {
1288 - /*
1289 - * Remove child objects that are in the DPRC in Linux,
1290 - * but not in the MC:
1291 - */
1292 - struct dprc_child_objs objs;
1293 -
1294 - objs.child_count = num_child_objects_in_mc;
1295 - objs.child_array = obj_desc_array;
1296 - device_for_each_child(&mc_bus_dev->dev, &objs,
1297 - __fsl_mc_device_remove_if_not_in_mc);
1298 - } else {
1299 - /*
1300 - * There are no child objects for this DPRC in the MC.
1301 - * So, remove all the child devices from Linux:
1302 - */
1303 - device_for_each_child(&mc_bus_dev->dev, NULL,
1304 - __fsl_mc_device_remove);
1305 - }
1306 -}
1307 -
1308 -static int __fsl_mc_device_match(struct device *dev, void *data)
1309 -{
1310 - struct dprc_obj_desc *obj_desc = data;
1311 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
1312 -
1313 - return FSL_MC_DEVICE_MATCH(mc_dev, obj_desc);
1314 -}
1315 -
1316 -static struct fsl_mc_device *fsl_mc_device_lookup(struct dprc_obj_desc
1317 - *obj_desc,
1318 - struct fsl_mc_device
1319 - *mc_bus_dev)
1320 -{
1321 - struct device *dev;
1322 -
1323 - dev = device_find_child(&mc_bus_dev->dev, obj_desc,
1324 - __fsl_mc_device_match);
1325 -
1326 - return dev ? to_fsl_mc_device(dev) : NULL;
1327 -}
1328 -
1329 -/**
1330 - * check_plugged_state_change - Check change in an MC object's plugged state
1331 - *
1332 - * @mc_dev: pointer to the fsl-mc device for a given MC object
1333 - * @obj_desc: pointer to the MC object's descriptor in the MC
1334 - *
1335 - * If the plugged state has changed from unplugged to plugged, the fsl-mc
1336 - * device is bound to the corresponding device driver.
1337 - * If the plugged state has changed from plugged to unplugged, the fsl-mc
1338 - * device is unbound from the corresponding device driver.
1339 - */
1340 -static void check_plugged_state_change(struct fsl_mc_device *mc_dev,
1341 - struct dprc_obj_desc *obj_desc)
1342 -{
1343 - int error;
1344 - u32 plugged_flag_at_mc =
1345 - obj_desc->state & DPRC_OBJ_STATE_PLUGGED;
1346 -
1347 - if (plugged_flag_at_mc !=
1348 - (mc_dev->obj_desc.state & DPRC_OBJ_STATE_PLUGGED)) {
1349 - if (plugged_flag_at_mc) {
1350 - mc_dev->obj_desc.state |= DPRC_OBJ_STATE_PLUGGED;
1351 - error = device_attach(&mc_dev->dev);
1352 - if (error < 0) {
1353 - dev_err(&mc_dev->dev,
1354 - "device_attach() failed: %d\n",
1355 - error);
1356 - }
1357 - } else {
1358 - mc_dev->obj_desc.state &= ~DPRC_OBJ_STATE_PLUGGED;
1359 - device_release_driver(&mc_dev->dev);
1360 - }
1361 - }
1362 -}
1363 -
1364 -/**
1365 - * dprc_add_new_devices - Adds devices to the logical bus for a DPRC
1366 - *
1367 - * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
1368 - * @obj_desc_array: array of device descriptors for child devices currently
1369 - * present in the physical DPRC.
1370 - * @num_child_objects_in_mc: number of entries in obj_desc_array
1371 - *
1372 - * Synchronizes the state of the Linux bus driver with the actual
1373 - * state of the MC by adding objects that have been newly discovered
1374 - * in the physical DPRC.
1375 - */
1376 -static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev,
1377 - struct dprc_obj_desc *obj_desc_array,
1378 - int num_child_objects_in_mc)
1379 -{
1380 - int error;
1381 - int i;
1382 -
1383 - for (i = 0; i < num_child_objects_in_mc; i++) {
1384 - struct fsl_mc_device *child_dev;
1385 - struct dprc_obj_desc *obj_desc = &obj_desc_array[i];
1386 -
1387 - if (strlen(obj_desc->type) == 0)
1388 - continue;
1389 -
1390 - /*
1391 - * Check if device is already known to Linux:
1392 - */
1393 - child_dev = fsl_mc_device_lookup(obj_desc, mc_bus_dev);
1394 - if (child_dev) {
1395 - check_plugged_state_change(child_dev, obj_desc);
1396 - continue;
1397 - }
1398 -
1399 - error = fsl_mc_device_add(obj_desc, NULL, &mc_bus_dev->dev,
1400 - &child_dev);
1401 - if (error < 0)
1402 - continue;
1403 - }
1404 -}
1405 -
1406 -/**
1407 - * dprc_scan_objects - Discover objects in a DPRC
1408 - *
1409 - * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
1410 - * @total_irq_count: total number of IRQs needed by objects in the DPRC.
1411 - *
1412 - * Detects objects added and removed from a DPRC and synchronizes the
1413 - * state of the Linux bus driver, MC by adding and removing
1414 - * devices accordingly.
1415 - * Two types of devices can be found in a DPRC: allocatable objects (e.g.,
1416 - * dpbp, dpmcp) and non-allocatable devices (e.g., dprc, dpni).
1417 - * All allocatable devices needed to be probed before all non-allocatable
1418 - * devices, to ensure that device drivers for non-allocatable
1419 - * devices can allocate any type of allocatable devices.
1420 - * That is, we need to ensure that the corresponding resource pools are
1421 - * populated before they can get allocation requests from probe callbacks
1422 - * of the device drivers for the non-allocatable devices.
1423 - */
1424 -int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
1425 - unsigned int *total_irq_count)
1426 -{
1427 - int num_child_objects;
1428 - int dprc_get_obj_failures;
1429 - int error;
1430 - unsigned int irq_count = mc_bus_dev->obj_desc.irq_count;
1431 - struct dprc_obj_desc *child_obj_desc_array = NULL;
1432 -
1433 - error = dprc_get_obj_count(mc_bus_dev->mc_io,
1434 - 0,
1435 - mc_bus_dev->mc_handle,
1436 - &num_child_objects);
1437 - if (error < 0) {
1438 - dev_err(&mc_bus_dev->dev, "dprc_get_obj_count() failed: %d\n",
1439 - error);
1440 - return error;
1441 - }
1442 -
1443 - if (num_child_objects != 0) {
1444 - int i;
1445 -
1446 - child_obj_desc_array =
1447 - devm_kmalloc_array(&mc_bus_dev->dev, num_child_objects,
1448 - sizeof(*child_obj_desc_array),
1449 - GFP_KERNEL);
1450 - if (!child_obj_desc_array)
1451 - return -ENOMEM;
1452 -
1453 - /*
1454 - * Discover objects currently present in the physical DPRC:
1455 - */
1456 - dprc_get_obj_failures = 0;
1457 - for (i = 0; i < num_child_objects; i++) {
1458 - struct dprc_obj_desc *obj_desc =
1459 - &child_obj_desc_array[i];
1460 -
1461 - error = dprc_get_obj(mc_bus_dev->mc_io,
1462 - 0,
1463 - mc_bus_dev->mc_handle,
1464 - i, obj_desc);
1465 - if (error < 0) {
1466 - dev_err(&mc_bus_dev->dev,
1467 - "dprc_get_obj(i=%d) failed: %d\n",
1468 - i, error);
1469 - /*
1470 - * Mark the obj entry as "invalid", by using the
1471 - * empty string as obj type:
1472 - */
1473 - obj_desc->type[0] = '\0';
1474 - obj_desc->id = error;
1475 - dprc_get_obj_failures++;
1476 - continue;
1477 - }
1478 -
1479 - /*
1480 - * add a quirk for all versions of dpsec < 4.0...none
1481 - * are coherent regardless of what the MC reports.
1482 - */
1483 - if ((strcmp(obj_desc->type, "dpseci") == 0) &&
1484 - (obj_desc->ver_major < 4))
1485 - obj_desc->flags |=
1486 - DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY;
1487 -
1488 - irq_count += obj_desc->irq_count;
1489 - dev_dbg(&mc_bus_dev->dev,
1490 - "Discovered object: type %s, id %d\n",
1491 - obj_desc->type, obj_desc->id);
1492 - }
1493 -
1494 - if (dprc_get_obj_failures != 0) {
1495 - dev_err(&mc_bus_dev->dev,
1496 - "%d out of %d devices could not be retrieved\n",
1497 - dprc_get_obj_failures, num_child_objects);
1498 - }
1499 - }
1500 -
1501 - *total_irq_count = irq_count;
1502 - dprc_remove_devices(mc_bus_dev, child_obj_desc_array,
1503 - num_child_objects);
1504 -
1505 - dprc_add_new_devices(mc_bus_dev, child_obj_desc_array,
1506 - num_child_objects);
1507 -
1508 - if (child_obj_desc_array)
1509 - devm_kfree(&mc_bus_dev->dev, child_obj_desc_array);
1510 -
1511 - return 0;
1512 -}
1513 -EXPORT_SYMBOL_GPL(dprc_scan_objects);
1514 -
1515 -/**
1516 - * dprc_scan_container - Scans a physical DPRC and synchronizes Linux bus state
1517 - *
1518 - * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
1519 - *
1520 - * Scans the physical DPRC and synchronizes the state of the Linux
1521 - * bus driver with the actual state of the MC by adding and removing
1522 - * devices as appropriate.
1523 - */
1524 -int dprc_scan_container(struct fsl_mc_device *mc_bus_dev)
1525 -{
1526 - int error;
1527 - unsigned int irq_count;
1528 - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
1529 -
1530 - fsl_mc_init_all_resource_pools(mc_bus_dev);
1531 -
1532 - /*
1533 - * Discover objects in the DPRC:
1534 - */
1535 - mutex_lock(&mc_bus->scan_mutex);
1536 - error = dprc_scan_objects(mc_bus_dev, &irq_count);
1537 - mutex_unlock(&mc_bus->scan_mutex);
1538 - if (error < 0)
1539 - goto error;
1540 -
1541 - if (dev_get_msi_domain(&mc_bus_dev->dev) && !mc_bus->irq_resources) {
1542 - if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) {
1543 - dev_warn(&mc_bus_dev->dev,
1544 - "IRQs needed (%u) exceed IRQs preallocated (%u)\n",
1545 - irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
1546 - }
1547 -
1548 - error = fsl_mc_populate_irq_pool(
1549 - mc_bus,
1550 - FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
1551 - if (error < 0)
1552 - goto error;
1553 - }
1554 -
1555 - return 0;
1556 -error:
1557 - fsl_mc_cleanup_all_resource_pools(mc_bus_dev);
1558 - return error;
1559 -}
1560 -EXPORT_SYMBOL_GPL(dprc_scan_container);
1561 -
1562 -/**
1563 - * dprc_irq0_handler - Regular ISR for DPRC interrupt 0
1564 - *
1565 - * @irq: IRQ number of the interrupt being handled
1566 - * @arg: Pointer to device structure
1567 - */
1568 -static irqreturn_t dprc_irq0_handler(int irq_num, void *arg)
1569 -{
1570 - return IRQ_WAKE_THREAD;
1571 -}
1572 -
1573 -/**
1574 - * dprc_irq0_handler_thread - Handler thread function for DPRC interrupt 0
1575 - *
1576 - * @irq: IRQ number of the interrupt being handled
1577 - * @arg: Pointer to device structure
1578 - */
1579 -static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg)
1580 -{
1581 - int error;
1582 - u32 status;
1583 - struct device *dev = arg;
1584 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
1585 - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
1586 - struct fsl_mc_io *mc_io = mc_dev->mc_io;
1587 - struct msi_desc *msi_desc = mc_dev->irqs[0]->msi_desc;
1588 -
1589 - dev_dbg(dev, "DPRC IRQ %d triggered on CPU %u\n",
1590 - irq_num, smp_processor_id());
1591 -
1592 - if (WARN_ON(!(mc_dev->flags & FSL_MC_IS_DPRC)))
1593 - return IRQ_HANDLED;
1594 -
1595 - mutex_lock(&mc_bus->scan_mutex);
1596 - if (WARN_ON(!msi_desc || msi_desc->irq != (u32)irq_num))
1597 - goto out;
1598 -
1599 - status = 0;
1600 - error = dprc_get_irq_status(mc_io, 0, mc_dev->mc_handle, 0,
1601 - &status);
1602 - if (error < 0) {
1603 - dev_err(dev,
1604 - "dprc_get_irq_status() failed: %d\n", error);
1605 - goto out;
1606 - }
1607 -
1608 - error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0,
1609 - status);
1610 - if (error < 0) {
1611 - dev_err(dev,
1612 - "dprc_clear_irq_status() failed: %d\n", error);
1613 - goto out;
1614 - }
1615 -
1616 - if (status & (DPRC_IRQ_EVENT_OBJ_ADDED |
1617 - DPRC_IRQ_EVENT_OBJ_REMOVED |
1618 - DPRC_IRQ_EVENT_CONTAINER_DESTROYED |
1619 - DPRC_IRQ_EVENT_OBJ_DESTROYED |
1620 - DPRC_IRQ_EVENT_OBJ_CREATED)) {
1621 - unsigned int irq_count;
1622 -
1623 - error = dprc_scan_objects(mc_dev, &irq_count);
1624 - if (error < 0) {
1625 - /*
1626 - * If the error is -ENXIO, we ignore it, as it indicates
1627 - * that the object scan was aborted, as we detected that
1628 - * an object was removed from the DPRC in the MC, while
1629 - * we were scanning the DPRC.
1630 - */
1631 - if (error != -ENXIO) {
1632 - dev_err(dev, "dprc_scan_objects() failed: %d\n",
1633 - error);
1634 - }
1635 -
1636 - goto out;
1637 - }
1638 -
1639 - if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) {
1640 - dev_warn(dev,
1641 - "IRQs needed (%u) exceed IRQs preallocated (%u)\n",
1642 - irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
1643 - }
1644 - }
1645 -
1646 -out:
1647 - mutex_unlock(&mc_bus->scan_mutex);
1648 - return IRQ_HANDLED;
1649 -}
1650 -
1651 -/*
1652 - * Disable and clear interrupt for a given DPRC object
1653 - */
1654 -static int disable_dprc_irq(struct fsl_mc_device *mc_dev)
1655 -{
1656 - int error;
1657 - struct fsl_mc_io *mc_io = mc_dev->mc_io;
1658 -
1659 - WARN_ON(mc_dev->obj_desc.irq_count != 1);
1660 -
1661 - /*
1662 - * Disable generation of interrupt, while we configure it:
1663 - */
1664 - error = dprc_set_irq_enable(mc_io, 0, mc_dev->mc_handle, 0, 0);
1665 - if (error < 0) {
1666 - dev_err(&mc_dev->dev,
1667 - "Disabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n",
1668 - error);
1669 - return error;
1670 - }
1671 -
1672 - /*
1673 - * Disable all interrupt causes for the interrupt:
1674 - */
1675 - error = dprc_set_irq_mask(mc_io, 0, mc_dev->mc_handle, 0, 0x0);
1676 - if (error < 0) {
1677 - dev_err(&mc_dev->dev,
1678 - "Disabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n",
1679 - error);
1680 - return error;
1681 - }
1682 -
1683 - /*
1684 - * Clear any leftover interrupts:
1685 - */
1686 - error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, ~0x0U);
1687 - if (error < 0) {
1688 - dev_err(&mc_dev->dev,
1689 - "Disabling DPRC IRQ failed: dprc_clear_irq_status() failed: %d\n",
1690 - error);
1691 - return error;
1692 - }
1693 -
1694 - return 0;
1695 -}
1696 -
1697 -static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev)
1698 -{
1699 - int error;
1700 - struct fsl_mc_device_irq *irq = mc_dev->irqs[0];
1701 -
1702 - WARN_ON(mc_dev->obj_desc.irq_count != 1);
1703 -
1704 - /*
1705 - * NOTE: devm_request_threaded_irq() invokes the device-specific
1706 - * function that programs the MSI physically in the device
1707 - */
1708 - error = devm_request_threaded_irq(&mc_dev->dev,
1709 - irq->msi_desc->irq,
1710 - dprc_irq0_handler,
1711 - dprc_irq0_handler_thread,
1712 - IRQF_NO_SUSPEND | IRQF_ONESHOT,
1713 - "FSL MC DPRC irq0",
1714 - &mc_dev->dev);
1715 - if (error < 0) {
1716 - dev_err(&mc_dev->dev,
1717 - "devm_request_threaded_irq() failed: %d\n",
1718 - error);
1719 - return error;
1720 - }
1721 -
1722 - return 0;
1723 -}
1724 -
1725 -static int enable_dprc_irq(struct fsl_mc_device *mc_dev)
1726 -{
1727 - int error;
1728 -
1729 - /*
1730 - * Enable all interrupt causes for the interrupt:
1731 - */
1732 - error = dprc_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle, 0,
1733 - ~0x0u);
1734 - if (error < 0) {
1735 - dev_err(&mc_dev->dev,
1736 - "Enabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n",
1737 - error);
1738 -
1739 - return error;
1740 - }
1741 -
1742 - /*
1743 - * Enable generation of the interrupt:
1744 - */
1745 - error = dprc_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, 1);
1746 - if (error < 0) {
1747 - dev_err(&mc_dev->dev,
1748 - "Enabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n",
1749 - error);
1750 -
1751 - return error;
1752 - }
1753 -
1754 - return 0;
1755 -}
1756 -
1757 -/*
1758 - * Setup interrupt for a given DPRC device
1759 - */
1760 -static int dprc_setup_irq(struct fsl_mc_device *mc_dev)
1761 -{
1762 - int error;
1763 -
1764 - error = fsl_mc_allocate_irqs(mc_dev);
1765 - if (error < 0)
1766 - return error;
1767 -
1768 - error = disable_dprc_irq(mc_dev);
1769 - if (error < 0)
1770 - goto error_free_irqs;
1771 -
1772 - error = register_dprc_irq_handler(mc_dev);
1773 - if (error < 0)
1774 - goto error_free_irqs;
1775 -
1776 - error = enable_dprc_irq(mc_dev);
1777 - if (error < 0)
1778 - goto error_free_irqs;
1779 -
1780 - return 0;
1781 -
1782 -error_free_irqs:
1783 - fsl_mc_free_irqs(mc_dev);
1784 - return error;
1785 -}
1786 -
1787 -/**
1788 - * dprc_probe - callback invoked when a DPRC is being bound to this driver
1789 - *
1790 - * @mc_dev: Pointer to fsl-mc device representing a DPRC
1791 - *
1792 - * It opens the physical DPRC in the MC.
1793 - * It scans the DPRC to discover the MC objects contained in it.
1794 - * It creates the interrupt pool for the MC bus associated with the DPRC.
1795 - * It configures the interrupts for the DPRC device itself.
1796 - */
1797 -static int dprc_probe(struct fsl_mc_device *mc_dev)
1798 -{
1799 - int error;
1800 - size_t region_size;
1801 - struct device *parent_dev = mc_dev->dev.parent;
1802 - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
1803 - bool mc_io_created = false;
1804 - bool msi_domain_set = false;
1805 -
1806 - if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0))
1807 - return -EINVAL;
1808 -
1809 - if (WARN_ON(dev_get_msi_domain(&mc_dev->dev)))
1810 - return -EINVAL;
1811 -
1812 - if (!mc_dev->mc_io) {
1813 - /*
1814 - * This is a child DPRC:
1815 - */
1816 - if (WARN_ON(!dev_is_fsl_mc(parent_dev)))
1817 - return -EINVAL;
1818 -
1819 - if (WARN_ON(mc_dev->obj_desc.region_count == 0))
1820 - return -EINVAL;
1821 -
1822 - region_size = mc_dev->regions[0].end -
1823 - mc_dev->regions[0].start + 1;
1824 -
1825 - error = fsl_create_mc_io(&mc_dev->dev,
1826 - mc_dev->regions[0].start,
1827 - region_size,
1828 - NULL,
1829 - FSL_MC_IO_ATOMIC_CONTEXT_PORTAL,
1830 - &mc_dev->mc_io);
1831 - if (error < 0)
1832 - return error;
1833 -
1834 - mc_io_created = true;
1835 -
1836 - /*
1837 - * Inherit parent MSI domain:
1838 - */
1839 - dev_set_msi_domain(&mc_dev->dev,
1840 - dev_get_msi_domain(parent_dev));
1841 - msi_domain_set = true;
1842 - } else {
1843 - /*
1844 - * This is a root DPRC
1845 - */
1846 - struct irq_domain *mc_msi_domain;
1847 -
1848 - if (WARN_ON(dev_is_fsl_mc(parent_dev)))
1849 - return -EINVAL;
1850 -
1851 - error = fsl_mc_find_msi_domain(parent_dev,
1852 - &mc_msi_domain);
1853 - if (error < 0) {
1854 - dev_warn(&mc_dev->dev,
1855 - "WARNING: MC bus without interrupt support\n");
1856 - } else {
1857 - dev_set_msi_domain(&mc_dev->dev, mc_msi_domain);
1858 - msi_domain_set = true;
1859 - }
1860 - }
1861 -
1862 - error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
1863 - &mc_dev->mc_handle);
1864 - if (error < 0) {
1865 - dev_err(&mc_dev->dev, "dprc_open() failed: %d\n", error);
1866 - goto error_cleanup_msi_domain;
1867 - }
1868 -
1869 - error = dprc_get_attributes(mc_dev->mc_io, 0, mc_dev->mc_handle,
1870 - &mc_bus->dprc_attr);
1871 - if (error < 0) {
1872 - dev_err(&mc_dev->dev, "dprc_get_attributes() failed: %d\n",
1873 - error);
1874 - goto error_cleanup_open;
1875 - }
1876 -
1877 - if (mc_bus->dprc_attr.version.major < DPRC_MIN_VER_MAJOR ||
1878 - (mc_bus->dprc_attr.version.major == DPRC_MIN_VER_MAJOR &&
1879 - mc_bus->dprc_attr.version.minor < DPRC_MIN_VER_MINOR)) {
1880 - dev_err(&mc_dev->dev,
1881 - "ERROR: DPRC version %d.%d not supported\n",
1882 - mc_bus->dprc_attr.version.major,
1883 - mc_bus->dprc_attr.version.minor);
1884 - error = -ENOTSUPP;
1885 - goto error_cleanup_open;
1886 - }
1887 -
1888 - mutex_init(&mc_bus->scan_mutex);
1889 -
1890 - /*
1891 - * Discover MC objects in DPRC object:
1892 - */
1893 - error = dprc_scan_container(mc_dev);
1894 - if (error < 0)
1895 - goto error_cleanup_open;
1896 -
1897 - /*
1898 - * Configure interrupt for the DPRC object associated with this MC bus:
1899 - */
1900 - error = dprc_setup_irq(mc_dev);
1901 - if (error < 0)
1902 - goto error_cleanup_open;
1903 -
1904 - dev_info(&mc_dev->dev, "DPRC device bound to driver");
1905 - return 0;
1906 -
1907 -error_cleanup_open:
1908 - (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
1909 -
1910 -error_cleanup_msi_domain:
1911 - if (msi_domain_set)
1912 - dev_set_msi_domain(&mc_dev->dev, NULL);
1913 -
1914 - if (mc_io_created) {
1915 - fsl_destroy_mc_io(mc_dev->mc_io);
1916 - mc_dev->mc_io = NULL;
1917 - }
1918 -
1919 - return error;
1920 -}
1921 -
1922 -/*
1923 - * Tear down interrupt for a given DPRC object
1924 - */
1925 -static void dprc_teardown_irq(struct fsl_mc_device *mc_dev)
1926 -{
1927 - struct fsl_mc_device_irq *irq = mc_dev->irqs[0];
1928 -
1929 - (void)disable_dprc_irq(mc_dev);
1930 -
1931 - devm_free_irq(&mc_dev->dev, irq->msi_desc->irq, &mc_dev->dev);
1932 -
1933 - fsl_mc_free_irqs(mc_dev);
1934 -}
1935 -
1936 -/**
1937 - * dprc_remove - callback invoked when a DPRC is being unbound from this driver
1938 - *
1939 - * @mc_dev: Pointer to fsl-mc device representing the DPRC
1940 - *
1941 - * It removes the DPRC's child objects from Linux (not from the MC) and
1942 - * closes the DPRC device in the MC.
1943 - * It tears down the interrupts that were configured for the DPRC device.
1944 - * It destroys the interrupt pool associated with this MC bus.
1945 - */
1946 -static int dprc_remove(struct fsl_mc_device *mc_dev)
1947 -{
1948 - int error;
1949 - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
1950 -
1951 - if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0))
1952 - return -EINVAL;
1953 - if (WARN_ON(!mc_dev->mc_io))
1954 - return -EINVAL;
1955 -
1956 - if (WARN_ON(!mc_bus->irq_resources))
1957 - return -EINVAL;
1958 -
1959 - if (dev_get_msi_domain(&mc_dev->dev))
1960 - dprc_teardown_irq(mc_dev);
1961 -
1962 - device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove);
1963 -
1964 - if (dev_get_msi_domain(&mc_dev->dev)) {
1965 - fsl_mc_cleanup_irq_pool(mc_bus);
1966 - dev_set_msi_domain(&mc_dev->dev, NULL);
1967 - }
1968 -
1969 - fsl_mc_cleanup_all_resource_pools(mc_dev);
1970 -
1971 - error = dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
1972 - if (error < 0)
1973 - dev_err(&mc_dev->dev, "dprc_close() failed: %d\n", error);
1974 -
1975 - if (!fsl_mc_is_root_dprc(&mc_dev->dev)) {
1976 - fsl_destroy_mc_io(mc_dev->mc_io);
1977 - mc_dev->mc_io = NULL;
1978 - }
1979 -
1980 - dev_info(&mc_dev->dev, "DPRC device unbound from driver");
1981 - return 0;
1982 -}
1983 -
1984 -static const struct fsl_mc_device_id match_id_table[] = {
1985 - {
1986 - .vendor = FSL_MC_VENDOR_FREESCALE,
1987 - .obj_type = "dprc"},
1988 - {.vendor = 0x0},
1989 -};
1990 -
1991 -static struct fsl_mc_driver dprc_driver = {
1992 - .driver = {
1993 - .name = FSL_MC_DPRC_DRIVER_NAME,
1994 - .owner = THIS_MODULE,
1995 - .pm = NULL,
1996 - },
1997 - .match_id_table = match_id_table,
1998 - .probe = dprc_probe,
1999 - .remove = dprc_remove,
2000 -};
2001 -
2002 -int __init dprc_driver_init(void)
2003 -{
2004 - return fsl_mc_driver_register(&dprc_driver);
2005 -}
2006 -
2007 -void dprc_driver_exit(void)
2008 -{
2009 - fsl_mc_driver_unregister(&dprc_driver);
2010 -}
2011 --- /dev/null
2012 +++ b/drivers/bus/fsl-mc/dprc-driver.c
2013 @@ -0,0 +1,815 @@
2014 +// SPDX-License-Identifier: GPL-2.0
2015 +/*
2016 + * Freescale data path resource container (DPRC) driver
2017 + *
2018 + * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
2019 + * Author: German Rivera <German.Rivera@freescale.com>
2020 + *
2021 + */
2022 +
2023 +#include <linux/module.h>
2024 +#include <linux/slab.h>
2025 +#include <linux/interrupt.h>
2026 +#include <linux/msi.h>
2027 +#include <linux/fsl/mc.h>
2028 +
2029 +#include "fsl-mc-private.h"
2030 +
2031 +#define FSL_MC_DPRC_DRIVER_NAME "fsl_mc_dprc"
2032 +
2033 +struct fsl_mc_child_objs {
2034 + int child_count;
2035 + struct fsl_mc_obj_desc *child_array;
2036 +};
2037 +
2038 +static bool fsl_mc_device_match(struct fsl_mc_device *mc_dev,
2039 + struct fsl_mc_obj_desc *obj_desc)
2040 +{
2041 + return mc_dev->obj_desc.id == obj_desc->id &&
2042 + strcmp(mc_dev->obj_desc.type, obj_desc->type) == 0;
2043 +
2044 +}
2045 +
2046 +static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data)
2047 +{
2048 + int i;
2049 + struct fsl_mc_child_objs *objs;
2050 + struct fsl_mc_device *mc_dev;
2051 +
2052 + mc_dev = to_fsl_mc_device(dev);
2053 + objs = data;
2054 +
2055 + for (i = 0; i < objs->child_count; i++) {
2056 + struct fsl_mc_obj_desc *obj_desc = &objs->child_array[i];
2057 +
2058 + if (strlen(obj_desc->type) != 0 &&
2059 + fsl_mc_device_match(mc_dev, obj_desc))
2060 + break;
2061 + }
2062 +
2063 + if (i == objs->child_count)
2064 + fsl_mc_device_remove(mc_dev);
2065 +
2066 + return 0;
2067 +}
2068 +
2069 +static int __fsl_mc_device_remove(struct device *dev, void *data)
2070 +{
2071 + fsl_mc_device_remove(to_fsl_mc_device(dev));
2072 + return 0;
2073 +}
2074 +
2075 +/**
2076 + * dprc_remove_devices - Removes devices for objects removed from a DPRC
2077 + *
2078 + * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
2079 + * @obj_desc_array: array of object descriptors for child objects currently
2080 + * present in the DPRC in the MC.
2081 + * @num_child_objects_in_mc: number of entries in obj_desc_array
2082 + *
2083 + * Synchronizes the state of the Linux bus driver with the actual state of
2084 + * the MC by removing devices that represent MC objects that have
2085 + * been dynamically removed in the physical DPRC.
2086 + */
2087 +static void dprc_remove_devices(struct fsl_mc_device *mc_bus_dev,
2088 + struct fsl_mc_obj_desc *obj_desc_array,
2089 + int num_child_objects_in_mc)
2090 +{
2091 + if (num_child_objects_in_mc != 0) {
2092 + /*
2093 + * Remove child objects that are in the DPRC in Linux,
2094 + * but not in the MC:
2095 + */
2096 + struct fsl_mc_child_objs objs;
2097 +
2098 + objs.child_count = num_child_objects_in_mc;
2099 + objs.child_array = obj_desc_array;
2100 + device_for_each_child(&mc_bus_dev->dev, &objs,
2101 + __fsl_mc_device_remove_if_not_in_mc);
2102 + } else {
2103 + /*
2104 + * There are no child objects for this DPRC in the MC.
2105 + * So, remove all the child devices from Linux:
2106 + */
2107 + device_for_each_child(&mc_bus_dev->dev, NULL,
2108 + __fsl_mc_device_remove);
2109 + }
2110 +}
2111 +
2112 +static int __fsl_mc_device_match(struct device *dev, void *data)
2113 +{
2114 + struct fsl_mc_obj_desc *obj_desc = data;
2115 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
2116 +
2117 + return fsl_mc_device_match(mc_dev, obj_desc);
2118 +}
2119 +
2120 +static struct fsl_mc_device *fsl_mc_device_lookup(struct fsl_mc_obj_desc
2121 + *obj_desc,
2122 + struct fsl_mc_device
2123 + *mc_bus_dev)
2124 +{
2125 + struct device *dev;
2126 +
2127 + dev = device_find_child(&mc_bus_dev->dev, obj_desc,
2128 + __fsl_mc_device_match);
2129 +
2130 + return dev ? to_fsl_mc_device(dev) : NULL;
2131 +}
2132 +
2133 +/**
2134 + * check_plugged_state_change - Check change in an MC object's plugged state
2135 + *
2136 + * @mc_dev: pointer to the fsl-mc device for a given MC object
2137 + * @obj_desc: pointer to the MC object's descriptor in the MC
2138 + *
2139 + * If the plugged state has changed from unplugged to plugged, the fsl-mc
2140 + * device is bound to the corresponding device driver.
2141 + * If the plugged state has changed from plugged to unplugged, the fsl-mc
2142 + * device is unbound from the corresponding device driver.
2143 + */
2144 +static void check_plugged_state_change(struct fsl_mc_device *mc_dev,
2145 + struct fsl_mc_obj_desc *obj_desc)
2146 +{
2147 + int error;
2148 + u32 plugged_flag_at_mc =
2149 + obj_desc->state & FSL_MC_OBJ_STATE_PLUGGED;
2150 +
2151 + if (plugged_flag_at_mc !=
2152 + (mc_dev->obj_desc.state & FSL_MC_OBJ_STATE_PLUGGED)) {
2153 + if (plugged_flag_at_mc) {
2154 + mc_dev->obj_desc.state |= FSL_MC_OBJ_STATE_PLUGGED;
2155 + error = device_attach(&mc_dev->dev);
2156 + if (error < 0) {
2157 + dev_err(&mc_dev->dev,
2158 + "device_attach() failed: %d\n",
2159 + error);
2160 + }
2161 + } else {
2162 + mc_dev->obj_desc.state &= ~FSL_MC_OBJ_STATE_PLUGGED;
2163 + device_release_driver(&mc_dev->dev);
2164 + }
2165 + }
2166 +}
2167 +
2168 +/**
2169 + * dprc_add_new_devices - Adds devices to the logical bus for a DPRC
2170 + *
2171 + * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
2172 + * @driver_override: driver override to apply to new objects found in the
2173 + * DPRC, or NULL, if none.
2174 + * @obj_desc_array: array of device descriptors for child devices currently
2175 + * present in the physical DPRC.
2176 + * @num_child_objects_in_mc: number of entries in obj_desc_array
2177 + *
2178 + * Synchronizes the state of the Linux bus driver with the actual
2179 + * state of the MC by adding objects that have been newly discovered
2180 + * in the physical DPRC.
2181 + */
2182 +static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev,
2183 + const char *driver_override,
2184 + struct fsl_mc_obj_desc *obj_desc_array,
2185 + int num_child_objects_in_mc)
2186 +{
2187 + int error;
2188 + int i;
2189 +
2190 + for (i = 0; i < num_child_objects_in_mc; i++) {
2191 + struct fsl_mc_device *child_dev;
2192 + struct fsl_mc_obj_desc *obj_desc = &obj_desc_array[i];
2193 +
2194 + if (strlen(obj_desc->type) == 0)
2195 + continue;
2196 +
2197 + /*
2198 + * Check if device is already known to Linux:
2199 + */
2200 + child_dev = fsl_mc_device_lookup(obj_desc, mc_bus_dev);
2201 + if (child_dev) {
2202 + check_plugged_state_change(child_dev, obj_desc);
2203 + put_device(&child_dev->dev);
2204 + continue;
2205 + }
2206 +
2207 + error = fsl_mc_device_add(obj_desc, NULL, &mc_bus_dev->dev,
2208 + driver_override, &child_dev);
2209 + if (error < 0)
2210 + continue;
2211 + }
2212 +}
2213 +
2214 +/**
2215 + * dprc_scan_objects - Discover objects in a DPRC
2216 + *
2217 + * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
2218 + * @driver_override: driver override to apply to new objects found in the
2219 + * DPRC, or NULL, if none.
2220 + * @total_irq_count: If argument is provided the function populates the
2221 + * total number of IRQs created by objects in the DPRC.
2222 + *
2223 + * Detects objects added and removed from a DPRC and synchronizes the
2224 + * state of the Linux bus driver, MC by adding and removing
2225 + * devices accordingly.
2226 + * Two types of devices can be found in a DPRC: allocatable objects (e.g.,
2227 + * dpbp, dpmcp) and non-allocatable devices (e.g., dprc, dpni).
2228 + * All allocatable devices needed to be probed before all non-allocatable
2229 + * devices, to ensure that device drivers for non-allocatable
2230 + * devices can allocate any type of allocatable devices.
2231 + * That is, we need to ensure that the corresponding resource pools are
2232 + * populated before they can get allocation requests from probe callbacks
2233 + * of the device drivers for the non-allocatable devices.
2234 + */
2235 +int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
2236 + const char *driver_override,
2237 + unsigned int *total_irq_count)
2238 +{
2239 + int num_child_objects;
2240 + int dprc_get_obj_failures;
2241 + int error;
2242 + unsigned int irq_count = mc_bus_dev->obj_desc.irq_count;
2243 + struct fsl_mc_obj_desc *child_obj_desc_array = NULL;
2244 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
2245 +
2246 + error = dprc_get_obj_count(mc_bus_dev->mc_io,
2247 + 0,
2248 + mc_bus_dev->mc_handle,
2249 + &num_child_objects);
2250 + if (error < 0) {
2251 + dev_err(&mc_bus_dev->dev, "dprc_get_obj_count() failed: %d\n",
2252 + error);
2253 + return error;
2254 + }
2255 +
2256 + if (num_child_objects != 0) {
2257 + int i;
2258 +
2259 + child_obj_desc_array =
2260 + devm_kmalloc_array(&mc_bus_dev->dev, num_child_objects,
2261 + sizeof(*child_obj_desc_array),
2262 + GFP_KERNEL);
2263 + if (!child_obj_desc_array)
2264 + return -ENOMEM;
2265 +
2266 + /*
2267 + * Discover objects currently present in the physical DPRC:
2268 + */
2269 + dprc_get_obj_failures = 0;
2270 + for (i = 0; i < num_child_objects; i++) {
2271 + struct fsl_mc_obj_desc *obj_desc =
2272 + &child_obj_desc_array[i];
2273 +
2274 + error = dprc_get_obj(mc_bus_dev->mc_io,
2275 + 0,
2276 + mc_bus_dev->mc_handle,
2277 + i, obj_desc);
2278 + if (error < 0) {
2279 + dev_err(&mc_bus_dev->dev,
2280 + "dprc_get_obj(i=%d) failed: %d\n",
2281 + i, error);
2282 + /*
2283 + * Mark the obj entry as "invalid", by using the
2284 + * empty string as obj type:
2285 + */
2286 + obj_desc->type[0] = '\0';
2287 + obj_desc->id = error;
2288 + dprc_get_obj_failures++;
2289 + continue;
2290 + }
2291 +
2292 + /*
2293 + * add a quirk for all versions of dpsec < 4.0...none
2294 + * are coherent regardless of what the MC reports.
2295 + */
2296 + if ((strcmp(obj_desc->type, "dpseci") == 0) &&
2297 + (obj_desc->ver_major < 4))
2298 + obj_desc->flags |=
2299 + FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY;
2300 +
2301 + irq_count += obj_desc->irq_count;
2302 + dev_dbg(&mc_bus_dev->dev,
2303 + "Discovered object: type %s, id %d\n",
2304 + obj_desc->type, obj_desc->id);
2305 + }
2306 +
2307 + if (dprc_get_obj_failures != 0) {
2308 + dev_err(&mc_bus_dev->dev,
2309 + "%d out of %d devices could not be retrieved\n",
2310 + dprc_get_obj_failures, num_child_objects);
2311 + }
2312 + }
2313 +
2314 + /*
2315 + * Allocate IRQ's before binding the scanned devices with their
2316 + * respective drivers.
2317 + */
2318 + if (dev_get_msi_domain(&mc_bus_dev->dev) && !mc_bus->irq_resources) {
2319 + if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) {
2320 + dev_warn(&mc_bus_dev->dev,
2321 + "IRQs needed (%u) exceed IRQs preallocated (%u)\n",
2322 + irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
2323 + }
2324 +
2325 + error = fsl_mc_populate_irq_pool(mc_bus,
2326 + FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
2327 + if (error < 0)
2328 + return error;
2329 + }
2330 +
2331 + if (total_irq_count)
2332 + *total_irq_count = irq_count;
2333 +
2334 + dprc_remove_devices(mc_bus_dev, child_obj_desc_array,
2335 + num_child_objects);
2336 +
2337 + dprc_add_new_devices(mc_bus_dev, driver_override, child_obj_desc_array,
2338 + num_child_objects);
2339 +
2340 + if (child_obj_desc_array)
2341 + devm_kfree(&mc_bus_dev->dev, child_obj_desc_array);
2342 +
2343 + return 0;
2344 +}
2345 +
2346 +/**
2347 + * dprc_scan_container - Scans a physical DPRC and synchronizes Linux bus state
2348 + *
2349 + * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
2350 + *
2351 + * Scans the physical DPRC and synchronizes the state of the Linux
2352 + * bus driver with the actual state of the MC by adding and removing
2353 + * devices as appropriate.
2354 + */
2355 +static int dprc_scan_container(struct fsl_mc_device *mc_bus_dev)
2356 +{
2357 + int error;
2358 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
2359 +
2360 + fsl_mc_init_all_resource_pools(mc_bus_dev);
2361 +
2362 + /*
2363 + * Discover objects in the DPRC:
2364 + */
2365 + mutex_lock(&mc_bus->scan_mutex);
2366 + error = dprc_scan_objects(mc_bus_dev, NULL, NULL);
2367 + mutex_unlock(&mc_bus->scan_mutex);
2368 + if (error < 0) {
2369 + fsl_mc_cleanup_all_resource_pools(mc_bus_dev);
2370 + return error;
2371 + }
2372 +
2373 + return 0;
2374 +}
2375 +
2376 +/**
2377 + * dprc_irq0_handler - Regular ISR for DPRC interrupt 0
2378 + *
2379 + * @irq: IRQ number of the interrupt being handled
2380 + * @arg: Pointer to device structure
2381 + */
2382 +static irqreturn_t dprc_irq0_handler(int irq_num, void *arg)
2383 +{
2384 + return IRQ_WAKE_THREAD;
2385 +}
2386 +
2387 +/**
2388 + * dprc_irq0_handler_thread - Handler thread function for DPRC interrupt 0
2389 + *
2390 + * @irq: IRQ number of the interrupt being handled
2391 + * @arg: Pointer to device structure
2392 + */
2393 +static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg)
2394 +{
2395 + int error;
2396 + u32 status;
2397 + struct device *dev = arg;
2398 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
2399 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
2400 + struct fsl_mc_io *mc_io = mc_dev->mc_io;
2401 + struct msi_desc *msi_desc = mc_dev->irqs[0]->msi_desc;
2402 +
2403 + dev_dbg(dev, "DPRC IRQ %d triggered on CPU %u\n",
2404 + irq_num, smp_processor_id());
2405 +
2406 + if (!(mc_dev->flags & FSL_MC_IS_DPRC))
2407 + return IRQ_HANDLED;
2408 +
2409 + mutex_lock(&mc_bus->scan_mutex);
2410 + if (!msi_desc || msi_desc->irq != (u32)irq_num)
2411 + goto out;
2412 +
2413 + status = 0;
2414 + error = dprc_get_irq_status(mc_io, 0, mc_dev->mc_handle, 0,
2415 + &status);
2416 + if (error < 0) {
2417 + dev_err(dev,
2418 + "dprc_get_irq_status() failed: %d\n", error);
2419 + goto out;
2420 + }
2421 +
2422 + error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0,
2423 + status);
2424 + if (error < 0) {
2425 + dev_err(dev,
2426 + "dprc_clear_irq_status() failed: %d\n", error);
2427 + goto out;
2428 + }
2429 +
2430 + if (status & (DPRC_IRQ_EVENT_OBJ_ADDED |
2431 + DPRC_IRQ_EVENT_OBJ_REMOVED |
2432 + DPRC_IRQ_EVENT_CONTAINER_DESTROYED |
2433 + DPRC_IRQ_EVENT_OBJ_DESTROYED |
2434 + DPRC_IRQ_EVENT_OBJ_CREATED)) {
2435 + unsigned int irq_count;
2436 +
2437 + error = dprc_scan_objects(mc_dev, NULL, &irq_count);
2438 + if (error < 0) {
2439 + /*
2440 + * If the error is -ENXIO, we ignore it, as it indicates
2441 + * that the object scan was aborted, as we detected that
2442 + * an object was removed from the DPRC in the MC, while
2443 + * we were scanning the DPRC.
2444 + */
2445 + if (error != -ENXIO) {
2446 + dev_err(dev, "dprc_scan_objects() failed: %d\n",
2447 + error);
2448 + }
2449 +
2450 + goto out;
2451 + }
2452 +
2453 + if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) {
2454 + dev_warn(dev,
2455 + "IRQs needed (%u) exceed IRQs preallocated (%u)\n",
2456 + irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
2457 + }
2458 + }
2459 +
2460 +out:
2461 + mutex_unlock(&mc_bus->scan_mutex);
2462 + return IRQ_HANDLED;
2463 +}
2464 +
2465 +/*
2466 + * Disable and clear interrupt for a given DPRC object
2467 + */
2468 +static int disable_dprc_irq(struct fsl_mc_device *mc_dev)
2469 +{
2470 + int error;
2471 + struct fsl_mc_io *mc_io = mc_dev->mc_io;
2472 +
2473 + /*
2474 + * Disable generation of interrupt, while we configure it:
2475 + */
2476 + error = dprc_set_irq_enable(mc_io, 0, mc_dev->mc_handle, 0, 0);
2477 + if (error < 0) {
2478 + dev_err(&mc_dev->dev,
2479 + "Disabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n",
2480 + error);
2481 + return error;
2482 + }
2483 +
2484 + /*
2485 + * Disable all interrupt causes for the interrupt:
2486 + */
2487 + error = dprc_set_irq_mask(mc_io, 0, mc_dev->mc_handle, 0, 0x0);
2488 + if (error < 0) {
2489 + dev_err(&mc_dev->dev,
2490 + "Disabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n",
2491 + error);
2492 + return error;
2493 + }
2494 +
2495 + /*
2496 + * Clear any leftover interrupts:
2497 + */
2498 + error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, ~0x0U);
2499 + if (error < 0) {
2500 + dev_err(&mc_dev->dev,
2501 + "Disabling DPRC IRQ failed: dprc_clear_irq_status() failed: %d\n",
2502 + error);
2503 + return error;
2504 + }
2505 +
2506 + return 0;
2507 +}
2508 +
2509 +static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev)
2510 +{
2511 + int error;
2512 + struct fsl_mc_device_irq *irq = mc_dev->irqs[0];
2513 +
2514 + /*
2515 + * NOTE: devm_request_threaded_irq() invokes the device-specific
2516 + * function that programs the MSI physically in the device
2517 + */
2518 + error = devm_request_threaded_irq(&mc_dev->dev,
2519 + irq->msi_desc->irq,
2520 + dprc_irq0_handler,
2521 + dprc_irq0_handler_thread,
2522 + IRQF_NO_SUSPEND | IRQF_ONESHOT,
2523 + dev_name(&mc_dev->dev),
2524 + &mc_dev->dev);
2525 + if (error < 0) {
2526 + dev_err(&mc_dev->dev,
2527 + "devm_request_threaded_irq() failed: %d\n",
2528 + error);
2529 + return error;
2530 + }
2531 +
2532 + return 0;
2533 +}
2534 +
2535 +static int enable_dprc_irq(struct fsl_mc_device *mc_dev)
2536 +{
2537 + int error;
2538 +
2539 + /*
2540 + * Enable all interrupt causes for the interrupt:
2541 + */
2542 + error = dprc_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle, 0,
2543 + ~0x0u);
2544 + if (error < 0) {
2545 + dev_err(&mc_dev->dev,
2546 + "Enabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n",
2547 + error);
2548 +
2549 + return error;
2550 + }
2551 +
2552 + /*
2553 + * Enable generation of the interrupt:
2554 + */
2555 + error = dprc_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, 1);
2556 + if (error < 0) {
2557 + dev_err(&mc_dev->dev,
2558 + "Enabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n",
2559 + error);
2560 +
2561 + return error;
2562 + }
2563 +
2564 + return 0;
2565 +}
2566 +
2567 +/*
2568 + * Setup interrupt for a given DPRC device
2569 + */
2570 +static int dprc_setup_irq(struct fsl_mc_device *mc_dev)
2571 +{
2572 + int error;
2573 +
2574 + error = fsl_mc_allocate_irqs(mc_dev);
2575 + if (error < 0)
2576 + return error;
2577 +
2578 + error = disable_dprc_irq(mc_dev);
2579 + if (error < 0)
2580 + goto error_free_irqs;
2581 +
2582 + error = register_dprc_irq_handler(mc_dev);
2583 + if (error < 0)
2584 + goto error_free_irqs;
2585 +
2586 + error = enable_dprc_irq(mc_dev);
2587 + if (error < 0)
2588 + goto error_free_irqs;
2589 +
2590 + return 0;
2591 +
2592 +error_free_irqs:
2593 + fsl_mc_free_irqs(mc_dev);
2594 + return error;
2595 +}
2596 +
2597 +/**
2598 + * dprc_probe - callback invoked when a DPRC is being bound to this driver
2599 + *
2600 + * @mc_dev: Pointer to fsl-mc device representing a DPRC
2601 + *
2602 + * It opens the physical DPRC in the MC.
2603 + * It scans the DPRC to discover the MC objects contained in it.
2604 + * It creates the interrupt pool for the MC bus associated with the DPRC.
2605 + * It configures the interrupts for the DPRC device itself.
2606 + */
2607 +static int dprc_probe(struct fsl_mc_device *mc_dev)
2608 +{
2609 + int error;
2610 + size_t region_size;
2611 + struct device *parent_dev = mc_dev->dev.parent;
2612 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
2613 + bool mc_io_created = false;
2614 + bool msi_domain_set = false;
2615 + u16 major_ver, minor_ver;
2616 +
2617 + if (!is_fsl_mc_bus_dprc(mc_dev))
2618 + return -EINVAL;
2619 +
2620 + if (dev_get_msi_domain(&mc_dev->dev))
2621 + return -EINVAL;
2622 +
2623 + if (!mc_dev->mc_io) {
2624 + /*
2625 + * This is a child DPRC:
2626 + */
2627 + if (!dev_is_fsl_mc(parent_dev))
2628 + return -EINVAL;
2629 +
2630 + if (mc_dev->obj_desc.region_count == 0)
2631 + return -EINVAL;
2632 +
2633 + region_size = resource_size(mc_dev->regions);
2634 +
2635 + error = fsl_create_mc_io(&mc_dev->dev,
2636 + mc_dev->regions[0].start,
2637 + region_size,
2638 + NULL,
2639 + FSL_MC_IO_ATOMIC_CONTEXT_PORTAL,
2640 + &mc_dev->mc_io);
2641 + if (error < 0)
2642 + return error;
2643 +
2644 + mc_io_created = true;
2645 +
2646 + /*
2647 + * Inherit parent MSI domain:
2648 + */
2649 + dev_set_msi_domain(&mc_dev->dev,
2650 + dev_get_msi_domain(parent_dev));
2651 + msi_domain_set = true;
2652 + } else {
2653 + /*
2654 + * This is a root DPRC
2655 + */
2656 + struct irq_domain *mc_msi_domain;
2657 +
2658 + if (dev_is_fsl_mc(parent_dev))
2659 + return -EINVAL;
2660 +
2661 + error = fsl_mc_find_msi_domain(parent_dev,
2662 + &mc_msi_domain);
2663 + if (error < 0) {
2664 + dev_warn(&mc_dev->dev,
2665 + "WARNING: MC bus without interrupt support\n");
2666 + } else {
2667 + dev_set_msi_domain(&mc_dev->dev, mc_msi_domain);
2668 + msi_domain_set = true;
2669 + }
2670 + }
2671 +
2672 + error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
2673 + &mc_dev->mc_handle);
2674 + if (error < 0) {
2675 + dev_err(&mc_dev->dev, "dprc_open() failed: %d\n", error);
2676 + goto error_cleanup_msi_domain;
2677 + }
2678 +
2679 + error = dprc_get_attributes(mc_dev->mc_io, 0, mc_dev->mc_handle,
2680 + &mc_bus->dprc_attr);
2681 + if (error < 0) {
2682 + dev_err(&mc_dev->dev, "dprc_get_attributes() failed: %d\n",
2683 + error);
2684 + goto error_cleanup_open;
2685 + }
2686 +
2687 + error = dprc_get_api_version(mc_dev->mc_io, 0,
2688 + &major_ver,
2689 + &minor_ver);
2690 + if (error < 0) {
2691 + dev_err(&mc_dev->dev, "dprc_get_api_version() failed: %d\n",
2692 + error);
2693 + goto error_cleanup_open;
2694 + }
2695 +
2696 + if (major_ver < DPRC_MIN_VER_MAJOR ||
2697 + (major_ver == DPRC_MIN_VER_MAJOR &&
2698 + minor_ver < DPRC_MIN_VER_MINOR)) {
2699 + dev_err(&mc_dev->dev,
2700 + "ERROR: DPRC version %d.%d not supported\n",
2701 + major_ver, minor_ver);
2702 + error = -ENOTSUPP;
2703 + goto error_cleanup_open;
2704 + }
2705 +
2706 + mutex_init(&mc_bus->scan_mutex);
2707 +
2708 + /*
2709 + * Discover MC objects in DPRC object:
2710 + */
2711 + error = dprc_scan_container(mc_dev);
2712 + if (error < 0)
2713 + goto error_cleanup_open;
2714 +
2715 + /*
2716 + * Configure interrupt for the DPRC object associated with this MC bus:
2717 + */
2718 + error = dprc_setup_irq(mc_dev);
2719 + if (error < 0)
2720 + goto error_cleanup_open;
2721 +
2722 + dev_info(&mc_dev->dev, "DPRC device bound to driver");
2723 + return 0;
2724 +
2725 +error_cleanup_open:
2726 + (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
2727 +
2728 +error_cleanup_msi_domain:
2729 + if (msi_domain_set)
2730 + dev_set_msi_domain(&mc_dev->dev, NULL);
2731 +
2732 + if (mc_io_created) {
2733 + fsl_destroy_mc_io(mc_dev->mc_io);
2734 + mc_dev->mc_io = NULL;
2735 + }
2736 +
2737 + return error;
2738 +}
2739 +
2740 +/*
2741 + * Tear down interrupt for a given DPRC object
2742 + */
2743 +static void dprc_teardown_irq(struct fsl_mc_device *mc_dev)
2744 +{
2745 + struct fsl_mc_device_irq *irq = mc_dev->irqs[0];
2746 +
2747 + (void)disable_dprc_irq(mc_dev);
2748 +
2749 + devm_free_irq(&mc_dev->dev, irq->msi_desc->irq, &mc_dev->dev);
2750 +
2751 + fsl_mc_free_irqs(mc_dev);
2752 +}
2753 +
2754 +/**
2755 + * dprc_remove - callback invoked when a DPRC is being unbound from this driver
2756 + *
2757 + * @mc_dev: Pointer to fsl-mc device representing the DPRC
2758 + *
2759 + * It removes the DPRC's child objects from Linux (not from the MC) and
2760 + * closes the DPRC device in the MC.
2761 + * It tears down the interrupts that were configured for the DPRC device.
2762 + * It destroys the interrupt pool associated with this MC bus.
2763 + */
2764 +static int dprc_remove(struct fsl_mc_device *mc_dev)
2765 +{
2766 + int error;
2767 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
2768 +
2769 + if (!is_fsl_mc_bus_dprc(mc_dev))
2770 + return -EINVAL;
2771 + if (!mc_dev->mc_io)
2772 + return -EINVAL;
2773 +
2774 + if (!mc_bus->irq_resources)
2775 + return -EINVAL;
2776 +
2777 + if (dev_get_msi_domain(&mc_dev->dev))
2778 + dprc_teardown_irq(mc_dev);
2779 +
2780 + device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove);
2781 +
2782 + if (dev_get_msi_domain(&mc_dev->dev)) {
2783 + fsl_mc_cleanup_irq_pool(mc_bus);
2784 + dev_set_msi_domain(&mc_dev->dev, NULL);
2785 + }
2786 +
2787 + fsl_mc_cleanup_all_resource_pools(mc_dev);
2788 +
2789 + error = dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
2790 + if (error < 0)
2791 + dev_err(&mc_dev->dev, "dprc_close() failed: %d\n", error);
2792 +
2793 + if (!fsl_mc_is_root_dprc(&mc_dev->dev)) {
2794 + fsl_destroy_mc_io(mc_dev->mc_io);
2795 + mc_dev->mc_io = NULL;
2796 + }
2797 +
2798 + dev_info(&mc_dev->dev, "DPRC device unbound from driver");
2799 + return 0;
2800 +}
2801 +
2802 +static const struct fsl_mc_device_id match_id_table[] = {
2803 + {
2804 + .vendor = FSL_MC_VENDOR_FREESCALE,
2805 + .obj_type = "dprc"},
2806 + {.vendor = 0x0},
2807 +};
2808 +
2809 +static struct fsl_mc_driver dprc_driver = {
2810 + .driver = {
2811 + .name = FSL_MC_DPRC_DRIVER_NAME,
2812 + .owner = THIS_MODULE,
2813 + .pm = NULL,
2814 + },
2815 + .match_id_table = match_id_table,
2816 + .probe = dprc_probe,
2817 + .remove = dprc_remove,
2818 +};
2819 +
2820 +int __init dprc_driver_init(void)
2821 +{
2822 + return fsl_mc_driver_register(&dprc_driver);
2823 +}
2824 +
2825 +void dprc_driver_exit(void)
2826 +{
2827 + fsl_mc_driver_unregister(&dprc_driver);
2828 +}
2829 --- /dev/null
2830 +++ b/drivers/bus/fsl-mc/dprc.c
2831 @@ -0,0 +1,575 @@
2832 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
2833 +/*
2834 + * Copyright 2013-2016 Freescale Semiconductor Inc.
2835 + *
2836 + */
2837 +#include <linux/kernel.h>
2838 +#include <linux/fsl/mc.h>
2839 +
2840 +#include "fsl-mc-private.h"
2841 +
2842 +/**
2843 + * dprc_open() - Open DPRC object for use
2844 + * @mc_io: Pointer to MC portal's I/O object
2845 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
2846 + * @container_id: Container ID to open
2847 + * @token: Returned token of DPRC object
2848 + *
2849 + * Return: '0' on Success; Error code otherwise.
2850 + *
2851 + * @warning Required before any operation on the object.
2852 + */
2853 +int dprc_open(struct fsl_mc_io *mc_io,
2854 + u32 cmd_flags,
2855 + int container_id,
2856 + u16 *token)
2857 +{
2858 + struct fsl_mc_command cmd = { 0 };
2859 + struct dprc_cmd_open *cmd_params;
2860 + int err;
2861 +
2862 + /* prepare command */
2863 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_OPEN, cmd_flags,
2864 + 0);
2865 + cmd_params = (struct dprc_cmd_open *)cmd.params;
2866 + cmd_params->container_id = cpu_to_le32(container_id);
2867 +
2868 + /* send command to mc*/
2869 + err = mc_send_command(mc_io, &cmd);
2870 + if (err)
2871 + return err;
2872 +
2873 + /* retrieve response parameters */
2874 + *token = mc_cmd_hdr_read_token(&cmd);
2875 +
2876 + return 0;
2877 +}
2878 +EXPORT_SYMBOL_GPL(dprc_open);
2879 +
2880 +/**
2881 + * dprc_close() - Close the control session of the object
2882 + * @mc_io: Pointer to MC portal's I/O object
2883 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
2884 + * @token: Token of DPRC object
2885 + *
2886 + * After this function is called, no further operations are
2887 + * allowed on the object without opening a new control session.
2888 + *
2889 + * Return: '0' on Success; Error code otherwise.
2890 + */
2891 +int dprc_close(struct fsl_mc_io *mc_io,
2892 + u32 cmd_flags,
2893 + u16 token)
2894 +{
2895 + struct fsl_mc_command cmd = { 0 };
2896 +
2897 + /* prepare command */
2898 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLOSE, cmd_flags,
2899 + token);
2900 +
2901 + /* send command to mc*/
2902 + return mc_send_command(mc_io, &cmd);
2903 +}
2904 +EXPORT_SYMBOL_GPL(dprc_close);
2905 +
2906 +/**
2907 + * dprc_reset_container - Reset child container.
2908 + * @mc_io: Pointer to MC portal's I/O object
2909 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
2910 + * @token: Token of DPRC object
2911 + * @child_container_id: ID of the container to reset
2912 + *
2913 + * In case a software context crashes or becomes non-responsive, the parent
2914 + * may wish to reset its resources container before the software context is
2915 + * restarted.
2916 + *
2917 + * This routine informs all objects assigned to the child container that the
2918 + * container is being reset, so they may perform any cleanup operations that are
2919 + * needed. All objects handles that were owned by the child container shall be
2920 + * closed.
2921 + *
2922 + * Note that such request may be submitted even if the child software context
2923 + * has not crashed, but the resulting object cleanup operations will not be
2924 + * aware of that.
2925 + *
2926 + * Return: '0' on Success; Error code otherwise.
2927 + */
2928 +int dprc_reset_container(struct fsl_mc_io *mc_io,
2929 + u32 cmd_flags,
2930 + u16 token,
2931 + int child_container_id)
2932 +{
2933 + struct fsl_mc_command cmd = { 0 };
2934 + struct dprc_cmd_reset_container *cmd_params;
2935 +
2936 + /* prepare command */
2937 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_RESET_CONT,
2938 + cmd_flags, token);
2939 + cmd_params = (struct dprc_cmd_reset_container *)cmd.params;
2940 + cmd_params->child_container_id = cpu_to_le32(child_container_id);
2941 +
2942 + /* send command to mc*/
2943 + return mc_send_command(mc_io, &cmd);
2944 +}
2945 +EXPORT_SYMBOL_GPL(dprc_reset_container);
2946 +
2947 +/**
2948 + * dprc_set_irq() - Set IRQ information for the DPRC to trigger an interrupt.
2949 + * @mc_io: Pointer to MC portal's I/O object
2950 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
2951 + * @token: Token of DPRC object
2952 + * @irq_index: Identifies the interrupt index to configure
2953 + * @irq_cfg: IRQ configuration
2954 + *
2955 + * Return: '0' on Success; Error code otherwise.
2956 + */
2957 +int dprc_set_irq(struct fsl_mc_io *mc_io,
2958 + u32 cmd_flags,
2959 + u16 token,
2960 + u8 irq_index,
2961 + struct dprc_irq_cfg *irq_cfg)
2962 +{
2963 + struct fsl_mc_command cmd = { 0 };
2964 + struct dprc_cmd_set_irq *cmd_params;
2965 +
2966 + /* prepare command */
2967 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ,
2968 + cmd_flags,
2969 + token);
2970 + cmd_params = (struct dprc_cmd_set_irq *)cmd.params;
2971 + cmd_params->irq_val = cpu_to_le32(irq_cfg->val);
2972 + cmd_params->irq_index = irq_index;
2973 + cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr);
2974 + cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num);
2975 +
2976 + /* send command to mc*/
2977 + return mc_send_command(mc_io, &cmd);
2978 +}
2979 +
2980 +/**
2981 + * dprc_set_irq_enable() - Set overall interrupt state.
2982 + * @mc_io: Pointer to MC portal's I/O object
2983 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
2984 + * @token: Token of DPRC object
2985 + * @irq_index: The interrupt index to configure
2986 + * @en: Interrupt state - enable = 1, disable = 0
2987 + *
2988 + * Allows GPP software to control when interrupts are generated.
2989 + * Each interrupt can have up to 32 causes. The enable/disable control's the
2990 + * overall interrupt state. if the interrupt is disabled no causes will cause
2991 + * an interrupt.
2992 + *
2993 + * Return: '0' on Success; Error code otherwise.
2994 + */
2995 +int dprc_set_irq_enable(struct fsl_mc_io *mc_io,
2996 + u32 cmd_flags,
2997 + u16 token,
2998 + u8 irq_index,
2999 + u8 en)
3000 +{
3001 + struct fsl_mc_command cmd = { 0 };
3002 + struct dprc_cmd_set_irq_enable *cmd_params;
3003 +
3004 + /* prepare command */
3005 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_ENABLE,
3006 + cmd_flags, token);
3007 + cmd_params = (struct dprc_cmd_set_irq_enable *)cmd.params;
3008 + cmd_params->enable = en & DPRC_ENABLE;
3009 + cmd_params->irq_index = irq_index;
3010 +
3011 + /* send command to mc*/
3012 + return mc_send_command(mc_io, &cmd);
3013 +}
3014 +
3015 +/**
3016 + * dprc_set_irq_mask() - Set interrupt mask.
3017 + * @mc_io: Pointer to MC portal's I/O object
3018 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3019 + * @token: Token of DPRC object
3020 + * @irq_index: The interrupt index to configure
3021 + * @mask: event mask to trigger interrupt;
3022 + * each bit:
3023 + * 0 = ignore event
3024 + * 1 = consider event for asserting irq
3025 + *
3026 + * Every interrupt can have up to 32 causes and the interrupt model supports
3027 + * masking/unmasking each cause independently
3028 + *
3029 + * Return: '0' on Success; Error code otherwise.
3030 + */
3031 +int dprc_set_irq_mask(struct fsl_mc_io *mc_io,
3032 + u32 cmd_flags,
3033 + u16 token,
3034 + u8 irq_index,
3035 + u32 mask)
3036 +{
3037 + struct fsl_mc_command cmd = { 0 };
3038 + struct dprc_cmd_set_irq_mask *cmd_params;
3039 +
3040 + /* prepare command */
3041 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_MASK,
3042 + cmd_flags, token);
3043 + cmd_params = (struct dprc_cmd_set_irq_mask *)cmd.params;
3044 + cmd_params->mask = cpu_to_le32(mask);
3045 + cmd_params->irq_index = irq_index;
3046 +
3047 + /* send command to mc*/
3048 + return mc_send_command(mc_io, &cmd);
3049 +}
3050 +
3051 +/**
3052 + * dprc_get_irq_status() - Get the current status of any pending interrupts.
3053 + * @mc_io: Pointer to MC portal's I/O object
3054 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3055 + * @token: Token of DPRC object
3056 + * @irq_index: The interrupt index to configure
3057 + * @status: Returned interrupts status - one bit per cause:
3058 + * 0 = no interrupt pending
3059 + * 1 = interrupt pending
3060 + *
3061 + * Return: '0' on Success; Error code otherwise.
3062 + */
3063 +int dprc_get_irq_status(struct fsl_mc_io *mc_io,
3064 + u32 cmd_flags,
3065 + u16 token,
3066 + u8 irq_index,
3067 + u32 *status)
3068 +{
3069 + struct fsl_mc_command cmd = { 0 };
3070 + struct dprc_cmd_get_irq_status *cmd_params;
3071 + struct dprc_rsp_get_irq_status *rsp_params;
3072 + int err;
3073 +
3074 + /* prepare command */
3075 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_STATUS,
3076 + cmd_flags, token);
3077 + cmd_params = (struct dprc_cmd_get_irq_status *)cmd.params;
3078 + cmd_params->status = cpu_to_le32(*status);
3079 + cmd_params->irq_index = irq_index;
3080 +
3081 + /* send command to mc*/
3082 + err = mc_send_command(mc_io, &cmd);
3083 + if (err)
3084 + return err;
3085 +
3086 + /* retrieve response parameters */
3087 + rsp_params = (struct dprc_rsp_get_irq_status *)cmd.params;
3088 + *status = le32_to_cpu(rsp_params->status);
3089 +
3090 + return 0;
3091 +}
3092 +
3093 +/**
3094 + * dprc_clear_irq_status() - Clear a pending interrupt's status
3095 + * @mc_io: Pointer to MC portal's I/O object
3096 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3097 + * @token: Token of DPRC object
3098 + * @irq_index: The interrupt index to configure
3099 + * @status: bits to clear (W1C) - one bit per cause:
3100 + * 0 = don't change
3101 + * 1 = clear status bit
3102 + *
3103 + * Return: '0' on Success; Error code otherwise.
3104 + */
3105 +int dprc_clear_irq_status(struct fsl_mc_io *mc_io,
3106 + u32 cmd_flags,
3107 + u16 token,
3108 + u8 irq_index,
3109 + u32 status)
3110 +{
3111 + struct fsl_mc_command cmd = { 0 };
3112 + struct dprc_cmd_clear_irq_status *cmd_params;
3113 +
3114 + /* prepare command */
3115 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLEAR_IRQ_STATUS,
3116 + cmd_flags, token);
3117 + cmd_params = (struct dprc_cmd_clear_irq_status *)cmd.params;
3118 + cmd_params->status = cpu_to_le32(status);
3119 + cmd_params->irq_index = irq_index;
3120 +
3121 + /* send command to mc*/
3122 + return mc_send_command(mc_io, &cmd);
3123 +}
3124 +
3125 +/**
3126 + * dprc_get_attributes() - Obtains container attributes
3127 + * @mc_io: Pointer to MC portal's I/O object
3128 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3129 + * @token: Token of DPRC object
3130 + * @attributes Returned container attributes
3131 + *
3132 + * Return: '0' on Success; Error code otherwise.
3133 + */
3134 +int dprc_get_attributes(struct fsl_mc_io *mc_io,
3135 + u32 cmd_flags,
3136 + u16 token,
3137 + struct dprc_attributes *attr)
3138 +{
3139 + struct fsl_mc_command cmd = { 0 };
3140 + struct dprc_rsp_get_attributes *rsp_params;
3141 + int err;
3142 +
3143 + /* prepare command */
3144 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_ATTR,
3145 + cmd_flags,
3146 + token);
3147 +
3148 + /* send command to mc*/
3149 + err = mc_send_command(mc_io, &cmd);
3150 + if (err)
3151 + return err;
3152 +
3153 + /* retrieve response parameters */
3154 + rsp_params = (struct dprc_rsp_get_attributes *)cmd.params;
3155 + attr->container_id = le32_to_cpu(rsp_params->container_id);
3156 + attr->icid = le32_to_cpu(rsp_params->icid);
3157 + attr->options = le32_to_cpu(rsp_params->options);
3158 + attr->portal_id = le32_to_cpu(rsp_params->portal_id);
3159 +
3160 + return 0;
3161 +}
3162 +
3163 +/**
3164 + * dprc_get_obj_count() - Obtains the number of objects in the DPRC
3165 + * @mc_io: Pointer to MC portal's I/O object
3166 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3167 + * @token: Token of DPRC object
3168 + * @obj_count: Number of objects assigned to the DPRC
3169 + *
3170 + * Return: '0' on Success; Error code otherwise.
3171 + */
3172 +int dprc_get_obj_count(struct fsl_mc_io *mc_io,
3173 + u32 cmd_flags,
3174 + u16 token,
3175 + int *obj_count)
3176 +{
3177 + struct fsl_mc_command cmd = { 0 };
3178 + struct dprc_rsp_get_obj_count *rsp_params;
3179 + int err;
3180 +
3181 + /* prepare command */
3182 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_COUNT,
3183 + cmd_flags, token);
3184 +
3185 + /* send command to mc*/
3186 + err = mc_send_command(mc_io, &cmd);
3187 + if (err)
3188 + return err;
3189 +
3190 + /* retrieve response parameters */
3191 + rsp_params = (struct dprc_rsp_get_obj_count *)cmd.params;
3192 + *obj_count = le32_to_cpu(rsp_params->obj_count);
3193 +
3194 + return 0;
3195 +}
3196 +EXPORT_SYMBOL_GPL(dprc_get_obj_count);
3197 +
3198 +/**
3199 + * dprc_get_obj() - Get general information on an object
3200 + * @mc_io: Pointer to MC portal's I/O object
3201 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3202 + * @token: Token of DPRC object
3203 + * @obj_index: Index of the object to be queried (< obj_count)
3204 + * @obj_desc: Returns the requested object descriptor
3205 + *
3206 + * The object descriptors are retrieved one by one by incrementing
3207 + * obj_index up to (not including) the value of obj_count returned
3208 + * from dprc_get_obj_count(). dprc_get_obj_count() must
3209 + * be called prior to dprc_get_obj().
3210 + *
3211 + * Return: '0' on Success; Error code otherwise.
3212 + */
3213 +int dprc_get_obj(struct fsl_mc_io *mc_io,
3214 + u32 cmd_flags,
3215 + u16 token,
3216 + int obj_index,
3217 + struct fsl_mc_obj_desc *obj_desc)
3218 +{
3219 + struct fsl_mc_command cmd = { 0 };
3220 + struct dprc_cmd_get_obj *cmd_params;
3221 + struct dprc_rsp_get_obj *rsp_params;
3222 + int err;
3223 +
3224 + /* prepare command */
3225 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ,
3226 + cmd_flags,
3227 + token);
3228 + cmd_params = (struct dprc_cmd_get_obj *)cmd.params;
3229 + cmd_params->obj_index = cpu_to_le32(obj_index);
3230 +
3231 + /* send command to mc*/
3232 + err = mc_send_command(mc_io, &cmd);
3233 + if (err)
3234 + return err;
3235 +
3236 + /* retrieve response parameters */
3237 + rsp_params = (struct dprc_rsp_get_obj *)cmd.params;
3238 + obj_desc->id = le32_to_cpu(rsp_params->id);
3239 + obj_desc->vendor = le16_to_cpu(rsp_params->vendor);
3240 + obj_desc->irq_count = rsp_params->irq_count;
3241 + obj_desc->region_count = rsp_params->region_count;
3242 + obj_desc->state = le32_to_cpu(rsp_params->state);
3243 + obj_desc->ver_major = le16_to_cpu(rsp_params->version_major);
3244 + obj_desc->ver_minor = le16_to_cpu(rsp_params->version_minor);
3245 + obj_desc->flags = le16_to_cpu(rsp_params->flags);
3246 + strncpy(obj_desc->type, rsp_params->type, 16);
3247 + obj_desc->type[15] = '\0';
3248 + strncpy(obj_desc->label, rsp_params->label, 16);
3249 + obj_desc->label[15] = '\0';
3250 + return 0;
3251 +}
3252 +EXPORT_SYMBOL_GPL(dprc_get_obj);
3253 +
3254 +/**
3255 + * dprc_set_obj_irq() - Set IRQ information for object to trigger an interrupt.
3256 + * @mc_io: Pointer to MC portal's I/O object
3257 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3258 + * @token: Token of DPRC object
3259 + * @obj_type: Type of the object to set its IRQ
3260 + * @obj_id: ID of the object to set its IRQ
3261 + * @irq_index: The interrupt index to configure
3262 + * @irq_cfg: IRQ configuration
3263 + *
3264 + * Return: '0' on Success; Error code otherwise.
3265 + */
3266 +int dprc_set_obj_irq(struct fsl_mc_io *mc_io,
3267 + u32 cmd_flags,
3268 + u16 token,
3269 + char *obj_type,
3270 + int obj_id,
3271 + u8 irq_index,
3272 + struct dprc_irq_cfg *irq_cfg)
3273 +{
3274 + struct fsl_mc_command cmd = { 0 };
3275 + struct dprc_cmd_set_obj_irq *cmd_params;
3276 +
3277 + /* prepare command */
3278 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_OBJ_IRQ,
3279 + cmd_flags,
3280 + token);
3281 + cmd_params = (struct dprc_cmd_set_obj_irq *)cmd.params;
3282 + cmd_params->irq_val = cpu_to_le32(irq_cfg->val);
3283 + cmd_params->irq_index = irq_index;
3284 + cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr);
3285 + cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num);
3286 + cmd_params->obj_id = cpu_to_le32(obj_id);
3287 + strncpy(cmd_params->obj_type, obj_type, 16);
3288 + cmd_params->obj_type[15] = '\0';
3289 +
3290 + /* send command to mc*/
3291 + return mc_send_command(mc_io, &cmd);
3292 +}
3293 +EXPORT_SYMBOL_GPL(dprc_set_obj_irq);
3294 +
3295 +/**
3296 + * dprc_get_obj_region() - Get region information for a specified object.
3297 + * @mc_io: Pointer to MC portal's I/O object
3298 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3299 + * @token: Token of DPRC object
3300 + * @obj_type; Object type as returned in dprc_get_obj()
3301 + * @obj_id: Unique object instance as returned in dprc_get_obj()
3302 + * @region_index: The specific region to query
3303 + * @region_desc: Returns the requested region descriptor
3304 + *
3305 + * Return: '0' on Success; Error code otherwise.
3306 + */
3307 +int dprc_get_obj_region(struct fsl_mc_io *mc_io,
3308 + u32 cmd_flags,
3309 + u16 token,
3310 + char *obj_type,
3311 + int obj_id,
3312 + u8 region_index,
3313 + struct dprc_region_desc *region_desc)
3314 +{
3315 + struct fsl_mc_command cmd = { 0 };
3316 + struct dprc_cmd_get_obj_region *cmd_params;
3317 + struct dprc_rsp_get_obj_region *rsp_params;
3318 + int err;
3319 +
3320 + /* prepare command */
3321 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG,
3322 + cmd_flags, token);
3323 + cmd_params = (struct dprc_cmd_get_obj_region *)cmd.params;
3324 + cmd_params->obj_id = cpu_to_le32(obj_id);
3325 + cmd_params->region_index = region_index;
3326 + strncpy(cmd_params->obj_type, obj_type, 16);
3327 + cmd_params->obj_type[15] = '\0';
3328 +
3329 + /* send command to mc*/
3330 + err = mc_send_command(mc_io, &cmd);
3331 + if (err)
3332 + return err;
3333 +
3334 + /* retrieve response parameters */
3335 + rsp_params = (struct dprc_rsp_get_obj_region *)cmd.params;
3336 + region_desc->base_offset = le32_to_cpu(rsp_params->base_addr);
3337 + region_desc->size = le32_to_cpu(rsp_params->size);
3338 + region_desc->type = rsp_params->type;
3339 + region_desc->flags = le32_to_cpu(rsp_params->flags);
3340 +
3341 + return 0;
3342 +}
3343 +EXPORT_SYMBOL_GPL(dprc_get_obj_region);
3344 +
3345 +/**
3346 + * dprc_get_api_version - Get Data Path Resource Container API version
3347 + * @mc_io: Pointer to Mc portal's I/O object
3348 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3349 + * @major_ver: Major version of Data Path Resource Container API
3350 + * @minor_ver: Minor version of Data Path Resource Container API
3351 + *
3352 + * Return: '0' on Success; Error code otherwise.
3353 + */
3354 +int dprc_get_api_version(struct fsl_mc_io *mc_io,
3355 + u32 cmd_flags,
3356 + u16 *major_ver,
3357 + u16 *minor_ver)
3358 +{
3359 + struct fsl_mc_command cmd = { 0 };
3360 + int err;
3361 +
3362 + /* prepare command */
3363 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_API_VERSION,
3364 + cmd_flags, 0);
3365 +
3366 + /* send command to mc */
3367 + err = mc_send_command(mc_io, &cmd);
3368 + if (err)
3369 + return err;
3370 +
3371 + /* retrieve response parameters */
3372 + mc_cmd_read_api_version(&cmd, major_ver, minor_ver);
3373 +
3374 + return 0;
3375 +}
3376 +
3377 +/**
3378 + * dprc_get_container_id - Get container ID associated with a given portal.
3379 + * @mc_io: Pointer to Mc portal's I/O object
3380 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3381 + * @container_id: Requested container id
3382 + *
3383 + * Return: '0' on Success; Error code otherwise.
3384 + */
3385 +int dprc_get_container_id(struct fsl_mc_io *mc_io,
3386 + u32 cmd_flags,
3387 + int *container_id)
3388 +{
3389 + struct fsl_mc_command cmd = { 0 };
3390 + int err;
3391 +
3392 + /* prepare command */
3393 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONT_ID,
3394 + cmd_flags,
3395 + 0);
3396 +
3397 + /* send command to mc*/
3398 + err = mc_send_command(mc_io, &cmd);
3399 + if (err)
3400 + return err;
3401 +
3402 + /* retrieve response parameters */
3403 + *container_id = (int)mc_cmd_read_object_id(&cmd);
3404 +
3405 + return 0;
3406 +}
3407 --- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c
3408 +++ /dev/null
3409 @@ -1,668 +0,0 @@
3410 -/*
3411 - * Freescale MC object device allocator driver
3412 - *
3413 - * Copyright (C) 2013 Freescale Semiconductor, Inc.
3414 - *
3415 - * This file is licensed under the terms of the GNU General Public
3416 - * License version 2. This program is licensed "as is" without any
3417 - * warranty of any kind, whether express or implied.
3418 - */
3419 -
3420 -#include <linux/module.h>
3421 -#include <linux/msi.h>
3422 -#include "../include/mc-bus.h"
3423 -#include "../include/mc-sys.h"
3424 -#include "../include/dpbp-cmd.h"
3425 -#include "../include/dpcon-cmd.h"
3426 -
3427 -#include "fsl-mc-private.h"
3428 -
3429 -#define FSL_MC_IS_ALLOCATABLE(_obj_type) \
3430 - (strcmp(_obj_type, "dpbp") == 0 || \
3431 - strcmp(_obj_type, "dpmcp") == 0 || \
3432 - strcmp(_obj_type, "dpcon") == 0)
3433 -
3434 -/**
3435 - * fsl_mc_resource_pool_add_device - add allocatable device to a resource
3436 - * pool of a given MC bus
3437 - *
3438 - * @mc_bus: pointer to the MC bus
3439 - * @pool_type: MC bus pool type
3440 - * @mc_dev: Pointer to allocatable MC object device
3441 - *
3442 - * It adds an allocatable MC object device to a container's resource pool of
3443 - * the given resource type
3444 - */
3445 -static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus
3446 - *mc_bus,
3447 - enum fsl_mc_pool_type
3448 - pool_type,
3449 - struct fsl_mc_device
3450 - *mc_dev)
3451 -{
3452 - struct fsl_mc_resource_pool *res_pool;
3453 - struct fsl_mc_resource *resource;
3454 - struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
3455 - int error = -EINVAL;
3456 -
3457 - if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES))
3458 - goto out;
3459 - if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type)))
3460 - goto out;
3461 - if (WARN_ON(mc_dev->resource))
3462 - goto out;
3463 -
3464 - res_pool = &mc_bus->resource_pools[pool_type];
3465 - if (WARN_ON(res_pool->type != pool_type))
3466 - goto out;
3467 - if (WARN_ON(res_pool->mc_bus != mc_bus))
3468 - goto out;
3469 -
3470 - mutex_lock(&res_pool->mutex);
3471 -
3472 - if (WARN_ON(res_pool->max_count < 0))
3473 - goto out_unlock;
3474 - if (WARN_ON(res_pool->free_count < 0 ||
3475 - res_pool->free_count > res_pool->max_count))
3476 - goto out_unlock;
3477 -
3478 - resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource),
3479 - GFP_KERNEL);
3480 - if (!resource) {
3481 - error = -ENOMEM;
3482 - dev_err(&mc_bus_dev->dev,
3483 - "Failed to allocate memory for fsl_mc_resource\n");
3484 - goto out_unlock;
3485 - }
3486 -
3487 - resource->type = pool_type;
3488 - resource->id = mc_dev->obj_desc.id;
3489 - resource->data = mc_dev;
3490 - resource->parent_pool = res_pool;
3491 - INIT_LIST_HEAD(&resource->node);
3492 - list_add_tail(&resource->node, &res_pool->free_list);
3493 - mc_dev->resource = resource;
3494 - res_pool->free_count++;
3495 - res_pool->max_count++;
3496 - error = 0;
3497 -out_unlock:
3498 - mutex_unlock(&res_pool->mutex);
3499 -out:
3500 - return error;
3501 -}
3502 -
3503 -/**
3504 - * fsl_mc_resource_pool_remove_device - remove an allocatable device from a
3505 - * resource pool
3506 - *
3507 - * @mc_dev: Pointer to allocatable MC object device
3508 - *
3509 - * It permanently removes an allocatable MC object device from the resource
3510 - * pool, the device is currently in, as long as it is in the pool's free list.
3511 - */
3512 -static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device
3513 - *mc_dev)
3514 -{
3515 - struct fsl_mc_device *mc_bus_dev;
3516 - struct fsl_mc_bus *mc_bus;
3517 - struct fsl_mc_resource_pool *res_pool;
3518 - struct fsl_mc_resource *resource;
3519 - int error = -EINVAL;
3520 -
3521 - if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type)))
3522 - goto out;
3523 -
3524 - resource = mc_dev->resource;
3525 - if (WARN_ON(!resource || resource->data != mc_dev))
3526 - goto out;
3527 -
3528 - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
3529 - mc_bus = to_fsl_mc_bus(mc_bus_dev);
3530 - res_pool = resource->parent_pool;
3531 - if (WARN_ON(res_pool != &mc_bus->resource_pools[resource->type]))
3532 - goto out;
3533 -
3534 - mutex_lock(&res_pool->mutex);
3535 -
3536 - if (WARN_ON(res_pool->max_count <= 0))
3537 - goto out_unlock;
3538 - if (WARN_ON(res_pool->free_count <= 0 ||
3539 - res_pool->free_count > res_pool->max_count))
3540 - goto out_unlock;
3541 -
3542 - /*
3543 - * If the device is currently allocated, its resource is not
3544 - * in the free list and thus, the device cannot be removed.
3545 - */
3546 - if (list_empty(&resource->node)) {
3547 - error = -EBUSY;
3548 - dev_err(&mc_bus_dev->dev,
3549 - "Device %s cannot be removed from resource pool\n",
3550 - dev_name(&mc_dev->dev));
3551 - goto out_unlock;
3552 - }
3553 -
3554 - list_del_init(&resource->node);
3555 - res_pool->free_count--;
3556 - res_pool->max_count--;
3557 -
3558 - devm_kfree(&mc_bus_dev->dev, resource);
3559 - mc_dev->resource = NULL;
3560 - error = 0;
3561 -out_unlock:
3562 - mutex_unlock(&res_pool->mutex);
3563 -out:
3564 - return error;
3565 -}
3566 -
3567 -static const char *const fsl_mc_pool_type_strings[] = {
3568 - [FSL_MC_POOL_DPMCP] = "dpmcp",
3569 - [FSL_MC_POOL_DPBP] = "dpbp",
3570 - [FSL_MC_POOL_DPCON] = "dpcon",
3571 - [FSL_MC_POOL_IRQ] = "irq",
3572 -};
3573 -
3574 -static int __must_check object_type_to_pool_type(const char *object_type,
3575 - enum fsl_mc_pool_type
3576 - *pool_type)
3577 -{
3578 - unsigned int i;
3579 -
3580 - for (i = 0; i < ARRAY_SIZE(fsl_mc_pool_type_strings); i++) {
3581 - if (strcmp(object_type, fsl_mc_pool_type_strings[i]) == 0) {
3582 - *pool_type = i;
3583 - return 0;
3584 - }
3585 - }
3586 -
3587 - return -EINVAL;
3588 -}
3589 -
3590 -int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus,
3591 - enum fsl_mc_pool_type pool_type,
3592 - struct fsl_mc_resource **new_resource)
3593 -{
3594 - struct fsl_mc_resource_pool *res_pool;
3595 - struct fsl_mc_resource *resource;
3596 - struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
3597 - int error = -EINVAL;
3598 -
3599 - BUILD_BUG_ON(ARRAY_SIZE(fsl_mc_pool_type_strings) !=
3600 - FSL_MC_NUM_POOL_TYPES);
3601 -
3602 - *new_resource = NULL;
3603 - if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES))
3604 - goto out;
3605 -
3606 - res_pool = &mc_bus->resource_pools[pool_type];
3607 - if (WARN_ON(res_pool->mc_bus != mc_bus))
3608 - goto out;
3609 -
3610 - mutex_lock(&res_pool->mutex);
3611 - resource = list_first_entry_or_null(&res_pool->free_list,
3612 - struct fsl_mc_resource, node);
3613 -
3614 - if (!resource) {
3615 - WARN_ON(res_pool->free_count != 0);
3616 - error = -ENXIO;
3617 - dev_err(&mc_bus_dev->dev,
3618 - "No more resources of type %s left\n",
3619 - fsl_mc_pool_type_strings[pool_type]);
3620 - goto out_unlock;
3621 - }
3622 -
3623 - if (WARN_ON(resource->type != pool_type))
3624 - goto out_unlock;
3625 - if (WARN_ON(resource->parent_pool != res_pool))
3626 - goto out_unlock;
3627 - if (WARN_ON(res_pool->free_count <= 0 ||
3628 - res_pool->free_count > res_pool->max_count))
3629 - goto out_unlock;
3630 -
3631 - list_del_init(&resource->node);
3632 -
3633 - res_pool->free_count--;
3634 - error = 0;
3635 -out_unlock:
3636 - mutex_unlock(&res_pool->mutex);
3637 - *new_resource = resource;
3638 -out:
3639 - return error;
3640 -}
3641 -EXPORT_SYMBOL_GPL(fsl_mc_resource_allocate);
3642 -
3643 -void fsl_mc_resource_free(struct fsl_mc_resource *resource)
3644 -{
3645 - struct fsl_mc_resource_pool *res_pool;
3646 -
3647 - res_pool = resource->parent_pool;
3648 - if (WARN_ON(resource->type != res_pool->type))
3649 - return;
3650 -
3651 - mutex_lock(&res_pool->mutex);
3652 - if (WARN_ON(res_pool->free_count < 0 ||
3653 - res_pool->free_count >= res_pool->max_count))
3654 - goto out_unlock;
3655 -
3656 - if (WARN_ON(!list_empty(&resource->node)))
3657 - goto out_unlock;
3658 -
3659 - list_add_tail(&resource->node, &res_pool->free_list);
3660 - res_pool->free_count++;
3661 -out_unlock:
3662 - mutex_unlock(&res_pool->mutex);
3663 -}
3664 -EXPORT_SYMBOL_GPL(fsl_mc_resource_free);
3665 -
3666 -/**
3667 - * fsl_mc_object_allocate - Allocates a MC object device of the given
3668 - * pool type from a given MC bus
3669 - *
3670 - * @mc_dev: MC device for which the MC object device is to be allocated
3671 - * @pool_type: MC bus resource pool type
3672 - * @new_mc_dev: Pointer to area where the pointer to the allocated
3673 - * MC object device is to be returned
3674 - *
3675 - * This function allocates a MC object device from the device's parent DPRC,
3676 - * from the corresponding MC bus' pool of allocatable MC object devices of
3677 - * the given resource type. mc_dev cannot be a DPRC itself.
3678 - *
3679 - * NOTE: pool_type must be different from FSL_MC_POOL_MCP, since MC
3680 - * portals are allocated using fsl_mc_portal_allocate(), instead of
3681 - * this function.
3682 - */
3683 -int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
3684 - enum fsl_mc_pool_type pool_type,
3685 - struct fsl_mc_device **new_mc_adev)
3686 -{
3687 - struct fsl_mc_device *mc_bus_dev;
3688 - struct fsl_mc_bus *mc_bus;
3689 - struct fsl_mc_device *mc_adev;
3690 - int error = -EINVAL;
3691 - struct fsl_mc_resource *resource = NULL;
3692 -
3693 - *new_mc_adev = NULL;
3694 - if (WARN_ON(mc_dev->flags & FSL_MC_IS_DPRC))
3695 - goto error;
3696 -
3697 - if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent)))
3698 - goto error;
3699 -
3700 - if (WARN_ON(pool_type == FSL_MC_POOL_DPMCP))
3701 - goto error;
3702 -
3703 - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
3704 - mc_bus = to_fsl_mc_bus(mc_bus_dev);
3705 - error = fsl_mc_resource_allocate(mc_bus, pool_type, &resource);
3706 - if (error < 0)
3707 - goto error;
3708 -
3709 - mc_adev = resource->data;
3710 - if (WARN_ON(!mc_adev))
3711 - goto error;
3712 -
3713 - *new_mc_adev = mc_adev;
3714 - return 0;
3715 -error:
3716 - if (resource)
3717 - fsl_mc_resource_free(resource);
3718 -
3719 - return error;
3720 -}
3721 -EXPORT_SYMBOL_GPL(fsl_mc_object_allocate);
3722 -
3723 -/**
3724 - * fsl_mc_object_free - Returns an allocatable MC object device to the
3725 - * corresponding resource pool of a given MC bus.
3726 - *
3727 - * @mc_adev: Pointer to the MC object device
3728 - */
3729 -void fsl_mc_object_free(struct fsl_mc_device *mc_adev)
3730 -{
3731 - struct fsl_mc_resource *resource;
3732 -
3733 - resource = mc_adev->resource;
3734 - if (WARN_ON(resource->type == FSL_MC_POOL_DPMCP))
3735 - return;
3736 - if (WARN_ON(resource->data != mc_adev))
3737 - return;
3738 -
3739 - fsl_mc_resource_free(resource);
3740 -}
3741 -EXPORT_SYMBOL_GPL(fsl_mc_object_free);
3742 -
3743 -/*
3744 - * Initialize the interrupt pool associated with a MC bus.
3745 - * It allocates a block of IRQs from the GIC-ITS
3746 - */
3747 -int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
3748 - unsigned int irq_count)
3749 -{
3750 - unsigned int i;
3751 - struct msi_desc *msi_desc;
3752 - struct fsl_mc_device_irq *irq_resources;
3753 - struct fsl_mc_device_irq *mc_dev_irq;
3754 - int error;
3755 - struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
3756 - struct fsl_mc_resource_pool *res_pool =
3757 - &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
3758 -
3759 - if (WARN_ON(irq_count == 0 ||
3760 - irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS))
3761 - return -EINVAL;
3762 -
3763 - error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count);
3764 - if (error < 0)
3765 - return error;
3766 -
3767 - irq_resources = devm_kzalloc(&mc_bus_dev->dev,
3768 - sizeof(*irq_resources) * irq_count,
3769 - GFP_KERNEL);
3770 - if (!irq_resources) {
3771 - error = -ENOMEM;
3772 - goto cleanup_msi_irqs;
3773 - }
3774 -
3775 - for (i = 0; i < irq_count; i++) {
3776 - mc_dev_irq = &irq_resources[i];
3777 -
3778 - /*
3779 - * NOTE: This mc_dev_irq's MSI addr/value pair will be set
3780 - * by the fsl_mc_msi_write_msg() callback
3781 - */
3782 - mc_dev_irq->resource.type = res_pool->type;
3783 - mc_dev_irq->resource.data = mc_dev_irq;
3784 - mc_dev_irq->resource.parent_pool = res_pool;
3785 - INIT_LIST_HEAD(&mc_dev_irq->resource.node);
3786 - list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list);
3787 - }
3788 -
3789 - for_each_msi_entry(msi_desc, &mc_bus_dev->dev) {
3790 - mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index];
3791 - mc_dev_irq->msi_desc = msi_desc;
3792 - mc_dev_irq->resource.id = msi_desc->irq;
3793 - }
3794 -
3795 - res_pool->max_count = irq_count;
3796 - res_pool->free_count = irq_count;
3797 - mc_bus->irq_resources = irq_resources;
3798 - return 0;
3799 -
3800 -cleanup_msi_irqs:
3801 - fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
3802 - return error;
3803 -}
3804 -EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool);
3805 -
3806 -/**
3807 - * Teardown the interrupt pool associated with an MC bus.
3808 - * It frees the IRQs that were allocated to the pool, back to the GIC-ITS.
3809 - */
3810 -void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus)
3811 -{
3812 - struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
3813 - struct fsl_mc_resource_pool *res_pool =
3814 - &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
3815 -
3816 - if (WARN_ON(!mc_bus->irq_resources))
3817 - return;
3818 -
3819 - if (WARN_ON(res_pool->max_count == 0))
3820 - return;
3821 -
3822 - if (WARN_ON(res_pool->free_count != res_pool->max_count))
3823 - return;
3824 -
3825 - INIT_LIST_HEAD(&res_pool->free_list);
3826 - res_pool->max_count = 0;
3827 - res_pool->free_count = 0;
3828 - mc_bus->irq_resources = NULL;
3829 - fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
3830 -}
3831 -EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool);
3832 -
3833 -/**
3834 - * It allocates the IRQs required by a given MC object device. The
3835 - * IRQs are allocated from the interrupt pool associated with the
3836 - * MC bus that contains the device, if the device is not a DPRC device.
3837 - * Otherwise, the IRQs are allocated from the interrupt pool associated
3838 - * with the MC bus that represents the DPRC device itself.
3839 - */
3840 -int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev)
3841 -{
3842 - int i;
3843 - int irq_count;
3844 - int res_allocated_count = 0;
3845 - int error = -EINVAL;
3846 - struct fsl_mc_device_irq **irqs = NULL;
3847 - struct fsl_mc_bus *mc_bus;
3848 - struct fsl_mc_resource_pool *res_pool;
3849 -
3850 - if (WARN_ON(mc_dev->irqs))
3851 - return -EINVAL;
3852 -
3853 - irq_count = mc_dev->obj_desc.irq_count;
3854 - if (WARN_ON(irq_count == 0))
3855 - return -EINVAL;
3856 -
3857 - if (strcmp(mc_dev->obj_desc.type, "dprc") == 0)
3858 - mc_bus = to_fsl_mc_bus(mc_dev);
3859 - else
3860 - mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
3861 -
3862 - if (WARN_ON(!mc_bus->irq_resources))
3863 - return -EINVAL;
3864 -
3865 - res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
3866 - if (res_pool->free_count < irq_count) {
3867 - dev_err(&mc_dev->dev,
3868 - "Not able to allocate %u irqs for device\n", irq_count);
3869 - return -ENOSPC;
3870 - }
3871 -
3872 - irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]),
3873 - GFP_KERNEL);
3874 - if (!irqs)
3875 - return -ENOMEM;
3876 -
3877 - for (i = 0; i < irq_count; i++) {
3878 - struct fsl_mc_resource *resource;
3879 -
3880 - error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ,
3881 - &resource);
3882 - if (error < 0)
3883 - goto error_resource_alloc;
3884 -
3885 - irqs[i] = to_fsl_mc_irq(resource);
3886 - res_allocated_count++;
3887 -
3888 - WARN_ON(irqs[i]->mc_dev);
3889 - irqs[i]->mc_dev = mc_dev;
3890 - irqs[i]->dev_irq_index = i;
3891 - }
3892 -
3893 - mc_dev->irqs = irqs;
3894 - return 0;
3895 -
3896 -error_resource_alloc:
3897 - for (i = 0; i < res_allocated_count; i++) {
3898 - irqs[i]->mc_dev = NULL;
3899 - fsl_mc_resource_free(&irqs[i]->resource);
3900 - }
3901 -
3902 - return error;
3903 -}
3904 -EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs);
3905 -
3906 -/*
3907 - * It frees the IRQs that were allocated for a MC object device, by
3908 - * returning them to the corresponding interrupt pool.
3909 - */
3910 -void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev)
3911 -{
3912 - int i;
3913 - int irq_count;
3914 - struct fsl_mc_bus *mc_bus;
3915 - struct fsl_mc_device_irq **irqs = mc_dev->irqs;
3916 -
3917 - if (WARN_ON(!irqs))
3918 - return;
3919 -
3920 - irq_count = mc_dev->obj_desc.irq_count;
3921 -
3922 - if (strcmp(mc_dev->obj_desc.type, "dprc") == 0)
3923 - mc_bus = to_fsl_mc_bus(mc_dev);
3924 - else
3925 - mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
3926 -
3927 - if (WARN_ON(!mc_bus->irq_resources))
3928 - return;
3929 -
3930 - for (i = 0; i < irq_count; i++) {
3931 - WARN_ON(!irqs[i]->mc_dev);
3932 - irqs[i]->mc_dev = NULL;
3933 - fsl_mc_resource_free(&irqs[i]->resource);
3934 - }
3935 -
3936 - mc_dev->irqs = NULL;
3937 -}
3938 -EXPORT_SYMBOL_GPL(fsl_mc_free_irqs);
3939 -
3940 -void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
3941 -{
3942 - int pool_type;
3943 - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
3944 -
3945 - for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) {
3946 - struct fsl_mc_resource_pool *res_pool =
3947 - &mc_bus->resource_pools[pool_type];
3948 -
3949 - res_pool->type = pool_type;
3950 - res_pool->max_count = 0;
3951 - res_pool->free_count = 0;
3952 - res_pool->mc_bus = mc_bus;
3953 - INIT_LIST_HEAD(&res_pool->free_list);
3954 - mutex_init(&res_pool->mutex);
3955 - }
3956 -}
3957 -
3958 -static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev,
3959 - enum fsl_mc_pool_type pool_type)
3960 -{
3961 - struct fsl_mc_resource *resource;
3962 - struct fsl_mc_resource *next;
3963 - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
3964 - struct fsl_mc_resource_pool *res_pool =
3965 - &mc_bus->resource_pools[pool_type];
3966 - int free_count = 0;
3967 -
3968 - WARN_ON(res_pool->type != pool_type);
3969 - WARN_ON(res_pool->free_count != res_pool->max_count);
3970 -
3971 - list_for_each_entry_safe(resource, next, &res_pool->free_list, node) {
3972 - free_count++;
3973 - WARN_ON(resource->type != res_pool->type);
3974 - WARN_ON(resource->parent_pool != res_pool);
3975 - devm_kfree(&mc_bus_dev->dev, resource);
3976 - }
3977 -
3978 - WARN_ON(free_count != res_pool->free_count);
3979 -}
3980 -
3981 -void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
3982 -{
3983 - int pool_type;
3984 -
3985 - for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++)
3986 - fsl_mc_cleanup_resource_pool(mc_bus_dev, pool_type);
3987 -}
3988 -
3989 -/**
3990 - * fsl_mc_allocator_probe - callback invoked when an allocatable device is
3991 - * being added to the system
3992 - */
3993 -static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev)
3994 -{
3995 - enum fsl_mc_pool_type pool_type;
3996 - struct fsl_mc_device *mc_bus_dev;
3997 - struct fsl_mc_bus *mc_bus;
3998 - int error;
3999 -
4000 - if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type)))
4001 - return -EINVAL;
4002 -
4003 - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
4004 - if (WARN_ON(!dev_is_fsl_mc(&mc_bus_dev->dev)))
4005 - return -EINVAL;
4006 -
4007 - mc_bus = to_fsl_mc_bus(mc_bus_dev);
4008 - error = object_type_to_pool_type(mc_dev->obj_desc.type, &pool_type);
4009 - if (error < 0)
4010 - return error;
4011 -
4012 - error = fsl_mc_resource_pool_add_device(mc_bus, pool_type, mc_dev);
4013 - if (error < 0)
4014 - return error;
4015 -
4016 - dev_dbg(&mc_dev->dev,
4017 - "Allocatable MC object device bound to fsl_mc_allocator driver");
4018 - return 0;
4019 -}
4020 -
4021 -/**
4022 - * fsl_mc_allocator_remove - callback invoked when an allocatable device is
4023 - * being removed from the system
4024 - */
4025 -static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev)
4026 -{
4027 - int error;
4028 -
4029 - if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type)))
4030 - return -EINVAL;
4031 -
4032 - if (mc_dev->resource) {
4033 - error = fsl_mc_resource_pool_remove_device(mc_dev);
4034 - if (error < 0)
4035 - return error;
4036 - }
4037 -
4038 - dev_dbg(&mc_dev->dev,
4039 - "Allocatable MC object device unbound from fsl_mc_allocator driver");
4040 - return 0;
4041 -}
4042 -
4043 -static const struct fsl_mc_device_id match_id_table[] = {
4044 - {
4045 - .vendor = FSL_MC_VENDOR_FREESCALE,
4046 - .obj_type = "dpbp",
4047 - },
4048 - {
4049 - .vendor = FSL_MC_VENDOR_FREESCALE,
4050 - .obj_type = "dpmcp",
4051 - },
4052 - {
4053 - .vendor = FSL_MC_VENDOR_FREESCALE,
4054 - .obj_type = "dpcon",
4055 - },
4056 - {.vendor = 0x0},
4057 -};
4058 -
4059 -static struct fsl_mc_driver fsl_mc_allocator_driver = {
4060 - .driver = {
4061 - .name = "fsl_mc_allocator",
4062 - .pm = NULL,
4063 - },
4064 - .match_id_table = match_id_table,
4065 - .probe = fsl_mc_allocator_probe,
4066 - .remove = fsl_mc_allocator_remove,
4067 -};
4068 -
4069 -int __init fsl_mc_allocator_driver_init(void)
4070 -{
4071 - return fsl_mc_driver_register(&fsl_mc_allocator_driver);
4072 -}
4073 -
4074 -void fsl_mc_allocator_driver_exit(void)
4075 -{
4076 - fsl_mc_driver_unregister(&fsl_mc_allocator_driver);
4077 -}
4078 --- /dev/null
4079 +++ b/drivers/bus/fsl-mc/fsl-mc-allocator.c
4080 @@ -0,0 +1,655 @@
4081 +// SPDX-License-Identifier: GPL-2.0
4082 +/*
4083 + * fsl-mc object allocator driver
4084 + *
4085 + * Copyright (C) 2013-2016 Freescale Semiconductor, Inc.
4086 + *
4087 + */
4088 +
4089 +#include <linux/module.h>
4090 +#include <linux/msi.h>
4091 +#include <linux/fsl/mc.h>
4092 +
4093 +#include "fsl-mc-private.h"
4094 +
4095 +static bool __must_check fsl_mc_is_allocatable(struct fsl_mc_device *mc_dev)
4096 +{
4097 + return is_fsl_mc_bus_dpbp(mc_dev) ||
4098 + is_fsl_mc_bus_dpmcp(mc_dev) ||
4099 + is_fsl_mc_bus_dpcon(mc_dev);
4100 +}
4101 +
4102 +/**
4103 + * fsl_mc_resource_pool_add_device - add allocatable object to a resource
4104 + * pool of a given fsl-mc bus
4105 + *
4106 + * @mc_bus: pointer to the fsl-mc bus
4107 + * @pool_type: pool type
4108 + * @mc_dev: pointer to allocatable fsl-mc device
4109 + */
4110 +static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus
4111 + *mc_bus,
4112 + enum fsl_mc_pool_type
4113 + pool_type,
4114 + struct fsl_mc_device
4115 + *mc_dev)
4116 +{
4117 + struct fsl_mc_resource_pool *res_pool;
4118 + struct fsl_mc_resource *resource;
4119 + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
4120 + int error = -EINVAL;
4121 +
4122 + if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)
4123 + goto out;
4124 + if (!fsl_mc_is_allocatable(mc_dev))
4125 + goto out;
4126 + if (mc_dev->resource)
4127 + goto out;
4128 +
4129 + res_pool = &mc_bus->resource_pools[pool_type];
4130 + if (res_pool->type != pool_type)
4131 + goto out;
4132 + if (res_pool->mc_bus != mc_bus)
4133 + goto out;
4134 +
4135 + mutex_lock(&res_pool->mutex);
4136 +
4137 + if (res_pool->max_count < 0)
4138 + goto out_unlock;
4139 + if (res_pool->free_count < 0 ||
4140 + res_pool->free_count > res_pool->max_count)
4141 + goto out_unlock;
4142 +
4143 + resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource),
4144 + GFP_KERNEL);
4145 + if (!resource) {
4146 + error = -ENOMEM;
4147 + dev_err(&mc_bus_dev->dev,
4148 + "Failed to allocate memory for fsl_mc_resource\n");
4149 + goto out_unlock;
4150 + }
4151 +
4152 + resource->type = pool_type;
4153 + resource->id = mc_dev->obj_desc.id;
4154 + resource->data = mc_dev;
4155 + resource->parent_pool = res_pool;
4156 + INIT_LIST_HEAD(&resource->node);
4157 + list_add_tail(&resource->node, &res_pool->free_list);
4158 + mc_dev->resource = resource;
4159 + res_pool->free_count++;
4160 + res_pool->max_count++;
4161 + error = 0;
4162 +out_unlock:
4163 + mutex_unlock(&res_pool->mutex);
4164 +out:
4165 + return error;
4166 +}
4167 +
4168 +/**
4169 + * fsl_mc_resource_pool_remove_device - remove an allocatable device from a
4170 + * resource pool
4171 + *
4172 + * @mc_dev: pointer to allocatable fsl-mc device
4173 + *
4174 + * It permanently removes an allocatable fsl-mc device from the resource
4175 + * pool. It's an error if the device is in use.
4176 + */
4177 +static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device
4178 + *mc_dev)
4179 +{
4180 + struct fsl_mc_device *mc_bus_dev;
4181 + struct fsl_mc_bus *mc_bus;
4182 + struct fsl_mc_resource_pool *res_pool;
4183 + struct fsl_mc_resource *resource;
4184 + int error = -EINVAL;
4185 +
4186 + if (!fsl_mc_is_allocatable(mc_dev))
4187 + goto out;
4188 +
4189 + resource = mc_dev->resource;
4190 + if (!resource || resource->data != mc_dev)
4191 + goto out;
4192 +
4193 + mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
4194 + mc_bus = to_fsl_mc_bus(mc_bus_dev);
4195 + res_pool = resource->parent_pool;
4196 + if (res_pool != &mc_bus->resource_pools[resource->type])
4197 + goto out;
4198 +
4199 + mutex_lock(&res_pool->mutex);
4200 +
4201 + if (res_pool->max_count <= 0)
4202 + goto out_unlock;
4203 + if (res_pool->free_count <= 0 ||
4204 + res_pool->free_count > res_pool->max_count)
4205 + goto out_unlock;
4206 +
4207 + /*
4208 + * If the device is currently allocated, its resource is not
4209 + * in the free list and thus, the device cannot be removed.
4210 + */
4211 + if (list_empty(&resource->node)) {
4212 + error = -EBUSY;
4213 + dev_err(&mc_bus_dev->dev,
4214 + "Device %s cannot be removed from resource pool\n",
4215 + dev_name(&mc_dev->dev));
4216 + goto out_unlock;
4217 + }
4218 +
4219 + list_del_init(&resource->node);
4220 + res_pool->free_count--;
4221 + res_pool->max_count--;
4222 +
4223 + devm_kfree(&mc_bus_dev->dev, resource);
4224 + mc_dev->resource = NULL;
4225 + error = 0;
4226 +out_unlock:
4227 + mutex_unlock(&res_pool->mutex);
4228 +out:
4229 + return error;
4230 +}
4231 +
4232 +static const char *const fsl_mc_pool_type_strings[] = {
4233 + [FSL_MC_POOL_DPMCP] = "dpmcp",
4234 + [FSL_MC_POOL_DPBP] = "dpbp",
4235 + [FSL_MC_POOL_DPCON] = "dpcon",
4236 + [FSL_MC_POOL_IRQ] = "irq",
4237 +};
4238 +
4239 +static int __must_check object_type_to_pool_type(const char *object_type,
4240 + enum fsl_mc_pool_type
4241 + *pool_type)
4242 +{
4243 + unsigned int i;
4244 +
4245 + for (i = 0; i < ARRAY_SIZE(fsl_mc_pool_type_strings); i++) {
4246 + if (strcmp(object_type, fsl_mc_pool_type_strings[i]) == 0) {
4247 + *pool_type = i;
4248 + return 0;
4249 + }
4250 + }
4251 +
4252 + return -EINVAL;
4253 +}
4254 +
4255 +int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus,
4256 + enum fsl_mc_pool_type pool_type,
4257 + struct fsl_mc_resource **new_resource)
4258 +{
4259 + struct fsl_mc_resource_pool *res_pool;
4260 + struct fsl_mc_resource *resource;
4261 + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
4262 + int error = -EINVAL;
4263 +
4264 + BUILD_BUG_ON(ARRAY_SIZE(fsl_mc_pool_type_strings) !=
4265 + FSL_MC_NUM_POOL_TYPES);
4266 +
4267 + *new_resource = NULL;
4268 + if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)
4269 + goto out;
4270 +
4271 + res_pool = &mc_bus->resource_pools[pool_type];
4272 + if (res_pool->mc_bus != mc_bus)
4273 + goto out;
4274 +
4275 + mutex_lock(&res_pool->mutex);
4276 + resource = list_first_entry_or_null(&res_pool->free_list,
4277 + struct fsl_mc_resource, node);
4278 +
4279 + if (!resource) {
4280 + error = -ENXIO;
4281 + dev_err(&mc_bus_dev->dev,
4282 + "No more resources of type %s left\n",
4283 + fsl_mc_pool_type_strings[pool_type]);
4284 + goto out_unlock;
4285 + }
4286 +
4287 + if (resource->type != pool_type)
4288 + goto out_unlock;
4289 + if (resource->parent_pool != res_pool)
4290 + goto out_unlock;
4291 + if (res_pool->free_count <= 0 ||
4292 + res_pool->free_count > res_pool->max_count)
4293 + goto out_unlock;
4294 +
4295 + list_del_init(&resource->node);
4296 +
4297 + res_pool->free_count--;
4298 + error = 0;
4299 +out_unlock:
4300 + mutex_unlock(&res_pool->mutex);
4301 + *new_resource = resource;
4302 +out:
4303 + return error;
4304 +}
4305 +EXPORT_SYMBOL_GPL(fsl_mc_resource_allocate);
4306 +
4307 +void fsl_mc_resource_free(struct fsl_mc_resource *resource)
4308 +{
4309 + struct fsl_mc_resource_pool *res_pool;
4310 +
4311 + res_pool = resource->parent_pool;
4312 + if (resource->type != res_pool->type)
4313 + return;
4314 +
4315 + mutex_lock(&res_pool->mutex);
4316 + if (res_pool->free_count < 0 ||
4317 + res_pool->free_count >= res_pool->max_count)
4318 + goto out_unlock;
4319 +
4320 + if (!list_empty(&resource->node))
4321 + goto out_unlock;
4322 +
4323 + list_add_tail(&resource->node, &res_pool->free_list);
4324 + res_pool->free_count++;
4325 +out_unlock:
4326 + mutex_unlock(&res_pool->mutex);
4327 +}
4328 +EXPORT_SYMBOL_GPL(fsl_mc_resource_free);
4329 +
4330 +/**
4331 + * fsl_mc_object_allocate - Allocates an fsl-mc object of the given
4332 + * pool type from a given fsl-mc bus instance
4333 + *
4334 + * @mc_dev: fsl-mc device which is used in conjunction with the
4335 + * allocated object
4336 + * @pool_type: pool type
4337 + * @new_mc_dev: pointer to area where the pointer to the allocated device
4338 + * is to be returned
4339 + *
4340 + * Allocatable objects are always used in conjunction with some functional
4341 + * device. This function allocates an object of the specified type from
4342 + * the DPRC containing the functional device.
4343 + *
4344 + * NOTE: pool_type must be different from FSL_MC_POOL_MCP, since MC
4345 + * portals are allocated using fsl_mc_portal_allocate(), instead of
4346 + * this function.
4347 + */
4348 +int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
4349 + enum fsl_mc_pool_type pool_type,
4350 + struct fsl_mc_device **new_mc_adev)
4351 +{
4352 + struct fsl_mc_device *mc_bus_dev;
4353 + struct fsl_mc_bus *mc_bus;
4354 + struct fsl_mc_device *mc_adev;
4355 + int error = -EINVAL;
4356 + struct fsl_mc_resource *resource = NULL;
4357 +
4358 + *new_mc_adev = NULL;
4359 + if (mc_dev->flags & FSL_MC_IS_DPRC)
4360 + goto error;
4361 +
4362 + if (!dev_is_fsl_mc(mc_dev->dev.parent))
4363 + goto error;
4364 +
4365 + if (pool_type == FSL_MC_POOL_DPMCP)
4366 + goto error;
4367 +
4368 + mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
4369 + mc_bus = to_fsl_mc_bus(mc_bus_dev);
4370 + error = fsl_mc_resource_allocate(mc_bus, pool_type, &resource);
4371 + if (error < 0)
4372 + goto error;
4373 +
4374 + mc_adev = resource->data;
4375 + if (!mc_adev)
4376 + goto error;
4377 +
4378 + *new_mc_adev = mc_adev;
4379 + return 0;
4380 +error:
4381 + if (resource)
4382 + fsl_mc_resource_free(resource);
4383 +
4384 + return error;
4385 +}
4386 +EXPORT_SYMBOL_GPL(fsl_mc_object_allocate);
4387 +
4388 +/**
4389 + * fsl_mc_object_free - Returns an fsl-mc object to the resource
4390 + * pool where it came from.
4391 + * @mc_adev: Pointer to the fsl-mc device
4392 + */
4393 +void fsl_mc_object_free(struct fsl_mc_device *mc_adev)
4394 +{
4395 + struct fsl_mc_resource *resource;
4396 +
4397 + resource = mc_adev->resource;
4398 + if (resource->type == FSL_MC_POOL_DPMCP)
4399 + return;
4400 + if (resource->data != mc_adev)
4401 + return;
4402 +
4403 + fsl_mc_resource_free(resource);
4404 +}
4405 +EXPORT_SYMBOL_GPL(fsl_mc_object_free);
4406 +
4407 +/*
4408 + * A DPRC and the devices in the DPRC all share the same GIC-ITS device
4409 + * ID. A block of IRQs is pre-allocated and maintained in a pool
4410 + * from which devices can allocate them when needed.
4411 + */
4412 +
4413 +/*
4414 + * Initialize the interrupt pool associated with an fsl-mc bus.
4415 + * It allocates a block of IRQs from the GIC-ITS.
4416 + */
4417 +int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
4418 + unsigned int irq_count)
4419 +{
4420 + unsigned int i;
4421 + struct msi_desc *msi_desc;
4422 + struct fsl_mc_device_irq *irq_resources;
4423 + struct fsl_mc_device_irq *mc_dev_irq;
4424 + int error;
4425 + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
4426 + struct fsl_mc_resource_pool *res_pool =
4427 + &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
4428 +
4429 + if (irq_count == 0 ||
4430 + irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS)
4431 + return -EINVAL;
4432 +
4433 + error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count);
4434 + if (error < 0)
4435 + return error;
4436 +
4437 + irq_resources = devm_kzalloc(&mc_bus_dev->dev,
4438 + sizeof(*irq_resources) * irq_count,
4439 + GFP_KERNEL);
4440 + if (!irq_resources) {
4441 + error = -ENOMEM;
4442 + goto cleanup_msi_irqs;
4443 + }
4444 +
4445 + for (i = 0; i < irq_count; i++) {
4446 + mc_dev_irq = &irq_resources[i];
4447 +
4448 + /*
4449 + * NOTE: This mc_dev_irq's MSI addr/value pair will be set
4450 + * by the fsl_mc_msi_write_msg() callback
4451 + */
4452 + mc_dev_irq->resource.type = res_pool->type;
4453 + mc_dev_irq->resource.data = mc_dev_irq;
4454 + mc_dev_irq->resource.parent_pool = res_pool;
4455 + INIT_LIST_HEAD(&mc_dev_irq->resource.node);
4456 + list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list);
4457 + }
4458 +
4459 + for_each_msi_entry(msi_desc, &mc_bus_dev->dev) {
4460 + mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index];
4461 + mc_dev_irq->msi_desc = msi_desc;
4462 + mc_dev_irq->resource.id = msi_desc->irq;
4463 + }
4464 +
4465 + res_pool->max_count = irq_count;
4466 + res_pool->free_count = irq_count;
4467 + mc_bus->irq_resources = irq_resources;
4468 + return 0;
4469 +
4470 +cleanup_msi_irqs:
4471 + fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
4472 + return error;
4473 +}
4474 +EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool);
4475 +
4476 +/**
4477 + * Teardown the interrupt pool associated with an fsl-mc bus.
4478 + * It frees the IRQs that were allocated to the pool, back to the GIC-ITS.
4479 + */
4480 +void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus)
4481 +{
4482 + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
4483 + struct fsl_mc_resource_pool *res_pool =
4484 + &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
4485 +
4486 + if (!mc_bus->irq_resources)
4487 + return;
4488 +
4489 + if (res_pool->max_count == 0)
4490 + return;
4491 +
4492 + if (res_pool->free_count != res_pool->max_count)
4493 + return;
4494 +
4495 + INIT_LIST_HEAD(&res_pool->free_list);
4496 + res_pool->max_count = 0;
4497 + res_pool->free_count = 0;
4498 + mc_bus->irq_resources = NULL;
4499 + fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
4500 +}
4501 +EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool);
4502 +
4503 +/**
4504 + * Allocate the IRQs required by a given fsl-mc device.
4505 + */
4506 +int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev)
4507 +{
4508 + int i;
4509 + int irq_count;
4510 + int res_allocated_count = 0;
4511 + int error = -EINVAL;
4512 + struct fsl_mc_device_irq **irqs = NULL;
4513 + struct fsl_mc_bus *mc_bus;
4514 + struct fsl_mc_resource_pool *res_pool;
4515 +
4516 + if (mc_dev->irqs)
4517 + return -EINVAL;
4518 +
4519 + irq_count = mc_dev->obj_desc.irq_count;
4520 + if (irq_count == 0)
4521 + return -EINVAL;
4522 +
4523 + if (is_fsl_mc_bus_dprc(mc_dev))
4524 + mc_bus = to_fsl_mc_bus(mc_dev);
4525 + else
4526 + mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
4527 +
4528 + if (!mc_bus->irq_resources)
4529 + return -EINVAL;
4530 +
4531 + res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
4532 + if (res_pool->free_count < irq_count) {
4533 + dev_err(&mc_dev->dev,
4534 + "Not able to allocate %u irqs for device\n", irq_count);
4535 + return -ENOSPC;
4536 + }
4537 +
4538 + irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]),
4539 + GFP_KERNEL);
4540 + if (!irqs)
4541 + return -ENOMEM;
4542 +
4543 + for (i = 0; i < irq_count; i++) {
4544 + struct fsl_mc_resource *resource;
4545 +
4546 + error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ,
4547 + &resource);
4548 + if (error < 0)
4549 + goto error_resource_alloc;
4550 +
4551 + irqs[i] = to_fsl_mc_irq(resource);
4552 + res_allocated_count++;
4553 +
4554 + irqs[i]->mc_dev = mc_dev;
4555 + irqs[i]->dev_irq_index = i;
4556 + }
4557 +
4558 + mc_dev->irqs = irqs;
4559 + return 0;
4560 +
4561 +error_resource_alloc:
4562 + for (i = 0; i < res_allocated_count; i++) {
4563 + irqs[i]->mc_dev = NULL;
4564 + fsl_mc_resource_free(&irqs[i]->resource);
4565 + }
4566 +
4567 + return error;
4568 +}
4569 +EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs);
4570 +
4571 +/*
4572 + * Frees the IRQs that were allocated for an fsl-mc device.
4573 + */
4574 +void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev)
4575 +{
4576 + int i;
4577 + int irq_count;
4578 + struct fsl_mc_bus *mc_bus;
4579 + struct fsl_mc_device_irq **irqs = mc_dev->irqs;
4580 +
4581 + if (!irqs)
4582 + return;
4583 +
4584 + irq_count = mc_dev->obj_desc.irq_count;
4585 +
4586 + if (is_fsl_mc_bus_dprc(mc_dev))
4587 + mc_bus = to_fsl_mc_bus(mc_dev);
4588 + else
4589 + mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
4590 +
4591 + if (!mc_bus->irq_resources)
4592 + return;
4593 +
4594 + for (i = 0; i < irq_count; i++) {
4595 + irqs[i]->mc_dev = NULL;
4596 + fsl_mc_resource_free(&irqs[i]->resource);
4597 + }
4598 +
4599 + mc_dev->irqs = NULL;
4600 +}
4601 +EXPORT_SYMBOL_GPL(fsl_mc_free_irqs);
4602 +
4603 +void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
4604 +{
4605 + int pool_type;
4606 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
4607 +
4608 + for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) {
4609 + struct fsl_mc_resource_pool *res_pool =
4610 + &mc_bus->resource_pools[pool_type];
4611 +
4612 + res_pool->type = pool_type;
4613 + res_pool->max_count = 0;
4614 + res_pool->free_count = 0;
4615 + res_pool->mc_bus = mc_bus;
4616 + INIT_LIST_HEAD(&res_pool->free_list);
4617 + mutex_init(&res_pool->mutex);
4618 + }
4619 +}
4620 +EXPORT_SYMBOL_GPL(fsl_mc_init_all_resource_pools);
4621 +
4622 +static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev,
4623 + enum fsl_mc_pool_type pool_type)
4624 +{
4625 + struct fsl_mc_resource *resource;
4626 + struct fsl_mc_resource *next;
4627 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
4628 + struct fsl_mc_resource_pool *res_pool =
4629 + &mc_bus->resource_pools[pool_type];
4630 + int free_count = 0;
4631 +
4632 + list_for_each_entry_safe(resource, next, &res_pool->free_list, node) {
4633 + free_count++;
4634 + devm_kfree(&mc_bus_dev->dev, resource);
4635 + }
4636 +}
4637 +
4638 +void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
4639 +{
4640 + int pool_type;
4641 +
4642 + for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++)
4643 + fsl_mc_cleanup_resource_pool(mc_bus_dev, pool_type);
4644 +}
4645 +EXPORT_SYMBOL_GPL(fsl_mc_cleanup_all_resource_pools);
4646 +
4647 +/**
4648 + * fsl_mc_allocator_probe - callback invoked when an allocatable device is
4649 + * being added to the system
4650 + */
4651 +static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev)
4652 +{
4653 + enum fsl_mc_pool_type pool_type;
4654 + struct fsl_mc_device *mc_bus_dev;
4655 + struct fsl_mc_bus *mc_bus;
4656 + int error;
4657 +
4658 + if (!fsl_mc_is_allocatable(mc_dev))
4659 + return -EINVAL;
4660 +
4661 + mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
4662 + if (!dev_is_fsl_mc(&mc_bus_dev->dev))
4663 + return -EINVAL;
4664 +
4665 + mc_bus = to_fsl_mc_bus(mc_bus_dev);
4666 + error = object_type_to_pool_type(mc_dev->obj_desc.type, &pool_type);
4667 + if (error < 0)
4668 + return error;
4669 +
4670 + error = fsl_mc_resource_pool_add_device(mc_bus, pool_type, mc_dev);
4671 + if (error < 0)
4672 + return error;
4673 +
4674 + dev_dbg(&mc_dev->dev,
4675 + "Allocatable fsl-mc device bound to fsl_mc_allocator driver");
4676 + return 0;
4677 +}
4678 +
4679 +/**
4680 + * fsl_mc_allocator_remove - callback invoked when an allocatable device is
4681 + * being removed from the system
4682 + */
4683 +static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev)
4684 +{
4685 + int error;
4686 +
4687 + if (!fsl_mc_is_allocatable(mc_dev))
4688 + return -EINVAL;
4689 +
4690 + if (mc_dev->resource) {
4691 + error = fsl_mc_resource_pool_remove_device(mc_dev);
4692 + if (error < 0)
4693 + return error;
4694 + }
4695 +
4696 + dev_dbg(&mc_dev->dev,
4697 + "Allocatable fsl-mc device unbound from fsl_mc_allocator driver");
4698 + return 0;
4699 +}
4700 +
4701 +static const struct fsl_mc_device_id match_id_table[] = {
4702 + {
4703 + .vendor = FSL_MC_VENDOR_FREESCALE,
4704 + .obj_type = "dpbp",
4705 + },
4706 + {
4707 + .vendor = FSL_MC_VENDOR_FREESCALE,
4708 + .obj_type = "dpmcp",
4709 + },
4710 + {
4711 + .vendor = FSL_MC_VENDOR_FREESCALE,
4712 + .obj_type = "dpcon",
4713 + },
4714 + {.vendor = 0x0},
4715 +};
4716 +
4717 +static struct fsl_mc_driver fsl_mc_allocator_driver = {
4718 + .driver = {
4719 + .name = "fsl_mc_allocator",
4720 + .pm = NULL,
4721 + },
4722 + .match_id_table = match_id_table,
4723 + .probe = fsl_mc_allocator_probe,
4724 + .remove = fsl_mc_allocator_remove,
4725 +};
4726 +
4727 +int __init fsl_mc_allocator_driver_init(void)
4728 +{
4729 + return fsl_mc_driver_register(&fsl_mc_allocator_driver);
4730 +}
4731 +
4732 +void fsl_mc_allocator_driver_exit(void)
4733 +{
4734 + fsl_mc_driver_unregister(&fsl_mc_allocator_driver);
4735 +}
4736 --- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c
4737 +++ /dev/null
4738 @@ -1,920 +0,0 @@
4739 -/*
4740 - * Freescale Management Complex (MC) bus driver
4741 - *
4742 - * Copyright (C) 2014 Freescale Semiconductor, Inc.
4743 - * Author: German Rivera <German.Rivera@freescale.com>
4744 - *
4745 - * This file is licensed under the terms of the GNU General Public
4746 - * License version 2. This program is licensed "as is" without any
4747 - * warranty of any kind, whether express or implied.
4748 - */
4749 -
4750 -#include <linux/module.h>
4751 -#include <linux/of_device.h>
4752 -#include <linux/of_address.h>
4753 -#include <linux/ioport.h>
4754 -#include <linux/slab.h>
4755 -#include <linux/limits.h>
4756 -#include <linux/bitops.h>
4757 -#include <linux/msi.h>
4758 -#include <linux/dma-mapping.h>
4759 -#include "../include/mc-bus.h"
4760 -#include "../include/dpmng.h"
4761 -#include "../include/mc-sys.h"
4762 -
4763 -#include "fsl-mc-private.h"
4764 -#include "dprc-cmd.h"
4765 -
4766 -static struct kmem_cache *mc_dev_cache;
4767 -
4768 -/**
4769 - * Default DMA mask for devices on a fsl-mc bus
4770 - */
4771 -#define FSL_MC_DEFAULT_DMA_MASK (~0ULL)
4772 -
4773 -/**
4774 - * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device
4775 - * @root_mc_bus_dev: MC object device representing the root DPRC
4776 - * @num_translation_ranges: number of entries in addr_translation_ranges
4777 - * @translation_ranges: array of bus to system address translation ranges
4778 - */
4779 -struct fsl_mc {
4780 - struct fsl_mc_device *root_mc_bus_dev;
4781 - u8 num_translation_ranges;
4782 - struct fsl_mc_addr_translation_range *translation_ranges;
4783 -};
4784 -
4785 -/**
4786 - * struct fsl_mc_addr_translation_range - bus to system address translation
4787 - * range
4788 - * @mc_region_type: Type of MC region for the range being translated
4789 - * @start_mc_offset: Start MC offset of the range being translated
4790 - * @end_mc_offset: MC offset of the first byte after the range (last MC
4791 - * offset of the range is end_mc_offset - 1)
4792 - * @start_phys_addr: system physical address corresponding to start_mc_addr
4793 - */
4794 -struct fsl_mc_addr_translation_range {
4795 - enum dprc_region_type mc_region_type;
4796 - u64 start_mc_offset;
4797 - u64 end_mc_offset;
4798 - phys_addr_t start_phys_addr;
4799 -};
4800 -
4801 -/**
4802 - * fsl_mc_bus_match - device to driver matching callback
4803 - * @dev: the MC object device structure to match against
4804 - * @drv: the device driver to search for matching MC object device id
4805 - * structures
4806 - *
4807 - * Returns 1 on success, 0 otherwise.
4808 - */
4809 -static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv)
4810 -{
4811 - const struct fsl_mc_device_id *id;
4812 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
4813 - struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv);
4814 - bool found = false;
4815 -
4816 - if (WARN_ON(!fsl_mc_bus_exists()))
4817 - goto out;
4818 -
4819 - if (!mc_drv->match_id_table)
4820 - goto out;
4821 -
4822 - /*
4823 - * If the object is not 'plugged' don't match.
4824 - * Only exception is the root DPRC, which is a special case.
4825 - */
4826 - if ((mc_dev->obj_desc.state & DPRC_OBJ_STATE_PLUGGED) == 0 &&
4827 - !fsl_mc_is_root_dprc(&mc_dev->dev))
4828 - goto out;
4829 -
4830 - /*
4831 - * Traverse the match_id table of the given driver, trying to find
4832 - * a matching for the given MC object device.
4833 - */
4834 - for (id = mc_drv->match_id_table; id->vendor != 0x0; id++) {
4835 - if (id->vendor == mc_dev->obj_desc.vendor &&
4836 - strcmp(id->obj_type, mc_dev->obj_desc.type) == 0) {
4837 - found = true;
4838 -
4839 - break;
4840 - }
4841 - }
4842 -
4843 -out:
4844 - dev_dbg(dev, "%smatched\n", found ? "" : "not ");
4845 - return found;
4846 -}
4847 -
4848 -/**
4849 - * fsl_mc_bus_uevent - callback invoked when a device is added
4850 - */
4851 -static int fsl_mc_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
4852 -{
4853 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
4854 -
4855 - if (add_uevent_var(env, "MODALIAS=fsl-mc:v%08Xd%s",
4856 - mc_dev->obj_desc.vendor,
4857 - mc_dev->obj_desc.type))
4858 - return -ENOMEM;
4859 -
4860 - return 0;
4861 -}
4862 -
4863 -static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
4864 - char *buf)
4865 -{
4866 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
4867 -
4868 - return sprintf(buf, "fsl-mc:v%08Xd%s\n", mc_dev->obj_desc.vendor,
4869 - mc_dev->obj_desc.type);
4870 -}
4871 -static DEVICE_ATTR_RO(modalias);
4872 -
4873 -static struct attribute *fsl_mc_dev_attrs[] = {
4874 - &dev_attr_modalias.attr,
4875 - NULL,
4876 -};
4877 -
4878 -ATTRIBUTE_GROUPS(fsl_mc_dev);
4879 -
4880 -struct bus_type fsl_mc_bus_type = {
4881 - .name = "fsl-mc",
4882 - .match = fsl_mc_bus_match,
4883 - .uevent = fsl_mc_bus_uevent,
4884 - .dev_groups = fsl_mc_dev_groups,
4885 -};
4886 -EXPORT_SYMBOL_GPL(fsl_mc_bus_type);
4887 -
4888 -static atomic_t root_dprc_count = ATOMIC_INIT(0);
4889 -
4890 -static int fsl_mc_driver_probe(struct device *dev)
4891 -{
4892 - struct fsl_mc_driver *mc_drv;
4893 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
4894 - int error;
4895 -
4896 - if (WARN_ON(!dev->driver))
4897 - return -EINVAL;
4898 -
4899 - mc_drv = to_fsl_mc_driver(dev->driver);
4900 - if (WARN_ON(!mc_drv->probe))
4901 - return -EINVAL;
4902 -
4903 - error = mc_drv->probe(mc_dev);
4904 - if (error < 0) {
4905 - dev_err(dev, "MC object device probe callback failed: %d\n",
4906 - error);
4907 - return error;
4908 - }
4909 -
4910 - return 0;
4911 -}
4912 -
4913 -static int fsl_mc_driver_remove(struct device *dev)
4914 -{
4915 - struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver);
4916 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
4917 - int error;
4918 -
4919 - if (WARN_ON(!dev->driver))
4920 - return -EINVAL;
4921 -
4922 - error = mc_drv->remove(mc_dev);
4923 - if (error < 0) {
4924 - dev_err(dev,
4925 - "MC object device remove callback failed: %d\n",
4926 - error);
4927 - return error;
4928 - }
4929 -
4930 - return 0;
4931 -}
4932 -
4933 -static void fsl_mc_driver_shutdown(struct device *dev)
4934 -{
4935 - struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver);
4936 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
4937 -
4938 - mc_drv->shutdown(mc_dev);
4939 -}
4940 -
4941 -/**
4942 - * __fsl_mc_driver_register - registers a child device driver with the
4943 - * MC bus
4944 - *
4945 - * This function is implicitly invoked from the registration function of
4946 - * fsl_mc device drivers, which is generated by the
4947 - * module_fsl_mc_driver() macro.
4948 - */
4949 -int __fsl_mc_driver_register(struct fsl_mc_driver *mc_driver,
4950 - struct module *owner)
4951 -{
4952 - int error;
4953 -
4954 - mc_driver->driver.owner = owner;
4955 - mc_driver->driver.bus = &fsl_mc_bus_type;
4956 -
4957 - if (mc_driver->probe)
4958 - mc_driver->driver.probe = fsl_mc_driver_probe;
4959 -
4960 - if (mc_driver->remove)
4961 - mc_driver->driver.remove = fsl_mc_driver_remove;
4962 -
4963 - if (mc_driver->shutdown)
4964 - mc_driver->driver.shutdown = fsl_mc_driver_shutdown;
4965 -
4966 - error = driver_register(&mc_driver->driver);
4967 - if (error < 0) {
4968 - pr_err("driver_register() failed for %s: %d\n",
4969 - mc_driver->driver.name, error);
4970 - return error;
4971 - }
4972 -
4973 - pr_info("MC object device driver %s registered\n",
4974 - mc_driver->driver.name);
4975 - return 0;
4976 -}
4977 -EXPORT_SYMBOL_GPL(__fsl_mc_driver_register);
4978 -
4979 -/**
4980 - * fsl_mc_driver_unregister - unregisters a device driver from the
4981 - * MC bus
4982 - */
4983 -void fsl_mc_driver_unregister(struct fsl_mc_driver *mc_driver)
4984 -{
4985 - driver_unregister(&mc_driver->driver);
4986 -}
4987 -EXPORT_SYMBOL_GPL(fsl_mc_driver_unregister);
4988 -
4989 -/**
4990 - * fsl_mc_bus_exists - check if a root dprc exists
4991 - */
4992 -bool fsl_mc_bus_exists(void)
4993 -{
4994 - return atomic_read(&root_dprc_count) > 0;
4995 -}
4996 -EXPORT_SYMBOL_GPL(fsl_mc_bus_exists);
4997 -
4998 -/**
4999 - * fsl_mc_get_root_dprc - function to traverse to the root dprc
5000 - */
5001 -void fsl_mc_get_root_dprc(struct device *dev,
5002 - struct device **root_dprc_dev)
5003 -{
5004 - if (WARN_ON(!dev)) {
5005 - *root_dprc_dev = NULL;
5006 - } else if (WARN_ON(!dev_is_fsl_mc(dev))) {
5007 - *root_dprc_dev = NULL;
5008 - } else {
5009 - *root_dprc_dev = dev;
5010 - while (dev_is_fsl_mc((*root_dprc_dev)->parent))
5011 - *root_dprc_dev = (*root_dprc_dev)->parent;
5012 - }
5013 -}
5014 -EXPORT_SYMBOL_GPL(fsl_mc_get_root_dprc);
5015 -
5016 -static int get_dprc_attr(struct fsl_mc_io *mc_io,
5017 - int container_id, struct dprc_attributes *attr)
5018 -{
5019 - u16 dprc_handle;
5020 - int error;
5021 -
5022 - error = dprc_open(mc_io, 0, container_id, &dprc_handle);
5023 - if (error < 0) {
5024 - dev_err(mc_io->dev, "dprc_open() failed: %d\n", error);
5025 - return error;
5026 - }
5027 -
5028 - memset(attr, 0, sizeof(struct dprc_attributes));
5029 - error = dprc_get_attributes(mc_io, 0, dprc_handle, attr);
5030 - if (error < 0) {
5031 - dev_err(mc_io->dev, "dprc_get_attributes() failed: %d\n",
5032 - error);
5033 - goto common_cleanup;
5034 - }
5035 -
5036 - error = 0;
5037 -
5038 -common_cleanup:
5039 - (void)dprc_close(mc_io, 0, dprc_handle);
5040 - return error;
5041 -}
5042 -
5043 -static int get_dprc_icid(struct fsl_mc_io *mc_io,
5044 - int container_id, u16 *icid)
5045 -{
5046 - struct dprc_attributes attr;
5047 - int error;
5048 -
5049 - error = get_dprc_attr(mc_io, container_id, &attr);
5050 - if (error == 0)
5051 - *icid = attr.icid;
5052 -
5053 - return error;
5054 -}
5055 -
5056 -static int get_dprc_version(struct fsl_mc_io *mc_io,
5057 - int container_id, u16 *major, u16 *minor)
5058 -{
5059 - struct dprc_attributes attr;
5060 - int error;
5061 -
5062 - error = get_dprc_attr(mc_io, container_id, &attr);
5063 - if (error == 0) {
5064 - *major = attr.version.major;
5065 - *minor = attr.version.minor;
5066 - }
5067 -
5068 - return error;
5069 -}
5070 -
5071 -static int translate_mc_addr(struct fsl_mc_device *mc_dev,
5072 - enum dprc_region_type mc_region_type,
5073 - u64 mc_offset, phys_addr_t *phys_addr)
5074 -{
5075 - int i;
5076 - struct device *root_dprc_dev;
5077 - struct fsl_mc *mc;
5078 -
5079 - fsl_mc_get_root_dprc(&mc_dev->dev, &root_dprc_dev);
5080 - if (WARN_ON(!root_dprc_dev))
5081 - return -EINVAL;
5082 - mc = dev_get_drvdata(root_dprc_dev->parent);
5083 -
5084 - if (mc->num_translation_ranges == 0) {
5085 - /*
5086 - * Do identity mapping:
5087 - */
5088 - *phys_addr = mc_offset;
5089 - return 0;
5090 - }
5091 -
5092 - for (i = 0; i < mc->num_translation_ranges; i++) {
5093 - struct fsl_mc_addr_translation_range *range =
5094 - &mc->translation_ranges[i];
5095 -
5096 - if (mc_region_type == range->mc_region_type &&
5097 - mc_offset >= range->start_mc_offset &&
5098 - mc_offset < range->end_mc_offset) {
5099 - *phys_addr = range->start_phys_addr +
5100 - (mc_offset - range->start_mc_offset);
5101 - return 0;
5102 - }
5103 - }
5104 -
5105 - return -EFAULT;
5106 -}
5107 -
5108 -static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev,
5109 - struct fsl_mc_device *mc_bus_dev)
5110 -{
5111 - int i;
5112 - int error;
5113 - struct resource *regions;
5114 - struct dprc_obj_desc *obj_desc = &mc_dev->obj_desc;
5115 - struct device *parent_dev = mc_dev->dev.parent;
5116 - enum dprc_region_type mc_region_type;
5117 -
5118 - if (strcmp(obj_desc->type, "dprc") == 0 ||
5119 - strcmp(obj_desc->type, "dpmcp") == 0) {
5120 - mc_region_type = DPRC_REGION_TYPE_MC_PORTAL;
5121 - } else if (strcmp(obj_desc->type, "dpio") == 0) {
5122 - mc_region_type = DPRC_REGION_TYPE_QBMAN_PORTAL;
5123 - } else {
5124 - /*
5125 - * This function should not have been called for this MC object
5126 - * type, as this object type is not supposed to have MMIO
5127 - * regions
5128 - */
5129 - WARN_ON(true);
5130 - return -EINVAL;
5131 - }
5132 -
5133 - regions = kmalloc_array(obj_desc->region_count,
5134 - sizeof(regions[0]), GFP_KERNEL);
5135 - if (!regions)
5136 - return -ENOMEM;
5137 -
5138 - for (i = 0; i < obj_desc->region_count; i++) {
5139 - struct dprc_region_desc region_desc;
5140 -
5141 - error = dprc_get_obj_region(mc_bus_dev->mc_io,
5142 - 0,
5143 - mc_bus_dev->mc_handle,
5144 - obj_desc->type,
5145 - obj_desc->id, i, &region_desc);
5146 - if (error < 0) {
5147 - dev_err(parent_dev,
5148 - "dprc_get_obj_region() failed: %d\n", error);
5149 - goto error_cleanup_regions;
5150 - }
5151 -
5152 - WARN_ON(region_desc.size == 0);
5153 - error = translate_mc_addr(mc_dev, mc_region_type,
5154 - region_desc.base_offset,
5155 - &regions[i].start);
5156 - if (error < 0) {
5157 - dev_err(parent_dev,
5158 - "Invalid MC offset: %#x (for %s.%d\'s region %d)\n",
5159 - region_desc.base_offset,
5160 - obj_desc->type, obj_desc->id, i);
5161 - goto error_cleanup_regions;
5162 - }
5163 -
5164 - regions[i].end = regions[i].start + region_desc.size - 1;
5165 - regions[i].name = "fsl-mc object MMIO region";
5166 - regions[i].flags = IORESOURCE_IO;
5167 - if (region_desc.flags & DPRC_REGION_CACHEABLE)
5168 - regions[i].flags |= IORESOURCE_CACHEABLE;
5169 - }
5170 -
5171 - mc_dev->regions = regions;
5172 - return 0;
5173 -
5174 -error_cleanup_regions:
5175 - kfree(regions);
5176 - return error;
5177 -}
5178 -
5179 -/**
5180 - * fsl_mc_is_root_dprc - function to check if a given device is a root dprc
5181 - */
5182 -bool fsl_mc_is_root_dprc(struct device *dev)
5183 -{
5184 - struct device *root_dprc_dev;
5185 -
5186 - fsl_mc_get_root_dprc(dev, &root_dprc_dev);
5187 - if (!root_dprc_dev)
5188 - return false;
5189 - return dev == root_dprc_dev;
5190 -}
5191 -
5192 -/**
5193 - * Add a newly discovered MC object device to be visible in Linux
5194 - */
5195 -int fsl_mc_device_add(struct dprc_obj_desc *obj_desc,
5196 - struct fsl_mc_io *mc_io,
5197 - struct device *parent_dev,
5198 - struct fsl_mc_device **new_mc_dev)
5199 -{
5200 - int error;
5201 - struct fsl_mc_device *mc_dev = NULL;
5202 - struct fsl_mc_bus *mc_bus = NULL;
5203 - struct fsl_mc_device *parent_mc_dev;
5204 -
5205 - if (dev_is_fsl_mc(parent_dev))
5206 - parent_mc_dev = to_fsl_mc_device(parent_dev);
5207 - else
5208 - parent_mc_dev = NULL;
5209 -
5210 - if (strcmp(obj_desc->type, "dprc") == 0) {
5211 - /*
5212 - * Allocate an MC bus device object:
5213 - */
5214 - mc_bus = devm_kzalloc(parent_dev, sizeof(*mc_bus), GFP_KERNEL);
5215 - if (!mc_bus)
5216 - return -ENOMEM;
5217 -
5218 - mc_dev = &mc_bus->mc_dev;
5219 - } else {
5220 - /*
5221 - * Allocate a regular fsl_mc_device object:
5222 - */
5223 - mc_dev = kmem_cache_zalloc(mc_dev_cache, GFP_KERNEL);
5224 - if (!mc_dev)
5225 - return -ENOMEM;
5226 - }
5227 -
5228 - mc_dev->obj_desc = *obj_desc;
5229 - mc_dev->mc_io = mc_io;
5230 - device_initialize(&mc_dev->dev);
5231 - mc_dev->dev.parent = parent_dev;
5232 - mc_dev->dev.bus = &fsl_mc_bus_type;
5233 - dev_set_name(&mc_dev->dev, "%s.%d", obj_desc->type, obj_desc->id);
5234 -
5235 - if (strcmp(obj_desc->type, "dprc") == 0) {
5236 - struct fsl_mc_io *mc_io2;
5237 -
5238 - mc_dev->flags |= FSL_MC_IS_DPRC;
5239 -
5240 - /*
5241 - * To get the DPRC's ICID, we need to open the DPRC
5242 - * in get_dprc_icid(). For child DPRCs, we do so using the
5243 - * parent DPRC's MC portal instead of the child DPRC's MC
5244 - * portal, in case the child DPRC is already opened with
5245 - * its own portal (e.g., the DPRC used by AIOP).
5246 - *
5247 - * NOTE: There cannot be more than one active open for a
5248 - * given MC object, using the same MC portal.
5249 - */
5250 - if (parent_mc_dev) {
5251 - /*
5252 - * device being added is a child DPRC device
5253 - */
5254 - mc_io2 = parent_mc_dev->mc_io;
5255 - } else {
5256 - /*
5257 - * device being added is the root DPRC device
5258 - */
5259 - if (WARN_ON(!mc_io)) {
5260 - error = -EINVAL;
5261 - goto error_cleanup_dev;
5262 - }
5263 -
5264 - mc_io2 = mc_io;
5265 -
5266 - atomic_inc(&root_dprc_count);
5267 - }
5268 -
5269 - error = get_dprc_icid(mc_io2, obj_desc->id, &mc_dev->icid);
5270 - if (error < 0)
5271 - goto error_cleanup_dev;
5272 - } else {
5273 - /*
5274 - * A non-DPRC MC object device has to be a child of another
5275 - * MC object (specifically a DPRC object)
5276 - */
5277 - mc_dev->icid = parent_mc_dev->icid;
5278 - mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK;
5279 - mc_dev->dev.dma_mask = &mc_dev->dma_mask;
5280 - dev_set_msi_domain(&mc_dev->dev,
5281 - dev_get_msi_domain(&parent_mc_dev->dev));
5282 - }
5283 -
5284 - /*
5285 - * Get MMIO regions for the device from the MC:
5286 - *
5287 - * NOTE: the root DPRC is a special case as its MMIO region is
5288 - * obtained from the device tree
5289 - */
5290 - if (parent_mc_dev && obj_desc->region_count != 0) {
5291 - error = fsl_mc_device_get_mmio_regions(mc_dev,
5292 - parent_mc_dev);
5293 - if (error < 0)
5294 - goto error_cleanup_dev;
5295 - }
5296 -
5297 - /* Objects are coherent, unless 'no shareability' flag set. */
5298 - if (!(obj_desc->flags & DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY))
5299 - arch_setup_dma_ops(&mc_dev->dev, 0, 0, NULL, true);
5300 -
5301 - /*
5302 - * The device-specific probe callback will get invoked by device_add()
5303 - */
5304 - error = device_add(&mc_dev->dev);
5305 - if (error < 0) {
5306 - dev_err(parent_dev,
5307 - "device_add() failed for device %s: %d\n",
5308 - dev_name(&mc_dev->dev), error);
5309 - goto error_cleanup_dev;
5310 - }
5311 -
5312 - (void)get_device(&mc_dev->dev);
5313 - dev_dbg(parent_dev, "Added MC object device %s\n",
5314 - dev_name(&mc_dev->dev));
5315 -
5316 - *new_mc_dev = mc_dev;
5317 - return 0;
5318 -
5319 -error_cleanup_dev:
5320 - kfree(mc_dev->regions);
5321 - if (mc_bus)
5322 - devm_kfree(parent_dev, mc_bus);
5323 - else
5324 - kmem_cache_free(mc_dev_cache, mc_dev);
5325 -
5326 - return error;
5327 -}
5328 -EXPORT_SYMBOL_GPL(fsl_mc_device_add);
5329 -
5330 -/**
5331 - * fsl_mc_device_remove - Remove a MC object device from being visible to
5332 - * Linux
5333 - *
5334 - * @mc_dev: Pointer to a MC object device object
5335 - */
5336 -void fsl_mc_device_remove(struct fsl_mc_device *mc_dev)
5337 -{
5338 - struct fsl_mc_bus *mc_bus = NULL;
5339 -
5340 - kfree(mc_dev->regions);
5341 -
5342 - /*
5343 - * The device-specific remove callback will get invoked by device_del()
5344 - */
5345 - device_del(&mc_dev->dev);
5346 - put_device(&mc_dev->dev);
5347 -
5348 - if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) {
5349 - mc_bus = to_fsl_mc_bus(mc_dev);
5350 -
5351 - if (fsl_mc_is_root_dprc(&mc_dev->dev)) {
5352 - if (atomic_read(&root_dprc_count) > 0)
5353 - atomic_dec(&root_dprc_count);
5354 - else
5355 - WARN_ON(1);
5356 - }
5357 - }
5358 -
5359 - if (mc_bus)
5360 - devm_kfree(mc_dev->dev.parent, mc_bus);
5361 - else
5362 - kmem_cache_free(mc_dev_cache, mc_dev);
5363 -}
5364 -EXPORT_SYMBOL_GPL(fsl_mc_device_remove);
5365 -
5366 -static int parse_mc_ranges(struct device *dev,
5367 - int *paddr_cells,
5368 - int *mc_addr_cells,
5369 - int *mc_size_cells,
5370 - const __be32 **ranges_start,
5371 - u8 *num_ranges)
5372 -{
5373 - const __be32 *prop;
5374 - int range_tuple_cell_count;
5375 - int ranges_len;
5376 - int tuple_len;
5377 - struct device_node *mc_node = dev->of_node;
5378 -
5379 - *ranges_start = of_get_property(mc_node, "ranges", &ranges_len);
5380 - if (!(*ranges_start) || !ranges_len) {
5381 - dev_warn(dev,
5382 - "missing or empty ranges property for device tree node '%s'\n",
5383 - mc_node->name);
5384 -
5385 - *num_ranges = 0;
5386 - return 0;
5387 - }
5388 -
5389 - *paddr_cells = of_n_addr_cells(mc_node);
5390 -
5391 - prop = of_get_property(mc_node, "#address-cells", NULL);
5392 - if (prop)
5393 - *mc_addr_cells = be32_to_cpup(prop);
5394 - else
5395 - *mc_addr_cells = *paddr_cells;
5396 -
5397 - prop = of_get_property(mc_node, "#size-cells", NULL);
5398 - if (prop)
5399 - *mc_size_cells = be32_to_cpup(prop);
5400 - else
5401 - *mc_size_cells = of_n_size_cells(mc_node);
5402 -
5403 - range_tuple_cell_count = *paddr_cells + *mc_addr_cells +
5404 - *mc_size_cells;
5405 -
5406 - tuple_len = range_tuple_cell_count * sizeof(__be32);
5407 - if (ranges_len % tuple_len != 0) {
5408 - dev_err(dev, "malformed ranges property '%s'\n", mc_node->name);
5409 - return -EINVAL;
5410 - }
5411 -
5412 - *num_ranges = ranges_len / tuple_len;
5413 - return 0;
5414 -}
5415 -
5416 -static int get_mc_addr_translation_ranges(struct device *dev,
5417 - struct fsl_mc_addr_translation_range
5418 - **ranges,
5419 - u8 *num_ranges)
5420 -{
5421 - int error;
5422 - int paddr_cells;
5423 - int mc_addr_cells;
5424 - int mc_size_cells;
5425 - int i;
5426 - const __be32 *ranges_start;
5427 - const __be32 *cell;
5428 -
5429 - error = parse_mc_ranges(dev,
5430 - &paddr_cells,
5431 - &mc_addr_cells,
5432 - &mc_size_cells,
5433 - &ranges_start,
5434 - num_ranges);
5435 - if (error < 0)
5436 - return error;
5437 -
5438 - if (!(*num_ranges)) {
5439 - /*
5440 - * Missing or empty ranges property ("ranges;") for the
5441 - * 'fsl,qoriq-mc' node. In this case, identity mapping
5442 - * will be used.
5443 - */
5444 - *ranges = NULL;
5445 - return 0;
5446 - }
5447 -
5448 - *ranges = devm_kcalloc(dev, *num_ranges,
5449 - sizeof(struct fsl_mc_addr_translation_range),
5450 - GFP_KERNEL);
5451 - if (!(*ranges))
5452 - return -ENOMEM;
5453 -
5454 - cell = ranges_start;
5455 - for (i = 0; i < *num_ranges; ++i) {
5456 - struct fsl_mc_addr_translation_range *range = &(*ranges)[i];
5457 -
5458 - range->mc_region_type = of_read_number(cell, 1);
5459 - range->start_mc_offset = of_read_number(cell + 1,
5460 - mc_addr_cells - 1);
5461 - cell += mc_addr_cells;
5462 - range->start_phys_addr = of_read_number(cell, paddr_cells);
5463 - cell += paddr_cells;
5464 - range->end_mc_offset = range->start_mc_offset +
5465 - of_read_number(cell, mc_size_cells);
5466 -
5467 - cell += mc_size_cells;
5468 - }
5469 -
5470 - return 0;
5471 -}
5472 -
5473 -/**
5474 - * fsl_mc_bus_probe - callback invoked when the root MC bus is being
5475 - * added
5476 - */
5477 -static int fsl_mc_bus_probe(struct platform_device *pdev)
5478 -{
5479 - struct dprc_obj_desc obj_desc;
5480 - int error;
5481 - struct fsl_mc *mc;
5482 - struct fsl_mc_device *mc_bus_dev = NULL;
5483 - struct fsl_mc_io *mc_io = NULL;
5484 - int container_id;
5485 - phys_addr_t mc_portal_phys_addr;
5486 - u32 mc_portal_size;
5487 - struct mc_version mc_version;
5488 - struct resource res;
5489 -
5490 - dev_info(&pdev->dev, "Root MC bus device probed");
5491 -
5492 - mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL);
5493 - if (!mc)
5494 - return -ENOMEM;
5495 -
5496 - platform_set_drvdata(pdev, mc);
5497 -
5498 - /*
5499 - * Get physical address of MC portal for the root DPRC:
5500 - */
5501 - error = of_address_to_resource(pdev->dev.of_node, 0, &res);
5502 - if (error < 0) {
5503 - dev_err(&pdev->dev,
5504 - "of_address_to_resource() failed for %s\n",
5505 - pdev->dev.of_node->full_name);
5506 - return error;
5507 - }
5508 -
5509 - mc_portal_phys_addr = res.start;
5510 - mc_portal_size = resource_size(&res);
5511 - error = fsl_create_mc_io(&pdev->dev, mc_portal_phys_addr,
5512 - mc_portal_size, NULL,
5513 - FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, &mc_io);
5514 - if (error < 0)
5515 - return error;
5516 -
5517 - error = mc_get_version(mc_io, 0, &mc_version);
5518 - if (error != 0) {
5519 - dev_err(&pdev->dev,
5520 - "mc_get_version() failed with error %d\n", error);
5521 - goto error_cleanup_mc_io;
5522 - }
5523 -
5524 - dev_info(&pdev->dev,
5525 - "Freescale Management Complex Firmware version: %u.%u.%u\n",
5526 - mc_version.major, mc_version.minor, mc_version.revision);
5527 -
5528 - error = get_mc_addr_translation_ranges(&pdev->dev,
5529 - &mc->translation_ranges,
5530 - &mc->num_translation_ranges);
5531 - if (error < 0)
5532 - goto error_cleanup_mc_io;
5533 -
5534 - error = dpmng_get_container_id(mc_io, 0, &container_id);
5535 - if (error < 0) {
5536 - dev_err(&pdev->dev,
5537 - "dpmng_get_container_id() failed: %d\n", error);
5538 - goto error_cleanup_mc_io;
5539 - }
5540 -
5541 - memset(&obj_desc, 0, sizeof(struct dprc_obj_desc));
5542 - error = get_dprc_version(mc_io, container_id,
5543 - &obj_desc.ver_major, &obj_desc.ver_minor);
5544 - if (error < 0)
5545 - goto error_cleanup_mc_io;
5546 -
5547 - obj_desc.vendor = FSL_MC_VENDOR_FREESCALE;
5548 - strcpy(obj_desc.type, "dprc");
5549 - obj_desc.id = container_id;
5550 - obj_desc.irq_count = 1;
5551 - obj_desc.region_count = 0;
5552 -
5553 - error = fsl_mc_device_add(&obj_desc, mc_io, &pdev->dev, &mc_bus_dev);
5554 - if (error < 0)
5555 - goto error_cleanup_mc_io;
5556 -
5557 - mc->root_mc_bus_dev = mc_bus_dev;
5558 - return 0;
5559 -
5560 -error_cleanup_mc_io:
5561 - fsl_destroy_mc_io(mc_io);
5562 - return error;
5563 -}
5564 -
5565 -/**
5566 - * fsl_mc_bus_remove - callback invoked when the root MC bus is being
5567 - * removed
5568 - */
5569 -static int fsl_mc_bus_remove(struct platform_device *pdev)
5570 -{
5571 - struct fsl_mc *mc = platform_get_drvdata(pdev);
5572 -
5573 - if (WARN_ON(!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev)))
5574 - return -EINVAL;
5575 -
5576 - fsl_mc_device_remove(mc->root_mc_bus_dev);
5577 -
5578 - fsl_destroy_mc_io(mc->root_mc_bus_dev->mc_io);
5579 - mc->root_mc_bus_dev->mc_io = NULL;
5580 -
5581 - dev_info(&pdev->dev, "Root MC bus device removed");
5582 - return 0;
5583 -}
5584 -
5585 -static const struct of_device_id fsl_mc_bus_match_table[] = {
5586 - {.compatible = "fsl,qoriq-mc",},
5587 - {},
5588 -};
5589 -
5590 -MODULE_DEVICE_TABLE(of, fsl_mc_bus_match_table);
5591 -
5592 -static struct platform_driver fsl_mc_bus_driver = {
5593 - .driver = {
5594 - .name = "fsl_mc_bus",
5595 - .pm = NULL,
5596 - .of_match_table = fsl_mc_bus_match_table,
5597 - },
5598 - .probe = fsl_mc_bus_probe,
5599 - .remove = fsl_mc_bus_remove,
5600 -};
5601 -
5602 -static int __init fsl_mc_bus_driver_init(void)
5603 -{
5604 - int error;
5605 -
5606 - mc_dev_cache = kmem_cache_create("fsl_mc_device",
5607 - sizeof(struct fsl_mc_device), 0, 0,
5608 - NULL);
5609 - if (!mc_dev_cache) {
5610 - pr_err("Could not create fsl_mc_device cache\n");
5611 - return -ENOMEM;
5612 - }
5613 -
5614 - error = bus_register(&fsl_mc_bus_type);
5615 - if (error < 0) {
5616 - pr_err("fsl-mc bus type registration failed: %d\n", error);
5617 - goto error_cleanup_cache;
5618 - }
5619 -
5620 - pr_info("fsl-mc bus type registered\n");
5621 -
5622 - error = platform_driver_register(&fsl_mc_bus_driver);
5623 - if (error < 0) {
5624 - pr_err("platform_driver_register() failed: %d\n", error);
5625 - goto error_cleanup_bus;
5626 - }
5627 -
5628 - error = dprc_driver_init();
5629 - if (error < 0)
5630 - goto error_cleanup_driver;
5631 -
5632 - error = fsl_mc_allocator_driver_init();
5633 - if (error < 0)
5634 - goto error_cleanup_dprc_driver;
5635 -
5636 - error = its_fsl_mc_msi_init();
5637 - if (error < 0)
5638 - goto error_cleanup_mc_allocator;
5639 -
5640 - return 0;
5641 -
5642 -error_cleanup_mc_allocator:
5643 - fsl_mc_allocator_driver_exit();
5644 -
5645 -error_cleanup_dprc_driver:
5646 - dprc_driver_exit();
5647 -
5648 -error_cleanup_driver:
5649 - platform_driver_unregister(&fsl_mc_bus_driver);
5650 -
5651 -error_cleanup_bus:
5652 - bus_unregister(&fsl_mc_bus_type);
5653 -
5654 -error_cleanup_cache:
5655 - kmem_cache_destroy(mc_dev_cache);
5656 - return error;
5657 -}
5658 -postcore_initcall(fsl_mc_bus_driver_init);
5659 --- /dev/null
5660 +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
5661 @@ -0,0 +1,1151 @@
5662 +// SPDX-License-Identifier: GPL-2.0
5663 +/*
5664 + * Freescale Management Complex (MC) bus driver
5665 + *
5666 + * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
5667 + * Author: German Rivera <German.Rivera@freescale.com>
5668 + *
5669 + */
5670 +
5671 +#define pr_fmt(fmt) "fsl-mc: " fmt
5672 +
5673 +#include <linux/module.h>
5674 +#include <linux/of_device.h>
5675 +#include <linux/of_address.h>
5676 +#include <linux/ioport.h>
5677 +#include <linux/slab.h>
5678 +#include <linux/limits.h>
5679 +#include <linux/bitops.h>
5680 +#include <linux/msi.h>
5681 +#include <linux/dma-mapping.h>
5682 +#include <linux/fsl/mc.h>
5683 +
5684 +#include "fsl-mc-private.h"
5685 +
5686 +/**
5687 + * Default DMA mask for devices on a fsl-mc bus
5688 + */
5689 +#define FSL_MC_DEFAULT_DMA_MASK (~0ULL)
5690 +
5691 +/**
5692 + * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device
5693 + * @root_mc_bus_dev: fsl-mc device representing the root DPRC
5694 + * @num_translation_ranges: number of entries in addr_translation_ranges
5695 + * @translation_ranges: array of bus to system address translation ranges
5696 + */
5697 +struct fsl_mc {
5698 + struct fsl_mc_device *root_mc_bus_dev;
5699 + u8 num_translation_ranges;
5700 + struct fsl_mc_addr_translation_range *translation_ranges;
5701 +};
5702 +
5703 +/**
5704 + * struct fsl_mc_addr_translation_range - bus to system address translation
5705 + * range
5706 + * @mc_region_type: Type of MC region for the range being translated
5707 + * @start_mc_offset: Start MC offset of the range being translated
5708 + * @end_mc_offset: MC offset of the first byte after the range (last MC
5709 + * offset of the range is end_mc_offset - 1)
5710 + * @start_phys_addr: system physical address corresponding to start_mc_addr
5711 + */
5712 +struct fsl_mc_addr_translation_range {
5713 + enum dprc_region_type mc_region_type;
5714 + u64 start_mc_offset;
5715 + u64 end_mc_offset;
5716 + phys_addr_t start_phys_addr;
5717 +};
5718 +
5719 +/**
5720 + * struct mc_version
5721 + * @major: Major version number: incremented on API compatibility changes
5722 + * @minor: Minor version number: incremented on API additions (that are
5723 + * backward compatible); reset when major version is incremented
5724 + * @revision: Internal revision number: incremented on implementation changes
5725 + * and/or bug fixes that have no impact on API
5726 + */
5727 +struct mc_version {
5728 + u32 major;
5729 + u32 minor;
5730 + u32 revision;
5731 +};
5732 +
5733 +/**
5734 + * fsl_mc_bus_match - device to driver matching callback
5735 + * @dev: the fsl-mc device to match against
5736 + * @drv: the device driver to search for matching fsl-mc object type
5737 + * structures
5738 + *
5739 + * Returns 1 on success, 0 otherwise.
5740 + */
5741 +static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv)
5742 +{
5743 + const struct fsl_mc_device_id *id;
5744 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
5745 + struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv);
5746 + bool found = false;
5747 +
5748 + /* When driver_override is set, only bind to the matching driver */
5749 + if (mc_dev->driver_override) {
5750 + found = !strcmp(mc_dev->driver_override, mc_drv->driver.name);
5751 + goto out;
5752 + }
5753 +
5754 + if (!mc_drv->match_id_table)
5755 + goto out;
5756 +
5757 + /*
5758 + * If the object is not 'plugged' don't match.
5759 + * Only exception is the root DPRC, which is a special case.
5760 + */
5761 + if ((mc_dev->obj_desc.state & FSL_MC_OBJ_STATE_PLUGGED) == 0 &&
5762 + !fsl_mc_is_root_dprc(&mc_dev->dev))
5763 + goto out;
5764 +
5765 + /*
5766 + * Traverse the match_id table of the given driver, trying to find
5767 + * a matching for the given device.
5768 + */
5769 + for (id = mc_drv->match_id_table; id->vendor != 0x0; id++) {
5770 + if (id->vendor == mc_dev->obj_desc.vendor &&
5771 + strcmp(id->obj_type, mc_dev->obj_desc.type) == 0) {
5772 + found = true;
5773 +
5774 + break;
5775 + }
5776 + }
5777 +
5778 +out:
5779 + dev_dbg(dev, "%smatched\n", found ? "" : "not ");
5780 + return found;
5781 +}
5782 +
5783 +/**
5784 + * fsl_mc_bus_uevent - callback invoked when a device is added
5785 + */
5786 +static int fsl_mc_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
5787 +{
5788 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
5789 +
5790 + if (add_uevent_var(env, "MODALIAS=fsl-mc:v%08Xd%s",
5791 + mc_dev->obj_desc.vendor,
5792 + mc_dev->obj_desc.type))
5793 + return -ENOMEM;
5794 +
5795 + return 0;
5796 +}
5797 +
5798 +static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
5799 + char *buf)
5800 +{
5801 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
5802 +
5803 + return sprintf(buf, "fsl-mc:v%08Xd%s\n", mc_dev->obj_desc.vendor,
5804 + mc_dev->obj_desc.type);
5805 +}
5806 +static DEVICE_ATTR_RO(modalias);
5807 +
5808 +static ssize_t rescan_store(struct device *dev,
5809 + struct device_attribute *attr,
5810 + const char *buf, size_t count)
5811 +{
5812 + struct fsl_mc_device *root_mc_dev;
5813 + struct fsl_mc_bus *root_mc_bus;
5814 + unsigned long val;
5815 +
5816 + if (!fsl_mc_is_root_dprc(dev))
5817 + return -EINVAL;
5818 +
5819 + root_mc_dev = to_fsl_mc_device(dev);
5820 + root_mc_bus = to_fsl_mc_bus(root_mc_dev);
5821 +
5822 + if (kstrtoul(buf, 0, &val) < 0)
5823 + return -EINVAL;
5824 +
5825 + if (val) {
5826 + mutex_lock(&root_mc_bus->scan_mutex);
5827 + dprc_scan_objects(root_mc_dev, NULL, NULL);
5828 + mutex_unlock(&root_mc_bus->scan_mutex);
5829 + }
5830 +
5831 + return count;
5832 +}
5833 +static DEVICE_ATTR_WO(rescan);
5834 +
5835 +static ssize_t driver_override_store(struct device *dev,
5836 + struct device_attribute *attr,
5837 + const char *buf, size_t count)
5838 +{
5839 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
5840 + const char *driver_override, *old = mc_dev->driver_override;
5841 + char *cp;
5842 +
5843 + if (WARN_ON(dev->bus != &fsl_mc_bus_type))
5844 + return -EINVAL;
5845 +
5846 + if (count >= (PAGE_SIZE - 1))
5847 + return -EINVAL;
5848 +
5849 + driver_override = kstrndup(buf, count, GFP_KERNEL);
5850 + if (!driver_override)
5851 + return -ENOMEM;
5852 +
5853 + cp = strchr(driver_override, '\n');
5854 + if (cp)
5855 + *cp = '\0';
5856 +
5857 + if (strlen(driver_override)) {
5858 + mc_dev->driver_override = driver_override;
5859 + } else {
5860 + kfree(driver_override);
5861 + mc_dev->driver_override = NULL;
5862 + }
5863 +
5864 + kfree(old);
5865 +
5866 + return count;
5867 +}
5868 +
5869 +static ssize_t driver_override_show(struct device *dev,
5870 + struct device_attribute *attr, char *buf)
5871 +{
5872 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
5873 +
5874 + return snprintf(buf, PAGE_SIZE, "%s\n", mc_dev->driver_override);
5875 +}
5876 +static DEVICE_ATTR_RW(driver_override);
5877 +
5878 +static struct attribute *fsl_mc_dev_attrs[] = {
5879 + &dev_attr_modalias.attr,
5880 + &dev_attr_rescan.attr,
5881 + &dev_attr_driver_override.attr,
5882 + NULL,
5883 +};
5884 +
5885 +ATTRIBUTE_GROUPS(fsl_mc_dev);
5886 +
5887 +static int scan_fsl_mc_bus(struct device *dev, void *data)
5888 +{
5889 + struct fsl_mc_device *root_mc_dev;
5890 + struct fsl_mc_bus *root_mc_bus;
5891 +
5892 + if (!fsl_mc_is_root_dprc(dev))
5893 + goto exit;
5894 +
5895 + root_mc_dev = to_fsl_mc_device(dev);
5896 + root_mc_bus = to_fsl_mc_bus(root_mc_dev);
5897 + mutex_lock(&root_mc_bus->scan_mutex);
5898 + dprc_scan_objects(root_mc_dev, NULL, NULL);
5899 + mutex_unlock(&root_mc_bus->scan_mutex);
5900 +
5901 +exit:
5902 + return 0;
5903 +}
5904 +
5905 +static ssize_t bus_rescan_store(struct bus_type *bus,
5906 + const char *buf, size_t count)
5907 +{
5908 + unsigned long val;
5909 +
5910 + if (kstrtoul(buf, 0, &val) < 0)
5911 + return -EINVAL;
5912 +
5913 + if (val)
5914 + bus_for_each_dev(bus, NULL, NULL, scan_fsl_mc_bus);
5915 +
5916 + return count;
5917 +}
5918 +static BUS_ATTR(rescan, 0220, NULL, bus_rescan_store);
5919 +
5920 +static struct attribute *fsl_mc_bus_attrs[] = {
5921 + &bus_attr_rescan.attr,
5922 + NULL,
5923 +};
5924 +
5925 +static const struct attribute_group fsl_mc_bus_group = {
5926 + .attrs = fsl_mc_bus_attrs,
5927 +};
5928 +
5929 +static const struct attribute_group *fsl_mc_bus_groups[] = {
5930 + &fsl_mc_bus_group,
5931 + NULL,
5932 +};
5933 +
5934 +struct bus_type fsl_mc_bus_type = {
5935 + .name = "fsl-mc",
5936 + .match = fsl_mc_bus_match,
5937 + .uevent = fsl_mc_bus_uevent,
5938 + .dev_groups = fsl_mc_dev_groups,
5939 + .bus_groups = fsl_mc_bus_groups,
5940 +};
5941 +EXPORT_SYMBOL_GPL(fsl_mc_bus_type);
5942 +
5943 +struct device_type fsl_mc_bus_dprc_type = {
5944 + .name = "fsl_mc_bus_dprc"
5945 +};
5946 +
5947 +struct device_type fsl_mc_bus_dpni_type = {
5948 + .name = "fsl_mc_bus_dpni"
5949 +};
5950 +
5951 +struct device_type fsl_mc_bus_dpio_type = {
5952 + .name = "fsl_mc_bus_dpio"
5953 +};
5954 +
5955 +struct device_type fsl_mc_bus_dpsw_type = {
5956 + .name = "fsl_mc_bus_dpsw"
5957 +};
5958 +
5959 +struct device_type fsl_mc_bus_dpdmux_type = {
5960 + .name = "fsl_mc_bus_dpdmux"
5961 +};
5962 +
5963 +struct device_type fsl_mc_bus_dpbp_type = {
5964 + .name = "fsl_mc_bus_dpbp"
5965 +};
5966 +
5967 +struct device_type fsl_mc_bus_dpcon_type = {
5968 + .name = "fsl_mc_bus_dpcon"
5969 +};
5970 +
5971 +struct device_type fsl_mc_bus_dpmcp_type = {
5972 + .name = "fsl_mc_bus_dpmcp"
5973 +};
5974 +
5975 +struct device_type fsl_mc_bus_dpmac_type = {
5976 + .name = "fsl_mc_bus_dpmac"
5977 +};
5978 +
5979 +struct device_type fsl_mc_bus_dprtc_type = {
5980 + .name = "fsl_mc_bus_dprtc"
5981 +};
5982 +
5983 +struct device_type fsl_mc_bus_dpseci_type = {
5984 + .name = "fsl_mc_bus_dpseci"
5985 +};
5986 +
5987 +struct device_type fsl_mc_bus_dpdcei_type = {
5988 + .name = "fsl_mc_bus_dpdcei"
5989 +};
5990 +
5991 +struct device_type fsl_mc_bus_dpaiop_type = {
5992 + .name = "fsl_mc_bus_dpaiop"
5993 +};
5994 +
5995 +struct device_type fsl_mc_bus_dpci_type = {
5996 + .name = "fsl_mc_bus_dpci"
5997 +};
5998 +
5999 +struct device_type fsl_mc_bus_dpdmai_type = {
6000 + .name = "fsl_mc_bus_dpdmai"
6001 +};
6002 +
6003 +static struct device_type *fsl_mc_get_device_type(const char *type)
6004 +{
6005 + static const struct {
6006 + struct device_type *dev_type;
6007 + const char *type;
6008 + } dev_types[] = {
6009 + { &fsl_mc_bus_dprc_type, "dprc" },
6010 + { &fsl_mc_bus_dpni_type, "dpni" },
6011 + { &fsl_mc_bus_dpio_type, "dpio" },
6012 + { &fsl_mc_bus_dpsw_type, "dpsw" },
6013 + { &fsl_mc_bus_dpdmux_type, "dpdmux" },
6014 + { &fsl_mc_bus_dpbp_type, "dpbp" },
6015 + { &fsl_mc_bus_dpcon_type, "dpcon" },
6016 + { &fsl_mc_bus_dpmcp_type, "dpmcp" },
6017 + { &fsl_mc_bus_dpmac_type, "dpmac" },
6018 + { &fsl_mc_bus_dprtc_type, "dprtc" },
6019 + { &fsl_mc_bus_dpseci_type, "dpseci" },
6020 + { &fsl_mc_bus_dpdcei_type, "dpdcei" },
6021 + { &fsl_mc_bus_dpaiop_type, "dpaiop" },
6022 + { &fsl_mc_bus_dpci_type, "dpci" },
6023 + { &fsl_mc_bus_dpdmai_type, "dpdmai" },
6024 + { NULL, NULL }
6025 + };
6026 + int i;
6027 +
6028 + for (i = 0; dev_types[i].dev_type; i++)
6029 + if (!strcmp(dev_types[i].type, type))
6030 + return dev_types[i].dev_type;
6031 +
6032 + return NULL;
6033 +}
6034 +
6035 +static int fsl_mc_driver_probe(struct device *dev)
6036 +{
6037 + struct fsl_mc_driver *mc_drv;
6038 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6039 + int error;
6040 +
6041 + mc_drv = to_fsl_mc_driver(dev->driver);
6042 +
6043 + error = mc_drv->probe(mc_dev);
6044 + if (error < 0) {
6045 + if (error != -EPROBE_DEFER)
6046 + dev_err(dev, "%s failed: %d\n", __func__, error);
6047 + return error;
6048 + }
6049 +
6050 + return 0;
6051 +}
6052 +
6053 +static int fsl_mc_driver_remove(struct device *dev)
6054 +{
6055 + struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver);
6056 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6057 + int error;
6058 +
6059 + error = mc_drv->remove(mc_dev);
6060 + if (error < 0) {
6061 + dev_err(dev, "%s failed: %d\n", __func__, error);
6062 + return error;
6063 + }
6064 +
6065 + return 0;
6066 +}
6067 +
6068 +static void fsl_mc_driver_shutdown(struct device *dev)
6069 +{
6070 + struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver);
6071 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6072 +
6073 + mc_drv->shutdown(mc_dev);
6074 +}
6075 +
6076 +/**
6077 + * __fsl_mc_driver_register - registers a child device driver with the
6078 + * MC bus
6079 + *
6080 + * This function is implicitly invoked from the registration function of
6081 + * fsl_mc device drivers, which is generated by the
6082 + * module_fsl_mc_driver() macro.
6083 + */
6084 +int __fsl_mc_driver_register(struct fsl_mc_driver *mc_driver,
6085 + struct module *owner)
6086 +{
6087 + int error;
6088 +
6089 + mc_driver->driver.owner = owner;
6090 + mc_driver->driver.bus = &fsl_mc_bus_type;
6091 +
6092 + if (mc_driver->probe)
6093 + mc_driver->driver.probe = fsl_mc_driver_probe;
6094 +
6095 + if (mc_driver->remove)
6096 + mc_driver->driver.remove = fsl_mc_driver_remove;
6097 +
6098 + if (mc_driver->shutdown)
6099 + mc_driver->driver.shutdown = fsl_mc_driver_shutdown;
6100 +
6101 + error = driver_register(&mc_driver->driver);
6102 + if (error < 0) {
6103 + pr_err("driver_register() failed for %s: %d\n",
6104 + mc_driver->driver.name, error);
6105 + return error;
6106 + }
6107 +
6108 + return 0;
6109 +}
6110 +EXPORT_SYMBOL_GPL(__fsl_mc_driver_register);
6111 +
6112 +/**
6113 + * fsl_mc_driver_unregister - unregisters a device driver from the
6114 + * MC bus
6115 + */
6116 +void fsl_mc_driver_unregister(struct fsl_mc_driver *mc_driver)
6117 +{
6118 + driver_unregister(&mc_driver->driver);
6119 +}
6120 +EXPORT_SYMBOL_GPL(fsl_mc_driver_unregister);
6121 +
6122 +/**
6123 + * mc_get_version() - Retrieves the Management Complex firmware
6124 + * version information
6125 + * @mc_io: Pointer to opaque I/O object
6126 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
6127 + * @mc_ver_info: Returned version information structure
6128 + *
6129 + * Return: '0' on Success; Error code otherwise.
6130 + */
6131 +static int mc_get_version(struct fsl_mc_io *mc_io,
6132 + u32 cmd_flags,
6133 + struct mc_version *mc_ver_info)
6134 +{
6135 + struct fsl_mc_command cmd = { 0 };
6136 + struct dpmng_rsp_get_version *rsp_params;
6137 + int err;
6138 +
6139 + /* prepare command */
6140 + cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_VERSION,
6141 + cmd_flags,
6142 + 0);
6143 +
6144 + /* send command to mc*/
6145 + err = mc_send_command(mc_io, &cmd);
6146 + if (err)
6147 + return err;
6148 +
6149 + /* retrieve response parameters */
6150 + rsp_params = (struct dpmng_rsp_get_version *)cmd.params;
6151 + mc_ver_info->revision = le32_to_cpu(rsp_params->revision);
6152 + mc_ver_info->major = le32_to_cpu(rsp_params->version_major);
6153 + mc_ver_info->minor = le32_to_cpu(rsp_params->version_minor);
6154 +
6155 + return 0;
6156 +}
6157 +
6158 +/**
6159 + * fsl_mc_get_root_dprc - function to traverse to the root dprc
6160 + */
6161 +void fsl_mc_get_root_dprc(struct device *dev,
6162 + struct device **root_dprc_dev)
6163 +{
6164 + if (!dev) {
6165 + *root_dprc_dev = NULL;
6166 + } else if (!dev_is_fsl_mc(dev)) {
6167 + *root_dprc_dev = NULL;
6168 + } else {
6169 + *root_dprc_dev = dev;
6170 + while (dev_is_fsl_mc((*root_dprc_dev)->parent))
6171 + *root_dprc_dev = (*root_dprc_dev)->parent;
6172 + }
6173 +}
6174 +EXPORT_SYMBOL_GPL(fsl_mc_get_root_dprc);
6175 +
6176 +static int get_dprc_attr(struct fsl_mc_io *mc_io,
6177 + int container_id, struct dprc_attributes *attr)
6178 +{
6179 + u16 dprc_handle;
6180 + int error;
6181 +
6182 + error = dprc_open(mc_io, 0, container_id, &dprc_handle);
6183 + if (error < 0) {
6184 + dev_err(mc_io->dev, "dprc_open() failed: %d\n", error);
6185 + return error;
6186 + }
6187 +
6188 + memset(attr, 0, sizeof(struct dprc_attributes));
6189 + error = dprc_get_attributes(mc_io, 0, dprc_handle, attr);
6190 + if (error < 0) {
6191 + dev_err(mc_io->dev, "dprc_get_attributes() failed: %d\n",
6192 + error);
6193 + goto common_cleanup;
6194 + }
6195 +
6196 + error = 0;
6197 +
6198 +common_cleanup:
6199 + (void)dprc_close(mc_io, 0, dprc_handle);
6200 + return error;
6201 +}
6202 +
6203 +static int get_dprc_icid(struct fsl_mc_io *mc_io,
6204 + int container_id, u32 *icid)
6205 +{
6206 + struct dprc_attributes attr;
6207 + int error;
6208 +
6209 + error = get_dprc_attr(mc_io, container_id, &attr);
6210 + if (error == 0)
6211 + *icid = attr.icid;
6212 +
6213 + return error;
6214 +}
6215 +
6216 +static int translate_mc_addr(struct fsl_mc_device *mc_dev,
6217 + enum dprc_region_type mc_region_type,
6218 + u64 mc_offset, phys_addr_t *phys_addr)
6219 +{
6220 + int i;
6221 + struct device *root_dprc_dev;
6222 + struct fsl_mc *mc;
6223 +
6224 + fsl_mc_get_root_dprc(&mc_dev->dev, &root_dprc_dev);
6225 + mc = dev_get_drvdata(root_dprc_dev->parent);
6226 +
6227 + if (mc->num_translation_ranges == 0) {
6228 + /*
6229 + * Do identity mapping:
6230 + */
6231 + *phys_addr = mc_offset;
6232 + return 0;
6233 + }
6234 +
6235 + for (i = 0; i < mc->num_translation_ranges; i++) {
6236 + struct fsl_mc_addr_translation_range *range =
6237 + &mc->translation_ranges[i];
6238 +
6239 + if (mc_region_type == range->mc_region_type &&
6240 + mc_offset >= range->start_mc_offset &&
6241 + mc_offset < range->end_mc_offset) {
6242 + *phys_addr = range->start_phys_addr +
6243 + (mc_offset - range->start_mc_offset);
6244 + return 0;
6245 + }
6246 + }
6247 +
6248 + return -EFAULT;
6249 +}
6250 +
6251 +static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev,
6252 + struct fsl_mc_device *mc_bus_dev)
6253 +{
6254 + int i;
6255 + int error;
6256 + struct resource *regions;
6257 + struct fsl_mc_obj_desc *obj_desc = &mc_dev->obj_desc;
6258 + struct device *parent_dev = mc_dev->dev.parent;
6259 + enum dprc_region_type mc_region_type;
6260 +
6261 + if (is_fsl_mc_bus_dprc(mc_dev) ||
6262 + is_fsl_mc_bus_dpmcp(mc_dev)) {
6263 + mc_region_type = DPRC_REGION_TYPE_MC_PORTAL;
6264 + } else if (is_fsl_mc_bus_dpio(mc_dev)) {
6265 + mc_region_type = DPRC_REGION_TYPE_QBMAN_PORTAL;
6266 + } else {
6267 + /*
6268 + * This function should not have been called for this MC object
6269 + * type, as this object type is not supposed to have MMIO
6270 + * regions
6271 + */
6272 + return -EINVAL;
6273 + }
6274 +
6275 + regions = kmalloc_array(obj_desc->region_count,
6276 + sizeof(regions[0]), GFP_KERNEL);
6277 + if (!regions)
6278 + return -ENOMEM;
6279 +
6280 + for (i = 0; i < obj_desc->region_count; i++) {
6281 + struct dprc_region_desc region_desc;
6282 +
6283 + error = dprc_get_obj_region(mc_bus_dev->mc_io,
6284 + 0,
6285 + mc_bus_dev->mc_handle,
6286 + obj_desc->type,
6287 + obj_desc->id, i, &region_desc);
6288 + if (error < 0) {
6289 + dev_err(parent_dev,
6290 + "dprc_get_obj_region() failed: %d\n", error);
6291 + goto error_cleanup_regions;
6292 + }
6293 +
6294 + error = translate_mc_addr(mc_dev, mc_region_type,
6295 + region_desc.base_offset,
6296 + &regions[i].start);
6297 + if (error < 0) {
6298 + dev_err(parent_dev,
6299 + "Invalid MC offset: %#x (for %s.%d\'s region %d)\n",
6300 + region_desc.base_offset,
6301 + obj_desc->type, obj_desc->id, i);
6302 + goto error_cleanup_regions;
6303 + }
6304 +
6305 + regions[i].end = regions[i].start + region_desc.size - 1;
6306 + regions[i].name = "fsl-mc object MMIO region";
6307 + regions[i].flags = IORESOURCE_IO;
6308 + if (region_desc.flags & DPRC_REGION_CACHEABLE)
6309 + regions[i].flags |= IORESOURCE_CACHEABLE;
6310 + }
6311 +
6312 + mc_dev->regions = regions;
6313 + return 0;
6314 +
6315 +error_cleanup_regions:
6316 + kfree(regions);
6317 + return error;
6318 +}
6319 +
6320 +/**
6321 + * fsl_mc_is_root_dprc - function to check if a given device is a root dprc
6322 + */
6323 +bool fsl_mc_is_root_dprc(struct device *dev)
6324 +{
6325 + struct device *root_dprc_dev;
6326 +
6327 + fsl_mc_get_root_dprc(dev, &root_dprc_dev);
6328 + if (!root_dprc_dev)
6329 + return false;
6330 + return dev == root_dprc_dev;
6331 +}
6332 +
6333 +static void fsl_mc_device_release(struct device *dev)
6334 +{
6335 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6336 +
6337 + kfree(mc_dev->regions);
6338 +
6339 + if (is_fsl_mc_bus_dprc(mc_dev))
6340 + kfree(to_fsl_mc_bus(mc_dev));
6341 + else
6342 + kfree(mc_dev);
6343 +}
6344 +
6345 +/**
6346 + * Add a newly discovered fsl-mc device to be visible in Linux
6347 + */
6348 +int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc,
6349 + struct fsl_mc_io *mc_io,
6350 + struct device *parent_dev,
6351 + const char *driver_override,
6352 + struct fsl_mc_device **new_mc_dev)
6353 +{
6354 + int error;
6355 + struct fsl_mc_device *mc_dev = NULL;
6356 + struct fsl_mc_bus *mc_bus = NULL;
6357 + struct fsl_mc_device *parent_mc_dev;
6358 + struct device *fsl_mc_platform_dev;
6359 + struct device_node *fsl_mc_platform_node;
6360 +
6361 + if (dev_is_fsl_mc(parent_dev))
6362 + parent_mc_dev = to_fsl_mc_device(parent_dev);
6363 + else
6364 + parent_mc_dev = NULL;
6365 +
6366 + if (strcmp(obj_desc->type, "dprc") == 0) {
6367 + /*
6368 + * Allocate an MC bus device object:
6369 + */
6370 + mc_bus = kzalloc(sizeof(*mc_bus), GFP_KERNEL);
6371 + if (!mc_bus)
6372 + return -ENOMEM;
6373 +
6374 + mc_dev = &mc_bus->mc_dev;
6375 + } else {
6376 + /*
6377 + * Allocate a regular fsl_mc_device object:
6378 + */
6379 + mc_dev = kzalloc(sizeof(*mc_dev), GFP_KERNEL);
6380 + if (!mc_dev)
6381 + return -ENOMEM;
6382 + }
6383 +
6384 + mc_dev->obj_desc = *obj_desc;
6385 + mc_dev->mc_io = mc_io;
6386 +
6387 + if (driver_override) {
6388 + /*
6389 + * We trust driver_override, so we don't need to use
6390 + * kstrndup() here
6391 + */
6392 + mc_dev->driver_override = kstrdup(driver_override, GFP_KERNEL);
6393 + if (!mc_dev->driver_override) {
6394 + error = -ENOMEM;
6395 + goto error_cleanup_dev;
6396 + }
6397 + }
6398 +
6399 + device_initialize(&mc_dev->dev);
6400 + mc_dev->dev.parent = parent_dev;
6401 + mc_dev->dev.bus = &fsl_mc_bus_type;
6402 + mc_dev->dev.release = fsl_mc_device_release;
6403 + mc_dev->dev.type = fsl_mc_get_device_type(obj_desc->type);
6404 + if (!mc_dev->dev.type) {
6405 + error = -ENODEV;
6406 + dev_err(parent_dev, "unknown device type %s\n", obj_desc->type);
6407 + goto error_cleanup_dev;
6408 + }
6409 + dev_set_name(&mc_dev->dev, "%s.%d", obj_desc->type, obj_desc->id);
6410 +
6411 + if (strcmp(obj_desc->type, "dprc") == 0) {
6412 + struct fsl_mc_io *mc_io2;
6413 +
6414 + mc_dev->flags |= FSL_MC_IS_DPRC;
6415 +
6416 + /*
6417 + * To get the DPRC's ICID, we need to open the DPRC
6418 + * in get_dprc_icid(). For child DPRCs, we do so using the
6419 + * parent DPRC's MC portal instead of the child DPRC's MC
6420 + * portal, in case the child DPRC is already opened with
6421 + * its own portal (e.g., the DPRC used by AIOP).
6422 + *
6423 + * NOTE: There cannot be more than one active open for a
6424 + * given MC object, using the same MC portal.
6425 + */
6426 + if (parent_mc_dev) {
6427 + /*
6428 + * device being added is a child DPRC device
6429 + */
6430 + mc_io2 = parent_mc_dev->mc_io;
6431 + } else {
6432 + /*
6433 + * device being added is the root DPRC device
6434 + */
6435 + if (!mc_io) {
6436 + error = -EINVAL;
6437 + goto error_cleanup_dev;
6438 + }
6439 +
6440 + mc_io2 = mc_io;
6441 + }
6442 +
6443 + error = get_dprc_icid(mc_io2, obj_desc->id, &mc_dev->icid);
6444 + if (error < 0)
6445 + goto error_cleanup_dev;
6446 + } else {
6447 + /*
6448 + * A non-DPRC object has to be a child of a DPRC, use the
6449 + * parent's ICID and interrupt domain.
6450 + */
6451 + mc_dev->icid = parent_mc_dev->icid;
6452 + mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK;
6453 + mc_dev->dev.dma_mask = &mc_dev->dma_mask;
6454 + mc_dev->dev.coherent_dma_mask = mc_dev->dma_mask;
6455 + dev_set_msi_domain(&mc_dev->dev,
6456 + dev_get_msi_domain(&parent_mc_dev->dev));
6457 + }
6458 +
6459 + /*
6460 + * Get MMIO regions for the device from the MC:
6461 + *
6462 + * NOTE: the root DPRC is a special case as its MMIO region is
6463 + * obtained from the device tree
6464 + */
6465 + if (parent_mc_dev && obj_desc->region_count != 0) {
6466 + error = fsl_mc_device_get_mmio_regions(mc_dev,
6467 + parent_mc_dev);
6468 + if (error < 0)
6469 + goto error_cleanup_dev;
6470 + }
6471 +
6472 + fsl_mc_platform_dev = &mc_dev->dev;
6473 + while (dev_is_fsl_mc(fsl_mc_platform_dev))
6474 + fsl_mc_platform_dev = fsl_mc_platform_dev->parent;
6475 + fsl_mc_platform_node = fsl_mc_platform_dev->of_node;
6476 +
6477 + /* Set up the iommu configuration for the devices. */
6478 + fsl_mc_dma_configure(mc_dev, fsl_mc_platform_node,
6479 + !(obj_desc->flags & DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY));
6480 +
6481 + /*
6482 + * The device-specific probe callback will get invoked by device_add()
6483 + */
6484 + error = device_add(&mc_dev->dev);
6485 + if (error < 0) {
6486 + dev_err(parent_dev,
6487 + "device_add() failed for device %s: %d\n",
6488 + dev_name(&mc_dev->dev), error);
6489 + goto error_cleanup_dev;
6490 + }
6491 +
6492 + dev_dbg(parent_dev, "added %s\n", dev_name(&mc_dev->dev));
6493 +
6494 + *new_mc_dev = mc_dev;
6495 + return 0;
6496 +
6497 +error_cleanup_dev:
6498 + kfree(mc_dev->regions);
6499 + kfree(mc_bus);
6500 + kfree(mc_dev);
6501 +
6502 + return error;
6503 +}
6504 +EXPORT_SYMBOL_GPL(fsl_mc_device_add);
6505 +
6506 +/**
6507 + * fsl_mc_device_remove - Remove an fsl-mc device from being visible to
6508 + * Linux
6509 + *
6510 + * @mc_dev: Pointer to an fsl-mc device
6511 + */
6512 +void fsl_mc_device_remove(struct fsl_mc_device *mc_dev)
6513 +{
6514 + kfree(mc_dev->driver_override);
6515 + mc_dev->driver_override = NULL;
6516 +
6517 + /*
6518 + * The device-specific remove callback will get invoked by device_del()
6519 + */
6520 + device_del(&mc_dev->dev);
6521 + put_device(&mc_dev->dev);
6522 +}
6523 +EXPORT_SYMBOL_GPL(fsl_mc_device_remove);
6524 +
6525 +static int parse_mc_ranges(struct device *dev,
6526 + int *paddr_cells,
6527 + int *mc_addr_cells,
6528 + int *mc_size_cells,
6529 + const __be32 **ranges_start)
6530 +{
6531 + const __be32 *prop;
6532 + int range_tuple_cell_count;
6533 + int ranges_len;
6534 + int tuple_len;
6535 + struct device_node *mc_node = dev->of_node;
6536 +
6537 + *ranges_start = of_get_property(mc_node, "ranges", &ranges_len);
6538 + if (!(*ranges_start) || !ranges_len) {
6539 + dev_warn(dev,
6540 + "missing or empty ranges property for device tree node '%s'\n",
6541 + mc_node->name);
6542 + return 0;
6543 + }
6544 +
6545 + *paddr_cells = of_n_addr_cells(mc_node);
6546 +
6547 + prop = of_get_property(mc_node, "#address-cells", NULL);
6548 + if (prop)
6549 + *mc_addr_cells = be32_to_cpup(prop);
6550 + else
6551 + *mc_addr_cells = *paddr_cells;
6552 +
6553 + prop = of_get_property(mc_node, "#size-cells", NULL);
6554 + if (prop)
6555 + *mc_size_cells = be32_to_cpup(prop);
6556 + else
6557 + *mc_size_cells = of_n_size_cells(mc_node);
6558 +
6559 + range_tuple_cell_count = *paddr_cells + *mc_addr_cells +
6560 + *mc_size_cells;
6561 +
6562 + tuple_len = range_tuple_cell_count * sizeof(__be32);
6563 + if (ranges_len % tuple_len != 0) {
6564 + dev_err(dev, "malformed ranges property '%s'\n", mc_node->name);
6565 + return -EINVAL;
6566 + }
6567 +
6568 + return ranges_len / tuple_len;
6569 +}
6570 +
6571 +static int get_mc_addr_translation_ranges(struct device *dev,
6572 + struct fsl_mc_addr_translation_range
6573 + **ranges,
6574 + u8 *num_ranges)
6575 +{
6576 + int ret;
6577 + int paddr_cells;
6578 + int mc_addr_cells;
6579 + int mc_size_cells;
6580 + int i;
6581 + const __be32 *ranges_start;
6582 + const __be32 *cell;
6583 +
6584 + ret = parse_mc_ranges(dev,
6585 + &paddr_cells,
6586 + &mc_addr_cells,
6587 + &mc_size_cells,
6588 + &ranges_start);
6589 + if (ret < 0)
6590 + return ret;
6591 +
6592 + *num_ranges = ret;
6593 + if (!ret) {
6594 + /*
6595 + * Missing or empty ranges property ("ranges;") for the
6596 + * 'fsl,qoriq-mc' node. In this case, identity mapping
6597 + * will be used.
6598 + */
6599 + *ranges = NULL;
6600 + return 0;
6601 + }
6602 +
6603 + *ranges = devm_kcalloc(dev, *num_ranges,
6604 + sizeof(struct fsl_mc_addr_translation_range),
6605 + GFP_KERNEL);
6606 + if (!(*ranges))
6607 + return -ENOMEM;
6608 +
6609 + cell = ranges_start;
6610 + for (i = 0; i < *num_ranges; ++i) {
6611 + struct fsl_mc_addr_translation_range *range = &(*ranges)[i];
6612 +
6613 + range->mc_region_type = of_read_number(cell, 1);
6614 + range->start_mc_offset = of_read_number(cell + 1,
6615 + mc_addr_cells - 1);
6616 + cell += mc_addr_cells;
6617 + range->start_phys_addr = of_read_number(cell, paddr_cells);
6618 + cell += paddr_cells;
6619 + range->end_mc_offset = range->start_mc_offset +
6620 + of_read_number(cell, mc_size_cells);
6621 +
6622 + cell += mc_size_cells;
6623 + }
6624 +
6625 + return 0;
6626 +}
6627 +
6628 +/**
6629 + * fsl_mc_bus_probe - callback invoked when the root MC bus is being
6630 + * added
6631 + */
6632 +static int fsl_mc_bus_probe(struct platform_device *pdev)
6633 +{
6634 + struct fsl_mc_obj_desc obj_desc;
6635 + int error;
6636 + struct fsl_mc *mc;
6637 + struct fsl_mc_device *mc_bus_dev = NULL;
6638 + struct fsl_mc_io *mc_io = NULL;
6639 + struct fsl_mc_bus *mc_bus = NULL;
6640 + int container_id;
6641 + phys_addr_t mc_portal_phys_addr;
6642 + u32 mc_portal_size;
6643 + struct mc_version mc_version;
6644 + struct resource res;
6645 +
6646 + mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL);
6647 + if (!mc)
6648 + return -ENOMEM;
6649 +
6650 + platform_set_drvdata(pdev, mc);
6651 +
6652 + /*
6653 + * Get physical address of MC portal for the root DPRC:
6654 + */
6655 + error = of_address_to_resource(pdev->dev.of_node, 0, &res);
6656 + if (error < 0) {
6657 + dev_err(&pdev->dev,
6658 + "of_address_to_resource() failed for %pOF\n",
6659 + pdev->dev.of_node);
6660 + return error;
6661 + }
6662 +
6663 + mc_portal_phys_addr = res.start;
6664 + mc_portal_size = resource_size(&res);
6665 + error = fsl_create_mc_io(&pdev->dev, mc_portal_phys_addr,
6666 + mc_portal_size, NULL,
6667 + FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, &mc_io);
6668 + if (error < 0)
6669 + return error;
6670 +
6671 + error = mc_get_version(mc_io, 0, &mc_version);
6672 + if (error != 0) {
6673 + dev_err(&pdev->dev,
6674 + "mc_get_version() failed with error %d\n", error);
6675 + goto error_cleanup_mc_io;
6676 + }
6677 +
6678 + dev_info(&pdev->dev, "MC firmware version: %u.%u.%u\n",
6679 + mc_version.major, mc_version.minor, mc_version.revision);
6680 +
6681 + error = get_mc_addr_translation_ranges(&pdev->dev,
6682 + &mc->translation_ranges,
6683 + &mc->num_translation_ranges);
6684 + if (error < 0)
6685 + goto error_cleanup_mc_io;
6686 +
6687 + error = dprc_get_container_id(mc_io, 0, &container_id);
6688 + if (error < 0) {
6689 + dev_err(&pdev->dev,
6690 + "dprc_get_container_id() failed: %d\n", error);
6691 + goto error_cleanup_mc_io;
6692 + }
6693 +
6694 + memset(&obj_desc, 0, sizeof(struct fsl_mc_obj_desc));
6695 + error = dprc_get_api_version(mc_io, 0,
6696 + &obj_desc.ver_major,
6697 + &obj_desc.ver_minor);
6698 + if (error < 0)
6699 + goto error_cleanup_mc_io;
6700 +
6701 + obj_desc.vendor = FSL_MC_VENDOR_FREESCALE;
6702 + strcpy(obj_desc.type, "dprc");
6703 + obj_desc.id = container_id;
6704 + obj_desc.irq_count = 1;
6705 + obj_desc.region_count = 0;
6706 +
6707 + error = fsl_mc_device_add(&obj_desc, mc_io, &pdev->dev, NULL,
6708 + &mc_bus_dev);
6709 + if (error < 0)
6710 + goto error_cleanup_mc_io;
6711 +
6712 + mc_bus = to_fsl_mc_bus(mc_bus_dev);
6713 + error = fsl_mc_restool_create_device_file(mc_bus);
6714 + if (error < 0)
6715 + goto error_cleanup_device;
6716 +
6717 + mc->root_mc_bus_dev = mc_bus_dev;
6718 +
6719 + return 0;
6720 +
6721 +error_cleanup_device:
6722 + fsl_mc_device_remove(mc_bus_dev);
6723 +
6724 +error_cleanup_mc_io:
6725 + fsl_destroy_mc_io(mc_io);
6726 + return error;
6727 +}
6728 +
6729 +/**
6730 + * fsl_mc_bus_remove - callback invoked when the root MC bus is being
6731 + * removed
6732 + */
6733 +static int fsl_mc_bus_remove(struct platform_device *pdev)
6734 +{
6735 + struct fsl_mc *mc = platform_get_drvdata(pdev);
6736 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc->root_mc_bus_dev);
6737 +
6738 + if (!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev))
6739 + return -EINVAL;
6740 +
6741 + fsl_mc_restool_remove_device_file(mc_bus);
6742 + fsl_mc_device_remove(mc->root_mc_bus_dev);
6743 +
6744 + fsl_destroy_mc_io(mc->root_mc_bus_dev->mc_io);
6745 + mc->root_mc_bus_dev->mc_io = NULL;
6746 +
6747 + return 0;
6748 +}
6749 +
6750 +static const struct of_device_id fsl_mc_bus_match_table[] = {
6751 + {.compatible = "fsl,qoriq-mc",},
6752 + {},
6753 +};
6754 +
6755 +MODULE_DEVICE_TABLE(of, fsl_mc_bus_match_table);
6756 +
6757 +static struct platform_driver fsl_mc_bus_driver = {
6758 + .driver = {
6759 + .name = "fsl_mc_bus",
6760 + .pm = NULL,
6761 + .of_match_table = fsl_mc_bus_match_table,
6762 + },
6763 + .probe = fsl_mc_bus_probe,
6764 + .remove = fsl_mc_bus_remove,
6765 +};
6766 +
6767 +static int __init fsl_mc_bus_driver_init(void)
6768 +{
6769 + int error;
6770 +
6771 + error = bus_register(&fsl_mc_bus_type);
6772 + if (error < 0) {
6773 + pr_err("bus type registration failed: %d\n", error);
6774 + goto error_cleanup_cache;
6775 + }
6776 +
6777 + error = platform_driver_register(&fsl_mc_bus_driver);
6778 + if (error < 0) {
6779 + pr_err("platform_driver_register() failed: %d\n", error);
6780 + goto error_cleanup_bus;
6781 + }
6782 +
6783 + error = dprc_driver_init();
6784 + if (error < 0)
6785 + goto error_cleanup_driver;
6786 +
6787 + error = fsl_mc_allocator_driver_init();
6788 + if (error < 0)
6789 + goto error_cleanup_dprc_driver;
6790 +
6791 + error = fsl_mc_restool_init();
6792 + if (error < 0)
6793 + goto error_cleanup_mc_allocator;
6794 +
6795 + return 0;
6796 +
6797 +error_cleanup_mc_allocator:
6798 + fsl_mc_allocator_driver_exit();
6799 +
6800 +error_cleanup_dprc_driver:
6801 + dprc_driver_exit();
6802 +
6803 +error_cleanup_driver:
6804 + platform_driver_unregister(&fsl_mc_bus_driver);
6805 +
6806 +error_cleanup_bus:
6807 + bus_unregister(&fsl_mc_bus_type);
6808 +
6809 +error_cleanup_cache:
6810 + return error;
6811 +}
6812 +postcore_initcall(fsl_mc_bus_driver_init);
6813 --- /dev/null
6814 +++ b/drivers/bus/fsl-mc/fsl-mc-iommu.c
6815 @@ -0,0 +1,78 @@
6816 +/*
6817 + * Copyright 2016 Freescale Semiconductor, Inc.
6818 + * Copyright 2017 NXP
6819 + * Author: Nipun Gupta <nipun.gupta@nxp.com>
6820 + *
6821 + * This file is licensed under the terms of the GNU General Public
6822 + * License version 2. This program is licensed "as is" without any
6823 + * warranty of any kind, whether express or implied.
6824 + */
6825 +
6826 +#include <linux/iommu.h>
6827 +#include <linux/of.h>
6828 +#include <linux/of_iommu.h>
6829 +#include <linux/fsl/mc.h>
6830 +
6831 +/* Setup the IOMMU for the DPRC container */
6832 +static const struct iommu_ops
6833 +*fsl_mc_iommu_configure(struct fsl_mc_device *mc_dev,
6834 + struct device_node *fsl_mc_platform_node)
6835 +{
6836 + struct of_phandle_args iommu_spec;
6837 + const struct iommu_ops *ops;
6838 + u32 iommu_phandle;
6839 + struct device_node *iommu_node;
6840 + const __be32 *map = NULL;
6841 + int iommu_cells, map_len, ret;
6842 +
6843 + map = of_get_property(fsl_mc_platform_node, "iommu-map", &map_len);
6844 + if (!map)
6845 + return NULL;
6846 +
6847 + ops = mc_dev->dev.bus->iommu_ops;
6848 + if (!ops || !ops->of_xlate)
6849 + return NULL;
6850 +
6851 + iommu_phandle = be32_to_cpup(map + 1);
6852 + iommu_node = of_find_node_by_phandle(iommu_phandle);
6853 +
6854 + if (of_property_read_u32(iommu_node, "#iommu-cells", &iommu_cells)) {
6855 + pr_err("%s: missing #iommu-cells property\n", iommu_node->name);
6856 + return NULL;
6857 + }
6858 +
6859 + /* Initialize the fwspec */
6860 + ret = iommu_fwspec_init(&mc_dev->dev, &iommu_node->fwnode, ops);
6861 + if (ret)
6862 + return NULL;
6863 +
6864 + /*
6865 + * Fill in the required stream-id before calling the iommu's
6866 + * ops->xlate callback.
6867 + */
6868 + iommu_spec.np = iommu_node;
6869 + iommu_spec.args[0] = mc_dev->icid;
6870 + iommu_spec.args_count = 1;
6871 +
6872 + ret = ops->of_xlate(&mc_dev->dev, &iommu_spec);
6873 + if (ret)
6874 + return NULL;
6875 +
6876 + of_node_put(iommu_spec.np);
6877 +
6878 + return ops;
6879 +}
6880 +
6881 +/* Set up DMA configuration for fsl-mc devices */
6882 +void fsl_mc_dma_configure(struct fsl_mc_device *mc_dev,
6883 + struct device_node *fsl_mc_platform_node, int coherent)
6884 +{
6885 + const struct iommu_ops *ops;
6886 +
6887 + ops = fsl_mc_iommu_configure(mc_dev, fsl_mc_platform_node);
6888 +
6889 + mc_dev->dev.coherent_dma_mask = DMA_BIT_MASK(48);
6890 + mc_dev->dev.dma_mask = &mc_dev->dev.coherent_dma_mask;
6891 + arch_setup_dma_ops(&mc_dev->dev, 0,
6892 + mc_dev->dev.coherent_dma_mask + 1, ops, coherent);
6893 +}
6894 --- a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c
6895 +++ /dev/null
6896 @@ -1,285 +0,0 @@
6897 -/*
6898 - * Freescale Management Complex (MC) bus driver MSI support
6899 - *
6900 - * Copyright (C) 2015 Freescale Semiconductor, Inc.
6901 - * Author: German Rivera <German.Rivera@freescale.com>
6902 - *
6903 - * This file is licensed under the terms of the GNU General Public
6904 - * License version 2. This program is licensed "as is" without any
6905 - * warranty of any kind, whether express or implied.
6906 - */
6907 -
6908 -#include <linux/of_device.h>
6909 -#include <linux/of_address.h>
6910 -#include <linux/irqchip/arm-gic-v3.h>
6911 -#include <linux/of_irq.h>
6912 -#include <linux/irq.h>
6913 -#include <linux/irqdomain.h>
6914 -#include <linux/msi.h>
6915 -#include "../include/mc-bus.h"
6916 -#include "fsl-mc-private.h"
6917 -
6918 -/*
6919 - * Generate a unique ID identifying the interrupt (only used within the MSI
6920 - * irqdomain. Combine the icid with the interrupt index.
6921 - */
6922 -static irq_hw_number_t fsl_mc_domain_calc_hwirq(struct fsl_mc_device *dev,
6923 - struct msi_desc *desc)
6924 -{
6925 - /*
6926 - * Make the base hwirq value for ICID*10000 so it is readable
6927 - * as a decimal value in /proc/interrupts.
6928 - */
6929 - return (irq_hw_number_t)(desc->fsl_mc.msi_index + (dev->icid * 10000));
6930 -}
6931 -
6932 -static void fsl_mc_msi_set_desc(msi_alloc_info_t *arg,
6933 - struct msi_desc *desc)
6934 -{
6935 - arg->desc = desc;
6936 - arg->hwirq = fsl_mc_domain_calc_hwirq(to_fsl_mc_device(desc->dev),
6937 - desc);
6938 -}
6939 -
6940 -static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info)
6941 -{
6942 - struct msi_domain_ops *ops = info->ops;
6943 -
6944 - if (WARN_ON(!ops))
6945 - return;
6946 -
6947 - /*
6948 - * set_desc should not be set by the caller
6949 - */
6950 - if (!ops->set_desc)
6951 - ops->set_desc = fsl_mc_msi_set_desc;
6952 -}
6953 -
6954 -static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev,
6955 - struct fsl_mc_device_irq *mc_dev_irq)
6956 -{
6957 - int error;
6958 - struct fsl_mc_device *owner_mc_dev = mc_dev_irq->mc_dev;
6959 - struct msi_desc *msi_desc = mc_dev_irq->msi_desc;
6960 - struct dprc_irq_cfg irq_cfg;
6961 -
6962 - /*
6963 - * msi_desc->msg.address is 0x0 when this function is invoked in
6964 - * the free_irq() code path. In this case, for the MC, we don't
6965 - * really need to "unprogram" the MSI, so we just return.
6966 - */
6967 - if (msi_desc->msg.address_lo == 0x0 && msi_desc->msg.address_hi == 0x0)
6968 - return;
6969 -
6970 - if (WARN_ON(!owner_mc_dev))
6971 - return;
6972 -
6973 - irq_cfg.paddr = ((u64)msi_desc->msg.address_hi << 32) |
6974 - msi_desc->msg.address_lo;
6975 - irq_cfg.val = msi_desc->msg.data;
6976 - irq_cfg.irq_num = msi_desc->irq;
6977 -
6978 - if (owner_mc_dev == mc_bus_dev) {
6979 - /*
6980 - * IRQ is for the mc_bus_dev's DPRC itself
6981 - */
6982 - error = dprc_set_irq(mc_bus_dev->mc_io,
6983 - MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI,
6984 - mc_bus_dev->mc_handle,
6985 - mc_dev_irq->dev_irq_index,
6986 - &irq_cfg);
6987 - if (error < 0) {
6988 - dev_err(&owner_mc_dev->dev,
6989 - "dprc_set_irq() failed: %d\n", error);
6990 - }
6991 - } else {
6992 - /*
6993 - * IRQ is for for a child device of mc_bus_dev
6994 - */
6995 - error = dprc_set_obj_irq(mc_bus_dev->mc_io,
6996 - MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI,
6997 - mc_bus_dev->mc_handle,
6998 - owner_mc_dev->obj_desc.type,
6999 - owner_mc_dev->obj_desc.id,
7000 - mc_dev_irq->dev_irq_index,
7001 - &irq_cfg);
7002 - if (error < 0) {
7003 - dev_err(&owner_mc_dev->dev,
7004 - "dprc_obj_set_irq() failed: %d\n", error);
7005 - }
7006 - }
7007 -}
7008 -
7009 -/*
7010 - * NOTE: This function is invoked with interrupts disabled
7011 - */
7012 -static void fsl_mc_msi_write_msg(struct irq_data *irq_data,
7013 - struct msi_msg *msg)
7014 -{
7015 - struct msi_desc *msi_desc = irq_data_get_msi_desc(irq_data);
7016 - struct fsl_mc_device *mc_bus_dev = to_fsl_mc_device(msi_desc->dev);
7017 - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
7018 - struct fsl_mc_device_irq *mc_dev_irq =
7019 - &mc_bus->irq_resources[msi_desc->fsl_mc.msi_index];
7020 -
7021 - WARN_ON(mc_dev_irq->msi_desc != msi_desc);
7022 - msi_desc->msg = *msg;
7023 -
7024 - /*
7025 - * Program the MSI (paddr, value) pair in the device:
7026 - */
7027 - __fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq);
7028 -}
7029 -
7030 -static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info)
7031 -{
7032 - struct irq_chip *chip = info->chip;
7033 -
7034 - if (WARN_ON((!chip)))
7035 - return;
7036 -
7037 - /*
7038 - * irq_write_msi_msg should not be set by the caller
7039 - */
7040 - if (!chip->irq_write_msi_msg)
7041 - chip->irq_write_msi_msg = fsl_mc_msi_write_msg;
7042 -}
7043 -
7044 -/**
7045 - * fsl_mc_msi_create_irq_domain - Create a fsl-mc MSI interrupt domain
7046 - * @np: Optional device-tree node of the interrupt controller
7047 - * @info: MSI domain info
7048 - * @parent: Parent irq domain
7049 - *
7050 - * Updates the domain and chip ops and creates a fsl-mc MSI
7051 - * interrupt domain.
7052 - *
7053 - * Returns:
7054 - * A domain pointer or NULL in case of failure.
7055 - */
7056 -struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode,
7057 - struct msi_domain_info *info,
7058 - struct irq_domain *parent)
7059 -{
7060 - struct irq_domain *domain;
7061 -
7062 - if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS)
7063 - fsl_mc_msi_update_dom_ops(info);
7064 - if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
7065 - fsl_mc_msi_update_chip_ops(info);
7066 -
7067 - domain = msi_create_irq_domain(fwnode, info, parent);
7068 - if (domain)
7069 - domain->bus_token = DOMAIN_BUS_FSL_MC_MSI;
7070 -
7071 - return domain;
7072 -}
7073 -
7074 -int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
7075 - struct irq_domain **mc_msi_domain)
7076 -{
7077 - struct irq_domain *msi_domain;
7078 - struct device_node *mc_of_node = mc_platform_dev->of_node;
7079 -
7080 - msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node,
7081 - DOMAIN_BUS_FSL_MC_MSI);
7082 - if (!msi_domain) {
7083 - pr_err("Unable to find fsl-mc MSI domain for %s\n",
7084 - mc_of_node->full_name);
7085 -
7086 - return -ENOENT;
7087 - }
7088 -
7089 - *mc_msi_domain = msi_domain;
7090 - return 0;
7091 -}
7092 -
7093 -static void fsl_mc_msi_free_descs(struct device *dev)
7094 -{
7095 - struct msi_desc *desc, *tmp;
7096 -
7097 - list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) {
7098 - list_del(&desc->list);
7099 - free_msi_entry(desc);
7100 - }
7101 -}
7102 -
7103 -static int fsl_mc_msi_alloc_descs(struct device *dev, unsigned int irq_count)
7104 -
7105 -{
7106 - unsigned int i;
7107 - int error;
7108 - struct msi_desc *msi_desc;
7109 -
7110 - for (i = 0; i < irq_count; i++) {
7111 - msi_desc = alloc_msi_entry(dev, 1, NULL);
7112 - if (!msi_desc) {
7113 - dev_err(dev, "Failed to allocate msi entry\n");
7114 - error = -ENOMEM;
7115 - goto cleanup_msi_descs;
7116 - }
7117 -
7118 - msi_desc->fsl_mc.msi_index = i;
7119 - INIT_LIST_HEAD(&msi_desc->list);
7120 - list_add_tail(&msi_desc->list, dev_to_msi_list(dev));
7121 - }
7122 -
7123 - return 0;
7124 -
7125 -cleanup_msi_descs:
7126 - fsl_mc_msi_free_descs(dev);
7127 - return error;
7128 -}
7129 -
7130 -int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
7131 - unsigned int irq_count)
7132 -{
7133 - struct irq_domain *msi_domain;
7134 - int error;
7135 -
7136 - if (WARN_ON(!list_empty(dev_to_msi_list(dev))))
7137 - return -EINVAL;
7138 -
7139 - error = fsl_mc_msi_alloc_descs(dev, irq_count);
7140 - if (error < 0)
7141 - return error;
7142 -
7143 - msi_domain = dev_get_msi_domain(dev);
7144 - if (WARN_ON(!msi_domain)) {
7145 - error = -EINVAL;
7146 - goto cleanup_msi_descs;
7147 - }
7148 -
7149 - /*
7150 - * NOTE: Calling this function will trigger the invocation of the
7151 - * its_fsl_mc_msi_prepare() callback
7152 - */
7153 - error = msi_domain_alloc_irqs(msi_domain, dev, irq_count);
7154 -
7155 - if (error) {
7156 - dev_err(dev, "Failed to allocate IRQs\n");
7157 - goto cleanup_msi_descs;
7158 - }
7159 -
7160 - return 0;
7161 -
7162 -cleanup_msi_descs:
7163 - fsl_mc_msi_free_descs(dev);
7164 - return error;
7165 -}
7166 -
7167 -void fsl_mc_msi_domain_free_irqs(struct device *dev)
7168 -{
7169 - struct irq_domain *msi_domain;
7170 -
7171 - msi_domain = dev_get_msi_domain(dev);
7172 - if (WARN_ON(!msi_domain))
7173 - return;
7174 -
7175 - msi_domain_free_irqs(msi_domain, dev);
7176 -
7177 - if (WARN_ON(list_empty(dev_to_msi_list(dev))))
7178 - return;
7179 -
7180 - fsl_mc_msi_free_descs(dev);
7181 -}
7182 --- /dev/null
7183 +++ b/drivers/bus/fsl-mc/fsl-mc-msi.c
7184 @@ -0,0 +1,285 @@
7185 +// SPDX-License-Identifier: GPL-2.0
7186 +/*
7187 + * Freescale Management Complex (MC) bus driver MSI support
7188 + *
7189 + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
7190 + * Author: German Rivera <German.Rivera@freescale.com>
7191 + *
7192 + */
7193 +
7194 +#include <linux/of_device.h>
7195 +#include <linux/of_address.h>
7196 +#include <linux/of_irq.h>
7197 +#include <linux/irq.h>
7198 +#include <linux/irqdomain.h>
7199 +#include <linux/msi.h>
7200 +
7201 +#include "fsl-mc-private.h"
7202 +
7203 +#ifdef GENERIC_MSI_DOMAIN_OPS
7204 +/*
7205 + * Generate a unique ID identifying the interrupt (only used within the MSI
7206 + * irqdomain. Combine the icid with the interrupt index.
7207 + */
7208 +static irq_hw_number_t fsl_mc_domain_calc_hwirq(struct fsl_mc_device *dev,
7209 + struct msi_desc *desc)
7210 +{
7211 + /*
7212 + * Make the base hwirq value for ICID*10000 so it is readable
7213 + * as a decimal value in /proc/interrupts.
7214 + */
7215 + return (irq_hw_number_t)(desc->fsl_mc.msi_index + (dev->icid * 10000));
7216 +}
7217 +
7218 +static void fsl_mc_msi_set_desc(msi_alloc_info_t *arg,
7219 + struct msi_desc *desc)
7220 +{
7221 + arg->desc = desc;
7222 + arg->hwirq = fsl_mc_domain_calc_hwirq(to_fsl_mc_device(desc->dev),
7223 + desc);
7224 +}
7225 +#else
7226 +#define fsl_mc_msi_set_desc NULL
7227 +#endif
7228 +
7229 +static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info)
7230 +{
7231 + struct msi_domain_ops *ops = info->ops;
7232 +
7233 + if (!ops)
7234 + return;
7235 +
7236 + /*
7237 + * set_desc should not be set by the caller
7238 + */
7239 + if (!ops->set_desc)
7240 + ops->set_desc = fsl_mc_msi_set_desc;
7241 +}
7242 +
7243 +static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev,
7244 + struct fsl_mc_device_irq *mc_dev_irq)
7245 +{
7246 + int error;
7247 + struct fsl_mc_device *owner_mc_dev = mc_dev_irq->mc_dev;
7248 + struct msi_desc *msi_desc = mc_dev_irq->msi_desc;
7249 + struct dprc_irq_cfg irq_cfg;
7250 +
7251 + /*
7252 + * msi_desc->msg.address is 0x0 when this function is invoked in
7253 + * the free_irq() code path. In this case, for the MC, we don't
7254 + * really need to "unprogram" the MSI, so we just return.
7255 + */
7256 + if (msi_desc->msg.address_lo == 0x0 && msi_desc->msg.address_hi == 0x0)
7257 + return;
7258 +
7259 + if (!owner_mc_dev)
7260 + return;
7261 +
7262 + irq_cfg.paddr = ((u64)msi_desc->msg.address_hi << 32) |
7263 + msi_desc->msg.address_lo;
7264 + irq_cfg.val = msi_desc->msg.data;
7265 + irq_cfg.irq_num = msi_desc->irq;
7266 +
7267 + if (owner_mc_dev == mc_bus_dev) {
7268 + /*
7269 + * IRQ is for the mc_bus_dev's DPRC itself
7270 + */
7271 + error = dprc_set_irq(mc_bus_dev->mc_io,
7272 + MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI,
7273 + mc_bus_dev->mc_handle,
7274 + mc_dev_irq->dev_irq_index,
7275 + &irq_cfg);
7276 + if (error < 0) {
7277 + dev_err(&owner_mc_dev->dev,
7278 + "dprc_set_irq() failed: %d\n", error);
7279 + }
7280 + } else {
7281 + /*
7282 + * IRQ is for for a child device of mc_bus_dev
7283 + */
7284 + error = dprc_set_obj_irq(mc_bus_dev->mc_io,
7285 + MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI,
7286 + mc_bus_dev->mc_handle,
7287 + owner_mc_dev->obj_desc.type,
7288 + owner_mc_dev->obj_desc.id,
7289 + mc_dev_irq->dev_irq_index,
7290 + &irq_cfg);
7291 + if (error < 0) {
7292 + dev_err(&owner_mc_dev->dev,
7293 + "dprc_obj_set_irq() failed: %d\n", error);
7294 + }
7295 + }
7296 +}
7297 +
7298 +/*
7299 + * NOTE: This function is invoked with interrupts disabled
7300 + */
7301 +static void fsl_mc_msi_write_msg(struct irq_data *irq_data,
7302 + struct msi_msg *msg)
7303 +{
7304 + struct msi_desc *msi_desc = irq_data_get_msi_desc(irq_data);
7305 + struct fsl_mc_device *mc_bus_dev = to_fsl_mc_device(msi_desc->dev);
7306 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
7307 + struct fsl_mc_device_irq *mc_dev_irq =
7308 + &mc_bus->irq_resources[msi_desc->fsl_mc.msi_index];
7309 +
7310 + msi_desc->msg = *msg;
7311 +
7312 + /*
7313 + * Program the MSI (paddr, value) pair in the device:
7314 + */
7315 + __fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq);
7316 +}
7317 +
7318 +static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info)
7319 +{
7320 + struct irq_chip *chip = info->chip;
7321 +
7322 + if (!chip)
7323 + return;
7324 +
7325 + /*
7326 + * irq_write_msi_msg should not be set by the caller
7327 + */
7328 + if (!chip->irq_write_msi_msg)
7329 + chip->irq_write_msi_msg = fsl_mc_msi_write_msg;
7330 +}
7331 +
7332 +/**
7333 + * fsl_mc_msi_create_irq_domain - Create a fsl-mc MSI interrupt domain
7334 + * @np: Optional device-tree node of the interrupt controller
7335 + * @info: MSI domain info
7336 + * @parent: Parent irq domain
7337 + *
7338 + * Updates the domain and chip ops and creates a fsl-mc MSI
7339 + * interrupt domain.
7340 + *
7341 + * Returns:
7342 + * A domain pointer or NULL in case of failure.
7343 + */
7344 +struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode,
7345 + struct msi_domain_info *info,
7346 + struct irq_domain *parent)
7347 +{
7348 + struct irq_domain *domain;
7349 +
7350 + if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS)
7351 + fsl_mc_msi_update_dom_ops(info);
7352 + if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
7353 + fsl_mc_msi_update_chip_ops(info);
7354 +
7355 + domain = msi_create_irq_domain(fwnode, info, parent);
7356 + if (domain)
7357 + irq_domain_update_bus_token(domain, DOMAIN_BUS_FSL_MC_MSI);
7358 +
7359 + return domain;
7360 +}
7361 +
7362 +int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
7363 + struct irq_domain **mc_msi_domain)
7364 +{
7365 + struct irq_domain *msi_domain;
7366 + struct device_node *mc_of_node = mc_platform_dev->of_node;
7367 +
7368 + msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node,
7369 + DOMAIN_BUS_FSL_MC_MSI);
7370 + if (!msi_domain) {
7371 + pr_err("Unable to find fsl-mc MSI domain for %pOF\n",
7372 + mc_of_node);
7373 +
7374 + return -ENOENT;
7375 + }
7376 +
7377 + *mc_msi_domain = msi_domain;
7378 + return 0;
7379 +}
7380 +
7381 +static void fsl_mc_msi_free_descs(struct device *dev)
7382 +{
7383 + struct msi_desc *desc, *tmp;
7384 +
7385 + list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) {
7386 + list_del(&desc->list);
7387 + free_msi_entry(desc);
7388 + }
7389 +}
7390 +
7391 +static int fsl_mc_msi_alloc_descs(struct device *dev, unsigned int irq_count)
7392 +
7393 +{
7394 + unsigned int i;
7395 + int error;
7396 + struct msi_desc *msi_desc;
7397 +
7398 + for (i = 0; i < irq_count; i++) {
7399 + msi_desc = alloc_msi_entry(dev, 1, NULL);
7400 + if (!msi_desc) {
7401 + dev_err(dev, "Failed to allocate msi entry\n");
7402 + error = -ENOMEM;
7403 + goto cleanup_msi_descs;
7404 + }
7405 +
7406 + msi_desc->fsl_mc.msi_index = i;
7407 + INIT_LIST_HEAD(&msi_desc->list);
7408 + list_add_tail(&msi_desc->list, dev_to_msi_list(dev));
7409 + }
7410 +
7411 + return 0;
7412 +
7413 +cleanup_msi_descs:
7414 + fsl_mc_msi_free_descs(dev);
7415 + return error;
7416 +}
7417 +
7418 +int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
7419 + unsigned int irq_count)
7420 +{
7421 + struct irq_domain *msi_domain;
7422 + int error;
7423 +
7424 + if (!list_empty(dev_to_msi_list(dev)))
7425 + return -EINVAL;
7426 +
7427 + error = fsl_mc_msi_alloc_descs(dev, irq_count);
7428 + if (error < 0)
7429 + return error;
7430 +
7431 + msi_domain = dev_get_msi_domain(dev);
7432 + if (!msi_domain) {
7433 + error = -EINVAL;
7434 + goto cleanup_msi_descs;
7435 + }
7436 +
7437 + /*
7438 + * NOTE: Calling this function will trigger the invocation of the
7439 + * its_fsl_mc_msi_prepare() callback
7440 + */
7441 + error = msi_domain_alloc_irqs(msi_domain, dev, irq_count);
7442 +
7443 + if (error) {
7444 + dev_err(dev, "Failed to allocate IRQs\n");
7445 + goto cleanup_msi_descs;
7446 + }
7447 +
7448 + return 0;
7449 +
7450 +cleanup_msi_descs:
7451 + fsl_mc_msi_free_descs(dev);
7452 + return error;
7453 +}
7454 +
7455 +void fsl_mc_msi_domain_free_irqs(struct device *dev)
7456 +{
7457 + struct irq_domain *msi_domain;
7458 +
7459 + msi_domain = dev_get_msi_domain(dev);
7460 + if (!msi_domain)
7461 + return;
7462 +
7463 + msi_domain_free_irqs(msi_domain, dev);
7464 +
7465 + if (list_empty(dev_to_msi_list(dev)))
7466 + return;
7467 +
7468 + fsl_mc_msi_free_descs(dev);
7469 +}
7470 --- /dev/null
7471 +++ b/drivers/bus/fsl-mc/fsl-mc-private.h
7472 @@ -0,0 +1,223 @@
7473 +/* SPDX-License-Identifier: GPL-2.0 */
7474 +/*
7475 + * Freescale Management Complex (MC) bus private declarations
7476 + *
7477 + * Copyright (C) 2016 Freescale Semiconductor, Inc.
7478 + *
7479 + */
7480 +#ifndef _FSL_MC_PRIVATE_H_
7481 +#define _FSL_MC_PRIVATE_H_
7482 +
7483 +#include <linux/fsl/mc.h>
7484 +#include <linux/mutex.h>
7485 +#include <linux/cdev.h>
7486 +#include <linux/ioctl.h>
7487 +
7488 +/*
7489 + * Data Path Management Complex (DPMNG) General API
7490 + */
7491 +
7492 +/* DPMNG command versioning */
7493 +#define DPMNG_CMD_BASE_VERSION 1
7494 +#define DPMNG_CMD_ID_OFFSET 4
7495 +
7496 +#define DPMNG_CMD(id) (((id) << DPMNG_CMD_ID_OFFSET) | DPMNG_CMD_BASE_VERSION)
7497 +
7498 +/* DPMNG command IDs */
7499 +#define DPMNG_CMDID_GET_VERSION DPMNG_CMD(0x831)
7500 +
7501 +struct dpmng_rsp_get_version {
7502 + __le32 revision;
7503 + __le32 version_major;
7504 + __le32 version_minor;
7505 +};
7506 +
7507 +/*
7508 + * Data Path Management Command Portal (DPMCP) API
7509 + */
7510 +
7511 +/* Minimal supported DPMCP Version */
7512 +#define DPMCP_MIN_VER_MAJOR 3
7513 +#define DPMCP_MIN_VER_MINOR 0
7514 +
7515 +/* DPMCP command versioning */
7516 +#define DPMCP_CMD_BASE_VERSION 1
7517 +#define DPMCP_CMD_ID_OFFSET 4
7518 +
7519 +#define DPMCP_CMD(id) (((id) << DPMCP_CMD_ID_OFFSET) | DPMCP_CMD_BASE_VERSION)
7520 +
7521 +/* DPMCP command IDs */
7522 +#define DPMCP_CMDID_CLOSE DPMCP_CMD(0x800)
7523 +#define DPMCP_CMDID_OPEN DPMCP_CMD(0x80b)
7524 +#define DPMCP_CMDID_RESET DPMCP_CMD(0x005)
7525 +
7526 +struct dpmcp_cmd_open {
7527 + __le32 dpmcp_id;
7528 +};
7529 +
7530 +/*
7531 + * Initialization and runtime control APIs for DPMCP
7532 + */
7533 +int dpmcp_open(struct fsl_mc_io *mc_io,
7534 + u32 cmd_flags,
7535 + int dpmcp_id,
7536 + u16 *token);
7537 +
7538 +int dpmcp_close(struct fsl_mc_io *mc_io,
7539 + u32 cmd_flags,
7540 + u16 token);
7541 +
7542 +int dpmcp_reset(struct fsl_mc_io *mc_io,
7543 + u32 cmd_flags,
7544 + u16 token);
7545 +
7546 +/*
7547 + * Data Path Buffer Pool (DPBP) API
7548 + */
7549 +
7550 +/* DPBP Version */
7551 +#define DPBP_VER_MAJOR 3
7552 +#define DPBP_VER_MINOR 2
7553 +
7554 +/* Command versioning */
7555 +#define DPBP_CMD_BASE_VERSION 1
7556 +#define DPBP_CMD_ID_OFFSET 4
7557 +
7558 +#define DPBP_CMD(id) (((id) << DPBP_CMD_ID_OFFSET) | DPBP_CMD_BASE_VERSION)
7559 +
7560 +/* Command IDs */
7561 +#define DPBP_CMDID_CLOSE DPBP_CMD(0x800)
7562 +#define DPBP_CMDID_OPEN DPBP_CMD(0x804)
7563 +
7564 +#define DPBP_CMDID_ENABLE DPBP_CMD(0x002)
7565 +#define DPBP_CMDID_DISABLE DPBP_CMD(0x003)
7566 +#define DPBP_CMDID_GET_ATTR DPBP_CMD(0x004)
7567 +#define DPBP_CMDID_RESET DPBP_CMD(0x005)
7568 +
7569 +struct dpbp_cmd_open {
7570 + __le32 dpbp_id;
7571 +};
7572 +
7573 +#define DPBP_ENABLE 0x1
7574 +
7575 +struct dpbp_rsp_get_attributes {
7576 + /* response word 0 */
7577 + __le16 pad;
7578 + __le16 bpid;
7579 + __le32 id;
7580 + /* response word 1 */
7581 + __le16 version_major;
7582 + __le16 version_minor;
7583 +};
7584 +
7585 +/*
7586 + * Data Path Concentrator (DPCON) API
7587 + */
7588 +
7589 +/* DPCON Version */
7590 +#define DPCON_VER_MAJOR 3
7591 +#define DPCON_VER_MINOR 2
7592 +
7593 +/* Command versioning */
7594 +#define DPCON_CMD_BASE_VERSION 1
7595 +#define DPCON_CMD_ID_OFFSET 4
7596 +
7597 +#define DPCON_CMD(id) (((id) << DPCON_CMD_ID_OFFSET) | DPCON_CMD_BASE_VERSION)
7598 +
7599 +/* Command IDs */
7600 +#define DPCON_CMDID_CLOSE DPCON_CMD(0x800)
7601 +#define DPCON_CMDID_OPEN DPCON_CMD(0x808)
7602 +
7603 +#define DPCON_CMDID_ENABLE DPCON_CMD(0x002)
7604 +#define DPCON_CMDID_DISABLE DPCON_CMD(0x003)
7605 +#define DPCON_CMDID_GET_ATTR DPCON_CMD(0x004)
7606 +#define DPCON_CMDID_RESET DPCON_CMD(0x005)
7607 +
7608 +#define DPCON_CMDID_SET_NOTIFICATION DPCON_CMD(0x100)
7609 +
7610 +struct dpcon_cmd_open {
7611 + __le32 dpcon_id;
7612 +};
7613 +
7614 +#define DPCON_ENABLE 1
7615 +
7616 +struct dpcon_rsp_get_attr {
7617 + /* response word 0 */
7618 + __le32 id;
7619 + __le16 qbman_ch_id;
7620 + u8 num_priorities;
7621 + u8 pad;
7622 +};
7623 +
7624 +struct dpcon_cmd_set_notification {
7625 + /* cmd word 0 */
7626 + __le32 dpio_id;
7627 + u8 priority;
7628 + u8 pad[3];
7629 + /* cmd word 1 */
7630 + __le64 user_ctx;
7631 +};
7632 +
7633 +int __must_check fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc,
7634 + struct fsl_mc_io *mc_io,
7635 + struct device *parent_dev,
7636 + const char *driver_override,
7637 + struct fsl_mc_device **new_mc_dev);
7638 +
7639 +int __init dprc_driver_init(void);
7640 +
7641 +void dprc_driver_exit(void);
7642 +
7643 +int __init fsl_mc_allocator_driver_init(void);
7644 +
7645 +void fsl_mc_allocator_driver_exit(void);
7646 +
7647 +int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus,
7648 + enum fsl_mc_pool_type pool_type,
7649 + struct fsl_mc_resource
7650 + **new_resource);
7651 +
7652 +void fsl_mc_resource_free(struct fsl_mc_resource *resource);
7653 +
7654 +int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
7655 + unsigned int irq_count);
7656 +
7657 +void fsl_mc_msi_domain_free_irqs(struct device *dev);
7658 +
7659 +int __must_check fsl_create_mc_io(struct device *dev,
7660 + phys_addr_t mc_portal_phys_addr,
7661 + u32 mc_portal_size,
7662 + struct fsl_mc_device *dpmcp_dev,
7663 + u32 flags, struct fsl_mc_io **new_mc_io);
7664 +
7665 +void fsl_destroy_mc_io(struct fsl_mc_io *mc_io);
7666 +
7667 +bool fsl_mc_is_root_dprc(struct device *dev);
7668 +
7669 +#ifdef CONFIG_FSL_MC_RESTOOL
7670 +
7671 +int fsl_mc_restool_create_device_file(struct fsl_mc_bus *mc_bus);
7672 +
7673 +void fsl_mc_restool_remove_device_file(struct fsl_mc_bus *mc_bus);
7674 +
7675 +int fsl_mc_restool_init(void);
7676 +
7677 +#else
7678 +
7679 +static inline int fsl_mc_restool_create_device_file(struct fsl_mc_bus *mc_bus)
7680 +{
7681 + return 0;
7682 +}
7683 +
7684 +static inline void fsl_mc_restool_remove_device_file(struct fsl_mc_bus *mc_bus)
7685 +{
7686 +}
7687 +
7688 +static inline int fsl_mc_restool_init(void)
7689 +{
7690 + return 0;
7691 +}
7692 +
7693 +#endif
7694 +
7695 +#endif /* _FSL_MC_PRIVATE_H_ */
7696 --- /dev/null
7697 +++ b/drivers/bus/fsl-mc/fsl-mc-restool.c
7698 @@ -0,0 +1,219 @@
7699 +// SPDX-License-Identifier: GPL-2.0
7700 +/*
7701 + * Management Complex (MC) restool support
7702 + *
7703 + * Copyright 2018 NXP
7704 + *
7705 + */
7706 +
7707 +#include <linux/slab.h>
7708 +#include <linux/cdev.h>
7709 +#include <linux/fs.h>
7710 +#include <linux/uaccess.h>
7711 +
7712 +#include "fsl-mc-private.h"
7713 +
7714 +#define FSL_MC_BUS_MAX_MINORS 1
7715 +
7716 +static struct class *fsl_mc_bus_class;
7717 +static int fsl_mc_bus_major;
7718 +
7719 +static int fsl_mc_restool_send_command(unsigned long arg,
7720 + struct fsl_mc_io *mc_io)
7721 +{
7722 + struct fsl_mc_command mc_cmd;
7723 + int error;
7724 +
7725 + error = copy_from_user(&mc_cmd, (void __user *)arg, sizeof(mc_cmd));
7726 + if (error)
7727 + return -EFAULT;
7728 +
7729 + error = mc_send_command(mc_io, &mc_cmd);
7730 + if (error)
7731 + return error;
7732 +
7733 + error = copy_to_user((void __user *)arg, &mc_cmd, sizeof(mc_cmd));
7734 + if (error)
7735 + return -EFAULT;
7736 +
7737 + return 0;
7738 +}
7739 +
7740 +int fsl_mc_restool_init(void)
7741 +{
7742 + dev_t dev;
7743 + int error;
7744 +
7745 + fsl_mc_bus_class = class_create(THIS_MODULE, "fsl_mc_bus");
7746 + if (IS_ERR(fsl_mc_bus_class)) {
7747 + error = PTR_ERR(fsl_mc_bus_class);
7748 + return error;
7749 + }
7750 +
7751 + error = alloc_chrdev_region(&dev, 0,
7752 + FSL_MC_BUS_MAX_MINORS,
7753 + "fsl_mc_bus");
7754 + if (error < 0)
7755 + return error;
7756 +
7757 + fsl_mc_bus_major = MAJOR(dev);
7758 +
7759 + return 0;
7760 +}
7761 +
7762 +static int fsl_mc_restool_dev_open(struct inode *inode, struct file *filep)
7763 +{
7764 + struct fsl_mc_device *root_mc_device;
7765 + struct fsl_mc_restool *mc_restool;
7766 + struct fsl_mc_bus *mc_bus;
7767 + struct fsl_mc_io *dynamic_mc_io;
7768 + int error;
7769 +
7770 + mc_restool = container_of(inode->i_cdev, struct fsl_mc_restool, cdev);
7771 + mc_bus = container_of(mc_restool, struct fsl_mc_bus, restool_misc);
7772 + root_mc_device = &mc_bus->mc_dev;
7773 +
7774 + mutex_lock(&mc_restool->mutex);
7775 +
7776 + if (!mc_restool->local_instance_in_use) {
7777 + filep->private_data = root_mc_device->mc_io;
7778 + mc_restool->local_instance_in_use = true;
7779 + } else {
7780 + dynamic_mc_io = kzalloc(sizeof(*dynamic_mc_io), GFP_KERNEL);
7781 + if (!dynamic_mc_io) {
7782 + error = -ENOMEM;
7783 + goto error_alloc_mc_io;
7784 + }
7785 +
7786 + error = fsl_mc_portal_allocate(root_mc_device, 0,
7787 + &dynamic_mc_io);
7788 + if (error) {
7789 + pr_err("Could not allocate MC portal\n");
7790 + goto error_portal_allocate;
7791 + }
7792 +
7793 + mc_restool->dynamic_instance_count++;
7794 + filep->private_data = dynamic_mc_io;
7795 + }
7796 +
7797 + mutex_unlock(&mc_restool->mutex);
7798 +
7799 + return 0;
7800 +
7801 +error_portal_allocate:
7802 + kfree(dynamic_mc_io);
7803 +
7804 +error_alloc_mc_io:
7805 + mutex_unlock(&mc_restool->mutex);
7806 +
7807 + return error;
7808 +}
7809 +
7810 +static int fsl_mc_restool_dev_release(struct inode *inode, struct file *filep)
7811 +{
7812 + struct fsl_mc_device *root_mc_device;
7813 + struct fsl_mc_restool *mc_restool;
7814 + struct fsl_mc_bus *mc_bus;
7815 + struct fsl_mc_io *mc_io;
7816 +
7817 + mc_restool = container_of(inode->i_cdev, struct fsl_mc_restool, cdev);
7818 + mc_bus = container_of(mc_restool, struct fsl_mc_bus, restool_misc);
7819 + root_mc_device = &mc_bus->mc_dev;
7820 + mc_io = filep->private_data;
7821 +
7822 + mutex_lock(&mc_restool->mutex);
7823 +
7824 + if (WARN_ON(!mc_restool->local_instance_in_use &&
7825 + mc_restool->dynamic_instance_count == 0)) {
7826 + mutex_unlock(&mc_restool->mutex);
7827 + return -EINVAL;
7828 + }
7829 +
7830 + if (filep->private_data == root_mc_device->mc_io) {
7831 + mc_restool->local_instance_in_use = false;
7832 + } else {
7833 + fsl_mc_portal_free(mc_io);
7834 + kfree(mc_io);
7835 + mc_restool->dynamic_instance_count--;
7836 + }
7837 +
7838 + filep->private_data = NULL;
7839 + mutex_unlock(&mc_restool->mutex);
7840 +
7841 + return 0;
7842 +}
7843 +
7844 +static long fsl_mc_restool_dev_ioctl(struct file *file,
7845 + unsigned int cmd,
7846 + unsigned long arg)
7847 +{
7848 + int error;
7849 +
7850 + switch (cmd) {
7851 + case RESTOOL_SEND_MC_COMMAND:
7852 + error = fsl_mc_restool_send_command(arg, file->private_data);
7853 + break;
7854 + default:
7855 + pr_err("%s: unexpected ioctl call number\n", __func__);
7856 + error = -EINVAL;
7857 + }
7858 +
7859 + return error;
7860 +}
7861 +
7862 +static const struct file_operations fsl_mc_restool_dev_fops = {
7863 + .owner = THIS_MODULE,
7864 + .open = fsl_mc_restool_dev_open,
7865 + .release = fsl_mc_restool_dev_release,
7866 + .unlocked_ioctl = fsl_mc_restool_dev_ioctl,
7867 +};
7868 +
7869 +int fsl_mc_restool_create_device_file(struct fsl_mc_bus *mc_bus)
7870 +{
7871 + struct fsl_mc_device *mc_dev = &mc_bus->mc_dev;
7872 + struct fsl_mc_restool *mc_restool = &mc_bus->restool_misc;
7873 + int error;
7874 +
7875 + mc_restool = &mc_bus->restool_misc;
7876 + mc_restool->dev = MKDEV(fsl_mc_bus_major, 0);
7877 + cdev_init(&mc_restool->cdev, &fsl_mc_restool_dev_fops);
7878 +
7879 + error = cdev_add(&mc_restool->cdev,
7880 + mc_restool->dev,
7881 + FSL_MC_BUS_MAX_MINORS);
7882 + if (error)
7883 + return error;
7884 +
7885 + mc_restool->device = device_create(fsl_mc_bus_class,
7886 + NULL,
7887 + mc_restool->dev,
7888 + NULL,
7889 + "%s",
7890 + dev_name(&mc_dev->dev));
7891 + if (IS_ERR(mc_restool->device)) {
7892 + error = PTR_ERR(mc_restool->device);
7893 + goto error_device_create;
7894 + }
7895 +
7896 + mutex_init(&mc_restool->mutex);
7897 +
7898 + return 0;
7899 +
7900 +error_device_create:
7901 + cdev_del(&mc_restool->cdev);
7902 +
7903 + return error;
7904 +}
7905 +
7906 +void fsl_mc_restool_remove_device_file(struct fsl_mc_bus *mc_bus)
7907 +{
7908 + struct fsl_mc_restool *mc_restool = &mc_bus->restool_misc;
7909 +
7910 + if (WARN_ON(mc_restool->local_instance_in_use))
7911 + return;
7912 +
7913 + if (WARN_ON(mc_restool->dynamic_instance_count != 0))
7914 + return;
7915 +
7916 + cdev_del(&mc_restool->cdev);
7917 +}
7918 --- a/drivers/staging/fsl-mc/bus/mc-io.c
7919 +++ /dev/null
7920 @@ -1,320 +0,0 @@
7921 -/* Copyright 2013-2016 Freescale Semiconductor Inc.
7922 - *
7923 - * Redistribution and use in source and binary forms, with or without
7924 - * modification, are permitted provided that the following conditions are met:
7925 - * * Redistributions of source code must retain the above copyright
7926 - * notice, this list of conditions and the following disclaimer.
7927 - * * Redistributions in binary form must reproduce the above copyright
7928 - * notice, this list of conditions and the following disclaimer in the
7929 - * documentation and/or other materials provided with the distribution.
7930 - * * Neither the name of the above-listed copyright holders nor the
7931 - * names of any contributors may be used to endorse or promote products
7932 - * derived from this software without specific prior written permission.
7933 - *
7934 - *
7935 - * ALTERNATIVELY, this software may be distributed under the terms of the
7936 - * GNU General Public License ("GPL") as published by the Free Software
7937 - * Foundation, either version 2 of that License or (at your option) any
7938 - * later version.
7939 - *
7940 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
7941 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
7942 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
7943 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
7944 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
7945 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
7946 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
7947 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
7948 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
7949 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
7950 - * POSSIBILITY OF SUCH DAMAGE.
7951 - */
7952 -
7953 -#include <linux/io.h>
7954 -#include "../include/mc-bus.h"
7955 -#include "../include/mc-sys.h"
7956 -
7957 -#include "fsl-mc-private.h"
7958 -#include "dpmcp.h"
7959 -#include "dpmcp-cmd.h"
7960 -
7961 -static int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io,
7962 - struct fsl_mc_device *dpmcp_dev)
7963 -{
7964 - int error;
7965 -
7966 - if (WARN_ON(!dpmcp_dev))
7967 - return -EINVAL;
7968 -
7969 - if (WARN_ON(mc_io->dpmcp_dev))
7970 - return -EINVAL;
7971 -
7972 - if (WARN_ON(dpmcp_dev->mc_io))
7973 - return -EINVAL;
7974 -
7975 - error = dpmcp_open(mc_io,
7976 - 0,
7977 - dpmcp_dev->obj_desc.id,
7978 - &dpmcp_dev->mc_handle);
7979 - if (error < 0)
7980 - return error;
7981 -
7982 - mc_io->dpmcp_dev = dpmcp_dev;
7983 - dpmcp_dev->mc_io = mc_io;
7984 - return 0;
7985 -}
7986 -
7987 -static void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io)
7988 -{
7989 - int error;
7990 - struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
7991 -
7992 - if (WARN_ON(!dpmcp_dev))
7993 - return;
7994 -
7995 - if (WARN_ON(dpmcp_dev->mc_io != mc_io))
7996 - return;
7997 -
7998 - error = dpmcp_close(mc_io,
7999 - 0,
8000 - dpmcp_dev->mc_handle);
8001 - if (error < 0) {
8002 - dev_err(&dpmcp_dev->dev, "dpmcp_close() failed: %d\n",
8003 - error);
8004 - }
8005 -
8006 - mc_io->dpmcp_dev = NULL;
8007 - dpmcp_dev->mc_io = NULL;
8008 -}
8009 -
8010 -/**
8011 - * Creates an MC I/O object
8012 - *
8013 - * @dev: device to be associated with the MC I/O object
8014 - * @mc_portal_phys_addr: physical address of the MC portal to use
8015 - * @mc_portal_size: size in bytes of the MC portal
8016 - * @dpmcp-dev: Pointer to the DPMCP object associated with this MC I/O
8017 - * object or NULL if none.
8018 - * @flags: flags for the new MC I/O object
8019 - * @new_mc_io: Area to return pointer to newly created MC I/O object
8020 - *
8021 - * Returns '0' on Success; Error code otherwise.
8022 - */
8023 -int __must_check fsl_create_mc_io(struct device *dev,
8024 - phys_addr_t mc_portal_phys_addr,
8025 - u32 mc_portal_size,
8026 - struct fsl_mc_device *dpmcp_dev,
8027 - u32 flags, struct fsl_mc_io **new_mc_io)
8028 -{
8029 - int error;
8030 - struct fsl_mc_io *mc_io;
8031 - void __iomem *mc_portal_virt_addr;
8032 - struct resource *res;
8033 -
8034 - mc_io = devm_kzalloc(dev, sizeof(*mc_io), GFP_KERNEL);
8035 - if (!mc_io)
8036 - return -ENOMEM;
8037 -
8038 - mc_io->dev = dev;
8039 - mc_io->flags = flags;
8040 - mc_io->portal_phys_addr = mc_portal_phys_addr;
8041 - mc_io->portal_size = mc_portal_size;
8042 - if (flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
8043 - spin_lock_init(&mc_io->spinlock);
8044 - else
8045 - mutex_init(&mc_io->mutex);
8046 -
8047 - res = devm_request_mem_region(dev,
8048 - mc_portal_phys_addr,
8049 - mc_portal_size,
8050 - "mc_portal");
8051 - if (!res) {
8052 - dev_err(dev,
8053 - "devm_request_mem_region failed for MC portal %#llx\n",
8054 - mc_portal_phys_addr);
8055 - return -EBUSY;
8056 - }
8057 -
8058 - mc_portal_virt_addr = devm_ioremap_nocache(dev,
8059 - mc_portal_phys_addr,
8060 - mc_portal_size);
8061 - if (!mc_portal_virt_addr) {
8062 - dev_err(dev,
8063 - "devm_ioremap_nocache failed for MC portal %#llx\n",
8064 - mc_portal_phys_addr);
8065 - return -ENXIO;
8066 - }
8067 -
8068 - mc_io->portal_virt_addr = mc_portal_virt_addr;
8069 - if (dpmcp_dev) {
8070 - error = fsl_mc_io_set_dpmcp(mc_io, dpmcp_dev);
8071 - if (error < 0)
8072 - goto error_destroy_mc_io;
8073 - }
8074 -
8075 - *new_mc_io = mc_io;
8076 - return 0;
8077 -
8078 -error_destroy_mc_io:
8079 - fsl_destroy_mc_io(mc_io);
8080 - return error;
8081 -}
8082 -
8083 -/**
8084 - * Destroys an MC I/O object
8085 - *
8086 - * @mc_io: MC I/O object to destroy
8087 - */
8088 -void fsl_destroy_mc_io(struct fsl_mc_io *mc_io)
8089 -{
8090 - struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
8091 -
8092 - if (dpmcp_dev)
8093 - fsl_mc_io_unset_dpmcp(mc_io);
8094 -
8095 - devm_iounmap(mc_io->dev, mc_io->portal_virt_addr);
8096 - devm_release_mem_region(mc_io->dev,
8097 - mc_io->portal_phys_addr,
8098 - mc_io->portal_size);
8099 -
8100 - mc_io->portal_virt_addr = NULL;
8101 - devm_kfree(mc_io->dev, mc_io);
8102 -}
8103 -
8104 -/**
8105 - * fsl_mc_portal_allocate - Allocates an MC portal
8106 - *
8107 - * @mc_dev: MC device for which the MC portal is to be allocated
8108 - * @mc_io_flags: Flags for the fsl_mc_io object that wraps the allocated
8109 - * MC portal.
8110 - * @new_mc_io: Pointer to area where the pointer to the fsl_mc_io object
8111 - * that wraps the allocated MC portal is to be returned
8112 - *
8113 - * This function allocates an MC portal from the device's parent DPRC,
8114 - * from the corresponding MC bus' pool of MC portals and wraps
8115 - * it in a new fsl_mc_io object. If 'mc_dev' is a DPRC itself, the
8116 - * portal is allocated from its own MC bus.
8117 - */
8118 -int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
8119 - u16 mc_io_flags,
8120 - struct fsl_mc_io **new_mc_io)
8121 -{
8122 - struct fsl_mc_device *mc_bus_dev;
8123 - struct fsl_mc_bus *mc_bus;
8124 - phys_addr_t mc_portal_phys_addr;
8125 - size_t mc_portal_size;
8126 - struct fsl_mc_device *dpmcp_dev;
8127 - int error = -EINVAL;
8128 - struct fsl_mc_resource *resource = NULL;
8129 - struct fsl_mc_io *mc_io = NULL;
8130 -
8131 - if (mc_dev->flags & FSL_MC_IS_DPRC) {
8132 - mc_bus_dev = mc_dev;
8133 - } else {
8134 - if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent)))
8135 - return error;
8136 -
8137 - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
8138 - }
8139 -
8140 - mc_bus = to_fsl_mc_bus(mc_bus_dev);
8141 - *new_mc_io = NULL;
8142 - error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_DPMCP, &resource);
8143 - if (error < 0)
8144 - return error;
8145 -
8146 - error = -EINVAL;
8147 - dpmcp_dev = resource->data;
8148 - if (WARN_ON(!dpmcp_dev))
8149 - goto error_cleanup_resource;
8150 -
8151 - if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR ||
8152 - (dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR &&
8153 - dpmcp_dev->obj_desc.ver_minor < DPMCP_MIN_VER_MINOR)) {
8154 - dev_err(&dpmcp_dev->dev,
8155 - "ERROR: Version %d.%d of DPMCP not supported.\n",
8156 - dpmcp_dev->obj_desc.ver_major,
8157 - dpmcp_dev->obj_desc.ver_minor);
8158 - error = -ENOTSUPP;
8159 - goto error_cleanup_resource;
8160 - }
8161 -
8162 - if (WARN_ON(dpmcp_dev->obj_desc.region_count == 0))
8163 - goto error_cleanup_resource;
8164 -
8165 - mc_portal_phys_addr = dpmcp_dev->regions[0].start;
8166 - mc_portal_size = dpmcp_dev->regions[0].end -
8167 - dpmcp_dev->regions[0].start + 1;
8168 -
8169 - if (WARN_ON(mc_portal_size != mc_bus_dev->mc_io->portal_size))
8170 - goto error_cleanup_resource;
8171 -
8172 - error = fsl_create_mc_io(&mc_bus_dev->dev,
8173 - mc_portal_phys_addr,
8174 - mc_portal_size, dpmcp_dev,
8175 - mc_io_flags, &mc_io);
8176 - if (error < 0)
8177 - goto error_cleanup_resource;
8178 -
8179 - *new_mc_io = mc_io;
8180 - return 0;
8181 -
8182 -error_cleanup_resource:
8183 - fsl_mc_resource_free(resource);
8184 - return error;
8185 -}
8186 -EXPORT_SYMBOL_GPL(fsl_mc_portal_allocate);
8187 -
8188 -/**
8189 - * fsl_mc_portal_free - Returns an MC portal to the pool of free MC portals
8190 - * of a given MC bus
8191 - *
8192 - * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free
8193 - */
8194 -void fsl_mc_portal_free(struct fsl_mc_io *mc_io)
8195 -{
8196 - struct fsl_mc_device *dpmcp_dev;
8197 - struct fsl_mc_resource *resource;
8198 -
8199 - /*
8200 - * Every mc_io obtained by calling fsl_mc_portal_allocate() is supposed
8201 - * to have a DPMCP object associated with.
8202 - */
8203 - dpmcp_dev = mc_io->dpmcp_dev;
8204 - if (WARN_ON(!dpmcp_dev))
8205 - return;
8206 -
8207 - resource = dpmcp_dev->resource;
8208 - if (WARN_ON(!resource || resource->type != FSL_MC_POOL_DPMCP))
8209 - return;
8210 -
8211 - if (WARN_ON(resource->data != dpmcp_dev))
8212 - return;
8213 -
8214 - fsl_destroy_mc_io(mc_io);
8215 - fsl_mc_resource_free(resource);
8216 -}
8217 -EXPORT_SYMBOL_GPL(fsl_mc_portal_free);
8218 -
8219 -/**
8220 - * fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object
8221 - *
8222 - * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free
8223 - */
8224 -int fsl_mc_portal_reset(struct fsl_mc_io *mc_io)
8225 -{
8226 - int error;
8227 - struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
8228 -
8229 - if (WARN_ON(!dpmcp_dev))
8230 - return -EINVAL;
8231 -
8232 - error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle);
8233 - if (error < 0) {
8234 - dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error);
8235 - return error;
8236 - }
8237 -
8238 - return 0;
8239 -}
8240 -EXPORT_SYMBOL_GPL(fsl_mc_portal_reset);
8241 --- /dev/null
8242 +++ b/drivers/bus/fsl-mc/mc-io.c
8243 @@ -0,0 +1,268 @@
8244 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
8245 +/*
8246 + * Copyright 2013-2016 Freescale Semiconductor Inc.
8247 + *
8248 + */
8249 +
8250 +#include <linux/io.h>
8251 +#include <linux/fsl/mc.h>
8252 +
8253 +#include "fsl-mc-private.h"
8254 +
8255 +static int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io,
8256 + struct fsl_mc_device *dpmcp_dev)
8257 +{
8258 + int error;
8259 +
8260 + if (mc_io->dpmcp_dev)
8261 + return -EINVAL;
8262 +
8263 + if (dpmcp_dev->mc_io)
8264 + return -EINVAL;
8265 +
8266 + error = dpmcp_open(mc_io,
8267 + 0,
8268 + dpmcp_dev->obj_desc.id,
8269 + &dpmcp_dev->mc_handle);
8270 + if (error < 0)
8271 + return error;
8272 +
8273 + mc_io->dpmcp_dev = dpmcp_dev;
8274 + dpmcp_dev->mc_io = mc_io;
8275 + return 0;
8276 +}
8277 +
8278 +static void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io)
8279 +{
8280 + int error;
8281 + struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
8282 +
8283 + error = dpmcp_close(mc_io,
8284 + 0,
8285 + dpmcp_dev->mc_handle);
8286 + if (error < 0) {
8287 + dev_err(&dpmcp_dev->dev, "dpmcp_close() failed: %d\n",
8288 + error);
8289 + }
8290 +
8291 + mc_io->dpmcp_dev = NULL;
8292 + dpmcp_dev->mc_io = NULL;
8293 +}
8294 +
8295 +/**
8296 + * Creates an MC I/O object
8297 + *
8298 + * @dev: device to be associated with the MC I/O object
8299 + * @mc_portal_phys_addr: physical address of the MC portal to use
8300 + * @mc_portal_size: size in bytes of the MC portal
8301 + * @dpmcp-dev: Pointer to the DPMCP object associated with this MC I/O
8302 + * object or NULL if none.
8303 + * @flags: flags for the new MC I/O object
8304 + * @new_mc_io: Area to return pointer to newly created MC I/O object
8305 + *
8306 + * Returns '0' on Success; Error code otherwise.
8307 + */
8308 +int __must_check fsl_create_mc_io(struct device *dev,
8309 + phys_addr_t mc_portal_phys_addr,
8310 + u32 mc_portal_size,
8311 + struct fsl_mc_device *dpmcp_dev,
8312 + u32 flags, struct fsl_mc_io **new_mc_io)
8313 +{
8314 + int error;
8315 + struct fsl_mc_io *mc_io;
8316 + void __iomem *mc_portal_virt_addr;
8317 + struct resource *res;
8318 +
8319 + mc_io = devm_kzalloc(dev, sizeof(*mc_io), GFP_KERNEL);
8320 + if (!mc_io)
8321 + return -ENOMEM;
8322 +
8323 + mc_io->dev = dev;
8324 + mc_io->flags = flags;
8325 + mc_io->portal_phys_addr = mc_portal_phys_addr;
8326 + mc_io->portal_size = mc_portal_size;
8327 + if (flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
8328 + spin_lock_init(&mc_io->spinlock);
8329 + else
8330 + mutex_init(&mc_io->mutex);
8331 +
8332 + res = devm_request_mem_region(dev,
8333 + mc_portal_phys_addr,
8334 + mc_portal_size,
8335 + "mc_portal");
8336 + if (!res) {
8337 + dev_err(dev,
8338 + "devm_request_mem_region failed for MC portal %pa\n",
8339 + &mc_portal_phys_addr);
8340 + return -EBUSY;
8341 + }
8342 +
8343 + mc_portal_virt_addr = devm_ioremap_nocache(dev,
8344 + mc_portal_phys_addr,
8345 + mc_portal_size);
8346 + if (!mc_portal_virt_addr) {
8347 + dev_err(dev,
8348 + "devm_ioremap_nocache failed for MC portal %pa\n",
8349 + &mc_portal_phys_addr);
8350 + return -ENXIO;
8351 + }
8352 +
8353 + mc_io->portal_virt_addr = mc_portal_virt_addr;
8354 + if (dpmcp_dev) {
8355 + error = fsl_mc_io_set_dpmcp(mc_io, dpmcp_dev);
8356 + if (error < 0)
8357 + goto error_destroy_mc_io;
8358 + }
8359 +
8360 + *new_mc_io = mc_io;
8361 + return 0;
8362 +
8363 +error_destroy_mc_io:
8364 + fsl_destroy_mc_io(mc_io);
8365 + return error;
8366 +}
8367 +
8368 +/**
8369 + * Destroys an MC I/O object
8370 + *
8371 + * @mc_io: MC I/O object to destroy
8372 + */
8373 +void fsl_destroy_mc_io(struct fsl_mc_io *mc_io)
8374 +{
8375 + struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
8376 +
8377 + if (dpmcp_dev)
8378 + fsl_mc_io_unset_dpmcp(mc_io);
8379 +
8380 + devm_iounmap(mc_io->dev, mc_io->portal_virt_addr);
8381 + devm_release_mem_region(mc_io->dev,
8382 + mc_io->portal_phys_addr,
8383 + mc_io->portal_size);
8384 +
8385 + mc_io->portal_virt_addr = NULL;
8386 + devm_kfree(mc_io->dev, mc_io);
8387 +}
8388 +
8389 +/**
8390 + * fsl_mc_portal_allocate - Allocates an MC portal
8391 + *
8392 + * @mc_dev: MC device for which the MC portal is to be allocated
8393 + * @mc_io_flags: Flags for the fsl_mc_io object that wraps the allocated
8394 + * MC portal.
8395 + * @new_mc_io: Pointer to area where the pointer to the fsl_mc_io object
8396 + * that wraps the allocated MC portal is to be returned
8397 + *
8398 + * This function allocates an MC portal from the device's parent DPRC,
8399 + * from the corresponding MC bus' pool of MC portals and wraps
8400 + * it in a new fsl_mc_io object. If 'mc_dev' is a DPRC itself, the
8401 + * portal is allocated from its own MC bus.
8402 + */
8403 +int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
8404 + u16 mc_io_flags,
8405 + struct fsl_mc_io **new_mc_io)
8406 +{
8407 + struct fsl_mc_device *mc_bus_dev;
8408 + struct fsl_mc_bus *mc_bus;
8409 + phys_addr_t mc_portal_phys_addr;
8410 + size_t mc_portal_size;
8411 + struct fsl_mc_device *dpmcp_dev;
8412 + int error = -EINVAL;
8413 + struct fsl_mc_resource *resource = NULL;
8414 + struct fsl_mc_io *mc_io = NULL;
8415 +
8416 + if (mc_dev->flags & FSL_MC_IS_DPRC) {
8417 + mc_bus_dev = mc_dev;
8418 + } else {
8419 + if (!dev_is_fsl_mc(mc_dev->dev.parent))
8420 + return error;
8421 +
8422 + mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
8423 + }
8424 +
8425 + mc_bus = to_fsl_mc_bus(mc_bus_dev);
8426 + *new_mc_io = NULL;
8427 + error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_DPMCP, &resource);
8428 + if (error < 0)
8429 + return error;
8430 +
8431 + error = -EINVAL;
8432 + dpmcp_dev = resource->data;
8433 +
8434 + if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR ||
8435 + (dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR &&
8436 + dpmcp_dev->obj_desc.ver_minor < DPMCP_MIN_VER_MINOR)) {
8437 + dev_err(&dpmcp_dev->dev,
8438 + "ERROR: Version %d.%d of DPMCP not supported.\n",
8439 + dpmcp_dev->obj_desc.ver_major,
8440 + dpmcp_dev->obj_desc.ver_minor);
8441 + error = -ENOTSUPP;
8442 + goto error_cleanup_resource;
8443 + }
8444 +
8445 + mc_portal_phys_addr = dpmcp_dev->regions[0].start;
8446 + mc_portal_size = resource_size(dpmcp_dev->regions);
8447 +
8448 + error = fsl_create_mc_io(&mc_bus_dev->dev,
8449 + mc_portal_phys_addr,
8450 + mc_portal_size, dpmcp_dev,
8451 + mc_io_flags, &mc_io);
8452 + if (error < 0)
8453 + goto error_cleanup_resource;
8454 +
8455 + *new_mc_io = mc_io;
8456 + return 0;
8457 +
8458 +error_cleanup_resource:
8459 + fsl_mc_resource_free(resource);
8460 + return error;
8461 +}
8462 +EXPORT_SYMBOL_GPL(fsl_mc_portal_allocate);
8463 +
8464 +/**
8465 + * fsl_mc_portal_free - Returns an MC portal to the pool of free MC portals
8466 + * of a given MC bus
8467 + *
8468 + * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free
8469 + */
8470 +void fsl_mc_portal_free(struct fsl_mc_io *mc_io)
8471 +{
8472 + struct fsl_mc_device *dpmcp_dev;
8473 + struct fsl_mc_resource *resource;
8474 +
8475 + /*
8476 + * Every mc_io obtained by calling fsl_mc_portal_allocate() is supposed
8477 + * to have a DPMCP object associated with.
8478 + */
8479 + dpmcp_dev = mc_io->dpmcp_dev;
8480 +
8481 + resource = dpmcp_dev->resource;
8482 + if (!resource || resource->type != FSL_MC_POOL_DPMCP)
8483 + return;
8484 +
8485 + if (resource->data != dpmcp_dev)
8486 + return;
8487 +
8488 + fsl_destroy_mc_io(mc_io);
8489 + fsl_mc_resource_free(resource);
8490 +}
8491 +EXPORT_SYMBOL_GPL(fsl_mc_portal_free);
8492 +
8493 +/**
8494 + * fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object
8495 + *
8496 + * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free
8497 + */
8498 +int fsl_mc_portal_reset(struct fsl_mc_io *mc_io)
8499 +{
8500 + int error;
8501 + struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
8502 +
8503 + error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle);
8504 + if (error < 0) {
8505 + dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error);
8506 + return error;
8507 + }
8508 +
8509 + return 0;
8510 +}
8511 +EXPORT_SYMBOL_GPL(fsl_mc_portal_reset);
8512 --- a/drivers/staging/fsl-mc/bus/mc-sys.c
8513 +++ /dev/null
8514 @@ -1,317 +0,0 @@
8515 -/* Copyright 2013-2014 Freescale Semiconductor Inc.
8516 - *
8517 - * I/O services to send MC commands to the MC hardware
8518 - *
8519 - * Redistribution and use in source and binary forms, with or without
8520 - * modification, are permitted provided that the following conditions are met:
8521 - * * Redistributions of source code must retain the above copyright
8522 - * notice, this list of conditions and the following disclaimer.
8523 - * * Redistributions in binary form must reproduce the above copyright
8524 - * notice, this list of conditions and the following disclaimer in the
8525 - * documentation and/or other materials provided with the distribution.
8526 - * * Neither the name of the above-listed copyright holders nor the
8527 - * names of any contributors may be used to endorse or promote products
8528 - * derived from this software without specific prior written permission.
8529 - *
8530 - *
8531 - * ALTERNATIVELY, this software may be distributed under the terms of the
8532 - * GNU General Public License ("GPL") as published by the Free Software
8533 - * Foundation, either version 2 of that License or (at your option) any
8534 - * later version.
8535 - *
8536 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
8537 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
8538 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
8539 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
8540 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
8541 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
8542 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
8543 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
8544 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
8545 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
8546 - * POSSIBILITY OF SUCH DAMAGE.
8547 - */
8548 -
8549 -#include <linux/delay.h>
8550 -#include <linux/slab.h>
8551 -#include <linux/ioport.h>
8552 -#include <linux/device.h>
8553 -#include <linux/io.h>
8554 -#include "../include/mc-sys.h"
8555 -#include "../include/mc-cmd.h"
8556 -#include "../include/mc.h"
8557 -
8558 -#include "dpmcp.h"
8559 -
8560 -/**
8561 - * Timeout in milliseconds to wait for the completion of an MC command
8562 - */
8563 -#define MC_CMD_COMPLETION_TIMEOUT_MS 500
8564 -
8565 -/*
8566 - * usleep_range() min and max values used to throttle down polling
8567 - * iterations while waiting for MC command completion
8568 - */
8569 -#define MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS 10
8570 -#define MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS 500
8571 -
8572 -static enum mc_cmd_status mc_cmd_hdr_read_status(struct mc_command *cmd)
8573 -{
8574 - struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
8575 -
8576 - return (enum mc_cmd_status)hdr->status;
8577 -}
8578 -
8579 -static u16 mc_cmd_hdr_read_cmdid(struct mc_command *cmd)
8580 -{
8581 - struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
8582 - u16 cmd_id = le16_to_cpu(hdr->cmd_id);
8583 -
8584 - return (cmd_id & MC_CMD_HDR_CMDID_MASK) >> MC_CMD_HDR_CMDID_SHIFT;
8585 -}
8586 -
8587 -static int mc_status_to_error(enum mc_cmd_status status)
8588 -{
8589 - static const int mc_status_to_error_map[] = {
8590 - [MC_CMD_STATUS_OK] = 0,
8591 - [MC_CMD_STATUS_AUTH_ERR] = -EACCES,
8592 - [MC_CMD_STATUS_NO_PRIVILEGE] = -EPERM,
8593 - [MC_CMD_STATUS_DMA_ERR] = -EIO,
8594 - [MC_CMD_STATUS_CONFIG_ERR] = -ENXIO,
8595 - [MC_CMD_STATUS_TIMEOUT] = -ETIMEDOUT,
8596 - [MC_CMD_STATUS_NO_RESOURCE] = -ENAVAIL,
8597 - [MC_CMD_STATUS_NO_MEMORY] = -ENOMEM,
8598 - [MC_CMD_STATUS_BUSY] = -EBUSY,
8599 - [MC_CMD_STATUS_UNSUPPORTED_OP] = -ENOTSUPP,
8600 - [MC_CMD_STATUS_INVALID_STATE] = -ENODEV,
8601 - };
8602 -
8603 - if (WARN_ON((u32)status >= ARRAY_SIZE(mc_status_to_error_map)))
8604 - return -EINVAL;
8605 -
8606 - return mc_status_to_error_map[status];
8607 -}
8608 -
8609 -static const char *mc_status_to_string(enum mc_cmd_status status)
8610 -{
8611 - static const char *const status_strings[] = {
8612 - [MC_CMD_STATUS_OK] = "Command completed successfully",
8613 - [MC_CMD_STATUS_READY] = "Command ready to be processed",
8614 - [MC_CMD_STATUS_AUTH_ERR] = "Authentication error",
8615 - [MC_CMD_STATUS_NO_PRIVILEGE] = "No privilege",
8616 - [MC_CMD_STATUS_DMA_ERR] = "DMA or I/O error",
8617 - [MC_CMD_STATUS_CONFIG_ERR] = "Configuration error",
8618 - [MC_CMD_STATUS_TIMEOUT] = "Operation timed out",
8619 - [MC_CMD_STATUS_NO_RESOURCE] = "No resources",
8620 - [MC_CMD_STATUS_NO_MEMORY] = "No memory available",
8621 - [MC_CMD_STATUS_BUSY] = "Device is busy",
8622 - [MC_CMD_STATUS_UNSUPPORTED_OP] = "Unsupported operation",
8623 - [MC_CMD_STATUS_INVALID_STATE] = "Invalid state"
8624 - };
8625 -
8626 - if ((unsigned int)status >= ARRAY_SIZE(status_strings))
8627 - return "Unknown MC error";
8628 -
8629 - return status_strings[status];
8630 -}
8631 -
8632 -/**
8633 - * mc_write_command - writes a command to a Management Complex (MC) portal
8634 - *
8635 - * @portal: pointer to an MC portal
8636 - * @cmd: pointer to a filled command
8637 - */
8638 -static inline void mc_write_command(struct mc_command __iomem *portal,
8639 - struct mc_command *cmd)
8640 -{
8641 - int i;
8642 -
8643 - /* copy command parameters into the portal */
8644 - for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++)
8645 - __raw_writeq(cmd->params[i], &portal->params[i]);
8646 - __iowmb();
8647 -
8648 - /* submit the command by writing the header */
8649 - __raw_writeq(cmd->header, &portal->header);
8650 -}
8651 -
8652 -/**
8653 - * mc_read_response - reads the response for the last MC command from a
8654 - * Management Complex (MC) portal
8655 - *
8656 - * @portal: pointer to an MC portal
8657 - * @resp: pointer to command response buffer
8658 - *
8659 - * Returns MC_CMD_STATUS_OK on Success; Error code otherwise.
8660 - */
8661 -static inline enum mc_cmd_status mc_read_response(struct mc_command __iomem *
8662 - portal,
8663 - struct mc_command *resp)
8664 -{
8665 - int i;
8666 - enum mc_cmd_status status;
8667 -
8668 - /* Copy command response header from MC portal: */
8669 - __iormb();
8670 - resp->header = __raw_readq(&portal->header);
8671 - __iormb();
8672 - status = mc_cmd_hdr_read_status(resp);
8673 - if (status != MC_CMD_STATUS_OK)
8674 - return status;
8675 -
8676 - /* Copy command response data from MC portal: */
8677 - for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++)
8678 - resp->params[i] = __raw_readq(&portal->params[i]);
8679 - __iormb();
8680 -
8681 - return status;
8682 -}
8683 -
8684 -/**
8685 - * Waits for the completion of an MC command doing preemptible polling.
8686 - * uslepp_range() is called between polling iterations.
8687 - *
8688 - * @mc_io: MC I/O object to be used
8689 - * @cmd: command buffer to receive MC response
8690 - * @mc_status: MC command completion status
8691 - */
8692 -static int mc_polling_wait_preemptible(struct fsl_mc_io *mc_io,
8693 - struct mc_command *cmd,
8694 - enum mc_cmd_status *mc_status)
8695 -{
8696 - enum mc_cmd_status status;
8697 - unsigned long jiffies_until_timeout =
8698 - jiffies + msecs_to_jiffies(MC_CMD_COMPLETION_TIMEOUT_MS);
8699 -
8700 - /*
8701 - * Wait for response from the MC hardware:
8702 - */
8703 - for (;;) {
8704 - status = mc_read_response(mc_io->portal_virt_addr, cmd);
8705 - if (status != MC_CMD_STATUS_READY)
8706 - break;
8707 -
8708 - /*
8709 - * TODO: When MC command completion interrupts are supported
8710 - * call wait function here instead of usleep_range()
8711 - */
8712 - usleep_range(MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS,
8713 - MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
8714 -
8715 - if (time_after_eq(jiffies, jiffies_until_timeout)) {
8716 - dev_dbg(mc_io->dev,
8717 - "MC command timed out (portal: %#llx, obj handle: %#x, command: %#x)\n",
8718 - mc_io->portal_phys_addr,
8719 - (unsigned int)mc_cmd_hdr_read_token(cmd),
8720 - (unsigned int)mc_cmd_hdr_read_cmdid(cmd));
8721 -
8722 - return -ETIMEDOUT;
8723 - }
8724 - }
8725 -
8726 - *mc_status = status;
8727 - return 0;
8728 -}
8729 -
8730 -/**
8731 - * Waits for the completion of an MC command doing atomic polling.
8732 - * udelay() is called between polling iterations.
8733 - *
8734 - * @mc_io: MC I/O object to be used
8735 - * @cmd: command buffer to receive MC response
8736 - * @mc_status: MC command completion status
8737 - */
8738 -static int mc_polling_wait_atomic(struct fsl_mc_io *mc_io,
8739 - struct mc_command *cmd,
8740 - enum mc_cmd_status *mc_status)
8741 -{
8742 - enum mc_cmd_status status;
8743 - unsigned long timeout_usecs = MC_CMD_COMPLETION_TIMEOUT_MS * 1000;
8744 -
8745 - BUILD_BUG_ON((MC_CMD_COMPLETION_TIMEOUT_MS * 1000) %
8746 - MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS != 0);
8747 -
8748 - for (;;) {
8749 - status = mc_read_response(mc_io->portal_virt_addr, cmd);
8750 - if (status != MC_CMD_STATUS_READY)
8751 - break;
8752 -
8753 - udelay(MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
8754 - timeout_usecs -= MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS;
8755 - if (timeout_usecs == 0) {
8756 - dev_dbg(mc_io->dev,
8757 - "MC command timed out (portal: %#llx, obj handle: %#x, command: %#x)\n",
8758 - mc_io->portal_phys_addr,
8759 - (unsigned int)mc_cmd_hdr_read_token(cmd),
8760 - (unsigned int)mc_cmd_hdr_read_cmdid(cmd));
8761 -
8762 - return -ETIMEDOUT;
8763 - }
8764 - }
8765 -
8766 - *mc_status = status;
8767 - return 0;
8768 -}
8769 -
8770 -/**
8771 - * Sends a command to the MC device using the given MC I/O object
8772 - *
8773 - * @mc_io: MC I/O object to be used
8774 - * @cmd: command to be sent
8775 - *
8776 - * Returns '0' on Success; Error code otherwise.
8777 - */
8778 -int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd)
8779 -{
8780 - int error;
8781 - enum mc_cmd_status status;
8782 - unsigned long irq_flags = 0;
8783 -
8784 - if (WARN_ON(in_irq() &&
8785 - !(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)))
8786 - return -EINVAL;
8787 -
8788 - if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
8789 - spin_lock_irqsave(&mc_io->spinlock, irq_flags);
8790 - else
8791 - mutex_lock(&mc_io->mutex);
8792 -
8793 - /*
8794 - * Send command to the MC hardware:
8795 - */
8796 - mc_write_command(mc_io->portal_virt_addr, cmd);
8797 -
8798 - /*
8799 - * Wait for response from the MC hardware:
8800 - */
8801 - if (!(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL))
8802 - error = mc_polling_wait_preemptible(mc_io, cmd, &status);
8803 - else
8804 - error = mc_polling_wait_atomic(mc_io, cmd, &status);
8805 -
8806 - if (error < 0)
8807 - goto common_exit;
8808 -
8809 - if (status != MC_CMD_STATUS_OK) {
8810 - dev_dbg(mc_io->dev,
8811 - "MC command failed: portal: %#llx, obj handle: %#x, command: %#x, status: %s (%#x)\n",
8812 - mc_io->portal_phys_addr,
8813 - (unsigned int)mc_cmd_hdr_read_token(cmd),
8814 - (unsigned int)mc_cmd_hdr_read_cmdid(cmd),
8815 - mc_status_to_string(status),
8816 - (unsigned int)status);
8817 -
8818 - error = mc_status_to_error(status);
8819 - goto common_exit;
8820 - }
8821 -
8822 - error = 0;
8823 -common_exit:
8824 - if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
8825 - spin_unlock_irqrestore(&mc_io->spinlock, irq_flags);
8826 - else
8827 - mutex_unlock(&mc_io->mutex);
8828 -
8829 - return error;
8830 -}
8831 -EXPORT_SYMBOL(mc_send_command);
8832 --- /dev/null
8833 +++ b/drivers/bus/fsl-mc/mc-sys.c
8834 @@ -0,0 +1,296 @@
8835 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
8836 +/*
8837 + * Copyright 2013-2016 Freescale Semiconductor Inc.
8838 + *
8839 + * I/O services to send MC commands to the MC hardware
8840 + *
8841 + */
8842 +
8843 +#include <linux/delay.h>
8844 +#include <linux/slab.h>
8845 +#include <linux/ioport.h>
8846 +#include <linux/device.h>
8847 +#include <linux/io.h>
8848 +#include <linux/io-64-nonatomic-hi-lo.h>
8849 +#include <linux/fsl/mc.h>
8850 +
8851 +#include "fsl-mc-private.h"
8852 +
8853 +/**
8854 + * Timeout in milliseconds to wait for the completion of an MC command
8855 + */
8856 +#define MC_CMD_COMPLETION_TIMEOUT_MS 15000
8857 +
8858 +/*
8859 + * usleep_range() min and max values used to throttle down polling
8860 + * iterations while waiting for MC command completion
8861 + */
8862 +#define MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS 10
8863 +#define MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS 500
8864 +
8865 +static enum mc_cmd_status mc_cmd_hdr_read_status(struct fsl_mc_command *cmd)
8866 +{
8867 + struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
8868 +
8869 + return (enum mc_cmd_status)hdr->status;
8870 +}
8871 +
8872 +static u16 mc_cmd_hdr_read_cmdid(struct fsl_mc_command *cmd)
8873 +{
8874 + struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
8875 + u16 cmd_id = le16_to_cpu(hdr->cmd_id);
8876 +
8877 + return cmd_id;
8878 +}
8879 +
8880 +static int mc_status_to_error(enum mc_cmd_status status)
8881 +{
8882 + static const int mc_status_to_error_map[] = {
8883 + [MC_CMD_STATUS_OK] = 0,
8884 + [MC_CMD_STATUS_AUTH_ERR] = -EACCES,
8885 + [MC_CMD_STATUS_NO_PRIVILEGE] = -EPERM,
8886 + [MC_CMD_STATUS_DMA_ERR] = -EIO,
8887 + [MC_CMD_STATUS_CONFIG_ERR] = -ENXIO,
8888 + [MC_CMD_STATUS_TIMEOUT] = -ETIMEDOUT,
8889 + [MC_CMD_STATUS_NO_RESOURCE] = -ENAVAIL,
8890 + [MC_CMD_STATUS_NO_MEMORY] = -ENOMEM,
8891 + [MC_CMD_STATUS_BUSY] = -EBUSY,
8892 + [MC_CMD_STATUS_UNSUPPORTED_OP] = -ENOTSUPP,
8893 + [MC_CMD_STATUS_INVALID_STATE] = -ENODEV,
8894 + };
8895 +
8896 + if ((u32)status >= ARRAY_SIZE(mc_status_to_error_map))
8897 + return -EINVAL;
8898 +
8899 + return mc_status_to_error_map[status];
8900 +}
8901 +
8902 +static const char *mc_status_to_string(enum mc_cmd_status status)
8903 +{
8904 + static const char *const status_strings[] = {
8905 + [MC_CMD_STATUS_OK] = "Command completed successfully",
8906 + [MC_CMD_STATUS_READY] = "Command ready to be processed",
8907 + [MC_CMD_STATUS_AUTH_ERR] = "Authentication error",
8908 + [MC_CMD_STATUS_NO_PRIVILEGE] = "No privilege",
8909 + [MC_CMD_STATUS_DMA_ERR] = "DMA or I/O error",
8910 + [MC_CMD_STATUS_CONFIG_ERR] = "Configuration error",
8911 + [MC_CMD_STATUS_TIMEOUT] = "Operation timed out",
8912 + [MC_CMD_STATUS_NO_RESOURCE] = "No resources",
8913 + [MC_CMD_STATUS_NO_MEMORY] = "No memory available",
8914 + [MC_CMD_STATUS_BUSY] = "Device is busy",
8915 + [MC_CMD_STATUS_UNSUPPORTED_OP] = "Unsupported operation",
8916 + [MC_CMD_STATUS_INVALID_STATE] = "Invalid state"
8917 + };
8918 +
8919 + if ((unsigned int)status >= ARRAY_SIZE(status_strings))
8920 + return "Unknown MC error";
8921 +
8922 + return status_strings[status];
8923 +}
8924 +
8925 +/**
8926 + * mc_write_command - writes a command to a Management Complex (MC) portal
8927 + *
8928 + * @portal: pointer to an MC portal
8929 + * @cmd: pointer to a filled command
8930 + */
8931 +static inline void mc_write_command(struct fsl_mc_command __iomem *portal,
8932 + struct fsl_mc_command *cmd)
8933 +{
8934 + int i;
8935 +
8936 + /* copy command parameters into the portal */
8937 + for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++)
8938 + /*
8939 + * Data is already in the expected LE byte-order. Do an
8940 + * extra LE -> CPU conversion so that the CPU -> LE done in
8941 + * the device io write api puts it back in the right order.
8942 + */
8943 + writeq_relaxed(le64_to_cpu(cmd->params[i]), &portal->params[i]);
8944 +
8945 + /* submit the command by writing the header */
8946 + writeq(le64_to_cpu(cmd->header), &portal->header);
8947 +}
8948 +
8949 +/**
8950 + * mc_read_response - reads the response for the last MC command from a
8951 + * Management Complex (MC) portal
8952 + *
8953 + * @portal: pointer to an MC portal
8954 + * @resp: pointer to command response buffer
8955 + *
8956 + * Returns MC_CMD_STATUS_OK on Success; Error code otherwise.
8957 + */
8958 +static inline enum mc_cmd_status mc_read_response(struct fsl_mc_command __iomem
8959 + *portal,
8960 + struct fsl_mc_command *resp)
8961 +{
8962 + int i;
8963 + enum mc_cmd_status status;
8964 +
8965 + /* Copy command response header from MC portal: */
8966 + resp->header = cpu_to_le64(readq_relaxed(&portal->header));
8967 + status = mc_cmd_hdr_read_status(resp);
8968 + if (status != MC_CMD_STATUS_OK)
8969 + return status;
8970 +
8971 + /* Copy command response data from MC portal: */
8972 + for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++)
8973 + /*
8974 + * Data is expected to be in LE byte-order. Do an
8975 + * extra CPU -> LE to revert the LE -> CPU done in
8976 + * the device io read api.
8977 + */
8978 + resp->params[i] =
8979 + cpu_to_le64(readq_relaxed(&portal->params[i]));
8980 +
8981 + return status;
8982 +}
8983 +
8984 +/**
8985 + * Waits for the completion of an MC command doing preemptible polling.
8986 + * uslepp_range() is called between polling iterations.
8987 + *
8988 + * @mc_io: MC I/O object to be used
8989 + * @cmd: command buffer to receive MC response
8990 + * @mc_status: MC command completion status
8991 + */
8992 +static int mc_polling_wait_preemptible(struct fsl_mc_io *mc_io,
8993 + struct fsl_mc_command *cmd,
8994 + enum mc_cmd_status *mc_status)
8995 +{
8996 + enum mc_cmd_status status;
8997 + unsigned long jiffies_until_timeout =
8998 + jiffies + msecs_to_jiffies(MC_CMD_COMPLETION_TIMEOUT_MS);
8999 +
9000 + /*
9001 + * Wait for response from the MC hardware:
9002 + */
9003 + for (;;) {
9004 + status = mc_read_response(mc_io->portal_virt_addr, cmd);
9005 + if (status != MC_CMD_STATUS_READY)
9006 + break;
9007 +
9008 + /*
9009 + * TODO: When MC command completion interrupts are supported
9010 + * call wait function here instead of usleep_range()
9011 + */
9012 + usleep_range(MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS,
9013 + MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
9014 +
9015 + if (time_after_eq(jiffies, jiffies_until_timeout)) {
9016 + dev_dbg(mc_io->dev,
9017 + "MC command timed out (portal: %pa, dprc handle: %#x, command: %#x)\n",
9018 + &mc_io->portal_phys_addr,
9019 + (unsigned int)mc_cmd_hdr_read_token(cmd),
9020 + (unsigned int)mc_cmd_hdr_read_cmdid(cmd));
9021 +
9022 + return -ETIMEDOUT;
9023 + }
9024 + }
9025 +
9026 + *mc_status = status;
9027 + return 0;
9028 +}
9029 +
9030 +/**
9031 + * Waits for the completion of an MC command doing atomic polling.
9032 + * udelay() is called between polling iterations.
9033 + *
9034 + * @mc_io: MC I/O object to be used
9035 + * @cmd: command buffer to receive MC response
9036 + * @mc_status: MC command completion status
9037 + */
9038 +static int mc_polling_wait_atomic(struct fsl_mc_io *mc_io,
9039 + struct fsl_mc_command *cmd,
9040 + enum mc_cmd_status *mc_status)
9041 +{
9042 + enum mc_cmd_status status;
9043 + unsigned long timeout_usecs = MC_CMD_COMPLETION_TIMEOUT_MS * 1000;
9044 +
9045 + BUILD_BUG_ON((MC_CMD_COMPLETION_TIMEOUT_MS * 1000) %
9046 + MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS != 0);
9047 +
9048 + for (;;) {
9049 + status = mc_read_response(mc_io->portal_virt_addr, cmd);
9050 + if (status != MC_CMD_STATUS_READY)
9051 + break;
9052 +
9053 + udelay(MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
9054 + timeout_usecs -= MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS;
9055 + if (timeout_usecs == 0) {
9056 + dev_dbg(mc_io->dev,
9057 + "MC command timed out (portal: %pa, dprc handle: %#x, command: %#x)\n",
9058 + &mc_io->portal_phys_addr,
9059 + (unsigned int)mc_cmd_hdr_read_token(cmd),
9060 + (unsigned int)mc_cmd_hdr_read_cmdid(cmd));
9061 +
9062 + return -ETIMEDOUT;
9063 + }
9064 + }
9065 +
9066 + *mc_status = status;
9067 + return 0;
9068 +}
9069 +
9070 +/**
9071 + * Sends a command to the MC device using the given MC I/O object
9072 + *
9073 + * @mc_io: MC I/O object to be used
9074 + * @cmd: command to be sent
9075 + *
9076 + * Returns '0' on Success; Error code otherwise.
9077 + */
9078 +int mc_send_command(struct fsl_mc_io *mc_io, struct fsl_mc_command *cmd)
9079 +{
9080 + int error;
9081 + enum mc_cmd_status status;
9082 + unsigned long irq_flags = 0;
9083 +
9084 + if (in_irq() && !(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL))
9085 + return -EINVAL;
9086 +
9087 + if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
9088 + spin_lock_irqsave(&mc_io->spinlock, irq_flags);
9089 + else
9090 + mutex_lock(&mc_io->mutex);
9091 +
9092 + /*
9093 + * Send command to the MC hardware:
9094 + */
9095 + mc_write_command(mc_io->portal_virt_addr, cmd);
9096 +
9097 + /*
9098 + * Wait for response from the MC hardware:
9099 + */
9100 + if (!(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL))
9101 + error = mc_polling_wait_preemptible(mc_io, cmd, &status);
9102 + else
9103 + error = mc_polling_wait_atomic(mc_io, cmd, &status);
9104 +
9105 + if (error < 0)
9106 + goto common_exit;
9107 +
9108 + if (status != MC_CMD_STATUS_OK) {
9109 + dev_dbg(mc_io->dev,
9110 + "MC command failed: portal: %pa, dprc handle: %#x, command: %#x, status: %s (%#x)\n",
9111 + &mc_io->portal_phys_addr,
9112 + (unsigned int)mc_cmd_hdr_read_token(cmd),
9113 + (unsigned int)mc_cmd_hdr_read_cmdid(cmd),
9114 + mc_status_to_string(status),
9115 + (unsigned int)status);
9116 +
9117 + error = mc_status_to_error(status);
9118 + goto common_exit;
9119 + }
9120 +
9121 + error = 0;
9122 +common_exit:
9123 + if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
9124 + spin_unlock_irqrestore(&mc_io->spinlock, irq_flags);
9125 + else
9126 + mutex_unlock(&mc_io->mutex);
9127 +
9128 + return error;
9129 +}
9130 +EXPORT_SYMBOL_GPL(mc_send_command);
9131 --- a/drivers/irqchip/Kconfig
9132 +++ b/drivers/irqchip/Kconfig
9133 @@ -41,6 +41,12 @@ config ARM_GIC_V3_ITS
9134 depends on PCI_MSI
9135 select ACPI_IORT if ACPI
9136
9137 +config ARM_GIC_V3_ITS_FSL_MC
9138 + bool
9139 + depends on ARM_GIC_V3_ITS
9140 + depends on FSL_MC_BUS
9141 + default ARM_GIC_V3_ITS
9142 +
9143 config ARM_NVIC
9144 bool
9145 select IRQ_DOMAIN
9146 --- a/drivers/irqchip/Makefile
9147 +++ b/drivers/irqchip/Makefile
9148 @@ -29,6 +29,7 @@ obj-$(CONFIG_ARCH_REALVIEW) += irq-gic-
9149 obj-$(CONFIG_ARM_GIC_V2M) += irq-gic-v2m.o
9150 obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-common.o
9151 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
9152 +obj-$(CONFIG_ARM_GIC_V3_ITS_FSL_MC) += irq-gic-v3-its-fsl-mc-msi.o
9153 obj-$(CONFIG_PARTITION_PERCPU) += irq-partition-percpu.o
9154 obj-$(CONFIG_HISILICON_IRQ_MBIGEN) += irq-mbigen.o
9155 obj-$(CONFIG_ARM_NVIC) += irq-nvic.o
9156 --- a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c
9157 +++ /dev/null
9158 @@ -1,126 +0,0 @@
9159 -/*
9160 - * Freescale Management Complex (MC) bus driver MSI support
9161 - *
9162 - * Copyright (C) 2015 Freescale Semiconductor, Inc.
9163 - * Author: German Rivera <German.Rivera@freescale.com>
9164 - *
9165 - * This file is licensed under the terms of the GNU General Public
9166 - * License version 2. This program is licensed "as is" without any
9167 - * warranty of any kind, whether express or implied.
9168 - */
9169 -
9170 -#include <linux/of_device.h>
9171 -#include <linux/of_address.h>
9172 -#include <linux/irqchip/arm-gic-v3.h>
9173 -#include <linux/irq.h>
9174 -#include <linux/msi.h>
9175 -#include <linux/of.h>
9176 -#include <linux/of_irq.h>
9177 -#include "../include/mc-bus.h"
9178 -#include "fsl-mc-private.h"
9179 -
9180 -static struct irq_chip its_msi_irq_chip = {
9181 - .name = "fsl-mc-bus-msi",
9182 - .irq_mask = irq_chip_mask_parent,
9183 - .irq_unmask = irq_chip_unmask_parent,
9184 - .irq_eoi = irq_chip_eoi_parent,
9185 - .irq_set_affinity = msi_domain_set_affinity
9186 -};
9187 -
9188 -static int its_fsl_mc_msi_prepare(struct irq_domain *msi_domain,
9189 - struct device *dev,
9190 - int nvec, msi_alloc_info_t *info)
9191 -{
9192 - struct fsl_mc_device *mc_bus_dev;
9193 - struct msi_domain_info *msi_info;
9194 -
9195 - if (WARN_ON(!dev_is_fsl_mc(dev)))
9196 - return -EINVAL;
9197 -
9198 - mc_bus_dev = to_fsl_mc_device(dev);
9199 - if (WARN_ON(!(mc_bus_dev->flags & FSL_MC_IS_DPRC)))
9200 - return -EINVAL;
9201 -
9202 - /*
9203 - * Set the device Id to be passed to the GIC-ITS:
9204 - *
9205 - * NOTE: This device id corresponds to the IOMMU stream ID
9206 - * associated with the DPRC object (ICID).
9207 - */
9208 - info->scratchpad[0].ul = mc_bus_dev->icid;
9209 - msi_info = msi_get_domain_info(msi_domain->parent);
9210 - return msi_info->ops->msi_prepare(msi_domain->parent, dev, nvec, info);
9211 -}
9212 -
9213 -static struct msi_domain_ops its_fsl_mc_msi_ops = {
9214 - .msi_prepare = its_fsl_mc_msi_prepare,
9215 -};
9216 -
9217 -static struct msi_domain_info its_fsl_mc_msi_domain_info = {
9218 - .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS),
9219 - .ops = &its_fsl_mc_msi_ops,
9220 - .chip = &its_msi_irq_chip,
9221 -};
9222 -
9223 -static const struct of_device_id its_device_id[] = {
9224 - { .compatible = "arm,gic-v3-its", },
9225 - {},
9226 -};
9227 -
9228 -int __init its_fsl_mc_msi_init(void)
9229 -{
9230 - struct device_node *np;
9231 - struct irq_domain *parent;
9232 - struct irq_domain *mc_msi_domain;
9233 -
9234 - for (np = of_find_matching_node(NULL, its_device_id); np;
9235 - np = of_find_matching_node(np, its_device_id)) {
9236 - if (!of_device_is_available(np))
9237 - continue;
9238 - if (!of_property_read_bool(np, "msi-controller"))
9239 - continue;
9240 -
9241 - parent = irq_find_matching_host(np, DOMAIN_BUS_NEXUS);
9242 - if (!parent || !msi_get_domain_info(parent)) {
9243 - pr_err("%s: unable to locate ITS domain\n",
9244 - np->full_name);
9245 - continue;
9246 - }
9247 -
9248 - mc_msi_domain = fsl_mc_msi_create_irq_domain(
9249 - of_node_to_fwnode(np),
9250 - &its_fsl_mc_msi_domain_info,
9251 - parent);
9252 - if (!mc_msi_domain) {
9253 - pr_err("%s: unable to create fsl-mc domain\n",
9254 - np->full_name);
9255 - continue;
9256 - }
9257 -
9258 - WARN_ON(mc_msi_domain->
9259 - host_data != &its_fsl_mc_msi_domain_info);
9260 -
9261 - pr_info("fsl-mc MSI: %s domain created\n", np->full_name);
9262 - }
9263 -
9264 - return 0;
9265 -}
9266 -
9267 -void its_fsl_mc_msi_cleanup(void)
9268 -{
9269 - struct device_node *np;
9270 -
9271 - for (np = of_find_matching_node(NULL, its_device_id); np;
9272 - np = of_find_matching_node(np, its_device_id)) {
9273 - struct irq_domain *mc_msi_domain = irq_find_matching_host(
9274 - np,
9275 - DOMAIN_BUS_FSL_MC_MSI);
9276 -
9277 - if (!of_property_read_bool(np, "msi-controller"))
9278 - continue;
9279 -
9280 - if (mc_msi_domain &&
9281 - mc_msi_domain->host_data == &its_fsl_mc_msi_domain_info)
9282 - irq_domain_remove(mc_msi_domain);
9283 - }
9284 -}
9285 --- /dev/null
9286 +++ b/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c
9287 @@ -0,0 +1,98 @@
9288 +// SPDX-License-Identifier: GPL-2.0
9289 +/*
9290 + * Freescale Management Complex (MC) bus driver MSI support
9291 + *
9292 + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
9293 + * Author: German Rivera <German.Rivera@freescale.com>
9294 + *
9295 + */
9296 +
9297 +#include <linux/of_device.h>
9298 +#include <linux/of_address.h>
9299 +#include <linux/irq.h>
9300 +#include <linux/msi.h>
9301 +#include <linux/of.h>
9302 +#include <linux/of_irq.h>
9303 +#include <linux/fsl/mc.h>
9304 +
9305 +static struct irq_chip its_msi_irq_chip = {
9306 + .name = "ITS-fMSI",
9307 + .irq_mask = irq_chip_mask_parent,
9308 + .irq_unmask = irq_chip_unmask_parent,
9309 + .irq_eoi = irq_chip_eoi_parent,
9310 + .irq_set_affinity = msi_domain_set_affinity
9311 +};
9312 +
9313 +static int its_fsl_mc_msi_prepare(struct irq_domain *msi_domain,
9314 + struct device *dev,
9315 + int nvec, msi_alloc_info_t *info)
9316 +{
9317 + struct fsl_mc_device *mc_bus_dev;
9318 + struct msi_domain_info *msi_info;
9319 +
9320 + if (!dev_is_fsl_mc(dev))
9321 + return -EINVAL;
9322 +
9323 + mc_bus_dev = to_fsl_mc_device(dev);
9324 + if (!(mc_bus_dev->flags & FSL_MC_IS_DPRC))
9325 + return -EINVAL;
9326 +
9327 + /*
9328 + * Set the device Id to be passed to the GIC-ITS:
9329 + *
9330 + * NOTE: This device id corresponds to the IOMMU stream ID
9331 + * associated with the DPRC object (ICID).
9332 + */
9333 + info->scratchpad[0].ul = mc_bus_dev->icid;
9334 + msi_info = msi_get_domain_info(msi_domain->parent);
9335 + return msi_info->ops->msi_prepare(msi_domain->parent, dev, nvec, info);
9336 +}
9337 +
9338 +static struct msi_domain_ops its_fsl_mc_msi_ops __ro_after_init = {
9339 + .msi_prepare = its_fsl_mc_msi_prepare,
9340 +};
9341 +
9342 +static struct msi_domain_info its_fsl_mc_msi_domain_info = {
9343 + .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS),
9344 + .ops = &its_fsl_mc_msi_ops,
9345 + .chip = &its_msi_irq_chip,
9346 +};
9347 +
9348 +static const struct of_device_id its_device_id[] = {
9349 + { .compatible = "arm,gic-v3-its", },
9350 + {},
9351 +};
9352 +
9353 +static int __init its_fsl_mc_msi_init(void)
9354 +{
9355 + struct device_node *np;
9356 + struct irq_domain *parent;
9357 + struct irq_domain *mc_msi_domain;
9358 +
9359 + for (np = of_find_matching_node(NULL, its_device_id); np;
9360 + np = of_find_matching_node(np, its_device_id)) {
9361 + if (!of_property_read_bool(np, "msi-controller"))
9362 + continue;
9363 +
9364 + parent = irq_find_matching_host(np, DOMAIN_BUS_NEXUS);
9365 + if (!parent || !msi_get_domain_info(parent)) {
9366 + pr_err("%pOF: unable to locate ITS domain\n", np);
9367 + continue;
9368 + }
9369 +
9370 + mc_msi_domain = fsl_mc_msi_create_irq_domain(
9371 + of_node_to_fwnode(np),
9372 + &its_fsl_mc_msi_domain_info,
9373 + parent);
9374 + if (!mc_msi_domain) {
9375 + pr_err("%pOF: unable to create fsl-mc domain\n", np);
9376 + continue;
9377 + }
9378 +
9379 + pr_info("fsl-mc MSI: %pOF domain created\n", np);
9380 + }
9381 +
9382 + return 0;
9383 +}
9384 +
9385 +early_initcall(its_fsl_mc_msi_init);
9386 --- a/drivers/staging/fsl-mc/Kconfig
9387 +++ b/drivers/staging/fsl-mc/Kconfig
9388 @@ -1 +1,2 @@
9389 +# SPDX-License-Identifier: GPL-2.0
9390 source "drivers/staging/fsl-mc/bus/Kconfig"
9391 --- a/drivers/staging/fsl-mc/Makefile
9392 +++ b/drivers/staging/fsl-mc/Makefile
9393 @@ -1,2 +1,3 @@
9394 +# SPDX-License-Identifier: GPL-2.0
9395 # Freescale Management Complex (MC) bus drivers
9396 obj-$(CONFIG_FSL_MC_BUS) += bus/
9397 --- a/drivers/staging/fsl-mc/TODO
9398 +++ /dev/null
9399 @@ -1,18 +0,0 @@
9400 -* Add at least one device driver for a DPAA2 object (child device of the
9401 - fsl-mc bus). Most likely candidate for this is adding DPAA2 Ethernet
9402 - driver support, which depends on drivers for several objects: DPNI,
9403 - DPIO, DPMAC. Other pre-requisites include:
9404 -
9405 - * MC firmware uprev. The MC firmware upon which the fsl-mc
9406 - bus driver and DPAA2 object drivers are based is continuing
9407 - to evolve, so minor updates are needed to keep in sync with binary
9408 - interface changes to the MC.
9409 -
9410 -* Cleanup
9411 -
9412 -Please send any patches to Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
9413 -german.rivera@freescale.com, devel@driverdev.osuosl.org,
9414 -linux-kernel@vger.kernel.org
9415 -
9416 -[1] https://lkml.org/lkml/2015/7/9/93
9417 -[2] https://lkml.org/lkml/2015/7/7/712
9418 --- a/drivers/staging/fsl-mc/bus/Kconfig
9419 +++ b/drivers/staging/fsl-mc/bus/Kconfig
9420 @@ -1,25 +1,22 @@
9421 +# SPDX-License-Identifier: GPL-2.0
9422 #
9423 -# Freescale Management Complex (MC) bus drivers
9424 +# DPAA2 fsl-mc bus
9425 #
9426 -# Copyright (C) 2014 Freescale Semiconductor, Inc.
9427 +# Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
9428 #
9429 -# This file is released under the GPLv2
9430 -#
9431 -
9432 -config FSL_MC_BUS
9433 - bool "Freescale Management Complex (MC) bus driver"
9434 - depends on OF && ARM64
9435 - select GENERIC_MSI_IRQ_DOMAIN
9436 - help
9437 - Driver to enable the bus infrastructure for the Freescale
9438 - QorIQ Management Complex (fsl-mc). The fsl-mc is a hardware
9439 - module of the QorIQ LS2 SoCs, that does resource management
9440 - for hardware building-blocks in the SoC that can be used
9441 - to dynamically create networking hardware objects such as
9442 - network interfaces (NICs), crypto accelerator instances,
9443 - or L2 switches.
9444 -
9445 - Only enable this option when building the kernel for
9446 - Freescale QorQIQ LS2xxxx SoCs.
9447
9448 +config FSL_MC_DPIO
9449 + tristate "QorIQ DPAA2 DPIO driver"
9450 + depends on FSL_MC_BUS
9451 + help
9452 + Driver for the DPAA2 DPIO object. A DPIO provides queue and
9453 + buffer management facilities for software to interact with
9454 + other DPAA2 objects. This driver does not expose the DPIO
9455 + objects individually, but groups them under a service layer
9456 + API.
9457
9458 +config FSL_QBMAN_DEBUG
9459 + tristate "Freescale QBMAN Debug APIs"
9460 + depends on FSL_MC_DPIO
9461 + help
9462 + QBMan debug assistant APIs.
9463 --- a/drivers/staging/fsl-mc/bus/Makefile
9464 +++ b/drivers/staging/fsl-mc/bus/Makefile
9465 @@ -1,20 +1,9 @@
9466 +# SPDX-License-Identifier: GPL-2.0
9467 #
9468 # Freescale Management Complex (MC) bus drivers
9469 #
9470 # Copyright (C) 2014 Freescale Semiconductor, Inc.
9471 #
9472 -# This file is released under the GPLv2
9473 -#
9474 -obj-$(CONFIG_FSL_MC_BUS) += mc-bus-driver.o
9475
9476 -mc-bus-driver-objs := fsl-mc-bus.o \
9477 - mc-sys.o \
9478 - mc-io.o \
9479 - dprc.o \
9480 - dpmng.o \
9481 - dprc-driver.o \
9482 - fsl-mc-allocator.o \
9483 - fsl-mc-msi.o \
9484 - irq-gic-v3-its-fsl-mc-msi.o \
9485 - dpmcp.o \
9486 - dpbp.o
9487 +# MC DPIO driver
9488 +obj-$(CONFIG_FSL_MC_DPIO) += dpio/
9489 --- a/drivers/staging/fsl-mc/bus/dpbp.c
9490 +++ /dev/null
9491 @@ -1,691 +0,0 @@
9492 -/* Copyright 2013-2016 Freescale Semiconductor Inc.
9493 - *
9494 - * Redistribution and use in source and binary forms, with or without
9495 - * modification, are permitted provided that the following conditions are met:
9496 - * * Redistributions of source code must retain the above copyright
9497 - * notice, this list of conditions and the following disclaimer.
9498 - * * Redistributions in binary form must reproduce the above copyright
9499 - * notice, this list of conditions and the following disclaimer in the
9500 - * documentation and/or other materials provided with the distribution.
9501 - * * Neither the name of the above-listed copyright holders nor the
9502 - * names of any contributors may be used to endorse or promote products
9503 - * derived from this software without specific prior written permission.
9504 - *
9505 - *
9506 - * ALTERNATIVELY, this software may be distributed under the terms of the
9507 - * GNU General Public License ("GPL") as published by the Free Software
9508 - * Foundation, either version 2 of that License or (at your option) any
9509 - * later version.
9510 - *
9511 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9512 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9513 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9514 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
9515 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
9516 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
9517 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
9518 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
9519 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
9520 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
9521 - * POSSIBILITY OF SUCH DAMAGE.
9522 - */
9523 -#include "../include/mc-sys.h"
9524 -#include "../include/mc-cmd.h"
9525 -#include "../include/dpbp.h"
9526 -#include "../include/dpbp-cmd.h"
9527 -
9528 -/**
9529 - * dpbp_open() - Open a control session for the specified object.
9530 - * @mc_io: Pointer to MC portal's I/O object
9531 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
9532 - * @dpbp_id: DPBP unique ID
9533 - * @token: Returned token; use in subsequent API calls
9534 - *
9535 - * This function can be used to open a control session for an
9536 - * already created object; an object may have been declared in
9537 - * the DPL or by calling the dpbp_create function.
9538 - * This function returns a unique authentication token,
9539 - * associated with the specific object ID and the specific MC
9540 - * portal; this token must be used in all subsequent commands for
9541 - * this specific object
9542 - *
9543 - * Return: '0' on Success; Error code otherwise.
9544 - */
9545 -int dpbp_open(struct fsl_mc_io *mc_io,
9546 - u32 cmd_flags,
9547 - int dpbp_id,
9548 - u16 *token)
9549 -{
9550 - struct mc_command cmd = { 0 };
9551 - struct dpbp_cmd_open *cmd_params;
9552 - int err;
9553 -
9554 - /* prepare command */
9555 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_OPEN,
9556 - cmd_flags, 0);
9557 - cmd_params = (struct dpbp_cmd_open *)cmd.params;
9558 - cmd_params->dpbp_id = cpu_to_le32(dpbp_id);
9559 -
9560 - /* send command to mc*/
9561 - err = mc_send_command(mc_io, &cmd);
9562 - if (err)
9563 - return err;
9564 -
9565 - /* retrieve response parameters */
9566 - *token = mc_cmd_hdr_read_token(&cmd);
9567 -
9568 - return err;
9569 -}
9570 -EXPORT_SYMBOL(dpbp_open);
9571 -
9572 -/**
9573 - * dpbp_close() - Close the control session of the object
9574 - * @mc_io: Pointer to MC portal's I/O object
9575 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
9576 - * @token: Token of DPBP object
9577 - *
9578 - * After this function is called, no further operations are
9579 - * allowed on the object without opening a new control session.
9580 - *
9581 - * Return: '0' on Success; Error code otherwise.
9582 - */
9583 -int dpbp_close(struct fsl_mc_io *mc_io,
9584 - u32 cmd_flags,
9585 - u16 token)
9586 -{
9587 - struct mc_command cmd = { 0 };
9588 -
9589 - /* prepare command */
9590 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLOSE, cmd_flags,
9591 - token);
9592 -
9593 - /* send command to mc*/
9594 - return mc_send_command(mc_io, &cmd);
9595 -}
9596 -EXPORT_SYMBOL(dpbp_close);
9597 -
9598 -/**
9599 - * dpbp_create() - Create the DPBP object.
9600 - * @mc_io: Pointer to MC portal's I/O object
9601 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
9602 - * @cfg: Configuration structure
9603 - * @token: Returned token; use in subsequent API calls
9604 - *
9605 - * Create the DPBP object, allocate required resources and
9606 - * perform required initialization.
9607 - *
9608 - * The object can be created either by declaring it in the
9609 - * DPL file, or by calling this function.
9610 - * This function returns a unique authentication token,
9611 - * associated with the specific object ID and the specific MC
9612 - * portal; this token must be used in all subsequent calls to
9613 - * this specific object. For objects that are created using the
9614 - * DPL file, call dpbp_open function to get an authentication
9615 - * token first.
9616 - *
9617 - * Return: '0' on Success; Error code otherwise.
9618 - */
9619 -int dpbp_create(struct fsl_mc_io *mc_io,
9620 - u32 cmd_flags,
9621 - const struct dpbp_cfg *cfg,
9622 - u16 *token)
9623 -{
9624 - struct mc_command cmd = { 0 };
9625 - int err;
9626 -
9627 - (void)(cfg); /* unused */
9628 -
9629 - /* prepare command */
9630 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_CREATE,
9631 - cmd_flags, 0);
9632 -
9633 - /* send command to mc*/
9634 - err = mc_send_command(mc_io, &cmd);
9635 - if (err)
9636 - return err;
9637 -
9638 - /* retrieve response parameters */
9639 - *token = mc_cmd_hdr_read_token(&cmd);
9640 -
9641 - return 0;
9642 -}
9643 -
9644 -/**
9645 - * dpbp_destroy() - Destroy the DPBP object and release all its resources.
9646 - * @mc_io: Pointer to MC portal's I/O object
9647 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
9648 - * @token: Token of DPBP object
9649 - *
9650 - * Return: '0' on Success; error code otherwise.
9651 - */
9652 -int dpbp_destroy(struct fsl_mc_io *mc_io,
9653 - u32 cmd_flags,
9654 - u16 token)
9655 -{
9656 - struct mc_command cmd = { 0 };
9657 -
9658 - /* prepare command */
9659 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_DESTROY,
9660 - cmd_flags, token);
9661 -
9662 - /* send command to mc*/
9663 - return mc_send_command(mc_io, &cmd);
9664 -}
9665 -
9666 -/**
9667 - * dpbp_enable() - Enable the DPBP.
9668 - * @mc_io: Pointer to MC portal's I/O object
9669 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
9670 - * @token: Token of DPBP object
9671 - *
9672 - * Return: '0' on Success; Error code otherwise.
9673 - */
9674 -int dpbp_enable(struct fsl_mc_io *mc_io,
9675 - u32 cmd_flags,
9676 - u16 token)
9677 -{
9678 - struct mc_command cmd = { 0 };
9679 -
9680 - /* prepare command */
9681 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_ENABLE, cmd_flags,
9682 - token);
9683 -
9684 - /* send command to mc*/
9685 - return mc_send_command(mc_io, &cmd);
9686 -}
9687 -EXPORT_SYMBOL(dpbp_enable);
9688 -
9689 -/**
9690 - * dpbp_disable() - Disable the DPBP.
9691 - * @mc_io: Pointer to MC portal's I/O object
9692 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
9693 - * @token: Token of DPBP object
9694 - *
9695 - * Return: '0' on Success; Error code otherwise.
9696 - */
9697 -int dpbp_disable(struct fsl_mc_io *mc_io,
9698 - u32 cmd_flags,
9699 - u16 token)
9700 -{
9701 - struct mc_command cmd = { 0 };
9702 -
9703 - /* prepare command */
9704 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_DISABLE,
9705 - cmd_flags, token);
9706 -
9707 - /* send command to mc*/
9708 - return mc_send_command(mc_io, &cmd);
9709 -}
9710 -EXPORT_SYMBOL(dpbp_disable);
9711 -
9712 -/**
9713 - * dpbp_is_enabled() - Check if the DPBP is enabled.
9714 - * @mc_io: Pointer to MC portal's I/O object
9715 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
9716 - * @token: Token of DPBP object
9717 - * @en: Returns '1' if object is enabled; '0' otherwise
9718 - *
9719 - * Return: '0' on Success; Error code otherwise.
9720 - */
9721 -int dpbp_is_enabled(struct fsl_mc_io *mc_io,
9722 - u32 cmd_flags,
9723 - u16 token,
9724 - int *en)
9725 -{
9726 - struct mc_command cmd = { 0 };
9727 - struct dpbp_rsp_is_enabled *rsp_params;
9728 - int err;
9729 - /* prepare command */
9730 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_IS_ENABLED, cmd_flags,
9731 - token);
9732 -
9733 - /* send command to mc*/
9734 - err = mc_send_command(mc_io, &cmd);
9735 - if (err)
9736 - return err;
9737 -
9738 - /* retrieve response parameters */
9739 - rsp_params = (struct dpbp_rsp_is_enabled *)cmd.params;
9740 - *en = rsp_params->enabled & DPBP_ENABLE;
9741 -
9742 - return 0;
9743 -}
9744 -
9745 -/**
9746 - * dpbp_reset() - Reset the DPBP, returns the object to initial state.
9747 - * @mc_io: Pointer to MC portal's I/O object
9748 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
9749 - * @token: Token of DPBP object
9750 - *
9751 - * Return: '0' on Success; Error code otherwise.
9752 - */
9753 -int dpbp_reset(struct fsl_mc_io *mc_io,
9754 - u32 cmd_flags,
9755 - u16 token)
9756 -{
9757 - struct mc_command cmd = { 0 };
9758 -
9759 - /* prepare command */
9760 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_RESET,
9761 - cmd_flags, token);
9762 -
9763 - /* send command to mc*/
9764 - return mc_send_command(mc_io, &cmd);
9765 -}
9766 -
9767 -/**
9768 - * dpbp_set_irq() - Set IRQ information for the DPBP to trigger an interrupt.
9769 - * @mc_io: Pointer to MC portal's I/O object
9770 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
9771 - * @token: Token of DPBP object
9772 - * @irq_index: Identifies the interrupt index to configure
9773 - * @irq_cfg: IRQ configuration
9774 - *
9775 - * Return: '0' on Success; Error code otherwise.
9776 - */
9777 -int dpbp_set_irq(struct fsl_mc_io *mc_io,
9778 - u32 cmd_flags,
9779 - u16 token,
9780 - u8 irq_index,
9781 - struct dpbp_irq_cfg *irq_cfg)
9782 -{
9783 - struct mc_command cmd = { 0 };
9784 - struct dpbp_cmd_set_irq *cmd_params;
9785 -
9786 - /* prepare command */
9787 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_IRQ,
9788 - cmd_flags, token);
9789 - cmd_params = (struct dpbp_cmd_set_irq *)cmd.params;
9790 - cmd_params->irq_index = irq_index;
9791 - cmd_params->irq_val = cpu_to_le32(irq_cfg->val);
9792 - cmd_params->irq_addr = cpu_to_le64(irq_cfg->addr);
9793 - cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num);
9794 -
9795 - /* send command to mc*/
9796 - return mc_send_command(mc_io, &cmd);
9797 -}
9798 -
9799 -/**
9800 - * dpbp_get_irq() - Get IRQ information from the DPBP.
9801 - * @mc_io: Pointer to MC portal's I/O object
9802 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
9803 - * @token: Token of DPBP object
9804 - * @irq_index: The interrupt index to configure
9805 - * @type: Interrupt type: 0 represents message interrupt
9806 - * type (both irq_addr and irq_val are valid)
9807 - * @irq_cfg: IRQ attributes
9808 - *
9809 - * Return: '0' on Success; Error code otherwise.
9810 - */
9811 -int dpbp_get_irq(struct fsl_mc_io *mc_io,
9812 - u32 cmd_flags,
9813 - u16 token,
9814 - u8 irq_index,
9815 - int *type,
9816 - struct dpbp_irq_cfg *irq_cfg)
9817 -{
9818 - struct mc_command cmd = { 0 };
9819 - struct dpbp_cmd_get_irq *cmd_params;
9820 - struct dpbp_rsp_get_irq *rsp_params;
9821 - int err;
9822 -
9823 - /* prepare command */
9824 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ,
9825 - cmd_flags, token);
9826 - cmd_params = (struct dpbp_cmd_get_irq *)cmd.params;
9827 - cmd_params->irq_index = irq_index;
9828 -
9829 - /* send command to mc*/
9830 - err = mc_send_command(mc_io, &cmd);
9831 - if (err)
9832 - return err;
9833 -
9834 - /* retrieve response parameters */
9835 - rsp_params = (struct dpbp_rsp_get_irq *)cmd.params;
9836 - irq_cfg->val = le32_to_cpu(rsp_params->irq_val);
9837 - irq_cfg->addr = le64_to_cpu(rsp_params->irq_addr);
9838 - irq_cfg->irq_num = le32_to_cpu(rsp_params->irq_num);
9839 - *type = le32_to_cpu(rsp_params->type);
9840 -
9841 - return 0;
9842 -}
9843 -
9844 -/**
9845 - * dpbp_set_irq_enable() - Set overall interrupt state.
9846 - * @mc_io: Pointer to MC portal's I/O object
9847 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
9848 - * @token: Token of DPBP object
9849 - * @irq_index: The interrupt index to configure
9850 - * @en: Interrupt state - enable = 1, disable = 0
9851 - *
9852 - * Allows GPP software to control when interrupts are generated.
9853 - * Each interrupt can have up to 32 causes. The enable/disable control's the
9854 - * overall interrupt state. if the interrupt is disabled no causes will cause
9855 - * an interrupt.
9856 - *
9857 - * Return: '0' on Success; Error code otherwise.
9858 - */
9859 -int dpbp_set_irq_enable(struct fsl_mc_io *mc_io,
9860 - u32 cmd_flags,
9861 - u16 token,
9862 - u8 irq_index,
9863 - u8 en)
9864 -{
9865 - struct mc_command cmd = { 0 };
9866 - struct dpbp_cmd_set_irq_enable *cmd_params;
9867 -
9868 - /* prepare command */
9869 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_IRQ_ENABLE,
9870 - cmd_flags, token);
9871 - cmd_params = (struct dpbp_cmd_set_irq_enable *)cmd.params;
9872 - cmd_params->enable = en & DPBP_ENABLE;
9873 - cmd_params->irq_index = irq_index;
9874 -
9875 - /* send command to mc*/
9876 - return mc_send_command(mc_io, &cmd);
9877 -}
9878 -
9879 -/**
9880 - * dpbp_get_irq_enable() - Get overall interrupt state
9881 - * @mc_io: Pointer to MC portal's I/O object
9882 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
9883 - * @token: Token of DPBP object
9884 - * @irq_index: The interrupt index to configure
9885 - * @en: Returned interrupt state - enable = 1, disable = 0
9886 - *
9887 - * Return: '0' on Success; Error code otherwise.
9888 - */
9889 -int dpbp_get_irq_enable(struct fsl_mc_io *mc_io,
9890 - u32 cmd_flags,
9891 - u16 token,
9892 - u8 irq_index,
9893 - u8 *en)
9894 -{
9895 - struct mc_command cmd = { 0 };
9896 - struct dpbp_cmd_get_irq_enable *cmd_params;
9897 - struct dpbp_rsp_get_irq_enable *rsp_params;
9898 - int err;
9899 -
9900 - /* prepare command */
9901 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_ENABLE,
9902 - cmd_flags, token);
9903 - cmd_params = (struct dpbp_cmd_get_irq_enable *)cmd.params;
9904 - cmd_params->irq_index = irq_index;
9905 -
9906 - /* send command to mc*/
9907 - err = mc_send_command(mc_io, &cmd);
9908 - if (err)
9909 - return err;
9910 -
9911 - /* retrieve response parameters */
9912 - rsp_params = (struct dpbp_rsp_get_irq_enable *)cmd.params;
9913 - *en = rsp_params->enabled & DPBP_ENABLE;
9914 - return 0;
9915 -}
9916 -
9917 -/**
9918 - * dpbp_set_irq_mask() - Set interrupt mask.
9919 - * @mc_io: Pointer to MC portal's I/O object
9920 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
9921 - * @token: Token of DPBP object
9922 - * @irq_index: The interrupt index to configure
9923 - * @mask: Event mask to trigger interrupt;
9924 - * each bit:
9925 - * 0 = ignore event
9926 - * 1 = consider event for asserting IRQ
9927 - *
9928 - * Every interrupt can have up to 32 causes and the interrupt model supports
9929 - * masking/unmasking each cause independently
9930 - *
9931 - * Return: '0' on Success; Error code otherwise.
9932 - */
9933 -int dpbp_set_irq_mask(struct fsl_mc_io *mc_io,
9934 - u32 cmd_flags,
9935 - u16 token,
9936 - u8 irq_index,
9937 - u32 mask)
9938 -{
9939 - struct mc_command cmd = { 0 };
9940 - struct dpbp_cmd_set_irq_mask *cmd_params;
9941 -
9942 - /* prepare command */
9943 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_IRQ_MASK,
9944 - cmd_flags, token);
9945 - cmd_params = (struct dpbp_cmd_set_irq_mask *)cmd.params;
9946 - cmd_params->mask = cpu_to_le32(mask);
9947 - cmd_params->irq_index = irq_index;
9948 -
9949 - /* send command to mc*/
9950 - return mc_send_command(mc_io, &cmd);
9951 -}
9952 -
9953 -/**
9954 - * dpbp_get_irq_mask() - Get interrupt mask.
9955 - * @mc_io: Pointer to MC portal's I/O object
9956 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
9957 - * @token: Token of DPBP object
9958 - * @irq_index: The interrupt index to configure
9959 - * @mask: Returned event mask to trigger interrupt
9960 - *
9961 - * Every interrupt can have up to 32 causes and the interrupt model supports
9962 - * masking/unmasking each cause independently
9963 - *
9964 - * Return: '0' on Success; Error code otherwise.
9965 - */
9966 -int dpbp_get_irq_mask(struct fsl_mc_io *mc_io,
9967 - u32 cmd_flags,
9968 - u16 token,
9969 - u8 irq_index,
9970 - u32 *mask)
9971 -{
9972 - struct mc_command cmd = { 0 };
9973 - struct dpbp_cmd_get_irq_mask *cmd_params;
9974 - struct dpbp_rsp_get_irq_mask *rsp_params;
9975 - int err;
9976 -
9977 - /* prepare command */
9978 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_MASK,
9979 - cmd_flags, token);
9980 - cmd_params = (struct dpbp_cmd_get_irq_mask *)cmd.params;
9981 - cmd_params->irq_index = irq_index;
9982 -
9983 - /* send command to mc*/
9984 - err = mc_send_command(mc_io, &cmd);
9985 - if (err)
9986 - return err;
9987 -
9988 - /* retrieve response parameters */
9989 - rsp_params = (struct dpbp_rsp_get_irq_mask *)cmd.params;
9990 - *mask = le32_to_cpu(rsp_params->mask);
9991 -
9992 - return 0;
9993 -}
9994 -
9995 -/**
9996 - * dpbp_get_irq_status() - Get the current status of any pending interrupts.
9997 - *
9998 - * @mc_io: Pointer to MC portal's I/O object
9999 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
10000 - * @token: Token of DPBP object
10001 - * @irq_index: The interrupt index to configure
10002 - * @status: Returned interrupts status - one bit per cause:
10003 - * 0 = no interrupt pending
10004 - * 1 = interrupt pending
10005 - *
10006 - * Return: '0' on Success; Error code otherwise.
10007 - */
10008 -int dpbp_get_irq_status(struct fsl_mc_io *mc_io,
10009 - u32 cmd_flags,
10010 - u16 token,
10011 - u8 irq_index,
10012 - u32 *status)
10013 -{
10014 - struct mc_command cmd = { 0 };
10015 - struct dpbp_cmd_get_irq_status *cmd_params;
10016 - struct dpbp_rsp_get_irq_status *rsp_params;
10017 - int err;
10018 -
10019 - /* prepare command */
10020 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_STATUS,
10021 - cmd_flags, token);
10022 - cmd_params = (struct dpbp_cmd_get_irq_status *)cmd.params;
10023 - cmd_params->status = cpu_to_le32(*status);
10024 - cmd_params->irq_index = irq_index;
10025 -
10026 - /* send command to mc*/
10027 - err = mc_send_command(mc_io, &cmd);
10028 - if (err)
10029 - return err;
10030 -
10031 - /* retrieve response parameters */
10032 - rsp_params = (struct dpbp_rsp_get_irq_status *)cmd.params;
10033 - *status = le32_to_cpu(rsp_params->status);
10034 -
10035 - return 0;
10036 -}
10037 -
10038 -/**
10039 - * dpbp_clear_irq_status() - Clear a pending interrupt's status
10040 - *
10041 - * @mc_io: Pointer to MC portal's I/O object
10042 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
10043 - * @token: Token of DPBP object
10044 - * @irq_index: The interrupt index to configure
10045 - * @status: Bits to clear (W1C) - one bit per cause:
10046 - * 0 = don't change
10047 - * 1 = clear status bit
10048 - *
10049 - * Return: '0' on Success; Error code otherwise.
10050 - */
10051 -int dpbp_clear_irq_status(struct fsl_mc_io *mc_io,
10052 - u32 cmd_flags,
10053 - u16 token,
10054 - u8 irq_index,
10055 - u32 status)
10056 -{
10057 - struct mc_command cmd = { 0 };
10058 - struct dpbp_cmd_clear_irq_status *cmd_params;
10059 -
10060 - /* prepare command */
10061 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLEAR_IRQ_STATUS,
10062 - cmd_flags, token);
10063 - cmd_params = (struct dpbp_cmd_clear_irq_status *)cmd.params;
10064 - cmd_params->status = cpu_to_le32(status);
10065 - cmd_params->irq_index = irq_index;
10066 -
10067 - /* send command to mc*/
10068 - return mc_send_command(mc_io, &cmd);
10069 -}
10070 -
10071 -/**
10072 - * dpbp_get_attributes - Retrieve DPBP attributes.
10073 - *
10074 - * @mc_io: Pointer to MC portal's I/O object
10075 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
10076 - * @token: Token of DPBP object
10077 - * @attr: Returned object's attributes
10078 - *
10079 - * Return: '0' on Success; Error code otherwise.
10080 - */
10081 -int dpbp_get_attributes(struct fsl_mc_io *mc_io,
10082 - u32 cmd_flags,
10083 - u16 token,
10084 - struct dpbp_attr *attr)
10085 -{
10086 - struct mc_command cmd = { 0 };
10087 - struct dpbp_rsp_get_attributes *rsp_params;
10088 - int err;
10089 -
10090 - /* prepare command */
10091 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_ATTR,
10092 - cmd_flags, token);
10093 -
10094 - /* send command to mc*/
10095 - err = mc_send_command(mc_io, &cmd);
10096 - if (err)
10097 - return err;
10098 -
10099 - /* retrieve response parameters */
10100 - rsp_params = (struct dpbp_rsp_get_attributes *)cmd.params;
10101 - attr->bpid = le16_to_cpu(rsp_params->bpid);
10102 - attr->id = le32_to_cpu(rsp_params->id);
10103 - attr->version.major = le16_to_cpu(rsp_params->version_major);
10104 - attr->version.minor = le16_to_cpu(rsp_params->version_minor);
10105 -
10106 - return 0;
10107 -}
10108 -EXPORT_SYMBOL(dpbp_get_attributes);
10109 -
10110 -/**
10111 - * dpbp_set_notifications() - Set notifications towards software
10112 - * @mc_io: Pointer to MC portal's I/O object
10113 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
10114 - * @token: Token of DPBP object
10115 - * @cfg: notifications configuration
10116 - *
10117 - * Return: '0' on Success; Error code otherwise.
10118 - */
10119 -int dpbp_set_notifications(struct fsl_mc_io *mc_io,
10120 - u32 cmd_flags,
10121 - u16 token,
10122 - struct dpbp_notification_cfg *cfg)
10123 -{
10124 - struct mc_command cmd = { 0 };
10125 - struct dpbp_cmd_set_notifications *cmd_params;
10126 -
10127 - /* prepare command */
10128 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_NOTIFICATIONS,
10129 - cmd_flags, token);
10130 - cmd_params = (struct dpbp_cmd_set_notifications *)cmd.params;
10131 - cmd_params->depletion_entry = cpu_to_le32(cfg->depletion_entry);
10132 - cmd_params->depletion_exit = cpu_to_le32(cfg->depletion_exit);
10133 - cmd_params->surplus_entry = cpu_to_le32(cfg->surplus_entry);
10134 - cmd_params->surplus_exit = cpu_to_le32(cfg->surplus_exit);
10135 - cmd_params->options = cpu_to_le16(cfg->options);
10136 - cmd_params->message_ctx = cpu_to_le64(cfg->message_ctx);
10137 - cmd_params->message_iova = cpu_to_le64(cfg->message_iova);
10138 -
10139 - /* send command to mc*/
10140 - return mc_send_command(mc_io, &cmd);
10141 -}
10142 -
10143 -/**
10144 - * dpbp_get_notifications() - Get the notifications configuration
10145 - * @mc_io: Pointer to MC portal's I/O object
10146 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
10147 - * @token: Token of DPBP object
10148 - * @cfg: notifications configuration
10149 - *
10150 - * Return: '0' on Success; Error code otherwise.
10151 - */
10152 -int dpbp_get_notifications(struct fsl_mc_io *mc_io,
10153 - u32 cmd_flags,
10154 - u16 token,
10155 - struct dpbp_notification_cfg *cfg)
10156 -{
10157 - struct mc_command cmd = { 0 };
10158 - struct dpbp_rsp_get_notifications *rsp_params;
10159 - int err;
10160 -
10161 - /* prepare command */
10162 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_NOTIFICATIONS,
10163 - cmd_flags,
10164 - token);
10165 -
10166 - /* send command to mc*/
10167 - err = mc_send_command(mc_io, &cmd);
10168 - if (err)
10169 - return err;
10170 -
10171 - /* retrieve response parameters */
10172 - rsp_params = (struct dpbp_rsp_get_notifications *)cmd.params;
10173 - cfg->depletion_entry = le32_to_cpu(rsp_params->depletion_entry);
10174 - cfg->depletion_exit = le32_to_cpu(rsp_params->depletion_exit);
10175 - cfg->surplus_entry = le32_to_cpu(rsp_params->surplus_entry);
10176 - cfg->surplus_exit = le32_to_cpu(rsp_params->surplus_exit);
10177 - cfg->options = le16_to_cpu(rsp_params->options);
10178 - cfg->message_ctx = le64_to_cpu(rsp_params->message_ctx);
10179 - cfg->message_iova = le64_to_cpu(rsp_params->message_iova);
10180 -
10181 - return 0;
10182 -}
10183 --- /dev/null
10184 +++ b/drivers/staging/fsl-mc/bus/dpio/Makefile
10185 @@ -0,0 +1,8 @@
10186 +# SPDX-License-Identifier: GPL-2.0
10187 +#
10188 +# QorIQ DPAA2 DPIO driver
10189 +#
10190 +
10191 +obj-$(CONFIG_FSL_MC_DPIO) += fsl-mc-dpio.o
10192 +
10193 +fsl-mc-dpio-objs := dpio.o qbman-portal.o dpio-service.o dpio-driver.o
10194 --- /dev/null
10195 +++ b/drivers/staging/fsl-mc/bus/dpio/dpio-cmd.h
10196 @@ -0,0 +1,50 @@
10197 +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
10198 +/*
10199 + * Copyright 2013-2016 Freescale Semiconductor Inc.
10200 + * Copyright 2016 NXP
10201 + *
10202 + */
10203 +#ifndef _FSL_DPIO_CMD_H
10204 +#define _FSL_DPIO_CMD_H
10205 +
10206 +/* DPIO Version */
10207 +#define DPIO_VER_MAJOR 4
10208 +#define DPIO_VER_MINOR 2
10209 +
10210 +/* Command Versioning */
10211 +
10212 +#define DPIO_CMD_ID_OFFSET 4
10213 +#define DPIO_CMD_BASE_VERSION 1
10214 +
10215 +#define DPIO_CMD(id) (((id) << DPIO_CMD_ID_OFFSET) | DPIO_CMD_BASE_VERSION)
10216 +
10217 +/* Command IDs */
10218 +#define DPIO_CMDID_CLOSE DPIO_CMD(0x800)
10219 +#define DPIO_CMDID_OPEN DPIO_CMD(0x803)
10220 +#define DPIO_CMDID_GET_API_VERSION DPIO_CMD(0xa03)
10221 +#define DPIO_CMDID_ENABLE DPIO_CMD(0x002)
10222 +#define DPIO_CMDID_DISABLE DPIO_CMD(0x003)
10223 +#define DPIO_CMDID_GET_ATTR DPIO_CMD(0x004)
10224 +#define DPIO_CMDID_RESET DPIO_CMD(0x005)
10225 +
10226 +struct dpio_cmd_open {
10227 + __le32 dpio_id;
10228 +};
10229 +
10230 +#define DPIO_CHANNEL_MODE_MASK 0x3
10231 +
10232 +struct dpio_rsp_get_attr {
10233 + /* cmd word 0 */
10234 + __le32 id;
10235 + __le16 qbman_portal_id;
10236 + u8 num_priorities;
10237 + u8 channel_mode;
10238 + /* cmd word 1 */
10239 + __le64 qbman_portal_ce_addr;
10240 + /* cmd word 2 */
10241 + __le64 qbman_portal_ci_addr;
10242 + /* cmd word 3 */
10243 + __le32 qbman_version;
10244 +};
10245 +
10246 +#endif /* _FSL_DPIO_CMD_H */
10247 --- /dev/null
10248 +++ b/drivers/staging/fsl-mc/bus/dpio/dpio-driver.c
10249 @@ -0,0 +1,278 @@
10250 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
10251 +/*
10252 + * Copyright 2014-2016 Freescale Semiconductor Inc.
10253 + * Copyright 2016 NXP
10254 + *
10255 + */
10256 +
10257 +#include <linux/types.h>
10258 +#include <linux/init.h>
10259 +#include <linux/module.h>
10260 +#include <linux/platform_device.h>
10261 +#include <linux/interrupt.h>
10262 +#include <linux/msi.h>
10263 +#include <linux/dma-mapping.h>
10264 +#include <linux/delay.h>
10265 +
10266 +#include <linux/fsl/mc.h>
10267 +#include "../../include/dpaa2-io.h"
10268 +
10269 +#include "qbman-portal.h"
10270 +#include "dpio.h"
10271 +#include "dpio-cmd.h"
10272 +
10273 +MODULE_LICENSE("Dual BSD/GPL");
10274 +MODULE_AUTHOR("Freescale Semiconductor, Inc");
10275 +MODULE_DESCRIPTION("DPIO Driver");
10276 +
10277 +struct dpio_priv {
10278 + struct dpaa2_io *io;
10279 +};
10280 +
10281 +static irqreturn_t dpio_irq_handler(int irq_num, void *arg)
10282 +{
10283 + struct device *dev = (struct device *)arg;
10284 + struct dpio_priv *priv = dev_get_drvdata(dev);
10285 +
10286 + return dpaa2_io_irq(priv->io);
10287 +}
10288 +
10289 +static void unregister_dpio_irq_handlers(struct fsl_mc_device *dpio_dev)
10290 +{
10291 + struct fsl_mc_device_irq *irq;
10292 +
10293 + irq = dpio_dev->irqs[0];
10294 +
10295 + /* clear the affinity hint */
10296 + irq_set_affinity_hint(irq->msi_desc->irq, NULL);
10297 +}
10298 +
10299 +static int register_dpio_irq_handlers(struct fsl_mc_device *dpio_dev, int cpu)
10300 +{
10301 + struct dpio_priv *priv;
10302 + int error;
10303 + struct fsl_mc_device_irq *irq;
10304 + cpumask_t mask;
10305 +
10306 + priv = dev_get_drvdata(&dpio_dev->dev);
10307 +
10308 + irq = dpio_dev->irqs[0];
10309 + error = devm_request_irq(&dpio_dev->dev,
10310 + irq->msi_desc->irq,
10311 + dpio_irq_handler,
10312 + 0,
10313 + dev_name(&dpio_dev->dev),
10314 + &dpio_dev->dev);
10315 + if (error < 0) {
10316 + dev_err(&dpio_dev->dev,
10317 + "devm_request_irq() failed: %d\n",
10318 + error);
10319 + return error;
10320 + }
10321 +
10322 + /* set the affinity hint */
10323 + cpumask_clear(&mask);
10324 + cpumask_set_cpu(cpu, &mask);
10325 + if (irq_set_affinity_hint(irq->msi_desc->irq, &mask))
10326 + dev_err(&dpio_dev->dev,
10327 + "irq_set_affinity failed irq %d cpu %d\n",
10328 + irq->msi_desc->irq, cpu);
10329 +
10330 + return 0;
10331 +}
10332 +
10333 +static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev)
10334 +{
10335 + struct dpio_attr dpio_attrs;
10336 + struct dpaa2_io_desc desc;
10337 + struct dpio_priv *priv;
10338 + int err = -ENOMEM;
10339 + struct device *dev = &dpio_dev->dev;
10340 + static int next_cpu = -1;
10341 +
10342 + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
10343 + if (!priv)
10344 + goto err_priv_alloc;
10345 +
10346 + dev_set_drvdata(dev, priv);
10347 +
10348 + err = fsl_mc_portal_allocate(dpio_dev, 0, &dpio_dev->mc_io);
10349 + if (err) {
10350 + dev_dbg(dev, "MC portal allocation failed\n");
10351 + err = -EPROBE_DEFER;
10352 + goto err_mcportal;
10353 + }
10354 +
10355 + err = dpio_open(dpio_dev->mc_io, 0, dpio_dev->obj_desc.id,
10356 + &dpio_dev->mc_handle);
10357 + if (err) {
10358 + dev_err(dev, "dpio_open() failed\n");
10359 + goto err_open;
10360 + }
10361 +
10362 + err = dpio_reset(dpio_dev->mc_io, 0, dpio_dev->mc_handle);
10363 + if (err) {
10364 + dev_err(dev, "dpio_reset() failed\n");
10365 + goto err_reset;
10366 + }
10367 +
10368 + err = dpio_get_attributes(dpio_dev->mc_io, 0, dpio_dev->mc_handle,
10369 + &dpio_attrs);
10370 + if (err) {
10371 + dev_err(dev, "dpio_get_attributes() failed %d\n", err);
10372 + goto err_get_attr;
10373 + }
10374 + desc.qman_version = dpio_attrs.qbman_version;
10375 +
10376 + err = dpio_enable(dpio_dev->mc_io, 0, dpio_dev->mc_handle);
10377 + if (err) {
10378 + dev_err(dev, "dpio_enable() failed %d\n", err);
10379 + goto err_get_attr;
10380 + }
10381 +
10382 + /* initialize DPIO descriptor */
10383 + desc.receives_notifications = dpio_attrs.num_priorities ? 1 : 0;
10384 + desc.has_8prio = dpio_attrs.num_priorities == 8 ? 1 : 0;
10385 + desc.dpio_id = dpio_dev->obj_desc.id;
10386 +
10387 + /* get the cpu to use for the affinity hint */
10388 + if (next_cpu == -1)
10389 + next_cpu = cpumask_first(cpu_online_mask);
10390 + else
10391 + next_cpu = cpumask_next(next_cpu, cpu_online_mask);
10392 +
10393 + if (!cpu_possible(next_cpu)) {
10394 + dev_err(dev, "probe failed. Number of DPIOs exceeds NR_CPUS.\n");
10395 + err = -ERANGE;
10396 + goto err_allocate_irqs;
10397 + }
10398 + desc.cpu = next_cpu;
10399 +
10400 + /*
10401 + * Set the CENA regs to be the cache enabled area of the portal to
10402 + * achieve the best performance.
10403 + */
10404 + desc.regs_cena = ioremap_cache_ns(dpio_dev->regions[0].start,
10405 + resource_size(&dpio_dev->regions[0]));
10406 + desc.regs_cinh = ioremap(dpio_dev->regions[1].start,
10407 + resource_size(&dpio_dev->regions[1]));
10408 +
10409 + err = fsl_mc_allocate_irqs(dpio_dev);
10410 + if (err) {
10411 + dev_err(dev, "fsl_mc_allocate_irqs failed. err=%d\n", err);
10412 + goto err_allocate_irqs;
10413 + }
10414 +
10415 + err = register_dpio_irq_handlers(dpio_dev, desc.cpu);
10416 + if (err)
10417 + goto err_register_dpio_irq;
10418 +
10419 + priv->io = dpaa2_io_create(&desc);
10420 + if (!priv->io) {
10421 + dev_err(dev, "dpaa2_io_create failed\n");
10422 + goto err_dpaa2_io_create;
10423 + }
10424 +
10425 + dev_info(dev, "probed\n");
10426 + dev_dbg(dev, " receives_notifications = %d\n",
10427 + desc.receives_notifications);
10428 + dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle);
10429 + fsl_mc_portal_free(dpio_dev->mc_io);
10430 +
10431 + return 0;
10432 +
10433 +err_dpaa2_io_create:
10434 + unregister_dpio_irq_handlers(dpio_dev);
10435 +err_register_dpio_irq:
10436 + fsl_mc_free_irqs(dpio_dev);
10437 +err_allocate_irqs:
10438 + dpio_disable(dpio_dev->mc_io, 0, dpio_dev->mc_handle);
10439 +err_get_attr:
10440 +err_reset:
10441 + dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle);
10442 +err_open:
10443 + fsl_mc_portal_free(dpio_dev->mc_io);
10444 +err_mcportal:
10445 + dev_set_drvdata(dev, NULL);
10446 +err_priv_alloc:
10447 + return err;
10448 +}
10449 +
10450 +/* Tear down interrupts for a given DPIO object */
10451 +static void dpio_teardown_irqs(struct fsl_mc_device *dpio_dev)
10452 +{
10453 + unregister_dpio_irq_handlers(dpio_dev);
10454 + fsl_mc_free_irqs(dpio_dev);
10455 +}
10456 +
10457 +static int dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev)
10458 +{
10459 + struct device *dev;
10460 + struct dpio_priv *priv;
10461 + int err;
10462 +
10463 + dev = &dpio_dev->dev;
10464 + priv = dev_get_drvdata(dev);
10465 +
10466 + dpaa2_io_down(priv->io);
10467 +
10468 + dpio_teardown_irqs(dpio_dev);
10469 +
10470 + err = fsl_mc_portal_allocate(dpio_dev, 0, &dpio_dev->mc_io);
10471 + if (err) {
10472 + dev_err(dev, "MC portal allocation failed\n");
10473 + goto err_mcportal;
10474 + }
10475 +
10476 + err = dpio_open(dpio_dev->mc_io, 0, dpio_dev->obj_desc.id,
10477 + &dpio_dev->mc_handle);
10478 + if (err) {
10479 + dev_err(dev, "dpio_open() failed\n");
10480 + goto err_open;
10481 + }
10482 +
10483 + dpio_disable(dpio_dev->mc_io, 0, dpio_dev->mc_handle);
10484 +
10485 + dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle);
10486 +
10487 + fsl_mc_portal_free(dpio_dev->mc_io);
10488 +
10489 + dev_set_drvdata(dev, NULL);
10490 +
10491 + return 0;
10492 +
10493 +err_open:
10494 + fsl_mc_portal_free(dpio_dev->mc_io);
10495 +err_mcportal:
10496 + return err;
10497 +}
10498 +
10499 +static const struct fsl_mc_device_id dpaa2_dpio_match_id_table[] = {
10500 + {
10501 + .vendor = FSL_MC_VENDOR_FREESCALE,
10502 + .obj_type = "dpio",
10503 + },
10504 + { .vendor = 0x0 }
10505 +};
10506 +
10507 +static struct fsl_mc_driver dpaa2_dpio_driver = {
10508 + .driver = {
10509 + .name = KBUILD_MODNAME,
10510 + .owner = THIS_MODULE,
10511 + },
10512 + .probe = dpaa2_dpio_probe,
10513 + .remove = dpaa2_dpio_remove,
10514 + .match_id_table = dpaa2_dpio_match_id_table
10515 +};
10516 +
10517 +static int dpio_driver_init(void)
10518 +{
10519 + return fsl_mc_driver_register(&dpaa2_dpio_driver);
10520 +}
10521 +
10522 +static void dpio_driver_exit(void)
10523 +{
10524 + fsl_mc_driver_unregister(&dpaa2_dpio_driver);
10525 +}
10526 +module_init(dpio_driver_init);
10527 +module_exit(dpio_driver_exit);
10528 --- /dev/null
10529 +++ b/drivers/staging/fsl-mc/bus/dpio/dpio-service.c
10530 @@ -0,0 +1,780 @@
10531 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
10532 +/*
10533 + * Copyright 2014-2016 Freescale Semiconductor Inc.
10534 + * Copyright 2016 NXP
10535 + *
10536 + */
10537 +#include <linux/types.h>
10538 +#include <linux/fsl/mc.h>
10539 +#include "../../include/dpaa2-io.h"
10540 +#include <linux/init.h>
10541 +#include <linux/module.h>
10542 +#include <linux/platform_device.h>
10543 +#include <linux/interrupt.h>
10544 +#include <linux/dma-mapping.h>
10545 +#include <linux/slab.h>
10546 +
10547 +#include "dpio.h"
10548 +#include "qbman-portal.h"
10549 +
10550 +struct dpaa2_io {
10551 + struct dpaa2_io_desc dpio_desc;
10552 + struct qbman_swp_desc swp_desc;
10553 + struct qbman_swp *swp;
10554 + struct list_head node;
10555 + /* protect against multiple management commands */
10556 + spinlock_t lock_mgmt_cmd;
10557 + /* protect notifications list */
10558 + spinlock_t lock_notifications;
10559 + struct list_head notifications;
10560 +};
10561 +
10562 +struct dpaa2_io_store {
10563 + unsigned int max;
10564 + dma_addr_t paddr;
10565 + struct dpaa2_dq *vaddr;
10566 + void *alloced_addr; /* unaligned value from kmalloc() */
10567 + unsigned int idx; /* position of the next-to-be-returned entry */
10568 + struct qbman_swp *swp; /* portal used to issue VDQCR */
10569 + struct device *dev; /* device used for DMA mapping */
10570 +};
10571 +
10572 +/* keep a per cpu array of DPIOs for fast access */
10573 +static struct dpaa2_io *dpio_by_cpu[NR_CPUS];
10574 +static struct list_head dpio_list = LIST_HEAD_INIT(dpio_list);
10575 +static DEFINE_SPINLOCK(dpio_list_lock);
10576 +
10577 +static inline struct dpaa2_io *service_select_by_cpu(struct dpaa2_io *d,
10578 + int cpu)
10579 +{
10580 + if (d)
10581 + return d;
10582 +
10583 + if (cpu != DPAA2_IO_ANY_CPU && cpu >= num_possible_cpus())
10584 + return NULL;
10585 +
10586 + /*
10587 + * If cpu == -1, choose the current cpu, with no guarantees about
10588 + * potentially being migrated away.
10589 + */
10590 + if (cpu < 0)
10591 + cpu = smp_processor_id();
10592 +
10593 + /* If a specific cpu was requested, pick it up immediately */
10594 + return dpio_by_cpu[cpu];
10595 +}
10596 +
10597 +static inline struct dpaa2_io *service_select(struct dpaa2_io *d)
10598 +{
10599 + if (d)
10600 + return d;
10601 +
10602 + d = service_select_by_cpu(d, -1);
10603 + if (d)
10604 + return d;
10605 +
10606 + spin_lock(&dpio_list_lock);
10607 + d = list_entry(dpio_list.next, struct dpaa2_io, node);
10608 + list_del(&d->node);
10609 + list_add_tail(&d->node, &dpio_list);
10610 + spin_unlock(&dpio_list_lock);
10611 +
10612 + return d;
10613 +}
10614 +
10615 +/**
10616 + * dpaa2_io_service_select() - return a dpaa2_io service affined to this cpu
10617 + * @cpu: the cpu id
10618 + *
10619 + * Return the affine dpaa2_io service, or NULL if there is no service affined
10620 + * to the specified cpu. If DPAA2_IO_ANY_CPU is used, return the next available
10621 + * service.
10622 + */
10623 +struct dpaa2_io *dpaa2_io_service_select(int cpu)
10624 +{
10625 + if (cpu == DPAA2_IO_ANY_CPU)
10626 + return service_select(NULL);
10627 +
10628 + return service_select_by_cpu(NULL, cpu);
10629 +}
10630 +EXPORT_SYMBOL_GPL(dpaa2_io_service_select);
10631 +
10632 +/**
10633 + * dpaa2_io_create() - create a dpaa2_io object.
10634 + * @desc: the dpaa2_io descriptor
10635 + *
10636 + * Activates a "struct dpaa2_io" corresponding to the given config of an actual
10637 + * DPIO object.
10638 + *
10639 + * Return a valid dpaa2_io object for success, or NULL for failure.
10640 + */
10641 +struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc)
10642 +{
10643 + struct dpaa2_io *obj = kmalloc(sizeof(*obj), GFP_KERNEL);
10644 +
10645 + if (!obj)
10646 + return NULL;
10647 +
10648 + /* check if CPU is out of range (-1 means any cpu) */
10649 + if (desc->cpu != DPAA2_IO_ANY_CPU && desc->cpu >= num_possible_cpus()) {
10650 + kfree(obj);
10651 + return NULL;
10652 + }
10653 +
10654 + obj->dpio_desc = *desc;
10655 + obj->swp_desc.cena_bar = obj->dpio_desc.regs_cena;
10656 + obj->swp_desc.cinh_bar = obj->dpio_desc.regs_cinh;
10657 + obj->swp_desc.qman_version = obj->dpio_desc.qman_version;
10658 + obj->swp = qbman_swp_init(&obj->swp_desc);
10659 +
10660 + if (!obj->swp) {
10661 + kfree(obj);
10662 + return NULL;
10663 + }
10664 +
10665 + INIT_LIST_HEAD(&obj->node);
10666 + spin_lock_init(&obj->lock_mgmt_cmd);
10667 + spin_lock_init(&obj->lock_notifications);
10668 + INIT_LIST_HEAD(&obj->notifications);
10669 +
10670 + /* For now only enable DQRR interrupts */
10671 + qbman_swp_interrupt_set_trigger(obj->swp,
10672 + QBMAN_SWP_INTERRUPT_DQRI);
10673 + qbman_swp_interrupt_clear_status(obj->swp, 0xffffffff);
10674 + if (obj->dpio_desc.receives_notifications)
10675 + qbman_swp_push_set(obj->swp, 0, 1);
10676 +
10677 + spin_lock(&dpio_list_lock);
10678 + list_add_tail(&obj->node, &dpio_list);
10679 + if (desc->cpu >= 0 && !dpio_by_cpu[desc->cpu])
10680 + dpio_by_cpu[desc->cpu] = obj;
10681 + spin_unlock(&dpio_list_lock);
10682 +
10683 + return obj;
10684 +}
10685 +
10686 +/**
10687 + * dpaa2_io_down() - release the dpaa2_io object.
10688 + * @d: the dpaa2_io object to be released.
10689 + *
10690 + * The "struct dpaa2_io" type can represent an individual DPIO object (as
10691 + * described by "struct dpaa2_io_desc") or an instance of a "DPIO service",
10692 + * which can be used to group/encapsulate multiple DPIO objects. In all cases,
10693 + * each handle obtained should be released using this function.
10694 + */
10695 +void dpaa2_io_down(struct dpaa2_io *d)
10696 +{
10697 + kfree(d);
10698 +}
10699 +
10700 +#define DPAA_POLL_MAX 32
10701 +
10702 +/**
10703 + * dpaa2_io_irq() - ISR for DPIO interrupts
10704 + *
10705 + * @obj: the given DPIO object.
10706 + *
10707 + * Return IRQ_HANDLED for success or IRQ_NONE if there
10708 + * were no pending interrupts.
10709 + */
10710 +irqreturn_t dpaa2_io_irq(struct dpaa2_io *obj)
10711 +{
10712 + const struct dpaa2_dq *dq;
10713 + int max = 0;
10714 + struct qbman_swp *swp;
10715 + u32 status;
10716 +
10717 + swp = obj->swp;
10718 + status = qbman_swp_interrupt_read_status(swp);
10719 + if (!status)
10720 + return IRQ_NONE;
10721 +
10722 + dq = qbman_swp_dqrr_next(swp);
10723 + while (dq) {
10724 + if (qbman_result_is_SCN(dq)) {
10725 + struct dpaa2_io_notification_ctx *ctx;
10726 + u64 q64;
10727 +
10728 + q64 = qbman_result_SCN_ctx(dq);
10729 + ctx = (void *)(uintptr_t)q64;
10730 + ctx->cb(ctx);
10731 + } else {
10732 + pr_crit("fsl-mc-dpio: Unrecognised/ignored DQRR entry\n");
10733 + }
10734 + qbman_swp_dqrr_consume(swp, dq);
10735 + ++max;
10736 + if (max > DPAA_POLL_MAX)
10737 + goto done;
10738 + dq = qbman_swp_dqrr_next(swp);
10739 + }
10740 +done:
10741 + qbman_swp_interrupt_clear_status(swp, status);
10742 + qbman_swp_interrupt_set_inhibit(swp, 0);
10743 + return IRQ_HANDLED;
10744 +}
10745 +
10746 +/**
10747 + * dpaa2_io_service_register() - Prepare for servicing of FQDAN or CDAN
10748 + * notifications on the given DPIO service.
10749 + * @d: the given DPIO service.
10750 + * @ctx: the notification context.
10751 + *
10752 + * The caller should make the MC command to attach a DPAA2 object to
10753 + * a DPIO after this function completes successfully. In that way:
10754 + * (a) The DPIO service is "ready" to handle a notification arrival
10755 + * (which might happen before the "attach" command to MC has
10756 + * returned control of execution back to the caller)
10757 + * (b) The DPIO service can provide back to the caller the 'dpio_id' and
10758 + * 'qman64' parameters that it should pass along in the MC command
10759 + * in order for the object to be configured to produce the right
10760 + * notification fields to the DPIO service.
10761 + *
10762 + * Return 0 for success, or -ENODEV for failure.
10763 + */
10764 +int dpaa2_io_service_register(struct dpaa2_io *d,
10765 + struct dpaa2_io_notification_ctx *ctx)
10766 +{
10767 + unsigned long irqflags;
10768 +
10769 + d = service_select_by_cpu(d, ctx->desired_cpu);
10770 + if (!d)
10771 + return -ENODEV;
10772 +
10773 + ctx->dpio_id = d->dpio_desc.dpio_id;
10774 + ctx->qman64 = (u64)(uintptr_t)ctx;
10775 + ctx->dpio_private = d;
10776 + spin_lock_irqsave(&d->lock_notifications, irqflags);
10777 + list_add(&ctx->node, &d->notifications);
10778 + spin_unlock_irqrestore(&d->lock_notifications, irqflags);
10779 +
10780 + /* Enable the generation of CDAN notifications */
10781 + if (ctx->is_cdan)
10782 + return qbman_swp_CDAN_set_context_enable(d->swp,
10783 + (u16)ctx->id,
10784 + ctx->qman64);
10785 + return 0;
10786 +}
10787 +EXPORT_SYMBOL_GPL(dpaa2_io_service_register);
10788 +
10789 +/**
10790 + * dpaa2_io_service_deregister - The opposite of 'register'.
10791 + * @service: the given DPIO service.
10792 + * @ctx: the notification context.
10793 + *
10794 + * This function should be called only after sending the MC command to
10795 + * to detach the notification-producing device from the DPIO.
10796 + */
10797 +void dpaa2_io_service_deregister(struct dpaa2_io *service,
10798 + struct dpaa2_io_notification_ctx *ctx)
10799 +{
10800 + struct dpaa2_io *d = ctx->dpio_private;
10801 + unsigned long irqflags;
10802 +
10803 + if (ctx->is_cdan)
10804 + qbman_swp_CDAN_disable(d->swp, (u16)ctx->id);
10805 +
10806 + spin_lock_irqsave(&d->lock_notifications, irqflags);
10807 + list_del(&ctx->node);
10808 + spin_unlock_irqrestore(&d->lock_notifications, irqflags);
10809 +}
10810 +EXPORT_SYMBOL_GPL(dpaa2_io_service_deregister);
10811 +
10812 +/**
10813 + * dpaa2_io_service_rearm() - Rearm the notification for the given DPIO service.
10814 + * @d: the given DPIO service.
10815 + * @ctx: the notification context.
10816 + *
10817 + * Once a FQDAN/CDAN has been produced, the corresponding FQ/channel is
10818 + * considered "disarmed". Ie. the user can issue pull dequeue operations on that
10819 + * traffic source for as long as it likes. Eventually it may wish to "rearm"
10820 + * that source to allow it to produce another FQDAN/CDAN, that's what this
10821 + * function achieves.
10822 + *
10823 + * Return 0 for success.
10824 + */
10825 +int dpaa2_io_service_rearm(struct dpaa2_io *d,
10826 + struct dpaa2_io_notification_ctx *ctx)
10827 +{
10828 + unsigned long irqflags;
10829 + int err;
10830 +
10831 + d = service_select_by_cpu(d, ctx->desired_cpu);
10832 + if (!unlikely(d))
10833 + return -ENODEV;
10834 +
10835 + spin_lock_irqsave(&d->lock_mgmt_cmd, irqflags);
10836 + if (ctx->is_cdan)
10837 + err = qbman_swp_CDAN_enable(d->swp, (u16)ctx->id);
10838 + else
10839 + err = qbman_swp_fq_schedule(d->swp, ctx->id);
10840 + spin_unlock_irqrestore(&d->lock_mgmt_cmd, irqflags);
10841 +
10842 + return err;
10843 +}
10844 +EXPORT_SYMBOL_GPL(dpaa2_io_service_rearm);
10845 +
10846 +/**
10847 + * dpaa2_io_service_pull_fq() - pull dequeue functions from a fq.
10848 + * @d: the given DPIO service.
10849 + * @fqid: the given frame queue id.
10850 + * @s: the dpaa2_io_store object for the result.
10851 + *
10852 + * Return 0 for success, or error code for failure.
10853 + */
10854 +int dpaa2_io_service_pull_fq(struct dpaa2_io *d, u32 fqid,
10855 + struct dpaa2_io_store *s)
10856 +{
10857 + struct qbman_pull_desc pd;
10858 + int err;
10859 +
10860 + qbman_pull_desc_clear(&pd);
10861 + qbman_pull_desc_set_storage(&pd, s->vaddr, s->paddr, 1);
10862 + qbman_pull_desc_set_numframes(&pd, (u8)s->max);
10863 + qbman_pull_desc_set_fq(&pd, fqid);
10864 +
10865 + d = service_select(d);
10866 + if (!d)
10867 + return -ENODEV;
10868 + s->swp = d->swp;
10869 + err = qbman_swp_pull(d->swp, &pd);
10870 + if (err)
10871 + s->swp = NULL;
10872 +
10873 + return err;
10874 +}
10875 +EXPORT_SYMBOL(dpaa2_io_service_pull_fq);
10876 +
10877 +/**
10878 + * dpaa2_io_service_pull_channel() - pull dequeue functions from a channel.
10879 + * @d: the given DPIO service.
10880 + * @channelid: the given channel id.
10881 + * @s: the dpaa2_io_store object for the result.
10882 + *
10883 + * Return 0 for success, or error code for failure.
10884 + */
10885 +int dpaa2_io_service_pull_channel(struct dpaa2_io *d, u32 channelid,
10886 + struct dpaa2_io_store *s)
10887 +{
10888 + struct qbman_pull_desc pd;
10889 + int err;
10890 +
10891 + qbman_pull_desc_clear(&pd);
10892 + qbman_pull_desc_set_storage(&pd, s->vaddr, s->paddr, 1);
10893 + qbman_pull_desc_set_numframes(&pd, (u8)s->max);
10894 + qbman_pull_desc_set_channel(&pd, channelid, qbman_pull_type_prio);
10895 +
10896 + d = service_select(d);
10897 + if (!d)
10898 + return -ENODEV;
10899 +
10900 + s->swp = d->swp;
10901 + err = qbman_swp_pull(d->swp, &pd);
10902 + if (err)
10903 + s->swp = NULL;
10904 +
10905 + return err;
10906 +}
10907 +EXPORT_SYMBOL_GPL(dpaa2_io_service_pull_channel);
10908 +
10909 +/**
10910 + * dpaa2_io_service_enqueue_fq() - Enqueue a frame to a frame queue.
10911 + * @d: the given DPIO service.
10912 + * @fqid: the given frame queue id.
10913 + * @fd: the frame descriptor which is enqueued.
10914 + *
10915 + * Return 0 for successful enqueue, -EBUSY if the enqueue ring is not ready,
10916 + * or -ENODEV if there is no dpio service.
10917 + */
10918 +int dpaa2_io_service_enqueue_fq(struct dpaa2_io *d,
10919 + u32 fqid,
10920 + const struct dpaa2_fd *fd)
10921 +{
10922 + struct qbman_eq_desc ed;
10923 +
10924 + d = service_select(d);
10925 + if (!d)
10926 + return -ENODEV;
10927 +
10928 + qbman_eq_desc_clear(&ed);
10929 + qbman_eq_desc_set_no_orp(&ed, 0);
10930 + qbman_eq_desc_set_fq(&ed, fqid);
10931 +
10932 + return qbman_swp_enqueue(d->swp, &ed, fd);
10933 +}
10934 +EXPORT_SYMBOL(dpaa2_io_service_enqueue_fq);
10935 +
10936 +/**
10937 + * dpaa2_io_service_enqueue_qd() - Enqueue a frame to a QD.
10938 + * @d: the given DPIO service.
10939 + * @qdid: the given queuing destination id.
10940 + * @prio: the given queuing priority.
10941 + * @qdbin: the given queuing destination bin.
10942 + * @fd: the frame descriptor which is enqueued.
10943 + *
10944 + * Return 0 for successful enqueue, or -EBUSY if the enqueue ring is not ready,
10945 + * or -ENODEV if there is no dpio service.
10946 + */
10947 +int dpaa2_io_service_enqueue_qd(struct dpaa2_io *d,
10948 + u32 qdid, u8 prio, u16 qdbin,
10949 + const struct dpaa2_fd *fd)
10950 +{
10951 + struct qbman_eq_desc ed;
10952 +
10953 + d = service_select(d);
10954 + if (!d)
10955 + return -ENODEV;
10956 +
10957 + qbman_eq_desc_clear(&ed);
10958 + qbman_eq_desc_set_no_orp(&ed, 0);
10959 + qbman_eq_desc_set_qd(&ed, qdid, qdbin, prio);
10960 +
10961 + return qbman_swp_enqueue(d->swp, &ed, fd);
10962 +}
10963 +EXPORT_SYMBOL_GPL(dpaa2_io_service_enqueue_qd);
10964 +
10965 +/**
10966 + * dpaa2_io_service_release() - Release buffers to a buffer pool.
10967 + * @d: the given DPIO object.
10968 + * @bpid: the buffer pool id.
10969 + * @buffers: the buffers to be released.
10970 + * @num_buffers: the number of the buffers to be released.
10971 + *
10972 + * Return 0 for success, and negative error code for failure.
10973 + */
10974 +int dpaa2_io_service_release(struct dpaa2_io *d,
10975 + u32 bpid,
10976 + const u64 *buffers,
10977 + unsigned int num_buffers)
10978 +{
10979 + struct qbman_release_desc rd;
10980 +
10981 + d = service_select(d);
10982 + if (!d)
10983 + return -ENODEV;
10984 +
10985 + qbman_release_desc_clear(&rd);
10986 + qbman_release_desc_set_bpid(&rd, bpid);
10987 +
10988 + return qbman_swp_release(d->swp, &rd, buffers, num_buffers);
10989 +}
10990 +EXPORT_SYMBOL_GPL(dpaa2_io_service_release);
10991 +
10992 +/**
10993 + * dpaa2_io_service_acquire() - Acquire buffers from a buffer pool.
10994 + * @d: the given DPIO object.
10995 + * @bpid: the buffer pool id.
10996 + * @buffers: the buffer addresses for acquired buffers.
10997 + * @num_buffers: the expected number of the buffers to acquire.
10998 + *
10999 + * Return a negative error code if the command failed, otherwise it returns
11000 + * the number of buffers acquired, which may be less than the number requested.
11001 + * Eg. if the buffer pool is empty, this will return zero.
11002 + */
11003 +int dpaa2_io_service_acquire(struct dpaa2_io *d,
11004 + u32 bpid,
11005 + u64 *buffers,
11006 + unsigned int num_buffers)
11007 +{
11008 + unsigned long irqflags;
11009 + int err;
11010 +
11011 + d = service_select(d);
11012 + if (!d)
11013 + return -ENODEV;
11014 +
11015 + spin_lock_irqsave(&d->lock_mgmt_cmd, irqflags);
11016 + err = qbman_swp_acquire(d->swp, bpid, buffers, num_buffers);
11017 + spin_unlock_irqrestore(&d->lock_mgmt_cmd, irqflags);
11018 +
11019 + return err;
11020 +}
11021 +EXPORT_SYMBOL_GPL(dpaa2_io_service_acquire);
11022 +
11023 +/*
11024 + * 'Stores' are reusable memory blocks for holding dequeue results, and to
11025 + * assist with parsing those results.
11026 + */
11027 +
11028 +/**
11029 + * dpaa2_io_store_create() - Create the dma memory storage for dequeue result.
11030 + * @max_frames: the maximum number of dequeued result for frames, must be <= 16.
11031 + * @dev: the device to allow mapping/unmapping the DMAable region.
11032 + *
11033 + * The size of the storage is "max_frames*sizeof(struct dpaa2_dq)".
11034 + * The 'dpaa2_io_store' returned is a DPIO service managed object.
11035 + *
11036 + * Return pointer to dpaa2_io_store struct for successfuly created storage
11037 + * memory, or NULL on error.
11038 + */
11039 +struct dpaa2_io_store *dpaa2_io_store_create(unsigned int max_frames,
11040 + struct device *dev)
11041 +{
11042 + struct dpaa2_io_store *ret;
11043 + size_t size;
11044 +
11045 + if (!max_frames || (max_frames > 16))
11046 + return NULL;
11047 +
11048 + ret = kmalloc(sizeof(*ret), GFP_KERNEL);
11049 + if (!ret)
11050 + return NULL;
11051 +
11052 + ret->max = max_frames;
11053 + size = max_frames * sizeof(struct dpaa2_dq) + 64;
11054 + ret->alloced_addr = kzalloc(size, GFP_KERNEL);
11055 + if (!ret->alloced_addr) {
11056 + kfree(ret);
11057 + return NULL;
11058 + }
11059 +
11060 + ret->vaddr = PTR_ALIGN(ret->alloced_addr, 64);
11061 + ret->paddr = dma_map_single(dev, ret->vaddr,
11062 + sizeof(struct dpaa2_dq) * max_frames,
11063 + DMA_FROM_DEVICE);
11064 + if (dma_mapping_error(dev, ret->paddr)) {
11065 + kfree(ret->alloced_addr);
11066 + kfree(ret);
11067 + return NULL;
11068 + }
11069 +
11070 + ret->idx = 0;
11071 + ret->dev = dev;
11072 +
11073 + return ret;
11074 +}
11075 +EXPORT_SYMBOL_GPL(dpaa2_io_store_create);
11076 +
11077 +/**
11078 + * dpaa2_io_store_destroy() - Frees the dma memory storage for dequeue
11079 + * result.
11080 + * @s: the storage memory to be destroyed.
11081 + */
11082 +void dpaa2_io_store_destroy(struct dpaa2_io_store *s)
11083 +{
11084 + dma_unmap_single(s->dev, s->paddr, sizeof(struct dpaa2_dq) * s->max,
11085 + DMA_FROM_DEVICE);
11086 + kfree(s->alloced_addr);
11087 + kfree(s);
11088 +}
11089 +EXPORT_SYMBOL_GPL(dpaa2_io_store_destroy);
11090 +
11091 +/**
11092 + * dpaa2_io_store_next() - Determine when the next dequeue result is available.
11093 + * @s: the dpaa2_io_store object.
11094 + * @is_last: indicate whether this is the last frame in the pull command.
11095 + *
11096 + * When an object driver performs dequeues to a dpaa2_io_store, this function
11097 + * can be used to determine when the next frame result is available. Once
11098 + * this function returns non-NULL, a subsequent call to it will try to find
11099 + * the next dequeue result.
11100 + *
11101 + * Note that if a pull-dequeue has a NULL result because the target FQ/channel
11102 + * was empty, then this function will also return NULL (rather than expecting
11103 + * the caller to always check for this. As such, "is_last" can be used to
11104 + * differentiate between "end-of-empty-dequeue" and "still-waiting".
11105 + *
11106 + * Return dequeue result for a valid dequeue result, or NULL for empty dequeue.
11107 + */
11108 +struct dpaa2_dq *dpaa2_io_store_next(struct dpaa2_io_store *s, int *is_last)
11109 +{
11110 + int match;
11111 + struct dpaa2_dq *ret = &s->vaddr[s->idx];
11112 +
11113 + match = qbman_result_has_new_result(s->swp, ret);
11114 + if (!match) {
11115 + *is_last = 0;
11116 + return NULL;
11117 + }
11118 +
11119 + s->idx++;
11120 +
11121 + if (dpaa2_dq_is_pull_complete(ret)) {
11122 + *is_last = 1;
11123 + s->idx = 0;
11124 + /*
11125 + * If we get an empty dequeue result to terminate a zero-results
11126 + * vdqcr, return NULL to the caller rather than expecting him to
11127 + * check non-NULL results every time.
11128 + */
11129 + if (!(dpaa2_dq_flags(ret) & DPAA2_DQ_STAT_VALIDFRAME))
11130 + ret = NULL;
11131 + } else {
11132 + *is_last = 0;
11133 + }
11134 +
11135 + return ret;
11136 +}
11137 +EXPORT_SYMBOL_GPL(dpaa2_io_store_next);
11138 +
11139 +/**
11140 + * dpaa2_io_query_fq_count() - Get the frame and byte count for a given fq.
11141 + * @d: the given DPIO object.
11142 + * @fqid: the id of frame queue to be queried.
11143 + * @fcnt: the queried frame count.
11144 + * @bcnt: the queried byte count.
11145 + *
11146 + * Knowing the FQ count at run-time can be useful in debugging situations.
11147 + * The instantaneous frame- and byte-count are hereby returned.
11148 + *
11149 + * Return 0 for a successful query, and negative error code if query fails.
11150 + */
11151 +int dpaa2_io_query_fq_count(struct dpaa2_io *d, u32 fqid,
11152 + u32 *fcnt, u32 *bcnt)
11153 +{
11154 + struct qbman_fq_query_np_rslt state;
11155 + struct qbman_swp *swp;
11156 + unsigned long irqflags;
11157 + int ret;
11158 +
11159 + d = service_select(d);
11160 + if (!d)
11161 + return -ENODEV;
11162 +
11163 + swp = d->swp;
11164 + spin_lock_irqsave(&d->lock_mgmt_cmd, irqflags);
11165 + ret = qbman_fq_query_state(swp, fqid, &state);
11166 + spin_unlock_irqrestore(&d->lock_mgmt_cmd, irqflags);
11167 + if (ret)
11168 + return ret;
11169 + *fcnt = qbman_fq_state_frame_count(&state);
11170 + *bcnt = qbman_fq_state_byte_count(&state);
11171 +
11172 + return 0;
11173 +}
11174 +EXPORT_SYMBOL(dpaa2_io_query_fq_count);
11175 +
11176 +/**
11177 + * dpaa2_io_query_bp_count() - Query the number of buffers currently in a
11178 + * buffer pool.
11179 + * @d: the given DPIO object.
11180 + * @bpid: the index of buffer pool to be queried.
11181 + * @num: the queried number of buffers in the buffer pool.
11182 + *
11183 + * Return 0 for a successful query, and negative error code if query fails.
11184 + */
11185 +int dpaa2_io_query_bp_count(struct dpaa2_io *d, u32 bpid, u32 *num)
11186 +{
11187 + struct qbman_bp_query_rslt state;
11188 + struct qbman_swp *swp;
11189 + unsigned long irqflags;
11190 + int ret;
11191 +
11192 + d = service_select(d);
11193 + if (!d)
11194 + return -ENODEV;
11195 +
11196 + swp = d->swp;
11197 + spin_lock_irqsave(&d->lock_mgmt_cmd, irqflags);
11198 + ret = qbman_bp_query(swp, bpid, &state);
11199 + spin_unlock_irqrestore(&d->lock_mgmt_cmd, irqflags);
11200 + if (ret)
11201 + return ret;
11202 + *num = qbman_bp_info_num_free_bufs(&state);
11203 + return 0;
11204 +}
11205 +EXPORT_SYMBOL(dpaa2_io_query_bp_count);
11206 +
11207 +/**
11208 + * dpaa2_io_service_enqueue_orp_fq() - Enqueue a frame to a frame queue with
11209 + * order restoration
11210 + * @d: the given DPIO service.
11211 + * @fqid: the given frame queue id.
11212 + * @fd: the frame descriptor which is enqueued.
11213 + * @orpid: the order restoration point ID
11214 + * @seqnum: the order sequence number
11215 + * @last: must be set for the final frame if seqnum is shared (spilt frame)
11216 + *
11217 + * Performs an enqueue to a frame queue using the specified order restoration
11218 + * point. The QMan device will ensure the order of frames placed on the
11219 + * queue will be ordered as per the sequence number.
11220 + *
11221 + * In the case a frame is split it is possible to enqueue using the same
11222 + * sequence number more than once. The final frame in a shared sequence number
11223 + * most be indicated by setting last = 1. For non shared sequence numbers
11224 + * last = 1 must always be set.
11225 + *
11226 + * Return 0 for successful enqueue, or -EBUSY if the enqueue ring is not ready,
11227 + * or -ENODEV if there is no dpio service.
11228 + */
11229 +int dpaa2_io_service_enqueue_orp_fq(struct dpaa2_io *d, u32 fqid,
11230 + const struct dpaa2_fd *fd, u16 orpid,
11231 + u16 seqnum, int last)
11232 +{
11233 + struct qbman_eq_desc ed;
11234 +
11235 + d = service_select(d);
11236 + if (!d)
11237 + return -ENODEV;
11238 + qbman_eq_desc_clear(&ed);
11239 + qbman_eq_desc_set_orp(&ed, 0, orpid, seqnum, !last);
11240 + qbman_eq_desc_set_fq(&ed, fqid);
11241 + return qbman_swp_enqueue(d->swp, &ed, fd);
11242 +}
11243 +EXPORT_SYMBOL(dpaa2_io_service_enqueue_orp_fq);
11244 +
11245 +/**
11246 + * dpaa2_io_service_enqueue_orp_qd() - Enqueue a frame to a queueing destination
11247 + * with order restoration
11248 + * @d: the given DPIO service.
11249 + * @qdid: the given queuing destination id.
11250 + * @fd: the frame descriptor which is enqueued.
11251 + * @orpid: the order restoration point ID
11252 + * @seqnum: the order sequence number
11253 + * @last: must be set for the final frame if seqnum is shared (spilt frame)
11254 + *
11255 + * Performs an enqueue to a frame queue using the specified order restoration
11256 + * point. The QMan device will ensure the order of frames placed on the
11257 + * queue will be ordered as per the sequence number.
11258 + *
11259 + * In the case a frame is split it is possible to enqueue using the same
11260 + * sequence number more than once. The final frame in a shared sequence number
11261 + * most be indicated by setting last = 1. For non shared sequence numbers
11262 + * last = 1 must always be set.
11263 + *
11264 + * Return 0 for successful enqueue, or -EBUSY if the enqueue ring is not ready,
11265 + * or -ENODEV if there is no dpio service.
11266 + */
11267 +int dpaa2_io_service_enqueue_orp_qd(struct dpaa2_io *d, u32 qdid, u8 prio,
11268 + u16 qdbin, const struct dpaa2_fd *fd,
11269 + u16 orpid, u16 seqnum, int last)
11270 +{
11271 + struct qbman_eq_desc ed;
11272 +
11273 + d = service_select(d);
11274 + if (!d)
11275 + return -ENODEV;
11276 + qbman_eq_desc_clear(&ed);
11277 + qbman_eq_desc_set_orp(&ed, 0, orpid, seqnum, !last);
11278 + qbman_eq_desc_set_qd(&ed, qdid, qdbin, prio);
11279 + return qbman_swp_enqueue(d->swp, &ed, fd);
11280 +}
11281 +EXPORT_SYMBOL_GPL(dpaa2_io_service_enqueue_orp_qd);
11282 +
11283 +/**
11284 + * dpaa2_io_service_orp_seqnum_drop() - Remove a sequence number from
11285 + * an order restoration list
11286 + * @d: the given DPIO service.
11287 + * @orpid: Order restoration point to remove a sequence number from
11288 + * @seqnum: Sequence number to remove
11289 + *
11290 + * Removes a frames sequence number from an order restoration point without
11291 + * enqueing the frame. Used to indicate that the order restoration hardware
11292 + * should not expect to see this sequence number. Typically used to indicate
11293 + * a frame was terminated or dropped from a flow.
11294 + *
11295 + * Return 0 for successful enqueue, or -EBUSY if the enqueue ring is not ready,
11296 + * or -ENODEV if there is no dpio service.
11297 + */
11298 +int dpaa2_io_service_orp_seqnum_drop(struct dpaa2_io *d, u16 orpid, u16 seqnum)
11299 +{
11300 + struct qbman_eq_desc ed;
11301 + struct dpaa2_fd fd;
11302 +
11303 + d = service_select(d);
11304 + if (!d)
11305 + return -ENODEV;
11306 + qbman_eq_desc_clear(&ed);
11307 + qbman_eq_desc_set_orp_hole(&ed, orpid, seqnum);
11308 + return qbman_swp_enqueue(d->swp, &ed, &fd);
11309 +}
11310 +EXPORT_SYMBOL_GPL(dpaa2_io_service_orp_seqnum_drop);
11311 --- /dev/null
11312 +++ b/drivers/staging/fsl-mc/bus/dpio/dpio.c
11313 @@ -0,0 +1,221 @@
11314 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
11315 +/*
11316 + * Copyright 2013-2016 Freescale Semiconductor Inc.
11317 + * Copyright 2016 NXP
11318 + *
11319 + */
11320 +#include <linux/kernel.h>
11321 +#include <linux/fsl/mc.h>
11322 +
11323 +#include "dpio.h"
11324 +#include "dpio-cmd.h"
11325 +
11326 +/*
11327 + * Data Path I/O Portal API
11328 + * Contains initialization APIs and runtime control APIs for DPIO
11329 + */
11330 +
11331 +/**
11332 + * dpio_open() - Open a control session for the specified object
11333 + * @mc_io: Pointer to MC portal's I/O object
11334 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
11335 + * @dpio_id: DPIO unique ID
11336 + * @token: Returned token; use in subsequent API calls
11337 + *
11338 + * This function can be used to open a control session for an
11339 + * already created object; an object may have been declared in
11340 + * the DPL or by calling the dpio_create() function.
11341 + * This function returns a unique authentication token,
11342 + * associated with the specific object ID and the specific MC
11343 + * portal; this token must be used in all subsequent commands for
11344 + * this specific object.
11345 + *
11346 + * Return: '0' on Success; Error code otherwise.
11347 + */
11348 +int dpio_open(struct fsl_mc_io *mc_io,
11349 + u32 cmd_flags,
11350 + int dpio_id,
11351 + u16 *token)
11352 +{
11353 + struct fsl_mc_command cmd = { 0 };
11354 + struct dpio_cmd_open *dpio_cmd;
11355 + int err;
11356 +
11357 + /* prepare command */
11358 + cmd.header = mc_encode_cmd_header(DPIO_CMDID_OPEN,
11359 + cmd_flags,
11360 + 0);
11361 + dpio_cmd = (struct dpio_cmd_open *)cmd.params;
11362 + dpio_cmd->dpio_id = cpu_to_le32(dpio_id);
11363 +
11364 + err = mc_send_command(mc_io, &cmd);
11365 + if (err)
11366 + return err;
11367 +
11368 + /* retrieve response parameters */
11369 + *token = mc_cmd_hdr_read_token(&cmd);
11370 +
11371 + return 0;
11372 +}
11373 +
11374 +/**
11375 + * dpio_close() - Close the control session of the object
11376 + * @mc_io: Pointer to MC portal's I/O object
11377 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
11378 + * @token: Token of DPIO object
11379 + *
11380 + * Return: '0' on Success; Error code otherwise.
11381 + */
11382 +int dpio_close(struct fsl_mc_io *mc_io,
11383 + u32 cmd_flags,
11384 + u16 token)
11385 +{
11386 + struct fsl_mc_command cmd = { 0 };
11387 +
11388 + /* prepare command */
11389 + cmd.header = mc_encode_cmd_header(DPIO_CMDID_CLOSE,
11390 + cmd_flags,
11391 + token);
11392 +
11393 + return mc_send_command(mc_io, &cmd);
11394 +}
11395 +
11396 +/**
11397 + * dpio_enable() - Enable the DPIO, allow I/O portal operations.
11398 + * @mc_io: Pointer to MC portal's I/O object
11399 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
11400 + * @token: Token of DPIO object
11401 + *
11402 + * Return: '0' on Success; Error code otherwise
11403 + */
11404 +int dpio_enable(struct fsl_mc_io *mc_io,
11405 + u32 cmd_flags,
11406 + u16 token)
11407 +{
11408 + struct fsl_mc_command cmd = { 0 };
11409 +
11410 + /* prepare command */
11411 + cmd.header = mc_encode_cmd_header(DPIO_CMDID_ENABLE,
11412 + cmd_flags,
11413 + token);
11414 +
11415 + return mc_send_command(mc_io, &cmd);
11416 +}
11417 +
11418 +/**
11419 + * dpio_disable() - Disable the DPIO, stop any I/O portal operation.
11420 + * @mc_io: Pointer to MC portal's I/O object
11421 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
11422 + * @token: Token of DPIO object
11423 + *
11424 + * Return: '0' on Success; Error code otherwise
11425 + */
11426 +int dpio_disable(struct fsl_mc_io *mc_io,
11427 + u32 cmd_flags,
11428 + u16 token)
11429 +{
11430 + struct fsl_mc_command cmd = { 0 };
11431 +
11432 + /* prepare command */
11433 + cmd.header = mc_encode_cmd_header(DPIO_CMDID_DISABLE,
11434 + cmd_flags,
11435 + token);
11436 +
11437 + return mc_send_command(mc_io, &cmd);
11438 +}
11439 +
11440 +/**
11441 + * dpio_get_attributes() - Retrieve DPIO attributes
11442 + * @mc_io: Pointer to MC portal's I/O object
11443 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
11444 + * @token: Token of DPIO object
11445 + * @attr: Returned object's attributes
11446 + *
11447 + * Return: '0' on Success; Error code otherwise
11448 + */
11449 +int dpio_get_attributes(struct fsl_mc_io *mc_io,
11450 + u32 cmd_flags,
11451 + u16 token,
11452 + struct dpio_attr *attr)
11453 +{
11454 + struct fsl_mc_command cmd = { 0 };
11455 + struct dpio_rsp_get_attr *dpio_rsp;
11456 + int err;
11457 +
11458 + /* prepare command */
11459 + cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_ATTR,
11460 + cmd_flags,
11461 + token);
11462 +
11463 + err = mc_send_command(mc_io, &cmd);
11464 + if (err)
11465 + return err;
11466 +
11467 + /* retrieve response parameters */
11468 + dpio_rsp = (struct dpio_rsp_get_attr *)cmd.params;
11469 + attr->id = le32_to_cpu(dpio_rsp->id);
11470 + attr->qbman_portal_id = le16_to_cpu(dpio_rsp->qbman_portal_id);
11471 + attr->num_priorities = dpio_rsp->num_priorities;
11472 + attr->channel_mode = dpio_rsp->channel_mode & DPIO_CHANNEL_MODE_MASK;
11473 + attr->qbman_portal_ce_offset =
11474 + le64_to_cpu(dpio_rsp->qbman_portal_ce_addr);
11475 + attr->qbman_portal_ci_offset =
11476 + le64_to_cpu(dpio_rsp->qbman_portal_ci_addr);
11477 + attr->qbman_version = le32_to_cpu(dpio_rsp->qbman_version);
11478 +
11479 + return 0;
11480 +}
11481 +
11482 +/**
11483 + * dpio_get_api_version - Get Data Path I/O API version
11484 + * @mc_io: Pointer to MC portal's DPIO object
11485 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
11486 + * @major_ver: Major version of DPIO API
11487 + * @minor_ver: Minor version of DPIO API
11488 + *
11489 + * Return: '0' on Success; Error code otherwise
11490 + */
11491 +int dpio_get_api_version(struct fsl_mc_io *mc_io,
11492 + u32 cmd_flags,
11493 + u16 *major_ver,
11494 + u16 *minor_ver)
11495 +{
11496 + struct fsl_mc_command cmd = { 0 };
11497 + int err;
11498 +
11499 + /* prepare command */
11500 + cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_API_VERSION,
11501 + cmd_flags, 0);
11502 +
11503 + err = mc_send_command(mc_io, &cmd);
11504 + if (err)
11505 + return err;
11506 +
11507 + /* retrieve response parameters */
11508 + mc_cmd_read_api_version(&cmd, major_ver, minor_ver);
11509 +
11510 + return 0;
11511 +}
11512 +
11513 +/**
11514 + * dpio_reset() - Reset the DPIO, returns the object to initial state.
11515 + * @mc_io: Pointer to MC portal's I/O object
11516 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
11517 + * @token: Token of DPIO object
11518 + *
11519 + * Return: '0' on Success; Error code otherwise.
11520 + */
11521 +int dpio_reset(struct fsl_mc_io *mc_io,
11522 + u32 cmd_flags,
11523 + u16 token)
11524 +{
11525 + struct fsl_mc_command cmd = { 0 };
11526 +
11527 + /* prepare command */
11528 + cmd.header = mc_encode_cmd_header(DPIO_CMDID_RESET,
11529 + cmd_flags,
11530 + token);
11531 +
11532 + /* send command to mc*/
11533 + return mc_send_command(mc_io, &cmd);
11534 +}
11535 --- /dev/null
11536 +++ b/drivers/staging/fsl-mc/bus/dpio/dpio.h
11537 @@ -0,0 +1,87 @@
11538 +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
11539 +/*
11540 + * Copyright 2013-2016 Freescale Semiconductor Inc.
11541 + * Copyright 2016 NXP
11542 + *
11543 + */
11544 +#ifndef __FSL_DPIO_H
11545 +#define __FSL_DPIO_H
11546 +
11547 +struct fsl_mc_io;
11548 +
11549 +int dpio_open(struct fsl_mc_io *mc_io,
11550 + u32 cmd_flags,
11551 + int dpio_id,
11552 + u16 *token);
11553 +
11554 +int dpio_close(struct fsl_mc_io *mc_io,
11555 + u32 cmd_flags,
11556 + u16 token);
11557 +
11558 +/**
11559 + * enum dpio_channel_mode - DPIO notification channel mode
11560 + * @DPIO_NO_CHANNEL: No support for notification channel
11561 + * @DPIO_LOCAL_CHANNEL: Notifications on data availability can be received by a
11562 + * dedicated channel in the DPIO; user should point the queue's
11563 + * destination in the relevant interface to this DPIO
11564 + */
11565 +enum dpio_channel_mode {
11566 + DPIO_NO_CHANNEL = 0,
11567 + DPIO_LOCAL_CHANNEL = 1,
11568 +};
11569 +
11570 +/**
11571 + * struct dpio_cfg - Structure representing DPIO configuration
11572 + * @channel_mode: Notification channel mode
11573 + * @num_priorities: Number of priorities for the notification channel (1-8);
11574 + * relevant only if 'channel_mode = DPIO_LOCAL_CHANNEL'
11575 + */
11576 +struct dpio_cfg {
11577 + enum dpio_channel_mode channel_mode;
11578 + u8 num_priorities;
11579 +};
11580 +
11581 +int dpio_enable(struct fsl_mc_io *mc_io,
11582 + u32 cmd_flags,
11583 + u16 token);
11584 +
11585 +int dpio_disable(struct fsl_mc_io *mc_io,
11586 + u32 cmd_flags,
11587 + u16 token);
11588 +
11589 +/**
11590 + * struct dpio_attr - Structure representing DPIO attributes
11591 + * @id: DPIO object ID
11592 + * @qbman_portal_ce_offset: offset of the software portal cache-enabled area
11593 + * @qbman_portal_ci_offset: offset of the software portal cache-inhibited area
11594 + * @qbman_portal_id: Software portal ID
11595 + * @channel_mode: Notification channel mode
11596 + * @num_priorities: Number of priorities for the notification channel (1-8);
11597 + * relevant only if 'channel_mode = DPIO_LOCAL_CHANNEL'
11598 + * @qbman_version: QBMAN version
11599 + */
11600 +struct dpio_attr {
11601 + int id;
11602 + u64 qbman_portal_ce_offset;
11603 + u64 qbman_portal_ci_offset;
11604 + u16 qbman_portal_id;
11605 + enum dpio_channel_mode channel_mode;
11606 + u8 num_priorities;
11607 + u32 qbman_version;
11608 +};
11609 +
11610 +int dpio_get_attributes(struct fsl_mc_io *mc_io,
11611 + u32 cmd_flags,
11612 + u16 token,
11613 + struct dpio_attr *attr);
11614 +
11615 +int dpio_get_api_version(struct fsl_mc_io *mc_io,
11616 + u32 cmd_flags,
11617 + u16 *major_ver,
11618 + u16 *minor_ver);
11619 +
11620 +int dpio_reset(struct fsl_mc_io *mc_io,
11621 + u32 cmd_flags,
11622 + u16 token);
11623 +
11624 +#endif /* __FSL_DPIO_H */
11625 --- /dev/null
11626 +++ b/drivers/staging/fsl-mc/bus/dpio/qbman-portal.c
11627 @@ -0,0 +1,1164 @@
11628 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
11629 +/*
11630 + * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
11631 + * Copyright 2016 NXP
11632 + *
11633 + */
11634 +
11635 +#include <asm/cacheflush.h>
11636 +#include <linux/io.h>
11637 +#include <linux/slab.h>
11638 +#include "../../include/dpaa2-global.h"
11639 +
11640 +#include "qbman-portal.h"
11641 +
11642 +#define QMAN_REV_4000 0x04000000
11643 +#define QMAN_REV_4100 0x04010000
11644 +#define QMAN_REV_4101 0x04010001
11645 +#define QMAN_REV_MASK 0xffff0000
11646 +
11647 +/* All QBMan command and result structures use this "valid bit" encoding */
11648 +#define QB_VALID_BIT ((u32)0x80)
11649 +
11650 +/* QBMan portal management command codes */
11651 +#define QBMAN_MC_ACQUIRE 0x30
11652 +#define QBMAN_WQCHAN_CONFIGURE 0x46
11653 +
11654 +/* CINH register offsets */
11655 +#define QBMAN_CINH_SWP_EQAR 0x8c0
11656 +#define QBMAN_CINH_SWP_DQPI 0xa00
11657 +#define QBMAN_CINH_SWP_DCAP 0xac0
11658 +#define QBMAN_CINH_SWP_SDQCR 0xb00
11659 +#define QBMAN_CINH_SWP_RAR 0xcc0
11660 +#define QBMAN_CINH_SWP_ISR 0xe00
11661 +#define QBMAN_CINH_SWP_IER 0xe40
11662 +#define QBMAN_CINH_SWP_ISDR 0xe80
11663 +#define QBMAN_CINH_SWP_IIR 0xec0
11664 +
11665 +/* CENA register offsets */
11666 +#define QBMAN_CENA_SWP_EQCR(n) (0x000 + ((u32)(n) << 6))
11667 +#define QBMAN_CENA_SWP_DQRR(n) (0x200 + ((u32)(n) << 6))
11668 +#define QBMAN_CENA_SWP_RCR(n) (0x400 + ((u32)(n) << 6))
11669 +#define QBMAN_CENA_SWP_CR 0x600
11670 +#define QBMAN_CENA_SWP_RR(vb) (0x700 + ((u32)(vb) >> 1))
11671 +#define QBMAN_CENA_SWP_VDQCR 0x780
11672 +
11673 +/* Reverse mapping of QBMAN_CENA_SWP_DQRR() */
11674 +#define QBMAN_IDX_FROM_DQRR(p) (((unsigned long)(p) & 0x1ff) >> 6)
11675 +
11676 +/* Define token used to determine if response written to memory is valid */
11677 +#define QMAN_DQ_TOKEN_VALID 1
11678 +
11679 +/* SDQCR attribute codes */
11680 +#define QB_SDQCR_FC_SHIFT 29
11681 +#define QB_SDQCR_FC_MASK 0x1
11682 +#define QB_SDQCR_DCT_SHIFT 24
11683 +#define QB_SDQCR_DCT_MASK 0x3
11684 +#define QB_SDQCR_TOK_SHIFT 16
11685 +#define QB_SDQCR_TOK_MASK 0xff
11686 +#define QB_SDQCR_SRC_SHIFT 0
11687 +#define QB_SDQCR_SRC_MASK 0xffff
11688 +
11689 +/* opaque token for static dequeues */
11690 +#define QMAN_SDQCR_TOKEN 0xbb
11691 +
11692 +enum qbman_sdqcr_dct {
11693 + qbman_sdqcr_dct_null = 0,
11694 + qbman_sdqcr_dct_prio_ics,
11695 + qbman_sdqcr_dct_active_ics,
11696 + qbman_sdqcr_dct_active
11697 +};
11698 +
11699 +enum qbman_sdqcr_fc {
11700 + qbman_sdqcr_fc_one = 0,
11701 + qbman_sdqcr_fc_up_to_3 = 1
11702 +};
11703 +
11704 +#define dccvac(p) { asm volatile("dc cvac, %0;" : : "r" (p) : "memory"); }
11705 +#define dcivac(p) { asm volatile("dc ivac, %0" : : "r"(p) : "memory"); }
11706 +static inline void qbman_inval_prefetch(struct qbman_swp *p, uint32_t offset)
11707 +{
11708 + dcivac(p->addr_cena + offset);
11709 + prefetch(p->addr_cena + offset);
11710 +}
11711 +
11712 +/* Portal Access */
11713 +
11714 +static inline u32 qbman_read_register(struct qbman_swp *p, u32 offset)
11715 +{
11716 + return readl_relaxed(p->addr_cinh + offset);
11717 +}
11718 +
11719 +static inline void qbman_write_register(struct qbman_swp *p, u32 offset,
11720 + u32 value)
11721 +{
11722 + writel_relaxed(value, p->addr_cinh + offset);
11723 +}
11724 +
11725 +static inline void *qbman_get_cmd(struct qbman_swp *p, u32 offset)
11726 +{
11727 + return p->addr_cena + offset;
11728 +}
11729 +
11730 +#define QBMAN_CINH_SWP_CFG 0xd00
11731 +
11732 +#define SWP_CFG_DQRR_MF_SHIFT 20
11733 +#define SWP_CFG_EST_SHIFT 16
11734 +#define SWP_CFG_WN_SHIFT 14
11735 +#define SWP_CFG_RPM_SHIFT 12
11736 +#define SWP_CFG_DCM_SHIFT 10
11737 +#define SWP_CFG_EPM_SHIFT 8
11738 +#define SWP_CFG_SD_SHIFT 5
11739 +#define SWP_CFG_SP_SHIFT 4
11740 +#define SWP_CFG_SE_SHIFT 3
11741 +#define SWP_CFG_DP_SHIFT 2
11742 +#define SWP_CFG_DE_SHIFT 1
11743 +#define SWP_CFG_EP_SHIFT 0
11744 +
11745 +static inline u32 qbman_set_swp_cfg(u8 max_fill, u8 wn, u8 est, u8 rpm, u8 dcm,
11746 + u8 epm, int sd, int sp, int se,
11747 + int dp, int de, int ep)
11748 +{
11749 + return (max_fill << SWP_CFG_DQRR_MF_SHIFT |
11750 + est << SWP_CFG_EST_SHIFT |
11751 + wn << SWP_CFG_WN_SHIFT |
11752 + rpm << SWP_CFG_RPM_SHIFT |
11753 + dcm << SWP_CFG_DCM_SHIFT |
11754 + epm << SWP_CFG_EPM_SHIFT |
11755 + sd << SWP_CFG_SD_SHIFT |
11756 + sp << SWP_CFG_SP_SHIFT |
11757 + se << SWP_CFG_SE_SHIFT |
11758 + dp << SWP_CFG_DP_SHIFT |
11759 + de << SWP_CFG_DE_SHIFT |
11760 + ep << SWP_CFG_EP_SHIFT);
11761 +}
11762 +
11763 +/**
11764 + * qbman_swp_init() - Create a functional object representing the given
11765 + * QBMan portal descriptor.
11766 + * @d: the given qbman swp descriptor
11767 + *
11768 + * Return qbman_swp portal for success, NULL if the object cannot
11769 + * be created.
11770 + */
11771 +struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d)
11772 +{
11773 + struct qbman_swp *p = kmalloc(sizeof(*p), GFP_KERNEL);
11774 + u32 reg;
11775 +
11776 + if (!p)
11777 + return NULL;
11778 + p->desc = d;
11779 + p->mc.valid_bit = QB_VALID_BIT;
11780 + p->sdq = 0;
11781 + p->sdq |= qbman_sdqcr_dct_prio_ics << QB_SDQCR_DCT_SHIFT;
11782 + p->sdq |= qbman_sdqcr_fc_up_to_3 << QB_SDQCR_FC_SHIFT;
11783 + p->sdq |= QMAN_SDQCR_TOKEN << QB_SDQCR_TOK_SHIFT;
11784 +
11785 + atomic_set(&p->vdq.available, 1);
11786 + p->vdq.valid_bit = QB_VALID_BIT;
11787 + p->dqrr.next_idx = 0;
11788 + p->dqrr.valid_bit = QB_VALID_BIT;
11789 +
11790 + if ((p->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_4100) {
11791 + p->dqrr.dqrr_size = 4;
11792 + p->dqrr.reset_bug = 1;
11793 + } else {
11794 + p->dqrr.dqrr_size = 8;
11795 + p->dqrr.reset_bug = 0;
11796 + }
11797 +
11798 + p->addr_cena = d->cena_bar;
11799 + p->addr_cinh = d->cinh_bar;
11800 +
11801 + reg = qbman_set_swp_cfg(p->dqrr.dqrr_size,
11802 + 0, /* Writes cacheable */
11803 + 0, /* EQCR_CI stashing threshold */
11804 + 3, /* RPM: Valid bit mode, RCR in array mode */
11805 + 2, /* DCM: Discrete consumption ack mode */
11806 + 3, /* EPM: Valid bit mode, EQCR in array mode */
11807 + 0, /* mem stashing drop enable == FALSE */
11808 + 1, /* mem stashing priority == TRUE */
11809 + 0, /* mem stashing enable == FALSE */
11810 + 1, /* dequeue stashing priority == TRUE */
11811 + 0, /* dequeue stashing enable == FALSE */
11812 + 0); /* EQCR_CI stashing priority == FALSE */
11813 +
11814 + qbman_write_register(p, QBMAN_CINH_SWP_CFG, reg);
11815 + reg = qbman_read_register(p, QBMAN_CINH_SWP_CFG);
11816 + if (!reg) {
11817 + pr_err("qbman: the portal is not enabled!\n");
11818 + return NULL;
11819 + }
11820 +
11821 + /*
11822 + * SDQCR needs to be initialized to 0 when no channels are
11823 + * being dequeued from or else the QMan HW will indicate an
11824 + * error. The values that were calculated above will be
11825 + * applied when dequeues from a specific channel are enabled.
11826 + */
11827 + qbman_write_register(p, QBMAN_CINH_SWP_SDQCR, 0);
11828 + return p;
11829 +}
11830 +
11831 +/**
11832 + * qbman_swp_finish() - Create and destroy a functional object representing
11833 + * the given QBMan portal descriptor.
11834 + * @p: the qbman_swp object to be destroyed
11835 + */
11836 +void qbman_swp_finish(struct qbman_swp *p)
11837 +{
11838 + kfree(p);
11839 +}
11840 +
11841 +/**
11842 + * qbman_swp_interrupt_read_status()
11843 + * @p: the given software portal
11844 + *
11845 + * Return the value in the SWP_ISR register.
11846 + */
11847 +u32 qbman_swp_interrupt_read_status(struct qbman_swp *p)
11848 +{
11849 + return qbman_read_register(p, QBMAN_CINH_SWP_ISR);
11850 +}
11851 +
11852 +/**
11853 + * qbman_swp_interrupt_clear_status()
11854 + * @p: the given software portal
11855 + * @mask: The mask to clear in SWP_ISR register
11856 + */
11857 +void qbman_swp_interrupt_clear_status(struct qbman_swp *p, u32 mask)
11858 +{
11859 + qbman_write_register(p, QBMAN_CINH_SWP_ISR, mask);
11860 +}
11861 +
11862 +/**
11863 + * qbman_swp_interrupt_get_trigger() - read interrupt enable register
11864 + * @p: the given software portal
11865 + *
11866 + * Return the value in the SWP_IER register.
11867 + */
11868 +u32 qbman_swp_interrupt_get_trigger(struct qbman_swp *p)
11869 +{
11870 + return qbman_read_register(p, QBMAN_CINH_SWP_IER);
11871 +}
11872 +
11873 +/**
11874 + * qbman_swp_interrupt_set_trigger() - enable interrupts for a swp
11875 + * @p: the given software portal
11876 + * @mask: The mask of bits to enable in SWP_IER
11877 + */
11878 +void qbman_swp_interrupt_set_trigger(struct qbman_swp *p, u32 mask)
11879 +{
11880 + qbman_write_register(p, QBMAN_CINH_SWP_IER, mask);
11881 +}
11882 +
11883 +/**
11884 + * qbman_swp_interrupt_get_inhibit() - read interrupt mask register
11885 + * @p: the given software portal object
11886 + *
11887 + * Return the value in the SWP_IIR register.
11888 + */
11889 +int qbman_swp_interrupt_get_inhibit(struct qbman_swp *p)
11890 +{
11891 + return qbman_read_register(p, QBMAN_CINH_SWP_IIR);
11892 +}
11893 +
11894 +/**
11895 + * qbman_swp_interrupt_set_inhibit() - write interrupt mask register
11896 + * @p: the given software portal object
11897 + * @mask: The mask to set in SWP_IIR register
11898 + */
11899 +void qbman_swp_interrupt_set_inhibit(struct qbman_swp *p, int inhibit)
11900 +{
11901 + qbman_write_register(p, QBMAN_CINH_SWP_IIR, inhibit ? 0xffffffff : 0);
11902 +}
11903 +
11904 +/*
11905 + * Different management commands all use this common base layer of code to issue
11906 + * commands and poll for results.
11907 + */
11908 +
11909 +/*
11910 + * Returns a pointer to where the caller should fill in their management command
11911 + * (caller should ignore the verb byte)
11912 + */
11913 +void *qbman_swp_mc_start(struct qbman_swp *p)
11914 +{
11915 + return qbman_get_cmd(p, QBMAN_CENA_SWP_CR);
11916 +}
11917 +
11918 +/*
11919 + * Commits merges in the caller-supplied command verb (which should not include
11920 + * the valid-bit) and submits the command to hardware
11921 + */
11922 +void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, u8 cmd_verb)
11923 +{
11924 + u8 *v = cmd;
11925 +
11926 + dma_wmb();
11927 + *v = cmd_verb | p->mc.valid_bit;
11928 + dccvac(cmd);
11929 +}
11930 +
11931 +/*
11932 + * Checks for a completed response (returns non-NULL if only if the response
11933 + * is complete).
11934 + */
11935 +void *qbman_swp_mc_result(struct qbman_swp *p)
11936 +{
11937 + u32 *ret, verb;
11938 +
11939 + qbman_inval_prefetch(p, QBMAN_CENA_SWP_RR(p->mc.valid_bit));
11940 + ret = qbman_get_cmd(p, QBMAN_CENA_SWP_RR(p->mc.valid_bit));
11941 +
11942 + /* Remove the valid-bit - command completed if the rest is non-zero */
11943 + verb = ret[0] & ~QB_VALID_BIT;
11944 + if (!verb)
11945 + return NULL;
11946 + p->mc.valid_bit ^= QB_VALID_BIT;
11947 + return ret;
11948 +}
11949 +
11950 +#define QB_ENQUEUE_CMD_OPTIONS_SHIFT 0
11951 +enum qb_enqueue_commands {
11952 + enqueue_empty = 0,
11953 + enqueue_response_always = 1,
11954 + enqueue_rejects_to_fq = 2
11955 +};
11956 +
11957 +#define QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT 2
11958 +#define QB_ENQUEUE_CMD_IRQ_ON_DISPATCH_SHIFT 3
11959 +#define QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT 4
11960 +
11961 +/**
11962 + * qbman_eq_desc_clear() - Clear the contents of a descriptor to
11963 + * default/starting state.
11964 + */
11965 +void qbman_eq_desc_clear(struct qbman_eq_desc *d)
11966 +{
11967 + memset(d, 0, sizeof(*d));
11968 +}
11969 +
11970 +/**
11971 + * qbman_eq_desc_set_no_orp() - Set enqueue descriptor without orp
11972 + * @d: the enqueue descriptor.
11973 + * @response_success: 1 = enqueue with response always; 0 = enqueue with
11974 + * rejections returned on a FQ.
11975 + */
11976 +void qbman_eq_desc_set_no_orp(struct qbman_eq_desc *d, int respond_success)
11977 +{
11978 + d->verb &= ~(1 << QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT);
11979 + if (respond_success)
11980 + d->verb |= enqueue_response_always;
11981 + else
11982 + d->verb |= enqueue_rejects_to_fq;
11983 +}
11984 +
11985 +/**
11986 + * qbman_eq_desc_set_orp() - Set order-restoration in the enqueue descriptor
11987 + * @d: the enqueue descriptor.
11988 + * @response_success: 1 = enqueue with response always; 0 = enqueue with
11989 + * rejections returned on a FQ.
11990 + * @oprid: the order point record id.
11991 + * @seqnum: the order restoration sequence number.
11992 + * @incomplete: indicates whether this is the last fragments using the same
11993 + * sequence number.
11994 + */
11995 +void qbman_eq_desc_set_orp(struct qbman_eq_desc *d, int respond_success,
11996 + u16 oprid, u16 seqnum, int incomplete)
11997 +{
11998 + d->verb |= (1 << QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT);
11999 + if (respond_success)
12000 + d->verb |= enqueue_response_always;
12001 + else
12002 + d->verb |= enqueue_rejects_to_fq;
12003 + d->orpid = cpu_to_le16(oprid);
12004 + d->seqnum = cpu_to_le16((!!incomplete << 14) | seqnum);
12005 +}
12006 +
12007 +/**
12008 + * qbman_eq_desc_set_orp_hole() - fill a hole in the order-restoration sequence
12009 + * without any enqueue
12010 + * @d: the enqueue descriptor.
12011 + * @oprid: the order point record id.
12012 + * @seqnum: the order restoration sequence number.
12013 + */
12014 +void qbman_eq_desc_set_orp_hole(struct qbman_eq_desc *d, u16 oprid,
12015 + u16 seqnum)
12016 +{
12017 + d->verb |= (1 << QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT) | enqueue_empty;
12018 + d->orpid = cpu_to_le16(oprid);
12019 + d->seqnum = cpu_to_le16(seqnum);
12020 +}
12021 +
12022 +/*
12023 + * Exactly one of the following descriptor "targets" should be set. (Calling any
12024 + * one of these will replace the effect of any prior call to one of these.)
12025 + * -enqueue to a frame queue
12026 + * -enqueue to a queuing destination
12027 + */
12028 +
12029 +/**
12030 + * qbman_eq_desc_set_fq() - set the FQ for the enqueue command
12031 + * @d: the enqueue descriptor
12032 + * @fqid: the id of the frame queue to be enqueued
12033 + */
12034 +void qbman_eq_desc_set_fq(struct qbman_eq_desc *d, u32 fqid)
12035 +{
12036 + d->verb &= ~(1 << QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT);
12037 + d->tgtid = cpu_to_le32(fqid);
12038 +}
12039 +
12040 +/**
12041 + * qbman_eq_desc_set_qd() - Set Queuing Destination for the enqueue command
12042 + * @d: the enqueue descriptor
12043 + * @qdid: the id of the queuing destination to be enqueued
12044 + * @qd_bin: the queuing destination bin
12045 + * @qd_prio: the queuing destination priority
12046 + */
12047 +void qbman_eq_desc_set_qd(struct qbman_eq_desc *d, u32 qdid,
12048 + u32 qd_bin, u32 qd_prio)
12049 +{
12050 + d->verb |= 1 << QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT;
12051 + d->tgtid = cpu_to_le32(qdid);
12052 + d->qdbin = cpu_to_le16(qd_bin);
12053 + d->qpri = qd_prio;
12054 +}
12055 +
12056 +#define EQAR_IDX(eqar) ((eqar) & 0x7)
12057 +#define EQAR_VB(eqar) ((eqar) & 0x80)
12058 +#define EQAR_SUCCESS(eqar) ((eqar) & 0x100)
12059 +
12060 +/**
12061 + * qbman_swp_enqueue() - Issue an enqueue command
12062 + * @s: the software portal used for enqueue
12063 + * @d: the enqueue descriptor
12064 + * @fd: the frame descriptor to be enqueued
12065 + *
12066 + * Please note that 'fd' should only be NULL if the "action" of the
12067 + * descriptor is "orp_hole" or "orp_nesn".
12068 + *
12069 + * Return 0 for successful enqueue, -EBUSY if the EQCR is not ready.
12070 + */
12071 +int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d,
12072 + const struct dpaa2_fd *fd)
12073 +{
12074 + struct qbman_eq_desc *p;
12075 + u32 eqar = qbman_read_register(s, QBMAN_CINH_SWP_EQAR);
12076 +
12077 + if (!EQAR_SUCCESS(eqar))
12078 + return -EBUSY;
12079 +
12080 + p = qbman_get_cmd(s, QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar)));
12081 + /* This is mapped as DEVICE type memory, writes are
12082 + * with address alignment:
12083 + * desc.dca address alignment = 1
12084 + * desc.seqnum address alignment = 2
12085 + * desc.orpid address alignment = 4
12086 + * desc.tgtid address alignment = 8
12087 + */
12088 + p->dca = d->dca;
12089 + p->seqnum = d->seqnum;
12090 + p->orpid = d->orpid;
12091 + memcpy(&p->tgtid, &d->tgtid, 24);
12092 + memcpy(&p->fd, fd, sizeof(*fd));
12093 +
12094 + /* Set the verb byte, have to substitute in the valid-bit */
12095 + dma_wmb();
12096 + p->verb = d->verb | EQAR_VB(eqar);
12097 + dccvac(p);
12098 +
12099 + return 0;
12100 +}
12101 +
12102 +/* Static (push) dequeue */
12103 +
12104 +/**
12105 + * qbman_swp_push_get() - Get the push dequeue setup
12106 + * @p: the software portal object
12107 + * @channel_idx: the channel index to query
12108 + * @enabled: returned boolean to show whether the push dequeue is enabled
12109 + * for the given channel
12110 + */
12111 +void qbman_swp_push_get(struct qbman_swp *s, u8 channel_idx, int *enabled)
12112 +{
12113 + u16 src = (s->sdq >> QB_SDQCR_SRC_SHIFT) & QB_SDQCR_SRC_MASK;
12114 +
12115 + WARN_ON(channel_idx > 15);
12116 + *enabled = src | (1 << channel_idx);
12117 +}
12118 +
12119 +/**
12120 + * qbman_swp_push_set() - Enable or disable push dequeue
12121 + * @p: the software portal object
12122 + * @channel_idx: the channel index (0 to 15)
12123 + * @enable: enable or disable push dequeue
12124 + */
12125 +void qbman_swp_push_set(struct qbman_swp *s, u8 channel_idx, int enable)
12126 +{
12127 + u16 dqsrc;
12128 +
12129 + WARN_ON(channel_idx > 15);
12130 + if (enable)
12131 + s->sdq |= 1 << channel_idx;
12132 + else
12133 + s->sdq &= ~(1 << channel_idx);
12134 +
12135 + /* Read make the complete src map. If no channels are enabled
12136 + * the SDQCR must be 0 or else QMan will assert errors
12137 + */
12138 + dqsrc = (s->sdq >> QB_SDQCR_SRC_SHIFT) & QB_SDQCR_SRC_MASK;
12139 + if (dqsrc != 0)
12140 + qbman_write_register(s, QBMAN_CINH_SWP_SDQCR, s->sdq);
12141 + else
12142 + qbman_write_register(s, QBMAN_CINH_SWP_SDQCR, 0);
12143 +}
12144 +
12145 +#define QB_VDQCR_VERB_DCT_SHIFT 0
12146 +#define QB_VDQCR_VERB_DT_SHIFT 2
12147 +#define QB_VDQCR_VERB_RLS_SHIFT 4
12148 +#define QB_VDQCR_VERB_WAE_SHIFT 5
12149 +
12150 +enum qb_pull_dt_e {
12151 + qb_pull_dt_channel,
12152 + qb_pull_dt_workqueue,
12153 + qb_pull_dt_framequeue
12154 +};
12155 +
12156 +/**
12157 + * qbman_pull_desc_clear() - Clear the contents of a descriptor to
12158 + * default/starting state
12159 + * @d: the pull dequeue descriptor to be cleared
12160 + */
12161 +void qbman_pull_desc_clear(struct qbman_pull_desc *d)
12162 +{
12163 + memset(d, 0, sizeof(*d));
12164 +}
12165 +
12166 +/**
12167 + * qbman_pull_desc_set_storage()- Set the pull dequeue storage
12168 + * @d: the pull dequeue descriptor to be set
12169 + * @storage: the pointer of the memory to store the dequeue result
12170 + * @storage_phys: the physical address of the storage memory
12171 + * @stash: to indicate whether write allocate is enabled
12172 + *
12173 + * If not called, or if called with 'storage' as NULL, the result pull dequeues
12174 + * will produce results to DQRR. If 'storage' is non-NULL, then results are
12175 + * produced to the given memory location (using the DMA address which
12176 + * the caller provides in 'storage_phys'), and 'stash' controls whether or not
12177 + * those writes to main-memory express a cache-warming attribute.
12178 + */
12179 +void qbman_pull_desc_set_storage(struct qbman_pull_desc *d,
12180 + struct dpaa2_dq *storage,
12181 + dma_addr_t storage_phys,
12182 + int stash)
12183 +{
12184 + /* save the virtual address */
12185 + d->rsp_addr_virt = (u64)(uintptr_t)storage;
12186 +
12187 + if (!storage) {
12188 + d->verb &= ~(1 << QB_VDQCR_VERB_RLS_SHIFT);
12189 + return;
12190 + }
12191 + d->verb |= 1 << QB_VDQCR_VERB_RLS_SHIFT;
12192 + if (stash)
12193 + d->verb |= 1 << QB_VDQCR_VERB_WAE_SHIFT;
12194 + else
12195 + d->verb &= ~(1 << QB_VDQCR_VERB_WAE_SHIFT);
12196 +
12197 + d->rsp_addr = cpu_to_le64(storage_phys);
12198 +}
12199 +
12200 +/**
12201 + * qbman_pull_desc_set_numframes() - Set the number of frames to be dequeued
12202 + * @d: the pull dequeue descriptor to be set
12203 + * @numframes: number of frames to be set, must be between 1 and 16, inclusive
12204 + */
12205 +void qbman_pull_desc_set_numframes(struct qbman_pull_desc *d, u8 numframes)
12206 +{
12207 + d->numf = numframes - 1;
12208 +}
12209 +
12210 +void qbman_pull_desc_set_token(struct qbman_pull_desc *d, u8 token)
12211 +{
12212 + d->tok = token;
12213 +}
12214 +
12215 +/*
12216 + * Exactly one of the following descriptor "actions" should be set. (Calling any
12217 + * one of these will replace the effect of any prior call to one of these.)
12218 + * - pull dequeue from the given frame queue (FQ)
12219 + * - pull dequeue from any FQ in the given work queue (WQ)
12220 + * - pull dequeue from any FQ in any WQ in the given channel
12221 + */
12222 +
12223 +/**
12224 + * qbman_pull_desc_set_fq() - Set fqid from which the dequeue command dequeues
12225 + * @fqid: the frame queue index of the given FQ
12226 + */
12227 +void qbman_pull_desc_set_fq(struct qbman_pull_desc *d, u32 fqid)
12228 +{
12229 + d->verb |= 1 << QB_VDQCR_VERB_DCT_SHIFT;
12230 + d->verb |= qb_pull_dt_framequeue << QB_VDQCR_VERB_DT_SHIFT;
12231 + d->dq_src = cpu_to_le32(fqid);
12232 +}
12233 +
12234 +/**
12235 + * qbman_pull_desc_set_wq() - Set wqid from which the dequeue command dequeues
12236 + * @wqid: composed of channel id and wqid within the channel
12237 + * @dct: the dequeue command type
12238 + */
12239 +void qbman_pull_desc_set_wq(struct qbman_pull_desc *d, u32 wqid,
12240 + enum qbman_pull_type_e dct)
12241 +{
12242 + d->verb |= dct << QB_VDQCR_VERB_DCT_SHIFT;
12243 + d->verb |= qb_pull_dt_workqueue << QB_VDQCR_VERB_DT_SHIFT;
12244 + d->dq_src = cpu_to_le32(wqid);
12245 +}
12246 +
12247 +/**
12248 + * qbman_pull_desc_set_channel() - Set channelid from which the dequeue command
12249 + * dequeues
12250 + * @chid: the channel id to be dequeued
12251 + * @dct: the dequeue command type
12252 + */
12253 +void qbman_pull_desc_set_channel(struct qbman_pull_desc *d, u32 chid,
12254 + enum qbman_pull_type_e dct)
12255 +{
12256 + d->verb |= dct << QB_VDQCR_VERB_DCT_SHIFT;
12257 + d->verb |= qb_pull_dt_channel << QB_VDQCR_VERB_DT_SHIFT;
12258 + d->dq_src = cpu_to_le32(chid);
12259 +}
12260 +
12261 +/**
12262 + * qbman_swp_pull() - Issue the pull dequeue command
12263 + * @s: the software portal object
12264 + * @d: the software portal descriptor which has been configured with
12265 + * the set of qbman_pull_desc_set_*() calls
12266 + *
12267 + * Return 0 for success, and -EBUSY if the software portal is not ready
12268 + * to do pull dequeue.
12269 + */
12270 +int qbman_swp_pull(struct qbman_swp *s, struct qbman_pull_desc *d)
12271 +{
12272 + struct qbman_pull_desc *p;
12273 +
12274 + if (!atomic_dec_and_test(&s->vdq.available)) {
12275 + atomic_inc(&s->vdq.available);
12276 + return -EBUSY;
12277 + }
12278 + s->vdq.storage = (void *)(uintptr_t)d->rsp_addr_virt;
12279 + p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR);
12280 + p->numf = d->numf;
12281 + p->tok = QMAN_DQ_TOKEN_VALID;
12282 + p->dq_src = d->dq_src;
12283 + p->rsp_addr = d->rsp_addr;
12284 + p->rsp_addr_virt = d->rsp_addr_virt;
12285 + dma_wmb();
12286 +
12287 + /* Set the verb byte, have to substitute in the valid-bit */
12288 + p->verb = d->verb | s->vdq.valid_bit;
12289 + s->vdq.valid_bit ^= QB_VALID_BIT;
12290 + dccvac(p);
12291 +
12292 + return 0;
12293 +}
12294 +
12295 +#define QMAN_DQRR_PI_MASK 0xf
12296 +
12297 +/**
12298 + * qbman_swp_dqrr_next() - Get an valid DQRR entry
12299 + * @s: the software portal object
12300 + *
12301 + * Return NULL if there are no unconsumed DQRR entries. Return a DQRR entry
12302 + * only once, so repeated calls can return a sequence of DQRR entries, without
12303 + * requiring they be consumed immediately or in any particular order.
12304 + */
12305 +const struct dpaa2_dq *qbman_swp_dqrr_next(struct qbman_swp *s)
12306 +{
12307 + u32 verb;
12308 + u32 response_verb;
12309 + u32 flags;
12310 + struct dpaa2_dq *p;
12311 +
12312 + /* Before using valid-bit to detect if something is there, we have to
12313 + * handle the case of the DQRR reset bug...
12314 + */
12315 + if (unlikely(s->dqrr.reset_bug)) {
12316 + /*
12317 + * We pick up new entries by cache-inhibited producer index,
12318 + * which means that a non-coherent mapping would require us to
12319 + * invalidate and read *only* once that PI has indicated that
12320 + * there's an entry here. The first trip around the DQRR ring
12321 + * will be much less efficient than all subsequent trips around
12322 + * it...
12323 + */
12324 + u8 pi = qbman_read_register(s, QBMAN_CINH_SWP_DQPI) &
12325 + QMAN_DQRR_PI_MASK;
12326 +
12327 + /* there are new entries if pi != next_idx */
12328 + if (pi == s->dqrr.next_idx)
12329 + return NULL;
12330 +
12331 + /*
12332 + * if next_idx is/was the last ring index, and 'pi' is
12333 + * different, we can disable the workaround as all the ring
12334 + * entries have now been DMA'd to so valid-bit checking is
12335 + * repaired. Note: this logic needs to be based on next_idx
12336 + * (which increments one at a time), rather than on pi (which
12337 + * can burst and wrap-around between our snapshots of it).
12338 + */
12339 + if (s->dqrr.next_idx == (s->dqrr.dqrr_size - 1)) {
12340 + pr_debug("next_idx=%d, pi=%d, clear reset bug\n",
12341 + s->dqrr.next_idx, pi);
12342 + s->dqrr.reset_bug = 0;
12343 + }
12344 + qbman_inval_prefetch(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx));
12345 + }
12346 +
12347 + p = qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx));
12348 + verb = p->dq.verb;
12349 +
12350 + /*
12351 + * If the valid-bit isn't of the expected polarity, nothing there. Note,
12352 + * in the DQRR reset bug workaround, we shouldn't need to skip these
12353 + * check, because we've already determined that a new entry is available
12354 + * and we've invalidated the cacheline before reading it, so the
12355 + * valid-bit behaviour is repaired and should tell us what we already
12356 + * knew from reading PI.
12357 + */
12358 + if ((verb & QB_VALID_BIT) != s->dqrr.valid_bit) {
12359 + qbman_inval_prefetch(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx));
12360 + return NULL;
12361 + }
12362 + /*
12363 + * There's something there. Move "next_idx" attention to the next ring
12364 + * entry (and prefetch it) before returning what we found.
12365 + */
12366 + s->dqrr.next_idx++;
12367 + s->dqrr.next_idx &= s->dqrr.dqrr_size - 1; /* Wrap around */
12368 + if (!s->dqrr.next_idx)
12369 + s->dqrr.valid_bit ^= QB_VALID_BIT;
12370 +
12371 + /*
12372 + * If this is the final response to a volatile dequeue command
12373 + * indicate that the vdq is available
12374 + */
12375 + flags = p->dq.stat;
12376 + response_verb = verb & QBMAN_RESULT_MASK;
12377 + if ((response_verb == QBMAN_RESULT_DQ) &&
12378 + (flags & DPAA2_DQ_STAT_VOLATILE) &&
12379 + (flags & DPAA2_DQ_STAT_EXPIRED))
12380 + atomic_inc(&s->vdq.available);
12381 +
12382 + qbman_inval_prefetch(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx));
12383 +
12384 + return p;
12385 +}
12386 +
12387 +/**
12388 + * qbman_swp_dqrr_consume() - Consume DQRR entries previously returned from
12389 + * qbman_swp_dqrr_next().
12390 + * @s: the software portal object
12391 + * @dq: the DQRR entry to be consumed
12392 + */
12393 +void qbman_swp_dqrr_consume(struct qbman_swp *s, const struct dpaa2_dq *dq)
12394 +{
12395 + qbman_write_register(s, QBMAN_CINH_SWP_DCAP, QBMAN_IDX_FROM_DQRR(dq));
12396 +}
12397 +
12398 +/**
12399 + * qbman_result_has_new_result() - Check and get the dequeue response from the
12400 + * dq storage memory set in pull dequeue command
12401 + * @s: the software portal object
12402 + * @dq: the dequeue result read from the memory
12403 + *
12404 + * Return 1 for getting a valid dequeue result, or 0 for not getting a valid
12405 + * dequeue result.
12406 + *
12407 + * Only used for user-provided storage of dequeue results, not DQRR. For
12408 + * efficiency purposes, the driver will perform any required endianness
12409 + * conversion to ensure that the user's dequeue result storage is in host-endian
12410 + * format. As such, once the user has called qbman_result_has_new_result() and
12411 + * been returned a valid dequeue result, they should not call it again on
12412 + * the same memory location (except of course if another dequeue command has
12413 + * been executed to produce a new result to that location).
12414 + */
12415 +int qbman_result_has_new_result(struct qbman_swp *s, const struct dpaa2_dq *dq)
12416 +{
12417 + if (dq->dq.tok != QMAN_DQ_TOKEN_VALID)
12418 + return 0;
12419 +
12420 + /*
12421 + * Set token to be 0 so we will detect change back to 1
12422 + * next time the looping is traversed. Const is cast away here
12423 + * as we want users to treat the dequeue responses as read only.
12424 + */
12425 + ((struct dpaa2_dq *)dq)->dq.tok = 0;
12426 +
12427 + /*
12428 + * Determine whether VDQCR is available based on whether the
12429 + * current result is sitting in the first storage location of
12430 + * the busy command.
12431 + */
12432 + if (s->vdq.storage == dq) {
12433 + s->vdq.storage = NULL;
12434 + atomic_inc(&s->vdq.available);
12435 + }
12436 +
12437 + return 1;
12438 +}
12439 +
12440 +/**
12441 + * qbman_release_desc_clear() - Clear the contents of a descriptor to
12442 + * default/starting state.
12443 + */
12444 +void qbman_release_desc_clear(struct qbman_release_desc *d)
12445 +{
12446 + memset(d, 0, sizeof(*d));
12447 + d->verb = 1 << 5; /* Release Command Valid */
12448 +}
12449 +
12450 +/**
12451 + * qbman_release_desc_set_bpid() - Set the ID of the buffer pool to release to
12452 + */
12453 +void qbman_release_desc_set_bpid(struct qbman_release_desc *d, u16 bpid)
12454 +{
12455 + d->bpid = cpu_to_le16(bpid);
12456 +}
12457 +
12458 +/**
12459 + * qbman_release_desc_set_rcdi() - Determines whether or not the portal's RCDI
12460 + * interrupt source should be asserted after the release command is completed.
12461 + */
12462 +void qbman_release_desc_set_rcdi(struct qbman_release_desc *d, int enable)
12463 +{
12464 + if (enable)
12465 + d->verb |= 1 << 6;
12466 + else
12467 + d->verb &= ~(1 << 6);
12468 +}
12469 +
12470 +#define RAR_IDX(rar) ((rar) & 0x7)
12471 +#define RAR_VB(rar) ((rar) & 0x80)
12472 +#define RAR_SUCCESS(rar) ((rar) & 0x100)
12473 +
12474 +/**
12475 + * qbman_swp_release() - Issue a buffer release command
12476 + * @s: the software portal object
12477 + * @d: the release descriptor
12478 + * @buffers: a pointer pointing to the buffer address to be released
12479 + * @num_buffers: number of buffers to be released, must be less than 8
12480 + *
12481 + * Return 0 for success, -EBUSY if the release command ring is not ready.
12482 + */
12483 +int qbman_swp_release(struct qbman_swp *s, const struct qbman_release_desc *d,
12484 + const u64 *buffers, unsigned int num_buffers)
12485 +{
12486 + int i;
12487 + struct qbman_release_desc *p;
12488 + u32 rar;
12489 +
12490 + if (!num_buffers || (num_buffers > 7))
12491 + return -EINVAL;
12492 +
12493 + rar = qbman_read_register(s, QBMAN_CINH_SWP_RAR);
12494 + if (!RAR_SUCCESS(rar))
12495 + return -EBUSY;
12496 +
12497 + /* Start the release command */
12498 + p = qbman_get_cmd(s, QBMAN_CENA_SWP_RCR(RAR_IDX(rar)));
12499 + /* Copy the caller's buffer pointers to the command */
12500 + for (i = 0; i < num_buffers; i++)
12501 + p->buf[i] = cpu_to_le64(buffers[i]);
12502 + p->bpid = d->bpid;
12503 +
12504 + /*
12505 + * Set the verb byte, have to substitute in the valid-bit and the number
12506 + * of buffers.
12507 + */
12508 + dma_wmb();
12509 + p->verb = d->verb | RAR_VB(rar) | num_buffers;
12510 + dccvac(p);
12511 +
12512 + return 0;
12513 +}
12514 +
12515 +struct qbman_acquire_desc {
12516 + u8 verb;
12517 + u8 reserved;
12518 + __le16 bpid;
12519 + u8 num;
12520 + u8 reserved2[59];
12521 +};
12522 +
12523 +struct qbman_acquire_rslt {
12524 + u8 verb;
12525 + u8 rslt;
12526 + __le16 reserved;
12527 + u8 num;
12528 + u8 reserved2[3];
12529 + __le64 buf[7];
12530 +};
12531 +
12532 +/**
12533 + * qbman_swp_acquire() - Issue a buffer acquire command
12534 + * @s: the software portal object
12535 + * @bpid: the buffer pool index
12536 + * @buffers: a pointer pointing to the acquired buffer addresses
12537 + * @num_buffers: number of buffers to be acquired, must be less than 8
12538 + *
12539 + * Return 0 for success, or negative error code if the acquire command
12540 + * fails.
12541 + */
12542 +int qbman_swp_acquire(struct qbman_swp *s, u16 bpid, u64 *buffers,
12543 + unsigned int num_buffers)
12544 +{
12545 + struct qbman_acquire_desc *p;
12546 + struct qbman_acquire_rslt *r;
12547 + int i;
12548 +
12549 + if (!num_buffers || (num_buffers > 7))
12550 + return -EINVAL;
12551 +
12552 + /* Start the management command */
12553 + p = qbman_swp_mc_start(s);
12554 +
12555 + if (!p)
12556 + return -EBUSY;
12557 +
12558 + /* Encode the caller-provided attributes */
12559 + p->bpid = cpu_to_le16(bpid);
12560 + p->num = num_buffers;
12561 +
12562 + /* Complete the management command */
12563 + r = qbman_swp_mc_complete(s, p, QBMAN_MC_ACQUIRE);
12564 + if (unlikely(!r)) {
12565 + pr_err("qbman: acquire from BPID %d failed, no response\n",
12566 + bpid);
12567 + return -EIO;
12568 + }
12569 +
12570 + /* Decode the outcome */
12571 + WARN_ON((r->verb & 0x7f) != QBMAN_MC_ACQUIRE);
12572 +
12573 + /* Determine success or failure */
12574 + if (unlikely(r->rslt != QBMAN_MC_RSLT_OK)) {
12575 + pr_err("qbman: acquire from BPID 0x%x failed, code=0x%02x\n",
12576 + bpid, r->rslt);
12577 + return -EIO;
12578 + }
12579 +
12580 + WARN_ON(r->num > num_buffers);
12581 +
12582 + /* Copy the acquired buffers to the caller's array */
12583 + for (i = 0; i < r->num; i++)
12584 + buffers[i] = le64_to_cpu(r->buf[i]);
12585 +
12586 + return (int)r->num;
12587 +}
12588 +
12589 +struct qbman_alt_fq_state_desc {
12590 + u8 verb;
12591 + u8 reserved[3];
12592 + __le32 fqid;
12593 + u8 reserved2[56];
12594 +};
12595 +
12596 +struct qbman_alt_fq_state_rslt {
12597 + u8 verb;
12598 + u8 rslt;
12599 + u8 reserved[62];
12600 +};
12601 +
12602 +#define ALT_FQ_FQID_MASK 0x00FFFFFF
12603 +
12604 +int qbman_swp_alt_fq_state(struct qbman_swp *s, u32 fqid,
12605 + u8 alt_fq_verb)
12606 +{
12607 + struct qbman_alt_fq_state_desc *p;
12608 + struct qbman_alt_fq_state_rslt *r;
12609 +
12610 + /* Start the management command */
12611 + p = qbman_swp_mc_start(s);
12612 + if (!p)
12613 + return -EBUSY;
12614 +
12615 + p->fqid = cpu_to_le32(fqid & ALT_FQ_FQID_MASK);
12616 +
12617 + /* Complete the management command */
12618 + r = qbman_swp_mc_complete(s, p, alt_fq_verb);
12619 + if (unlikely(!r)) {
12620 + pr_err("qbman: mgmt cmd failed, no response (verb=0x%x)\n",
12621 + alt_fq_verb);
12622 + return -EIO;
12623 + }
12624 +
12625 + /* Decode the outcome */
12626 + WARN_ON((r->verb & QBMAN_RESULT_MASK) != alt_fq_verb);
12627 +
12628 + /* Determine success or failure */
12629 + if (unlikely(r->rslt != QBMAN_MC_RSLT_OK)) {
12630 + pr_err("qbman: ALT FQID %d failed: verb = 0x%08x code = 0x%02x\n",
12631 + fqid, r->verb, r->rslt);
12632 + return -EIO;
12633 + }
12634 +
12635 + return 0;
12636 +}
12637 +
12638 +struct qbman_cdan_ctrl_desc {
12639 + u8 verb;
12640 + u8 reserved;
12641 + __le16 ch;
12642 + u8 we;
12643 + u8 ctrl;
12644 + __le16 reserved2;
12645 + __le64 cdan_ctx;
12646 + u8 reserved3[48];
12647 +
12648 +};
12649 +
12650 +struct qbman_cdan_ctrl_rslt {
12651 + u8 verb;
12652 + u8 rslt;
12653 + __le16 ch;
12654 + u8 reserved[60];
12655 +};
12656 +
12657 +int qbman_swp_CDAN_set(struct qbman_swp *s, u16 channelid,
12658 + u8 we_mask, u8 cdan_en,
12659 + u64 ctx)
12660 +{
12661 + struct qbman_cdan_ctrl_desc *p = NULL;
12662 + struct qbman_cdan_ctrl_rslt *r = NULL;
12663 +
12664 + /* Start the management command */
12665 + p = qbman_swp_mc_start(s);
12666 + if (!p)
12667 + return -EBUSY;
12668 +
12669 + /* Encode the caller-provided attributes */
12670 + p->ch = cpu_to_le16(channelid);
12671 + p->we = we_mask;
12672 + if (cdan_en)
12673 + p->ctrl = 1;
12674 + else
12675 + p->ctrl = 0;
12676 + p->cdan_ctx = cpu_to_le64(ctx);
12677 +
12678 + /* Complete the management command */
12679 + r = qbman_swp_mc_complete(s, p, QBMAN_WQCHAN_CONFIGURE);
12680 + if (unlikely(!r)) {
12681 + pr_err("qbman: wqchan config failed, no response\n");
12682 + return -EIO;
12683 + }
12684 +
12685 + WARN_ON((r->verb & 0x7f) != QBMAN_WQCHAN_CONFIGURE);
12686 +
12687 + /* Determine success or failure */
12688 + if (unlikely(r->rslt != QBMAN_MC_RSLT_OK)) {
12689 + pr_err("qbman: CDAN cQID %d failed: code = 0x%02x\n",
12690 + channelid, r->rslt);
12691 + return -EIO;
12692 + }
12693 +
12694 + return 0;
12695 +}
12696 +
12697 +#define QBMAN_RESPONSE_VERB_MASK 0x7f
12698 +#define QBMAN_FQ_QUERY_NP 0x45
12699 +#define QBMAN_BP_QUERY 0x32
12700 +
12701 +struct qbman_fq_query_desc {
12702 + u8 verb;
12703 + u8 reserved[3];
12704 + u32 fqid;
12705 + u8 reserved2[56];
12706 +};
12707 +
12708 +int qbman_fq_query_state(struct qbman_swp *s, u32 fqid,
12709 + struct qbman_fq_query_np_rslt *r)
12710 +{
12711 + struct qbman_fq_query_desc *p;
12712 + void *resp;
12713 +
12714 + p = (struct qbman_fq_query_desc *)qbman_swp_mc_start(s);
12715 + if (!p)
12716 + return -EBUSY;
12717 +
12718 + /* FQID is a 24 bit value */
12719 + p->fqid = cpu_to_le32(fqid) & 0x00FFFFFF;
12720 + resp = qbman_swp_mc_complete(s, p, QBMAN_FQ_QUERY_NP);
12721 + if (!resp) {
12722 + pr_err("qbman: Query FQID %d NP fields failed, no response\n",
12723 + fqid);
12724 + return -EIO;
12725 + }
12726 + *r = *(struct qbman_fq_query_np_rslt *)resp;
12727 + /* Decode the outcome */
12728 + WARN_ON((r->verb & QBMAN_RESPONSE_VERB_MASK) != QBMAN_FQ_QUERY_NP);
12729 +
12730 + /* Determine success or failure */
12731 + if (r->rslt != QBMAN_MC_RSLT_OK) {
12732 + pr_err("Query NP fields of FQID 0x%x failed, code=0x%02x\n",
12733 + p->fqid, r->rslt);
12734 + return -EIO;
12735 + }
12736 +
12737 + return 0;
12738 +}
12739 +
12740 +u32 qbman_fq_state_frame_count(const struct qbman_fq_query_np_rslt *r)
12741 +{
12742 + return (r->frm_cnt & 0x00FFFFFF);
12743 +}
12744 +
12745 +u32 qbman_fq_state_byte_count(const struct qbman_fq_query_np_rslt *r)
12746 +{
12747 + return r->byte_cnt;
12748 +}
12749 +
12750 +struct qbman_bp_query_desc {
12751 + u8 verb;
12752 + u8 reserved;
12753 + u16 bpid;
12754 + u8 reserved2[60];
12755 +};
12756 +
12757 +int qbman_bp_query(struct qbman_swp *s, u32 bpid,
12758 + struct qbman_bp_query_rslt *r)
12759 +{
12760 + struct qbman_bp_query_desc *p;
12761 + void *resp;
12762 +
12763 + p = (struct qbman_bp_query_desc *)qbman_swp_mc_start(s);
12764 + if (!p)
12765 + return -EBUSY;
12766 +
12767 + p->bpid = bpid;
12768 + resp = qbman_swp_mc_complete(s, p, QBMAN_BP_QUERY);
12769 + if (!resp) {
12770 + pr_err("qbman: Query BPID %d fields failed, no response\n",
12771 + bpid);
12772 + return -EIO;
12773 + }
12774 + *r = *(struct qbman_bp_query_rslt *)resp;
12775 + /* Decode the outcome */
12776 + WARN_ON((r->verb & QBMAN_RESPONSE_VERB_MASK) != QBMAN_BP_QUERY);
12777 +
12778 + /* Determine success or failure */
12779 + if (r->rslt != QBMAN_MC_RSLT_OK) {
12780 + pr_err("Query fields of BPID 0x%x failed, code=0x%02x\n",
12781 + bpid, r->rslt);
12782 + return -EIO;
12783 + }
12784 +
12785 + return 0;
12786 +}
12787 +
12788 +u32 qbman_bp_info_num_free_bufs(struct qbman_bp_query_rslt *a)
12789 +{
12790 + return a->fill;
12791 +}
12792 --- /dev/null
12793 +++ b/drivers/staging/fsl-mc/bus/dpio/qbman-portal.h
12794 @@ -0,0 +1,505 @@
12795 +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
12796 +/*
12797 + * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
12798 + * Copyright 2016 NXP
12799 + *
12800 + */
12801 +#ifndef __FSL_QBMAN_PORTAL_H
12802 +#define __FSL_QBMAN_PORTAL_H
12803 +
12804 +#include "../../include/dpaa2-fd.h"
12805 +
12806 +struct dpaa2_dq;
12807 +struct qbman_swp;
12808 +
12809 +/* qbman software portal descriptor structure */
12810 +struct qbman_swp_desc {
12811 + void *cena_bar; /* Cache-enabled portal base address */
12812 + void *cinh_bar; /* Cache-inhibited portal base address */
12813 + u32 qman_version;
12814 +};
12815 +
12816 +#define QBMAN_SWP_INTERRUPT_EQRI 0x01
12817 +#define QBMAN_SWP_INTERRUPT_EQDI 0x02
12818 +#define QBMAN_SWP_INTERRUPT_DQRI 0x04
12819 +#define QBMAN_SWP_INTERRUPT_RCRI 0x08
12820 +#define QBMAN_SWP_INTERRUPT_RCDI 0x10
12821 +#define QBMAN_SWP_INTERRUPT_VDCI 0x20
12822 +
12823 +/* the structure for pull dequeue descriptor */
12824 +struct qbman_pull_desc {
12825 + u8 verb;
12826 + u8 numf;
12827 + u8 tok;
12828 + u8 reserved;
12829 + __le32 dq_src;
12830 + __le64 rsp_addr;
12831 + u64 rsp_addr_virt;
12832 + u8 padding[40];
12833 +};
12834 +
12835 +enum qbman_pull_type_e {
12836 + /* dequeue with priority precedence, respect intra-class scheduling */
12837 + qbman_pull_type_prio = 1,
12838 + /* dequeue with active FQ precedence, respect ICS */
12839 + qbman_pull_type_active,
12840 + /* dequeue with active FQ precedence, no ICS */
12841 + qbman_pull_type_active_noics
12842 +};
12843 +
12844 +/* Definitions for parsing dequeue entries */
12845 +#define QBMAN_RESULT_MASK 0x7f
12846 +#define QBMAN_RESULT_DQ 0x60
12847 +#define QBMAN_RESULT_FQRN 0x21
12848 +#define QBMAN_RESULT_FQRNI 0x22
12849 +#define QBMAN_RESULT_FQPN 0x24
12850 +#define QBMAN_RESULT_FQDAN 0x25
12851 +#define QBMAN_RESULT_CDAN 0x26
12852 +#define QBMAN_RESULT_CSCN_MEM 0x27
12853 +#define QBMAN_RESULT_CGCU 0x28
12854 +#define QBMAN_RESULT_BPSCN 0x29
12855 +#define QBMAN_RESULT_CSCN_WQ 0x2a
12856 +
12857 +/* QBMan FQ management command codes */
12858 +#define QBMAN_FQ_SCHEDULE 0x48
12859 +#define QBMAN_FQ_FORCE 0x49
12860 +#define QBMAN_FQ_XON 0x4d
12861 +#define QBMAN_FQ_XOFF 0x4e
12862 +
12863 +/* structure of enqueue descriptor */
12864 +struct qbman_eq_desc {
12865 + u8 verb;
12866 + u8 dca;
12867 + __le16 seqnum;
12868 + __le16 orpid;
12869 + __le16 reserved1;
12870 + __le32 tgtid;
12871 + __le32 tag;
12872 + __le16 qdbin;
12873 + u8 qpri;
12874 + u8 reserved[3];
12875 + u8 wae;
12876 + u8 rspid;
12877 + __le64 rsp_addr;
12878 + u8 fd[32];
12879 +};
12880 +
12881 +/* buffer release descriptor */
12882 +struct qbman_release_desc {
12883 + u8 verb;
12884 + u8 reserved;
12885 + __le16 bpid;
12886 + __le32 reserved2;
12887 + __le64 buf[7];
12888 +};
12889 +
12890 +/* Management command result codes */
12891 +#define QBMAN_MC_RSLT_OK 0xf0
12892 +
12893 +#define CODE_CDAN_WE_EN 0x1
12894 +#define CODE_CDAN_WE_CTX 0x4
12895 +
12896 +/* portal data structure */
12897 +struct qbman_swp {
12898 + const struct qbman_swp_desc *desc;
12899 + void __iomem *addr_cena;
12900 + void __iomem *addr_cinh;
12901 +
12902 + /* Management commands */
12903 + struct {
12904 + u32 valid_bit; /* 0x00 or 0x80 */
12905 + } mc;
12906 +
12907 + /* Push dequeues */
12908 + u32 sdq;
12909 +
12910 + /* Volatile dequeues */
12911 + struct {
12912 + atomic_t available; /* indicates if a command can be sent */
12913 + u32 valid_bit; /* 0x00 or 0x80 */
12914 + struct dpaa2_dq *storage; /* NULL if DQRR */
12915 + } vdq;
12916 +
12917 + /* DQRR */
12918 + struct {
12919 + u32 next_idx;
12920 + u32 valid_bit;
12921 + u8 dqrr_size;
12922 + int reset_bug; /* indicates dqrr reset workaround is needed */
12923 + } dqrr;
12924 +};
12925 +
12926 +struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d);
12927 +void qbman_swp_finish(struct qbman_swp *p);
12928 +u32 qbman_swp_interrupt_read_status(struct qbman_swp *p);
12929 +void qbman_swp_interrupt_clear_status(struct qbman_swp *p, u32 mask);
12930 +u32 qbman_swp_interrupt_get_trigger(struct qbman_swp *p);
12931 +void qbman_swp_interrupt_set_trigger(struct qbman_swp *p, u32 mask);
12932 +int qbman_swp_interrupt_get_inhibit(struct qbman_swp *p);
12933 +void qbman_swp_interrupt_set_inhibit(struct qbman_swp *p, int inhibit);
12934 +
12935 +void qbman_swp_push_get(struct qbman_swp *p, u8 channel_idx, int *enabled);
12936 +void qbman_swp_push_set(struct qbman_swp *p, u8 channel_idx, int enable);
12937 +
12938 +void qbman_pull_desc_clear(struct qbman_pull_desc *d);
12939 +void qbman_pull_desc_set_storage(struct qbman_pull_desc *d,
12940 + struct dpaa2_dq *storage,
12941 + dma_addr_t storage_phys,
12942 + int stash);
12943 +void qbman_pull_desc_set_numframes(struct qbman_pull_desc *d, u8 numframes);
12944 +void qbman_pull_desc_set_fq(struct qbman_pull_desc *d, u32 fqid);
12945 +void qbman_pull_desc_set_wq(struct qbman_pull_desc *d, u32 wqid,
12946 + enum qbman_pull_type_e dct);
12947 +void qbman_pull_desc_set_channel(struct qbman_pull_desc *d, u32 chid,
12948 + enum qbman_pull_type_e dct);
12949 +
12950 +int qbman_swp_pull(struct qbman_swp *p, struct qbman_pull_desc *d);
12951 +
12952 +const struct dpaa2_dq *qbman_swp_dqrr_next(struct qbman_swp *s);
12953 +void qbman_swp_dqrr_consume(struct qbman_swp *s, const struct dpaa2_dq *dq);
12954 +
12955 +int qbman_result_has_new_result(struct qbman_swp *p, const struct dpaa2_dq *dq);
12956 +
12957 +void qbman_eq_desc_clear(struct qbman_eq_desc *d);
12958 +void qbman_eq_desc_set_no_orp(struct qbman_eq_desc *d, int respond_success);
12959 +void qbman_eq_desc_set_orp(struct qbman_eq_desc *d, int respond_success,
12960 + u16 oprid, u16 seqnum, int incomplete);
12961 +void qbman_eq_desc_set_orp_hole(struct qbman_eq_desc *d, u16 oprid, u16 seqnum);
12962 +void qbman_eq_desc_set_token(struct qbman_eq_desc *d, u8 token);
12963 +void qbman_eq_desc_set_fq(struct qbman_eq_desc *d, u32 fqid);
12964 +void qbman_eq_desc_set_qd(struct qbman_eq_desc *d, u32 qdid,
12965 + u32 qd_bin, u32 qd_prio);
12966 +
12967 +int qbman_swp_enqueue(struct qbman_swp *p, const struct qbman_eq_desc *d,
12968 + const struct dpaa2_fd *fd);
12969 +
12970 +void qbman_release_desc_clear(struct qbman_release_desc *d);
12971 +void qbman_release_desc_set_bpid(struct qbman_release_desc *d, u16 bpid);
12972 +void qbman_release_desc_set_rcdi(struct qbman_release_desc *d, int enable);
12973 +
12974 +int qbman_swp_release(struct qbman_swp *s, const struct qbman_release_desc *d,
12975 + const u64 *buffers, unsigned int num_buffers);
12976 +int qbman_swp_acquire(struct qbman_swp *s, u16 bpid, u64 *buffers,
12977 + unsigned int num_buffers);
12978 +int qbman_swp_alt_fq_state(struct qbman_swp *s, u32 fqid,
12979 + u8 alt_fq_verb);
12980 +int qbman_swp_CDAN_set(struct qbman_swp *s, u16 channelid,
12981 + u8 we_mask, u8 cdan_en,
12982 + u64 ctx);
12983 +
12984 +void *qbman_swp_mc_start(struct qbman_swp *p);
12985 +void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, u8 cmd_verb);
12986 +void *qbman_swp_mc_result(struct qbman_swp *p);
12987 +
12988 +/**
12989 + * qbman_result_is_DQ() - check if the dequeue result is a dequeue response
12990 + * @dq: the dequeue result to be checked
12991 + *
12992 + * DQRR entries may contain non-dequeue results, ie. notifications
12993 + */
12994 +static inline int qbman_result_is_DQ(const struct dpaa2_dq *dq)
12995 +{
12996 + return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_DQ);
12997 +}
12998 +
12999 +/**
13000 + * qbman_result_is_SCN() - Check the dequeue result is notification or not
13001 + * @dq: the dequeue result to be checked
13002 + *
13003 + */
13004 +static inline int qbman_result_is_SCN(const struct dpaa2_dq *dq)
13005 +{
13006 + return !qbman_result_is_DQ(dq);
13007 +}
13008 +
13009 +/* FQ Data Availability */
13010 +static inline int qbman_result_is_FQDAN(const struct dpaa2_dq *dq)
13011 +{
13012 + return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_FQDAN);
13013 +}
13014 +
13015 +/* Channel Data Availability */
13016 +static inline int qbman_result_is_CDAN(const struct dpaa2_dq *dq)
13017 +{
13018 + return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_CDAN);
13019 +}
13020 +
13021 +/* Congestion State Change */
13022 +static inline int qbman_result_is_CSCN(const struct dpaa2_dq *dq)
13023 +{
13024 + return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_CSCN_WQ);
13025 +}
13026 +
13027 +/* Buffer Pool State Change */
13028 +static inline int qbman_result_is_BPSCN(const struct dpaa2_dq *dq)
13029 +{
13030 + return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_BPSCN);
13031 +}
13032 +
13033 +/* Congestion Group Count Update */
13034 +static inline int qbman_result_is_CGCU(const struct dpaa2_dq *dq)
13035 +{
13036 + return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_CGCU);
13037 +}
13038 +
13039 +/* Retirement */
13040 +static inline int qbman_result_is_FQRN(const struct dpaa2_dq *dq)
13041 +{
13042 + return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_FQRN);
13043 +}
13044 +
13045 +/* Retirement Immediate */
13046 +static inline int qbman_result_is_FQRNI(const struct dpaa2_dq *dq)
13047 +{
13048 + return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_FQRNI);
13049 +}
13050 +
13051 + /* Park */
13052 +static inline int qbman_result_is_FQPN(const struct dpaa2_dq *dq)
13053 +{
13054 + return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_FQPN);
13055 +}
13056 +
13057 +/**
13058 + * qbman_result_SCN_state() - Get the state field in State-change notification
13059 + */
13060 +static inline u8 qbman_result_SCN_state(const struct dpaa2_dq *scn)
13061 +{
13062 + return scn->scn.state;
13063 +}
13064 +
13065 +#define SCN_RID_MASK 0x00FFFFFF
13066 +
13067 +/**
13068 + * qbman_result_SCN_rid() - Get the resource id in State-change notification
13069 + */
13070 +static inline u32 qbman_result_SCN_rid(const struct dpaa2_dq *scn)
13071 +{
13072 + return le32_to_cpu(scn->scn.rid_tok) & SCN_RID_MASK;
13073 +}
13074 +
13075 +/**
13076 + * qbman_result_SCN_ctx() - Get the context data in State-change notification
13077 + */
13078 +static inline u64 qbman_result_SCN_ctx(const struct dpaa2_dq *scn)
13079 +{
13080 + return le64_to_cpu(scn->scn.ctx);
13081 +}
13082 +
13083 +/**
13084 + * qbman_swp_fq_schedule() - Move the fq to the scheduled state
13085 + * @s: the software portal object
13086 + * @fqid: the index of frame queue to be scheduled
13087 + *
13088 + * There are a couple of different ways that a FQ can end up parked state,
13089 + * This schedules it.
13090 + *
13091 + * Return 0 for success, or negative error code for failure.
13092 + */
13093 +static inline int qbman_swp_fq_schedule(struct qbman_swp *s, u32 fqid)
13094 +{
13095 + return qbman_swp_alt_fq_state(s, fqid, QBMAN_FQ_SCHEDULE);
13096 +}
13097 +
13098 +/**
13099 + * qbman_swp_fq_force() - Force the FQ to fully scheduled state
13100 + * @s: the software portal object
13101 + * @fqid: the index of frame queue to be forced
13102 + *
13103 + * Force eligible will force a tentatively-scheduled FQ to be fully-scheduled
13104 + * and thus be available for selection by any channel-dequeuing behaviour (push
13105 + * or pull). If the FQ is subsequently "dequeued" from the channel and is still
13106 + * empty at the time this happens, the resulting dq_entry will have no FD.
13107 + * (qbman_result_DQ_fd() will return NULL.)
13108 + *
13109 + * Return 0 for success, or negative error code for failure.
13110 + */
13111 +static inline int qbman_swp_fq_force(struct qbman_swp *s, u32 fqid)
13112 +{
13113 + return qbman_swp_alt_fq_state(s, fqid, QBMAN_FQ_FORCE);
13114 +}
13115 +
13116 +/**
13117 + * qbman_swp_fq_xon() - sets FQ flow-control to XON
13118 + * @s: the software portal object
13119 + * @fqid: the index of frame queue
13120 + *
13121 + * This setting doesn't affect enqueues to the FQ, just dequeues.
13122 + *
13123 + * Return 0 for success, or negative error code for failure.
13124 + */
13125 +static inline int qbman_swp_fq_xon(struct qbman_swp *s, u32 fqid)
13126 +{
13127 + return qbman_swp_alt_fq_state(s, fqid, QBMAN_FQ_XON);
13128 +}
13129 +
13130 +/**
13131 + * qbman_swp_fq_xoff() - sets FQ flow-control to XOFF
13132 + * @s: the software portal object
13133 + * @fqid: the index of frame queue
13134 + *
13135 + * This setting doesn't affect enqueues to the FQ, just dequeues.
13136 + * XOFF FQs will remain in the tenatively-scheduled state, even when
13137 + * non-empty, meaning they won't be selected for scheduled dequeuing.
13138 + * If a FQ is changed to XOFF after it had already become truly-scheduled
13139 + * to a channel, and a pull dequeue of that channel occurs that selects
13140 + * that FQ for dequeuing, then the resulting dq_entry will have no FD.
13141 + * (qbman_result_DQ_fd() will return NULL.)
13142 + *
13143 + * Return 0 for success, or negative error code for failure.
13144 + */
13145 +static inline int qbman_swp_fq_xoff(struct qbman_swp *s, u32 fqid)
13146 +{
13147 + return qbman_swp_alt_fq_state(s, fqid, QBMAN_FQ_XOFF);
13148 +}
13149 +
13150 +/* If the user has been allocated a channel object that is going to generate
13151 + * CDANs to another channel, then the qbman_swp_CDAN* functions will be
13152 + * necessary.
13153 + *
13154 + * CDAN-enabled channels only generate a single CDAN notification, after which
13155 + * they need to be reenabled before they'll generate another. The idea is
13156 + * that pull dequeuing will occur in reaction to the CDAN, followed by a
13157 + * reenable step. Each function generates a distinct command to hardware, so a
13158 + * combination function is provided if the user wishes to modify the "context"
13159 + * (which shows up in each CDAN message) each time they reenable, as a single
13160 + * command to hardware.
13161 + */
13162 +
13163 +/**
13164 + * qbman_swp_CDAN_set_context() - Set CDAN context
13165 + * @s: the software portal object
13166 + * @channelid: the channel index
13167 + * @ctx: the context to be set in CDAN
13168 + *
13169 + * Return 0 for success, or negative error code for failure.
13170 + */
13171 +static inline int qbman_swp_CDAN_set_context(struct qbman_swp *s, u16 channelid,
13172 + u64 ctx)
13173 +{
13174 + return qbman_swp_CDAN_set(s, channelid,
13175 + CODE_CDAN_WE_CTX,
13176 + 0, ctx);
13177 +}
13178 +
13179 +/**
13180 + * qbman_swp_CDAN_enable() - Enable CDAN for the channel
13181 + * @s: the software portal object
13182 + * @channelid: the index of the channel to generate CDAN
13183 + *
13184 + * Return 0 for success, or negative error code for failure.
13185 + */
13186 +static inline int qbman_swp_CDAN_enable(struct qbman_swp *s, u16 channelid)
13187 +{
13188 + return qbman_swp_CDAN_set(s, channelid,
13189 + CODE_CDAN_WE_EN,
13190 + 1, 0);
13191 +}
13192 +
13193 +/**
13194 + * qbman_swp_CDAN_disable() - disable CDAN for the channel
13195 + * @s: the software portal object
13196 + * @channelid: the index of the channel to generate CDAN
13197 + *
13198 + * Return 0 for success, or negative error code for failure.
13199 + */
13200 +static inline int qbman_swp_CDAN_disable(struct qbman_swp *s, u16 channelid)
13201 +{
13202 + return qbman_swp_CDAN_set(s, channelid,
13203 + CODE_CDAN_WE_EN,
13204 + 0, 0);
13205 +}
13206 +
13207 +/**
13208 + * qbman_swp_CDAN_set_context_enable() - Set CDAN contest and enable CDAN
13209 + * @s: the software portal object
13210 + * @channelid: the index of the channel to generate CDAN
13211 + * @ctx:i the context set in CDAN
13212 + *
13213 + * Return 0 for success, or negative error code for failure.
13214 + */
13215 +static inline int qbman_swp_CDAN_set_context_enable(struct qbman_swp *s,
13216 + u16 channelid,
13217 + u64 ctx)
13218 +{
13219 + return qbman_swp_CDAN_set(s, channelid,
13220 + CODE_CDAN_WE_EN | CODE_CDAN_WE_CTX,
13221 + 1, ctx);
13222 +}
13223 +
13224 +/* Wraps up submit + poll-for-result */
13225 +static inline void *qbman_swp_mc_complete(struct qbman_swp *swp, void *cmd,
13226 + u8 cmd_verb)
13227 +{
13228 + int loopvar = 1000;
13229 +
13230 + qbman_swp_mc_submit(swp, cmd, cmd_verb);
13231 +
13232 + do {
13233 + cmd = qbman_swp_mc_result(swp);
13234 + } while (!cmd && loopvar--);
13235 +
13236 + WARN_ON(!loopvar);
13237 +
13238 + return cmd;
13239 +}
13240 +
13241 +/* Query APIs */
13242 +struct qbman_fq_query_np_rslt {
13243 + u8 verb;
13244 + u8 rslt;
13245 + u8 st1;
13246 + u8 st2;
13247 + u8 reserved[2];
13248 + u16 od1_sfdr;
13249 + u16 od2_sfdr;
13250 + u16 od3_sfdr;
13251 + u16 ra1_sfdr;
13252 + u16 ra2_sfdr;
13253 + u32 pfdr_hptr;
13254 + u32 pfdr_tptr;
13255 + u32 frm_cnt;
13256 + u32 byte_cnt;
13257 + u16 ics_surp;
13258 + u8 is;
13259 + u8 reserved2[29];
13260 +};
13261 +
13262 +int qbman_fq_query_state(struct qbman_swp *s, u32 fqid,
13263 + struct qbman_fq_query_np_rslt *r);
13264 +u32 qbman_fq_state_frame_count(const struct qbman_fq_query_np_rslt *r);
13265 +u32 qbman_fq_state_byte_count(const struct qbman_fq_query_np_rslt *r);
13266 +
13267 +struct qbman_bp_query_rslt {
13268 + u8 verb;
13269 + u8 rslt;
13270 + u8 reserved[4];
13271 + u8 bdi;
13272 + u8 state;
13273 + u32 fill;
13274 + u32 hdotr;
13275 + u16 swdet;
13276 + u16 swdxt;
13277 + u16 hwdet;
13278 + u16 hwdxt;
13279 + u16 swset;
13280 + u16 swsxt;
13281 + u16 vbpid;
13282 + u16 icid;
13283 + u64 bpscn_addr;
13284 + u64 bpscn_ctx;
13285 + u16 hw_targ;
13286 + u8 dbe;
13287 + u8 reserved2;
13288 + u8 sdcnt;
13289 + u8 hdcnt;
13290 + u8 sscnt;
13291 + u8 reserved3[9];
13292 +};
13293 +
13294 +int qbman_bp_query(struct qbman_swp *s, u32 bpid,
13295 + struct qbman_bp_query_rslt *r);
13296 +
13297 +u32 qbman_bp_info_num_free_bufs(struct qbman_bp_query_rslt *a);
13298 +
13299 +#endif /* __FSL_QBMAN_PORTAL_H */
13300 --- a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h
13301 +++ /dev/null
13302 @@ -1,140 +0,0 @@
13303 -/* Copyright 2013-2016 Freescale Semiconductor Inc.
13304 - *
13305 - * Redistribution and use in source and binary forms, with or without
13306 - * modification, are permitted provided that the following conditions are met:
13307 - * * Redistributions of source code must retain the above copyright
13308 - * notice, this list of conditions and the following disclaimer.
13309 - * * Redistributions in binary form must reproduce the above copyright
13310 - * notice, this list of conditions and the following disclaimer in the
13311 - * documentation and/or other materials provided with the distribution.
13312 - * * Neither the name of the above-listed copyright holders nor the
13313 - * names of any contributors may be used to endorse or promote products
13314 - * derived from this software without specific prior written permission.
13315 - *
13316 - *
13317 - * ALTERNATIVELY, this software may be distributed under the terms of the
13318 - * GNU General Public License ("GPL") as published by the Free Software
13319 - * Foundation, either version 2 of that License or (at your option) any
13320 - * later version.
13321 - *
13322 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
13323 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13324 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13325 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
13326 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
13327 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
13328 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
13329 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
13330 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
13331 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
13332 - * POSSIBILITY OF SUCH DAMAGE.
13333 - */
13334 -#ifndef _FSL_DPMCP_CMD_H
13335 -#define _FSL_DPMCP_CMD_H
13336 -
13337 -/* Minimal supported DPMCP Version */
13338 -#define DPMCP_MIN_VER_MAJOR 3
13339 -#define DPMCP_MIN_VER_MINOR 0
13340 -
13341 -/* Command IDs */
13342 -#define DPMCP_CMDID_CLOSE 0x800
13343 -#define DPMCP_CMDID_OPEN 0x80b
13344 -#define DPMCP_CMDID_CREATE 0x90b
13345 -#define DPMCP_CMDID_DESTROY 0x900
13346 -
13347 -#define DPMCP_CMDID_GET_ATTR 0x004
13348 -#define DPMCP_CMDID_RESET 0x005
13349 -
13350 -#define DPMCP_CMDID_SET_IRQ 0x010
13351 -#define DPMCP_CMDID_GET_IRQ 0x011
13352 -#define DPMCP_CMDID_SET_IRQ_ENABLE 0x012
13353 -#define DPMCP_CMDID_GET_IRQ_ENABLE 0x013
13354 -#define DPMCP_CMDID_SET_IRQ_MASK 0x014
13355 -#define DPMCP_CMDID_GET_IRQ_MASK 0x015
13356 -#define DPMCP_CMDID_GET_IRQ_STATUS 0x016
13357 -
13358 -struct dpmcp_cmd_open {
13359 - __le32 dpmcp_id;
13360 -};
13361 -
13362 -struct dpmcp_cmd_create {
13363 - __le32 portal_id;
13364 -};
13365 -
13366 -struct dpmcp_cmd_set_irq {
13367 - /* cmd word 0 */
13368 - u8 irq_index;
13369 - u8 pad[3];
13370 - __le32 irq_val;
13371 - /* cmd word 1 */
13372 - __le64 irq_addr;
13373 - /* cmd word 2 */
13374 - __le32 irq_num;
13375 -};
13376 -
13377 -struct dpmcp_cmd_get_irq {
13378 - __le32 pad;
13379 - u8 irq_index;
13380 -};
13381 -
13382 -struct dpmcp_rsp_get_irq {
13383 - /* cmd word 0 */
13384 - __le32 irq_val;
13385 - __le32 pad;
13386 - /* cmd word 1 */
13387 - __le64 irq_paddr;
13388 - /* cmd word 2 */
13389 - __le32 irq_num;
13390 - __le32 type;
13391 -};
13392 -
13393 -#define DPMCP_ENABLE 0x1
13394 -
13395 -struct dpmcp_cmd_set_irq_enable {
13396 - u8 enable;
13397 - u8 pad[3];
13398 - u8 irq_index;
13399 -};
13400 -
13401 -struct dpmcp_cmd_get_irq_enable {
13402 - __le32 pad;
13403 - u8 irq_index;
13404 -};
13405 -
13406 -struct dpmcp_rsp_get_irq_enable {
13407 - u8 enabled;
13408 -};
13409 -
13410 -struct dpmcp_cmd_set_irq_mask {
13411 - __le32 mask;
13412 - u8 irq_index;
13413 -};
13414 -
13415 -struct dpmcp_cmd_get_irq_mask {
13416 - __le32 pad;
13417 - u8 irq_index;
13418 -};
13419 -
13420 -struct dpmcp_rsp_get_irq_mask {
13421 - __le32 mask;
13422 -};
13423 -
13424 -struct dpmcp_cmd_get_irq_status {
13425 - __le32 status;
13426 - u8 irq_index;
13427 -};
13428 -
13429 -struct dpmcp_rsp_get_irq_status {
13430 - __le32 status;
13431 -};
13432 -
13433 -struct dpmcp_rsp_get_attributes {
13434 - /* response word 0 */
13435 - __le32 pad;
13436 - __le32 id;
13437 - /* response word 1 */
13438 - __le16 version_major;
13439 - __le16 version_minor;
13440 -};
13441 -
13442 -#endif /* _FSL_DPMCP_CMD_H */
13443 --- a/drivers/staging/fsl-mc/bus/dpmcp.c
13444 +++ /dev/null
13445 @@ -1,504 +0,0 @@
13446 -/* Copyright 2013-2016 Freescale Semiconductor Inc.
13447 - *
13448 - * Redistribution and use in source and binary forms, with or without
13449 - * modification, are permitted provided that the following conditions are met:
13450 - * * Redistributions of source code must retain the above copyright
13451 - * notice, this list of conditions and the following disclaimer.
13452 - * * Redistributions in binary form must reproduce the above copyright
13453 - * notice, this list of conditions and the following disclaimer in the
13454 - * documentation and/or other materials provided with the distribution.
13455 - * * Neither the name of the above-listed copyright holders nor the
13456 - * names of any contributors may be used to endorse or promote products
13457 - * derived from this software without specific prior written permission.
13458 - *
13459 - *
13460 - * ALTERNATIVELY, this software may be distributed under the terms of the
13461 - * GNU General Public License ("GPL") as published by the Free Software
13462 - * Foundation, either version 2 of that License or (at your option) any
13463 - * later version.
13464 - *
13465 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
13466 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13467 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13468 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
13469 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
13470 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
13471 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
13472 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
13473 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
13474 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
13475 - * POSSIBILITY OF SUCH DAMAGE.
13476 - */
13477 -#include "../include/mc-sys.h"
13478 -#include "../include/mc-cmd.h"
13479 -
13480 -#include "dpmcp.h"
13481 -#include "dpmcp-cmd.h"
13482 -
13483 -/**
13484 - * dpmcp_open() - Open a control session for the specified object.
13485 - * @mc_io: Pointer to MC portal's I/O object
13486 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
13487 - * @dpmcp_id: DPMCP unique ID
13488 - * @token: Returned token; use in subsequent API calls
13489 - *
13490 - * This function can be used to open a control session for an
13491 - * already created object; an object may have been declared in
13492 - * the DPL or by calling the dpmcp_create function.
13493 - * This function returns a unique authentication token,
13494 - * associated with the specific object ID and the specific MC
13495 - * portal; this token must be used in all subsequent commands for
13496 - * this specific object
13497 - *
13498 - * Return: '0' on Success; Error code otherwise.
13499 - */
13500 -int dpmcp_open(struct fsl_mc_io *mc_io,
13501 - u32 cmd_flags,
13502 - int dpmcp_id,
13503 - u16 *token)
13504 -{
13505 - struct mc_command cmd = { 0 };
13506 - struct dpmcp_cmd_open *cmd_params;
13507 - int err;
13508 -
13509 - /* prepare command */
13510 - cmd.header = mc_encode_cmd_header(DPMCP_CMDID_OPEN,
13511 - cmd_flags, 0);
13512 - cmd_params = (struct dpmcp_cmd_open *)cmd.params;
13513 - cmd_params->dpmcp_id = cpu_to_le32(dpmcp_id);
13514 -
13515 - /* send command to mc*/
13516 - err = mc_send_command(mc_io, &cmd);
13517 - if (err)
13518 - return err;
13519 -
13520 - /* retrieve response parameters */
13521 - *token = mc_cmd_hdr_read_token(&cmd);
13522 -
13523 - return err;
13524 -}
13525 -
13526 -/**
13527 - * dpmcp_close() - Close the control session of the object
13528 - * @mc_io: Pointer to MC portal's I/O object
13529 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
13530 - * @token: Token of DPMCP object
13531 - *
13532 - * After this function is called, no further operations are
13533 - * allowed on the object without opening a new control session.
13534 - *
13535 - * Return: '0' on Success; Error code otherwise.
13536 - */
13537 -int dpmcp_close(struct fsl_mc_io *mc_io,
13538 - u32 cmd_flags,
13539 - u16 token)
13540 -{
13541 - struct mc_command cmd = { 0 };
13542 -
13543 - /* prepare command */
13544 - cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CLOSE,
13545 - cmd_flags, token);
13546 -
13547 - /* send command to mc*/
13548 - return mc_send_command(mc_io, &cmd);
13549 -}
13550 -
13551 -/**
13552 - * dpmcp_create() - Create the DPMCP object.
13553 - * @mc_io: Pointer to MC portal's I/O object
13554 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
13555 - * @cfg: Configuration structure
13556 - * @token: Returned token; use in subsequent API calls
13557 - *
13558 - * Create the DPMCP object, allocate required resources and
13559 - * perform required initialization.
13560 - *
13561 - * The object can be created either by declaring it in the
13562 - * DPL file, or by calling this function.
13563 - * This function returns a unique authentication token,
13564 - * associated with the specific object ID and the specific MC
13565 - * portal; this token must be used in all subsequent calls to
13566 - * this specific object. For objects that are created using the
13567 - * DPL file, call dpmcp_open function to get an authentication
13568 - * token first.
13569 - *
13570 - * Return: '0' on Success; Error code otherwise.
13571 - */
13572 -int dpmcp_create(struct fsl_mc_io *mc_io,
13573 - u32 cmd_flags,
13574 - const struct dpmcp_cfg *cfg,
13575 - u16 *token)
13576 -{
13577 - struct mc_command cmd = { 0 };
13578 - struct dpmcp_cmd_create *cmd_params;
13579 -
13580 - int err;
13581 -
13582 - /* prepare command */
13583 - cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CREATE,
13584 - cmd_flags, 0);
13585 - cmd_params = (struct dpmcp_cmd_create *)cmd.params;
13586 - cmd_params->portal_id = cpu_to_le32(cfg->portal_id);
13587 -
13588 - /* send command to mc*/
13589 - err = mc_send_command(mc_io, &cmd);
13590 - if (err)
13591 - return err;
13592 -
13593 - /* retrieve response parameters */
13594 - *token = mc_cmd_hdr_read_token(&cmd);
13595 -
13596 - return 0;
13597 -}
13598 -
13599 -/**
13600 - * dpmcp_destroy() - Destroy the DPMCP object and release all its resources.
13601 - * @mc_io: Pointer to MC portal's I/O object
13602 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
13603 - * @token: Token of DPMCP object
13604 - *
13605 - * Return: '0' on Success; error code otherwise.
13606 - */
13607 -int dpmcp_destroy(struct fsl_mc_io *mc_io,
13608 - u32 cmd_flags,
13609 - u16 token)
13610 -{
13611 - struct mc_command cmd = { 0 };
13612 -
13613 - /* prepare command */
13614 - cmd.header = mc_encode_cmd_header(DPMCP_CMDID_DESTROY,
13615 - cmd_flags, token);
13616 -
13617 - /* send command to mc*/
13618 - return mc_send_command(mc_io, &cmd);
13619 -}
13620 -
13621 -/**
13622 - * dpmcp_reset() - Reset the DPMCP, returns the object to initial state.
13623 - * @mc_io: Pointer to MC portal's I/O object
13624 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
13625 - * @token: Token of DPMCP object
13626 - *
13627 - * Return: '0' on Success; Error code otherwise.
13628 - */
13629 -int dpmcp_reset(struct fsl_mc_io *mc_io,
13630 - u32 cmd_flags,
13631 - u16 token)
13632 -{
13633 - struct mc_command cmd = { 0 };
13634 -
13635 - /* prepare command */
13636 - cmd.header = mc_encode_cmd_header(DPMCP_CMDID_RESET,
13637 - cmd_flags, token);
13638 -
13639 - /* send command to mc*/
13640 - return mc_send_command(mc_io, &cmd);
13641 -}
13642 -
13643 -/**
13644 - * dpmcp_set_irq() - Set IRQ information for the DPMCP to trigger an interrupt.
13645 - * @mc_io: Pointer to MC portal's I/O object
13646 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
13647 - * @token: Token of DPMCP object
13648 - * @irq_index: Identifies the interrupt index to configure
13649 - * @irq_cfg: IRQ configuration
13650 - *
13651 - * Return: '0' on Success; Error code otherwise.
13652 - */
13653 -int dpmcp_set_irq(struct fsl_mc_io *mc_io,
13654 - u32 cmd_flags,
13655 - u16 token,
13656 - u8 irq_index,
13657 - struct dpmcp_irq_cfg *irq_cfg)
13658 -{
13659 - struct mc_command cmd = { 0 };
13660 - struct dpmcp_cmd_set_irq *cmd_params;
13661 -
13662 - /* prepare command */
13663 - cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ,
13664 - cmd_flags, token);
13665 - cmd_params = (struct dpmcp_cmd_set_irq *)cmd.params;
13666 - cmd_params->irq_index = irq_index;
13667 - cmd_params->irq_val = cpu_to_le32(irq_cfg->val);
13668 - cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr);
13669 - cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num);
13670 -
13671 - /* send command to mc*/
13672 - return mc_send_command(mc_io, &cmd);
13673 -}
13674 -
13675 -/**
13676 - * dpmcp_get_irq() - Get IRQ information from the DPMCP.
13677 - * @mc_io: Pointer to MC portal's I/O object
13678 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
13679 - * @token: Token of DPMCP object
13680 - * @irq_index: The interrupt index to configure
13681 - * @type: Interrupt type: 0 represents message interrupt
13682 - * type (both irq_addr and irq_val are valid)
13683 - * @irq_cfg: IRQ attributes
13684 - *
13685 - * Return: '0' on Success; Error code otherwise.
13686 - */
13687 -int dpmcp_get_irq(struct fsl_mc_io *mc_io,
13688 - u32 cmd_flags,
13689 - u16 token,
13690 - u8 irq_index,
13691 - int *type,
13692 - struct dpmcp_irq_cfg *irq_cfg)
13693 -{
13694 - struct mc_command cmd = { 0 };
13695 - struct dpmcp_cmd_get_irq *cmd_params;
13696 - struct dpmcp_rsp_get_irq *rsp_params;
13697 - int err;
13698 -
13699 - /* prepare command */
13700 - cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ,
13701 - cmd_flags, token);
13702 - cmd_params = (struct dpmcp_cmd_get_irq *)cmd.params;
13703 - cmd_params->irq_index = irq_index;
13704 -
13705 - /* send command to mc*/
13706 - err = mc_send_command(mc_io, &cmd);
13707 - if (err)
13708 - return err;
13709 -
13710 - /* retrieve response parameters */
13711 - rsp_params = (struct dpmcp_rsp_get_irq *)cmd.params;
13712 - irq_cfg->val = le32_to_cpu(rsp_params->irq_val);
13713 - irq_cfg->paddr = le64_to_cpu(rsp_params->irq_paddr);
13714 - irq_cfg->irq_num = le32_to_cpu(rsp_params->irq_num);
13715 - *type = le32_to_cpu(rsp_params->type);
13716 - return 0;
13717 -}
13718 -
13719 -/**
13720 - * dpmcp_set_irq_enable() - Set overall interrupt state.
13721 - * @mc_io: Pointer to MC portal's I/O object
13722 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
13723 - * @token: Token of DPMCP object
13724 - * @irq_index: The interrupt index to configure
13725 - * @en: Interrupt state - enable = 1, disable = 0
13726 - *
13727 - * Allows GPP software to control when interrupts are generated.
13728 - * Each interrupt can have up to 32 causes. The enable/disable control's the
13729 - * overall interrupt state. if the interrupt is disabled no causes will cause
13730 - * an interrupt.
13731 - *
13732 - * Return: '0' on Success; Error code otherwise.
13733 - */
13734 -int dpmcp_set_irq_enable(struct fsl_mc_io *mc_io,
13735 - u32 cmd_flags,
13736 - u16 token,
13737 - u8 irq_index,
13738 - u8 en)
13739 -{
13740 - struct mc_command cmd = { 0 };
13741 - struct dpmcp_cmd_set_irq_enable *cmd_params;
13742 -
13743 - /* prepare command */
13744 - cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ_ENABLE,
13745 - cmd_flags, token);
13746 - cmd_params = (struct dpmcp_cmd_set_irq_enable *)cmd.params;
13747 - cmd_params->enable = en & DPMCP_ENABLE;
13748 - cmd_params->irq_index = irq_index;
13749 -
13750 - /* send command to mc*/
13751 - return mc_send_command(mc_io, &cmd);
13752 -}
13753 -
13754 -/**
13755 - * dpmcp_get_irq_enable() - Get overall interrupt state
13756 - * @mc_io: Pointer to MC portal's I/O object
13757 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
13758 - * @token: Token of DPMCP object
13759 - * @irq_index: The interrupt index to configure
13760 - * @en: Returned interrupt state - enable = 1, disable = 0
13761 - *
13762 - * Return: '0' on Success; Error code otherwise.
13763 - */
13764 -int dpmcp_get_irq_enable(struct fsl_mc_io *mc_io,
13765 - u32 cmd_flags,
13766 - u16 token,
13767 - u8 irq_index,
13768 - u8 *en)
13769 -{
13770 - struct mc_command cmd = { 0 };
13771 - struct dpmcp_cmd_get_irq_enable *cmd_params;
13772 - struct dpmcp_rsp_get_irq_enable *rsp_params;
13773 - int err;
13774 -
13775 - /* prepare command */
13776 - cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_ENABLE,
13777 - cmd_flags, token);
13778 - cmd_params = (struct dpmcp_cmd_get_irq_enable *)cmd.params;
13779 - cmd_params->irq_index = irq_index;
13780 -
13781 - /* send command to mc*/
13782 - err = mc_send_command(mc_io, &cmd);
13783 - if (err)
13784 - return err;
13785 -
13786 - /* retrieve response parameters */
13787 - rsp_params = (struct dpmcp_rsp_get_irq_enable *)cmd.params;
13788 - *en = rsp_params->enabled & DPMCP_ENABLE;
13789 - return 0;
13790 -}
13791 -
13792 -/**
13793 - * dpmcp_set_irq_mask() - Set interrupt mask.
13794 - * @mc_io: Pointer to MC portal's I/O object
13795 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
13796 - * @token: Token of DPMCP object
13797 - * @irq_index: The interrupt index to configure
13798 - * @mask: Event mask to trigger interrupt;
13799 - * each bit:
13800 - * 0 = ignore event
13801 - * 1 = consider event for asserting IRQ
13802 - *
13803 - * Every interrupt can have up to 32 causes and the interrupt model supports
13804 - * masking/unmasking each cause independently
13805 - *
13806 - * Return: '0' on Success; Error code otherwise.
13807 - */
13808 -int dpmcp_set_irq_mask(struct fsl_mc_io *mc_io,
13809 - u32 cmd_flags,
13810 - u16 token,
13811 - u8 irq_index,
13812 - u32 mask)
13813 -{
13814 - struct mc_command cmd = { 0 };
13815 - struct dpmcp_cmd_set_irq_mask *cmd_params;
13816 -
13817 - /* prepare command */
13818 - cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ_MASK,
13819 - cmd_flags, token);
13820 - cmd_params = (struct dpmcp_cmd_set_irq_mask *)cmd.params;
13821 - cmd_params->mask = cpu_to_le32(mask);
13822 - cmd_params->irq_index = irq_index;
13823 -
13824 - /* send command to mc*/
13825 - return mc_send_command(mc_io, &cmd);
13826 -}
13827 -
13828 -/**
13829 - * dpmcp_get_irq_mask() - Get interrupt mask.
13830 - * @mc_io: Pointer to MC portal's I/O object
13831 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
13832 - * @token: Token of DPMCP object
13833 - * @irq_index: The interrupt index to configure
13834 - * @mask: Returned event mask to trigger interrupt
13835 - *
13836 - * Every interrupt can have up to 32 causes and the interrupt model supports
13837 - * masking/unmasking each cause independently
13838 - *
13839 - * Return: '0' on Success; Error code otherwise.
13840 - */
13841 -int dpmcp_get_irq_mask(struct fsl_mc_io *mc_io,
13842 - u32 cmd_flags,
13843 - u16 token,
13844 - u8 irq_index,
13845 - u32 *mask)
13846 -{
13847 - struct mc_command cmd = { 0 };
13848 - struct dpmcp_cmd_get_irq_mask *cmd_params;
13849 - struct dpmcp_rsp_get_irq_mask *rsp_params;
13850 -
13851 - int err;
13852 -
13853 - /* prepare command */
13854 - cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_MASK,
13855 - cmd_flags, token);
13856 - cmd_params = (struct dpmcp_cmd_get_irq_mask *)cmd.params;
13857 - cmd_params->irq_index = irq_index;
13858 -
13859 - /* send command to mc*/
13860 - err = mc_send_command(mc_io, &cmd);
13861 - if (err)
13862 - return err;
13863 -
13864 - /* retrieve response parameters */
13865 - rsp_params = (struct dpmcp_rsp_get_irq_mask *)cmd.params;
13866 - *mask = le32_to_cpu(rsp_params->mask);
13867 -
13868 - return 0;
13869 -}
13870 -
13871 -/**
13872 - * dpmcp_get_irq_status() - Get the current status of any pending interrupts.
13873 - *
13874 - * @mc_io: Pointer to MC portal's I/O object
13875 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
13876 - * @token: Token of DPMCP object
13877 - * @irq_index: The interrupt index to configure
13878 - * @status: Returned interrupts status - one bit per cause:
13879 - * 0 = no interrupt pending
13880 - * 1 = interrupt pending
13881 - *
13882 - * Return: '0' on Success; Error code otherwise.
13883 - */
13884 -int dpmcp_get_irq_status(struct fsl_mc_io *mc_io,
13885 - u32 cmd_flags,
13886 - u16 token,
13887 - u8 irq_index,
13888 - u32 *status)
13889 -{
13890 - struct mc_command cmd = { 0 };
13891 - struct dpmcp_cmd_get_irq_status *cmd_params;
13892 - struct dpmcp_rsp_get_irq_status *rsp_params;
13893 - int err;
13894 -
13895 - /* prepare command */
13896 - cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_STATUS,
13897 - cmd_flags, token);
13898 - cmd_params = (struct dpmcp_cmd_get_irq_status *)cmd.params;
13899 - cmd_params->status = cpu_to_le32(*status);
13900 - cmd_params->irq_index = irq_index;
13901 -
13902 - /* send command to mc*/
13903 - err = mc_send_command(mc_io, &cmd);
13904 - if (err)
13905 - return err;
13906 -
13907 - /* retrieve response parameters */
13908 - rsp_params = (struct dpmcp_rsp_get_irq_status *)cmd.params;
13909 - *status = le32_to_cpu(rsp_params->status);
13910 -
13911 - return 0;
13912 -}
13913 -
13914 -/**
13915 - * dpmcp_get_attributes - Retrieve DPMCP attributes.
13916 - *
13917 - * @mc_io: Pointer to MC portal's I/O object
13918 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
13919 - * @token: Token of DPMCP object
13920 - * @attr: Returned object's attributes
13921 - *
13922 - * Return: '0' on Success; Error code otherwise.
13923 - */
13924 -int dpmcp_get_attributes(struct fsl_mc_io *mc_io,
13925 - u32 cmd_flags,
13926 - u16 token,
13927 - struct dpmcp_attr *attr)
13928 -{
13929 - struct mc_command cmd = { 0 };
13930 - struct dpmcp_rsp_get_attributes *rsp_params;
13931 - int err;
13932 -
13933 - /* prepare command */
13934 - cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_ATTR,
13935 - cmd_flags, token);
13936 -
13937 - /* send command to mc*/
13938 - err = mc_send_command(mc_io, &cmd);
13939 - if (err)
13940 - return err;
13941 -
13942 - /* retrieve response parameters */
13943 - rsp_params = (struct dpmcp_rsp_get_attributes *)cmd.params;
13944 - attr->id = le32_to_cpu(rsp_params->id);
13945 - attr->version.major = le16_to_cpu(rsp_params->version_major);
13946 - attr->version.minor = le16_to_cpu(rsp_params->version_minor);
13947 -
13948 - return 0;
13949 -}
13950 --- a/drivers/staging/fsl-mc/bus/dpmcp.h
13951 +++ /dev/null
13952 @@ -1,159 +0,0 @@
13953 -/* Copyright 2013-2015 Freescale Semiconductor Inc.
13954 - *
13955 - * Redistribution and use in source and binary forms, with or without
13956 - * modification, are permitted provided that the following conditions are met:
13957 - * * Redistributions of source code must retain the above copyright
13958 - * notice, this list of conditions and the following disclaimer.
13959 - * * Redistributions in binary form must reproduce the above copyright
13960 - * notice, this list of conditions and the following disclaimer in the
13961 - * documentation and/or other materials provided with the distribution.
13962 - * * Neither the name of the above-listed copyright holders nor the
13963 - * names of any contributors may be used to endorse or promote products
13964 - * derived from this software without specific prior written permission.
13965 - *
13966 - *
13967 - * ALTERNATIVELY, this software may be distributed under the terms of the
13968 - * GNU General Public License ("GPL") as published by the Free Software
13969 - * Foundation, either version 2 of that License or (at your option) any
13970 - * later version.
13971 - *
13972 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
13973 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13974 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13975 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
13976 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
13977 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
13978 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
13979 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
13980 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
13981 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
13982 - * POSSIBILITY OF SUCH DAMAGE.
13983 - */
13984 -#ifndef __FSL_DPMCP_H
13985 -#define __FSL_DPMCP_H
13986 -
13987 -/* Data Path Management Command Portal API
13988 - * Contains initialization APIs and runtime control APIs for DPMCP
13989 - */
13990 -
13991 -struct fsl_mc_io;
13992 -
13993 -int dpmcp_open(struct fsl_mc_io *mc_io,
13994 - uint32_t cmd_flags,
13995 - int dpmcp_id,
13996 - uint16_t *token);
13997 -
13998 -/* Get portal ID from pool */
13999 -#define DPMCP_GET_PORTAL_ID_FROM_POOL (-1)
14000 -
14001 -int dpmcp_close(struct fsl_mc_io *mc_io,
14002 - uint32_t cmd_flags,
14003 - uint16_t token);
14004 -
14005 -/**
14006 - * struct dpmcp_cfg - Structure representing DPMCP configuration
14007 - * @portal_id: Portal ID; 'DPMCP_GET_PORTAL_ID_FROM_POOL' to get the portal ID
14008 - * from pool
14009 - */
14010 -struct dpmcp_cfg {
14011 - int portal_id;
14012 -};
14013 -
14014 -int dpmcp_create(struct fsl_mc_io *mc_io,
14015 - uint32_t cmd_flags,
14016 - const struct dpmcp_cfg *cfg,
14017 - uint16_t *token);
14018 -
14019 -int dpmcp_destroy(struct fsl_mc_io *mc_io,
14020 - uint32_t cmd_flags,
14021 - uint16_t token);
14022 -
14023 -int dpmcp_reset(struct fsl_mc_io *mc_io,
14024 - uint32_t cmd_flags,
14025 - uint16_t token);
14026 -
14027 -/* IRQ */
14028 -/* IRQ Index */
14029 -#define DPMCP_IRQ_INDEX 0
14030 -/* irq event - Indicates that the link state changed */
14031 -#define DPMCP_IRQ_EVENT_CMD_DONE 0x00000001
14032 -
14033 -/**
14034 - * struct dpmcp_irq_cfg - IRQ configuration
14035 - * @paddr: Address that must be written to signal a message-based interrupt
14036 - * @val: Value to write into irq_addr address
14037 - * @irq_num: A user defined number associated with this IRQ
14038 - */
14039 -struct dpmcp_irq_cfg {
14040 - uint64_t paddr;
14041 - uint32_t val;
14042 - int irq_num;
14043 -};
14044 -
14045 -int dpmcp_set_irq(struct fsl_mc_io *mc_io,
14046 - uint32_t cmd_flags,
14047 - uint16_t token,
14048 - uint8_t irq_index,
14049 - struct dpmcp_irq_cfg *irq_cfg);
14050 -
14051 -int dpmcp_get_irq(struct fsl_mc_io *mc_io,
14052 - uint32_t cmd_flags,
14053 - uint16_t token,
14054 - uint8_t irq_index,
14055 - int *type,
14056 - struct dpmcp_irq_cfg *irq_cfg);
14057 -
14058 -int dpmcp_set_irq_enable(struct fsl_mc_io *mc_io,
14059 - uint32_t cmd_flags,
14060 - uint16_t token,
14061 - uint8_t irq_index,
14062 - uint8_t en);
14063 -
14064 -int dpmcp_get_irq_enable(struct fsl_mc_io *mc_io,
14065 - uint32_t cmd_flags,
14066 - uint16_t token,
14067 - uint8_t irq_index,
14068 - uint8_t *en);
14069 -
14070 -int dpmcp_set_irq_mask(struct fsl_mc_io *mc_io,
14071 - uint32_t cmd_flags,
14072 - uint16_t token,
14073 - uint8_t irq_index,
14074 - uint32_t mask);
14075 -
14076 -int dpmcp_get_irq_mask(struct fsl_mc_io *mc_io,
14077 - uint32_t cmd_flags,
14078 - uint16_t token,
14079 - uint8_t irq_index,
14080 - uint32_t *mask);
14081 -
14082 -int dpmcp_get_irq_status(struct fsl_mc_io *mc_io,
14083 - uint32_t cmd_flags,
14084 - uint16_t token,
14085 - uint8_t irq_index,
14086 - uint32_t *status);
14087 -
14088 -/**
14089 - * struct dpmcp_attr - Structure representing DPMCP attributes
14090 - * @id: DPMCP object ID
14091 - * @version: DPMCP version
14092 - */
14093 -struct dpmcp_attr {
14094 - int id;
14095 - /**
14096 - * struct version - Structure representing DPMCP version
14097 - * @major: DPMCP major version
14098 - * @minor: DPMCP minor version
14099 - */
14100 - struct {
14101 - uint16_t major;
14102 - uint16_t minor;
14103 - } version;
14104 -};
14105 -
14106 -int dpmcp_get_attributes(struct fsl_mc_io *mc_io,
14107 - uint32_t cmd_flags,
14108 - uint16_t token,
14109 - struct dpmcp_attr *attr);
14110 -
14111 -#endif /* __FSL_DPMCP_H */
14112 --- a/drivers/staging/fsl-mc/bus/dpmng-cmd.h
14113 +++ /dev/null
14114 @@ -1,58 +0,0 @@
14115 -/*
14116 - * Copyright 2013-2016 Freescale Semiconductor Inc.
14117 - *
14118 - * Redistribution and use in source and binary forms, with or without
14119 - * modification, are permitted provided that the following conditions are met:
14120 - * * Redistributions of source code must retain the above copyright
14121 - * notice, this list of conditions and the following disclaimer.
14122 - * * Redistributions in binary form must reproduce the above copyright
14123 - * notice, this list of conditions and the following disclaimer in the
14124 - * documentation and/or other materials provided with the distribution.
14125 - * * Neither the name of the above-listed copyright holders nor the
14126 - * names of any contributors may be used to endorse or promote products
14127 - * derived from this software without specific prior written permission.
14128 - *
14129 - *
14130 - * ALTERNATIVELY, this software may be distributed under the terms of the
14131 - * GNU General Public License ("GPL") as published by the Free Software
14132 - * Foundation, either version 2 of that License or (at your option) any
14133 - * later version.
14134 - *
14135 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14136 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14137 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14138 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
14139 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
14140 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
14141 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
14142 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
14143 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
14144 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
14145 - * POSSIBILITY OF SUCH DAMAGE.
14146 - */
14147 -
14148 -/*
14149 - * dpmng-cmd.h
14150 - *
14151 - * defines portal commands
14152 - *
14153 - */
14154 -
14155 -#ifndef __FSL_DPMNG_CMD_H
14156 -#define __FSL_DPMNG_CMD_H
14157 -
14158 -/* Command IDs */
14159 -#define DPMNG_CMDID_GET_CONT_ID 0x830
14160 -#define DPMNG_CMDID_GET_VERSION 0x831
14161 -
14162 -struct dpmng_rsp_get_container_id {
14163 - __le32 container_id;
14164 -};
14165 -
14166 -struct dpmng_rsp_get_version {
14167 - __le32 revision;
14168 - __le32 version_major;
14169 - __le32 version_minor;
14170 -};
14171 -
14172 -#endif /* __FSL_DPMNG_CMD_H */
14173 --- a/drivers/staging/fsl-mc/bus/dpmng.c
14174 +++ /dev/null
14175 @@ -1,107 +0,0 @@
14176 -/* Copyright 2013-2016 Freescale Semiconductor Inc.
14177 - *
14178 - * Redistribution and use in source and binary forms, with or without
14179 - * modification, are permitted provided that the following conditions are met:
14180 - * * Redistributions of source code must retain the above copyright
14181 - * notice, this list of conditions and the following disclaimer.
14182 - * * Redistributions in binary form must reproduce the above copyright
14183 - * notice, this list of conditions and the following disclaimer in the
14184 - * documentation and/or other materials provided with the distribution.
14185 - * * Neither the name of the above-listed copyright holders nor the
14186 - * names of any contributors may be used to endorse or promote products
14187 - * derived from this software without specific prior written permission.
14188 - *
14189 - *
14190 - * ALTERNATIVELY, this software may be distributed under the terms of the
14191 - * GNU General Public License ("GPL") as published by the Free Software
14192 - * Foundation, either version 2 of that License or (at your option) any
14193 - * later version.
14194 - *
14195 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14196 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14197 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14198 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
14199 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
14200 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
14201 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
14202 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
14203 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
14204 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
14205 - * POSSIBILITY OF SUCH DAMAGE.
14206 - */
14207 -#include "../include/mc-sys.h"
14208 -#include "../include/mc-cmd.h"
14209 -#include "../include/dpmng.h"
14210 -
14211 -#include "dpmng-cmd.h"
14212 -
14213 -/**
14214 - * mc_get_version() - Retrieves the Management Complex firmware
14215 - * version information
14216 - * @mc_io: Pointer to opaque I/O object
14217 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
14218 - * @mc_ver_info: Returned version information structure
14219 - *
14220 - * Return: '0' on Success; Error code otherwise.
14221 - */
14222 -int mc_get_version(struct fsl_mc_io *mc_io,
14223 - u32 cmd_flags,
14224 - struct mc_version *mc_ver_info)
14225 -{
14226 - struct mc_command cmd = { 0 };
14227 - struct dpmng_rsp_get_version *rsp_params;
14228 - int err;
14229 -
14230 - /* prepare command */
14231 - cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_VERSION,
14232 - cmd_flags,
14233 - 0);
14234 -
14235 - /* send command to mc*/
14236 - err = mc_send_command(mc_io, &cmd);
14237 - if (err)
14238 - return err;
14239 -
14240 - /* retrieve response parameters */
14241 - rsp_params = (struct dpmng_rsp_get_version *)cmd.params;
14242 - mc_ver_info->revision = le32_to_cpu(rsp_params->revision);
14243 - mc_ver_info->major = le32_to_cpu(rsp_params->version_major);
14244 - mc_ver_info->minor = le32_to_cpu(rsp_params->version_minor);
14245 -
14246 - return 0;
14247 -}
14248 -EXPORT_SYMBOL(mc_get_version);
14249 -
14250 -/**
14251 - * dpmng_get_container_id() - Get container ID associated with a given portal.
14252 - * @mc_io: Pointer to MC portal's I/O object
14253 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
14254 - * @container_id: Requested container ID
14255 - *
14256 - * Return: '0' on Success; Error code otherwise.
14257 - */
14258 -int dpmng_get_container_id(struct fsl_mc_io *mc_io,
14259 - u32 cmd_flags,
14260 - int *container_id)
14261 -{
14262 - struct mc_command cmd = { 0 };
14263 - struct dpmng_rsp_get_container_id *rsp_params;
14264 - int err;
14265 -
14266 - /* prepare command */
14267 - cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_CONT_ID,
14268 - cmd_flags,
14269 - 0);
14270 -
14271 - /* send command to mc*/
14272 - err = mc_send_command(mc_io, &cmd);
14273 - if (err)
14274 - return err;
14275 -
14276 - /* retrieve response parameters */
14277 - rsp_params = (struct dpmng_rsp_get_container_id *)cmd.params;
14278 - *container_id = le32_to_cpu(rsp_params->container_id);
14279 -
14280 - return 0;
14281 -}
14282 -
14283 --- a/drivers/staging/fsl-mc/bus/dprc-cmd.h
14284 +++ /dev/null
14285 @@ -1,465 +0,0 @@
14286 -/*
14287 - * Copyright 2013-2016 Freescale Semiconductor Inc.
14288 - *
14289 - * Redistribution and use in source and binary forms, with or without
14290 - * modification, are permitted provided that the following conditions are met:
14291 - * * Redistributions of source code must retain the above copyright
14292 - * notice, this list of conditions and the following disclaimer.
14293 - * * Redistributions in binary form must reproduce the above copyright
14294 - * notice, this list of conditions and the following disclaimer in the
14295 - * documentation and/or other materials provided with the distribution.
14296 - * * Neither the name of the above-listed copyright holders nor the
14297 - * names of any contributors may be used to endorse or promote products
14298 - * derived from this software without specific prior written permission.
14299 - *
14300 - *
14301 - * ALTERNATIVELY, this software may be distributed under the terms of the
14302 - * GNU General Public License ("GPL") as published by the Free Software
14303 - * Foundation, either version 2 of that License or (at your option) any
14304 - * later version.
14305 - *
14306 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14307 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14308 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14309 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
14310 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
14311 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
14312 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
14313 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
14314 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
14315 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
14316 - * POSSIBILITY OF SUCH DAMAGE.
14317 - */
14318 -
14319 -/*
14320 - * dprc-cmd.h
14321 - *
14322 - * defines dprc portal commands
14323 - *
14324 - */
14325 -
14326 -#ifndef _FSL_DPRC_CMD_H
14327 -#define _FSL_DPRC_CMD_H
14328 -
14329 -/* Minimal supported DPRC Version */
14330 -#define DPRC_MIN_VER_MAJOR 5
14331 -#define DPRC_MIN_VER_MINOR 0
14332 -
14333 -/* Command IDs */
14334 -#define DPRC_CMDID_CLOSE 0x800
14335 -#define DPRC_CMDID_OPEN 0x805
14336 -#define DPRC_CMDID_CREATE 0x905
14337 -
14338 -#define DPRC_CMDID_GET_ATTR 0x004
14339 -#define DPRC_CMDID_RESET_CONT 0x005
14340 -
14341 -#define DPRC_CMDID_SET_IRQ 0x010
14342 -#define DPRC_CMDID_GET_IRQ 0x011
14343 -#define DPRC_CMDID_SET_IRQ_ENABLE 0x012
14344 -#define DPRC_CMDID_GET_IRQ_ENABLE 0x013
14345 -#define DPRC_CMDID_SET_IRQ_MASK 0x014
14346 -#define DPRC_CMDID_GET_IRQ_MASK 0x015
14347 -#define DPRC_CMDID_GET_IRQ_STATUS 0x016
14348 -#define DPRC_CMDID_CLEAR_IRQ_STATUS 0x017
14349 -
14350 -#define DPRC_CMDID_CREATE_CONT 0x151
14351 -#define DPRC_CMDID_DESTROY_CONT 0x152
14352 -#define DPRC_CMDID_SET_RES_QUOTA 0x155
14353 -#define DPRC_CMDID_GET_RES_QUOTA 0x156
14354 -#define DPRC_CMDID_ASSIGN 0x157
14355 -#define DPRC_CMDID_UNASSIGN 0x158
14356 -#define DPRC_CMDID_GET_OBJ_COUNT 0x159
14357 -#define DPRC_CMDID_GET_OBJ 0x15A
14358 -#define DPRC_CMDID_GET_RES_COUNT 0x15B
14359 -#define DPRC_CMDID_GET_RES_IDS 0x15C
14360 -#define DPRC_CMDID_GET_OBJ_REG 0x15E
14361 -#define DPRC_CMDID_SET_OBJ_IRQ 0x15F
14362 -#define DPRC_CMDID_GET_OBJ_IRQ 0x160
14363 -#define DPRC_CMDID_SET_OBJ_LABEL 0x161
14364 -#define DPRC_CMDID_GET_OBJ_DESC 0x162
14365 -
14366 -#define DPRC_CMDID_CONNECT 0x167
14367 -#define DPRC_CMDID_DISCONNECT 0x168
14368 -#define DPRC_CMDID_GET_POOL 0x169
14369 -#define DPRC_CMDID_GET_POOL_COUNT 0x16A
14370 -
14371 -#define DPRC_CMDID_GET_CONNECTION 0x16C
14372 -
14373 -struct dprc_cmd_open {
14374 - __le32 container_id;
14375 -};
14376 -
14377 -struct dprc_cmd_create_container {
14378 - /* cmd word 0 */
14379 - __le32 options;
14380 - __le16 icid;
14381 - __le16 pad0;
14382 - /* cmd word 1 */
14383 - __le32 pad1;
14384 - __le32 portal_id;
14385 - /* cmd words 2-3 */
14386 - u8 label[16];
14387 -};
14388 -
14389 -struct dprc_rsp_create_container {
14390 - /* response word 0 */
14391 - __le64 pad0;
14392 - /* response word 1 */
14393 - __le32 child_container_id;
14394 - __le32 pad1;
14395 - /* response word 2 */
14396 - __le64 child_portal_addr;
14397 -};
14398 -
14399 -struct dprc_cmd_destroy_container {
14400 - __le32 child_container_id;
14401 -};
14402 -
14403 -struct dprc_cmd_reset_container {
14404 - __le32 child_container_id;
14405 -};
14406 -
14407 -struct dprc_cmd_set_irq {
14408 - /* cmd word 0 */
14409 - __le32 irq_val;
14410 - u8 irq_index;
14411 - u8 pad[3];
14412 - /* cmd word 1 */
14413 - __le64 irq_addr;
14414 - /* cmd word 2 */
14415 - __le32 irq_num;
14416 -};
14417 -
14418 -struct dprc_cmd_get_irq {
14419 - __le32 pad;
14420 - u8 irq_index;
14421 -};
14422 -
14423 -struct dprc_rsp_get_irq {
14424 - /* response word 0 */
14425 - __le32 irq_val;
14426 - __le32 pad;
14427 - /* response word 1 */
14428 - __le64 irq_addr;
14429 - /* response word 2 */
14430 - __le32 irq_num;
14431 - __le32 type;
14432 -};
14433 -
14434 -#define DPRC_ENABLE 0x1
14435 -
14436 -struct dprc_cmd_set_irq_enable {
14437 - u8 enable;
14438 - u8 pad[3];
14439 - u8 irq_index;
14440 -};
14441 -
14442 -struct dprc_cmd_get_irq_enable {
14443 - __le32 pad;
14444 - u8 irq_index;
14445 -};
14446 -
14447 -struct dprc_rsp_get_irq_enable {
14448 - u8 enabled;
14449 -};
14450 -
14451 -struct dprc_cmd_set_irq_mask {
14452 - __le32 mask;
14453 - u8 irq_index;
14454 -};
14455 -
14456 -struct dprc_cmd_get_irq_mask {
14457 - __le32 pad;
14458 - u8 irq_index;
14459 -};
14460 -
14461 -struct dprc_rsp_get_irq_mask {
14462 - __le32 mask;
14463 -};
14464 -
14465 -struct dprc_cmd_get_irq_status {
14466 - __le32 status;
14467 - u8 irq_index;
14468 -};
14469 -
14470 -struct dprc_rsp_get_irq_status {
14471 - __le32 status;
14472 -};
14473 -
14474 -struct dprc_cmd_clear_irq_status {
14475 - __le32 status;
14476 - u8 irq_index;
14477 -};
14478 -
14479 -struct dprc_rsp_get_attributes {
14480 - /* response word 0 */
14481 - __le32 container_id;
14482 - __le16 icid;
14483 - __le16 pad;
14484 - /* response word 1 */
14485 - __le32 options;
14486 - __le32 portal_id;
14487 - /* response word 2 */
14488 - __le16 version_major;
14489 - __le16 version_minor;
14490 -};
14491 -
14492 -struct dprc_cmd_set_res_quota {
14493 - /* cmd word 0 */
14494 - __le32 child_container_id;
14495 - __le16 quota;
14496 - __le16 pad;
14497 - /* cmd words 1-2 */
14498 - u8 type[16];
14499 -};
14500 -
14501 -struct dprc_cmd_get_res_quota {
14502 - /* cmd word 0 */
14503 - __le32 child_container_id;
14504 - __le32 pad;
14505 - /* cmd word 1-2 */
14506 - u8 type[16];
14507 -};
14508 -
14509 -struct dprc_rsp_get_res_quota {
14510 - __le32 pad;
14511 - __le16 quota;
14512 -};
14513 -
14514 -struct dprc_cmd_assign {
14515 - /* cmd word 0 */
14516 - __le32 container_id;
14517 - __le32 options;
14518 - /* cmd word 1 */
14519 - __le32 num;
14520 - __le32 id_base_align;
14521 - /* cmd word 2-3 */
14522 - u8 type[16];
14523 -};
14524 -
14525 -struct dprc_cmd_unassign {
14526 - /* cmd word 0 */
14527 - __le32 child_container_id;
14528 - __le32 options;
14529 - /* cmd word 1 */
14530 - __le32 num;
14531 - __le32 id_base_align;
14532 - /* cmd word 2-3 */
14533 - u8 type[16];
14534 -};
14535 -
14536 -struct dprc_rsp_get_pool_count {
14537 - __le32 pool_count;
14538 -};
14539 -
14540 -struct dprc_cmd_get_pool {
14541 - __le32 pool_index;
14542 -};
14543 -
14544 -struct dprc_rsp_get_pool {
14545 - /* response word 0 */
14546 - __le64 pad;
14547 - /* response word 1-2 */
14548 - u8 type[16];
14549 -};
14550 -
14551 -struct dprc_rsp_get_obj_count {
14552 - __le32 pad;
14553 - __le32 obj_count;
14554 -};
14555 -
14556 -struct dprc_cmd_get_obj {
14557 - __le32 obj_index;
14558 -};
14559 -
14560 -struct dprc_rsp_get_obj {
14561 - /* response word 0 */
14562 - __le32 pad0;
14563 - __le32 id;
14564 - /* response word 1 */
14565 - __le16 vendor;
14566 - u8 irq_count;
14567 - u8 region_count;
14568 - __le32 state;
14569 - /* response word 2 */
14570 - __le16 version_major;
14571 - __le16 version_minor;
14572 - __le16 flags;
14573 - __le16 pad1;
14574 - /* response word 3-4 */
14575 - u8 type[16];
14576 - /* response word 5-6 */
14577 - u8 label[16];
14578 -};
14579 -
14580 -struct dprc_cmd_get_obj_desc {
14581 - /* cmd word 0 */
14582 - __le32 obj_id;
14583 - __le32 pad;
14584 - /* cmd word 1-2 */
14585 - u8 type[16];
14586 -};
14587 -
14588 -struct dprc_rsp_get_obj_desc {
14589 - /* response word 0 */
14590 - __le32 pad0;
14591 - __le32 id;
14592 - /* response word 1 */
14593 - __le16 vendor;
14594 - u8 irq_count;
14595 - u8 region_count;
14596 - __le32 state;
14597 - /* response word 2 */
14598 - __le16 version_major;
14599 - __le16 version_minor;
14600 - __le16 flags;
14601 - __le16 pad1;
14602 - /* response word 3-4 */
14603 - u8 type[16];
14604 - /* response word 5-6 */
14605 - u8 label[16];
14606 -};
14607 -
14608 -struct dprc_cmd_get_res_count {
14609 - /* cmd word 0 */
14610 - __le64 pad;
14611 - /* cmd word 1-2 */
14612 - u8 type[16];
14613 -};
14614 -
14615 -struct dprc_rsp_get_res_count {
14616 - __le32 res_count;
14617 -};
14618 -
14619 -struct dprc_cmd_get_res_ids {
14620 - /* cmd word 0 */
14621 - u8 pad0[5];
14622 - u8 iter_status;
14623 - __le16 pad1;
14624 - /* cmd word 1 */
14625 - __le32 base_id;
14626 - __le32 last_id;
14627 - /* cmd word 2-3 */
14628 - u8 type[16];
14629 -};
14630 -
14631 -struct dprc_rsp_get_res_ids {
14632 - /* response word 0 */
14633 - u8 pad0[5];
14634 - u8 iter_status;
14635 - __le16 pad1;
14636 - /* response word 1 */
14637 - __le32 base_id;
14638 - __le32 last_id;
14639 -};
14640 -
14641 -struct dprc_cmd_get_obj_region {
14642 - /* cmd word 0 */
14643 - __le32 obj_id;
14644 - __le16 pad0;
14645 - u8 region_index;
14646 - u8 pad1;
14647 - /* cmd word 1-2 */
14648 - __le64 pad2[2];
14649 - /* cmd word 3-4 */
14650 - u8 obj_type[16];
14651 -};
14652 -
14653 -struct dprc_rsp_get_obj_region {
14654 - /* response word 0 */
14655 - __le64 pad;
14656 - /* response word 1 */
14657 - __le64 base_addr;
14658 - /* response word 2 */
14659 - __le32 size;
14660 -};
14661 -
14662 -struct dprc_cmd_set_obj_label {
14663 - /* cmd word 0 */
14664 - __le32 obj_id;
14665 - __le32 pad;
14666 - /* cmd word 1-2 */
14667 - u8 label[16];
14668 - /* cmd word 3-4 */
14669 - u8 obj_type[16];
14670 -};
14671 -
14672 -struct dprc_cmd_set_obj_irq {
14673 - /* cmd word 0 */
14674 - __le32 irq_val;
14675 - u8 irq_index;
14676 - u8 pad[3];
14677 - /* cmd word 1 */
14678 - __le64 irq_addr;
14679 - /* cmd word 2 */
14680 - __le32 irq_num;
14681 - __le32 obj_id;
14682 - /* cmd word 3-4 */
14683 - u8 obj_type[16];
14684 -};
14685 -
14686 -struct dprc_cmd_get_obj_irq {
14687 - /* cmd word 0 */
14688 - __le32 obj_id;
14689 - u8 irq_index;
14690 - u8 pad[3];
14691 - /* cmd word 1-2 */
14692 - u8 obj_type[16];
14693 -};
14694 -
14695 -struct dprc_rsp_get_obj_irq {
14696 - /* response word 0 */
14697 - __le32 irq_val;
14698 - __le32 pad;
14699 - /* response word 1 */
14700 - __le64 irq_addr;
14701 - /* response word 2 */
14702 - __le32 irq_num;
14703 - __le32 type;
14704 -};
14705 -
14706 -struct dprc_cmd_connect {
14707 - /* cmd word 0 */
14708 - __le32 ep1_id;
14709 - __le32 ep1_interface_id;
14710 - /* cmd word 1 */
14711 - __le32 ep2_id;
14712 - __le32 ep2_interface_id;
14713 - /* cmd word 2-3 */
14714 - u8 ep1_type[16];
14715 - /* cmd word 4 */
14716 - __le32 max_rate;
14717 - __le32 committed_rate;
14718 - /* cmd word 5-6 */
14719 - u8 ep2_type[16];
14720 -};
14721 -
14722 -struct dprc_cmd_disconnect {
14723 - /* cmd word 0 */
14724 - __le32 id;
14725 - __le32 interface_id;
14726 - /* cmd word 1-2 */
14727 - u8 type[16];
14728 -};
14729 -
14730 -struct dprc_cmd_get_connection {
14731 - /* cmd word 0 */
14732 - __le32 ep1_id;
14733 - __le32 ep1_interface_id;
14734 - /* cmd word 1-2 */
14735 - u8 ep1_type[16];
14736 -};
14737 -
14738 -struct dprc_rsp_get_connection {
14739 - /* response word 0-2 */
14740 - __le64 pad[3];
14741 - /* response word 3 */
14742 - __le32 ep2_id;
14743 - __le32 ep2_interface_id;
14744 - /* response word 4-5 */
14745 - u8 ep2_type[16];
14746 - /* response word 6 */
14747 - __le32 state;
14748 -};
14749 -
14750 -#endif /* _FSL_DPRC_CMD_H */
14751 --- a/drivers/staging/fsl-mc/bus/dprc.c
14752 +++ /dev/null
14753 @@ -1,1388 +0,0 @@
14754 -/* Copyright 2013-2016 Freescale Semiconductor Inc.
14755 - *
14756 - * Redistribution and use in source and binary forms, with or without
14757 - * modification, are permitted provided that the following conditions are met:
14758 - * * Redistributions of source code must retain the above copyright
14759 - * notice, this list of conditions and the following disclaimer.
14760 - * * Redistributions in binary form must reproduce the above copyright
14761 - * notice, this list of conditions and the following disclaimer in the
14762 - * documentation and/or other materials provided with the distribution.
14763 - * * Neither the name of the above-listed copyright holders nor the
14764 - * names of any contributors may be used to endorse or promote products
14765 - * derived from this software without specific prior written permission.
14766 - *
14767 - *
14768 - * ALTERNATIVELY, this software may be distributed under the terms of the
14769 - * GNU General Public License ("GPL") as published by the Free Software
14770 - * Foundation, either version 2 of that License or (at your option) any
14771 - * later version.
14772 - *
14773 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14774 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14775 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14776 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
14777 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
14778 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
14779 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
14780 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
14781 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
14782 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
14783 - * POSSIBILITY OF SUCH DAMAGE.
14784 - */
14785 -#include "../include/mc-sys.h"
14786 -#include "../include/mc-cmd.h"
14787 -#include "../include/dprc.h"
14788 -
14789 -#include "dprc-cmd.h"
14790 -
14791 -/**
14792 - * dprc_open() - Open DPRC object for use
14793 - * @mc_io: Pointer to MC portal's I/O object
14794 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
14795 - * @container_id: Container ID to open
14796 - * @token: Returned token of DPRC object
14797 - *
14798 - * Return: '0' on Success; Error code otherwise.
14799 - *
14800 - * @warning Required before any operation on the object.
14801 - */
14802 -int dprc_open(struct fsl_mc_io *mc_io,
14803 - u32 cmd_flags,
14804 - int container_id,
14805 - u16 *token)
14806 -{
14807 - struct mc_command cmd = { 0 };
14808 - struct dprc_cmd_open *cmd_params;
14809 - int err;
14810 -
14811 - /* prepare command */
14812 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_OPEN, cmd_flags,
14813 - 0);
14814 - cmd_params = (struct dprc_cmd_open *)cmd.params;
14815 - cmd_params->container_id = cpu_to_le32(container_id);
14816 -
14817 - /* send command to mc*/
14818 - err = mc_send_command(mc_io, &cmd);
14819 - if (err)
14820 - return err;
14821 -
14822 - /* retrieve response parameters */
14823 - *token = mc_cmd_hdr_read_token(&cmd);
14824 -
14825 - return 0;
14826 -}
14827 -EXPORT_SYMBOL(dprc_open);
14828 -
14829 -/**
14830 - * dprc_close() - Close the control session of the object
14831 - * @mc_io: Pointer to MC portal's I/O object
14832 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
14833 - * @token: Token of DPRC object
14834 - *
14835 - * After this function is called, no further operations are
14836 - * allowed on the object without opening a new control session.
14837 - *
14838 - * Return: '0' on Success; Error code otherwise.
14839 - */
14840 -int dprc_close(struct fsl_mc_io *mc_io,
14841 - u32 cmd_flags,
14842 - u16 token)
14843 -{
14844 - struct mc_command cmd = { 0 };
14845 -
14846 - /* prepare command */
14847 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLOSE, cmd_flags,
14848 - token);
14849 -
14850 - /* send command to mc*/
14851 - return mc_send_command(mc_io, &cmd);
14852 -}
14853 -EXPORT_SYMBOL(dprc_close);
14854 -
14855 -/**
14856 - * dprc_create_container() - Create child container
14857 - * @mc_io: Pointer to MC portal's I/O object
14858 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
14859 - * @token: Token of DPRC object
14860 - * @cfg: Child container configuration
14861 - * @child_container_id: Returned child container ID
14862 - * @child_portal_offset: Returned child portal offset from MC portal base
14863 - *
14864 - * Return: '0' on Success; Error code otherwise.
14865 - */
14866 -int dprc_create_container(struct fsl_mc_io *mc_io,
14867 - u32 cmd_flags,
14868 - u16 token,
14869 - struct dprc_cfg *cfg,
14870 - int *child_container_id,
14871 - u64 *child_portal_offset)
14872 -{
14873 - struct mc_command cmd = { 0 };
14874 - struct dprc_cmd_create_container *cmd_params;
14875 - struct dprc_rsp_create_container *rsp_params;
14876 - int err;
14877 -
14878 - /* prepare command */
14879 - cmd_params = (struct dprc_cmd_create_container *)cmd.params;
14880 - cmd_params->options = cpu_to_le32(cfg->options);
14881 - cmd_params->icid = cpu_to_le16(cfg->icid);
14882 - cmd_params->portal_id = cpu_to_le32(cfg->portal_id);
14883 - strncpy(cmd_params->label, cfg->label, 16);
14884 - cmd_params->label[15] = '\0';
14885 -
14886 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_CREATE_CONT,
14887 - cmd_flags, token);
14888 -
14889 - /* send command to mc*/
14890 - err = mc_send_command(mc_io, &cmd);
14891 - if (err)
14892 - return err;
14893 -
14894 - /* retrieve response parameters */
14895 - rsp_params = (struct dprc_rsp_create_container *)cmd.params;
14896 - *child_container_id = le32_to_cpu(rsp_params->child_container_id);
14897 - *child_portal_offset = le64_to_cpu(rsp_params->child_portal_addr);
14898 -
14899 - return 0;
14900 -}
14901 -
14902 -/**
14903 - * dprc_destroy_container() - Destroy child container.
14904 - * @mc_io: Pointer to MC portal's I/O object
14905 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
14906 - * @token: Token of DPRC object
14907 - * @child_container_id: ID of the container to destroy
14908 - *
14909 - * This function terminates the child container, so following this call the
14910 - * child container ID becomes invalid.
14911 - *
14912 - * Notes:
14913 - * - All resources and objects of the destroyed container are returned to the
14914 - * parent container or destroyed if were created be the destroyed container.
14915 - * - This function destroy all the child containers of the specified
14916 - * container prior to destroying the container itself.
14917 - *
14918 - * warning: Only the parent container is allowed to destroy a child policy
14919 - * Container 0 can't be destroyed
14920 - *
14921 - * Return: '0' on Success; Error code otherwise.
14922 - *
14923 - */
14924 -int dprc_destroy_container(struct fsl_mc_io *mc_io,
14925 - u32 cmd_flags,
14926 - u16 token,
14927 - int child_container_id)
14928 -{
14929 - struct mc_command cmd = { 0 };
14930 - struct dprc_cmd_destroy_container *cmd_params;
14931 -
14932 - /* prepare command */
14933 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_DESTROY_CONT,
14934 - cmd_flags, token);
14935 - cmd_params = (struct dprc_cmd_destroy_container *)cmd.params;
14936 - cmd_params->child_container_id = cpu_to_le32(child_container_id);
14937 -
14938 - /* send command to mc*/
14939 - return mc_send_command(mc_io, &cmd);
14940 -}
14941 -
14942 -/**
14943 - * dprc_reset_container - Reset child container.
14944 - * @mc_io: Pointer to MC portal's I/O object
14945 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
14946 - * @token: Token of DPRC object
14947 - * @child_container_id: ID of the container to reset
14948 - *
14949 - * In case a software context crashes or becomes non-responsive, the parent
14950 - * may wish to reset its resources container before the software context is
14951 - * restarted.
14952 - *
14953 - * This routine informs all objects assigned to the child container that the
14954 - * container is being reset, so they may perform any cleanup operations that are
14955 - * needed. All objects handles that were owned by the child container shall be
14956 - * closed.
14957 - *
14958 - * Note that such request may be submitted even if the child software context
14959 - * has not crashed, but the resulting object cleanup operations will not be
14960 - * aware of that.
14961 - *
14962 - * Return: '0' on Success; Error code otherwise.
14963 - */
14964 -int dprc_reset_container(struct fsl_mc_io *mc_io,
14965 - u32 cmd_flags,
14966 - u16 token,
14967 - int child_container_id)
14968 -{
14969 - struct mc_command cmd = { 0 };
14970 - struct dprc_cmd_reset_container *cmd_params;
14971 -
14972 - /* prepare command */
14973 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_RESET_CONT,
14974 - cmd_flags, token);
14975 - cmd_params = (struct dprc_cmd_reset_container *)cmd.params;
14976 - cmd_params->child_container_id = cpu_to_le32(child_container_id);
14977 -
14978 - /* send command to mc*/
14979 - return mc_send_command(mc_io, &cmd);
14980 -}
14981 -
14982 -/**
14983 - * dprc_get_irq() - Get IRQ information from the DPRC.
14984 - * @mc_io: Pointer to MC portal's I/O object
14985 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
14986 - * @token: Token of DPRC object
14987 - * @irq_index: The interrupt index to configure
14988 - * @type: Interrupt type: 0 represents message interrupt
14989 - * type (both irq_addr and irq_val are valid)
14990 - * @irq_cfg: IRQ attributes
14991 - *
14992 - * Return: '0' on Success; Error code otherwise.
14993 - */
14994 -int dprc_get_irq(struct fsl_mc_io *mc_io,
14995 - u32 cmd_flags,
14996 - u16 token,
14997 - u8 irq_index,
14998 - int *type,
14999 - struct dprc_irq_cfg *irq_cfg)
15000 -{
15001 - struct mc_command cmd = { 0 };
15002 - struct dprc_cmd_get_irq *cmd_params;
15003 - struct dprc_rsp_get_irq *rsp_params;
15004 - int err;
15005 -
15006 - /* prepare command */
15007 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ,
15008 - cmd_flags,
15009 - token);
15010 - cmd_params = (struct dprc_cmd_get_irq *)cmd.params;
15011 - cmd_params->irq_index = irq_index;
15012 -
15013 - /* send command to mc*/
15014 - err = mc_send_command(mc_io, &cmd);
15015 - if (err)
15016 - return err;
15017 -
15018 - /* retrieve response parameters */
15019 - rsp_params = (struct dprc_rsp_get_irq *)cmd.params;
15020 - irq_cfg->val = le32_to_cpu(rsp_params->irq_val);
15021 - irq_cfg->paddr = le64_to_cpu(rsp_params->irq_addr);
15022 - irq_cfg->irq_num = le32_to_cpu(rsp_params->irq_num);
15023 - *type = le32_to_cpu(rsp_params->type);
15024 -
15025 - return 0;
15026 -}
15027 -
15028 -/**
15029 - * dprc_set_irq() - Set IRQ information for the DPRC to trigger an interrupt.
15030 - * @mc_io: Pointer to MC portal's I/O object
15031 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
15032 - * @token: Token of DPRC object
15033 - * @irq_index: Identifies the interrupt index to configure
15034 - * @irq_cfg: IRQ configuration
15035 - *
15036 - * Return: '0' on Success; Error code otherwise.
15037 - */
15038 -int dprc_set_irq(struct fsl_mc_io *mc_io,
15039 - u32 cmd_flags,
15040 - u16 token,
15041 - u8 irq_index,
15042 - struct dprc_irq_cfg *irq_cfg)
15043 -{
15044 - struct mc_command cmd = { 0 };
15045 - struct dprc_cmd_set_irq *cmd_params;
15046 -
15047 - /* prepare command */
15048 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ,
15049 - cmd_flags,
15050 - token);
15051 - cmd_params = (struct dprc_cmd_set_irq *)cmd.params;
15052 - cmd_params->irq_val = cpu_to_le32(irq_cfg->val);
15053 - cmd_params->irq_index = irq_index;
15054 - cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr);
15055 - cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num);
15056 -
15057 - /* send command to mc*/
15058 - return mc_send_command(mc_io, &cmd);
15059 -}
15060 -
15061 -/**
15062 - * dprc_get_irq_enable() - Get overall interrupt state.
15063 - * @mc_io: Pointer to MC portal's I/O object
15064 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
15065 - * @token: Token of DPRC object
15066 - * @irq_index: The interrupt index to configure
15067 - * @en: Returned interrupt state - enable = 1, disable = 0
15068 - *
15069 - * Return: '0' on Success; Error code otherwise.
15070 - */
15071 -int dprc_get_irq_enable(struct fsl_mc_io *mc_io,
15072 - u32 cmd_flags,
15073 - u16 token,
15074 - u8 irq_index,
15075 - u8 *en)
15076 -{
15077 - struct mc_command cmd = { 0 };
15078 - struct dprc_cmd_get_irq_enable *cmd_params;
15079 - struct dprc_rsp_get_irq_enable *rsp_params;
15080 - int err;
15081 -
15082 - /* prepare command */
15083 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_ENABLE,
15084 - cmd_flags, token);
15085 - cmd_params = (struct dprc_cmd_get_irq_enable *)cmd.params;
15086 - cmd_params->irq_index = irq_index;
15087 -
15088 - /* send command to mc*/
15089 - err = mc_send_command(mc_io, &cmd);
15090 - if (err)
15091 - return err;
15092 -
15093 - /* retrieve response parameters */
15094 - rsp_params = (struct dprc_rsp_get_irq_enable *)cmd.params;
15095 - *en = rsp_params->enabled & DPRC_ENABLE;
15096 -
15097 - return 0;
15098 -}
15099 -
15100 -/**
15101 - * dprc_set_irq_enable() - Set overall interrupt state.
15102 - * @mc_io: Pointer to MC portal's I/O object
15103 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
15104 - * @token: Token of DPRC object
15105 - * @irq_index: The interrupt index to configure
15106 - * @en: Interrupt state - enable = 1, disable = 0
15107 - *
15108 - * Allows GPP software to control when interrupts are generated.
15109 - * Each interrupt can have up to 32 causes. The enable/disable control's the
15110 - * overall interrupt state. if the interrupt is disabled no causes will cause
15111 - * an interrupt.
15112 - *
15113 - * Return: '0' on Success; Error code otherwise.
15114 - */
15115 -int dprc_set_irq_enable(struct fsl_mc_io *mc_io,
15116 - u32 cmd_flags,
15117 - u16 token,
15118 - u8 irq_index,
15119 - u8 en)
15120 -{
15121 - struct mc_command cmd = { 0 };
15122 - struct dprc_cmd_set_irq_enable *cmd_params;
15123 -
15124 - /* prepare command */
15125 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_ENABLE,
15126 - cmd_flags, token);
15127 - cmd_params = (struct dprc_cmd_set_irq_enable *)cmd.params;
15128 - cmd_params->enable = en & DPRC_ENABLE;
15129 - cmd_params->irq_index = irq_index;
15130 -
15131 - /* send command to mc*/
15132 - return mc_send_command(mc_io, &cmd);
15133 -}
15134 -
15135 -/**
15136 - * dprc_get_irq_mask() - Get interrupt mask.
15137 - * @mc_io: Pointer to MC portal's I/O object
15138 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
15139 - * @token: Token of DPRC object
15140 - * @irq_index: The interrupt index to configure
15141 - * @mask: Returned event mask to trigger interrupt
15142 - *
15143 - * Every interrupt can have up to 32 causes and the interrupt model supports
15144 - * masking/unmasking each cause independently
15145 - *
15146 - * Return: '0' on Success; Error code otherwise.
15147 - */
15148 -int dprc_get_irq_mask(struct fsl_mc_io *mc_io,
15149 - u32 cmd_flags,
15150 - u16 token,
15151 - u8 irq_index,
15152 - u32 *mask)
15153 -{
15154 - struct mc_command cmd = { 0 };
15155 - struct dprc_cmd_get_irq_mask *cmd_params;
15156 - struct dprc_rsp_get_irq_mask *rsp_params;
15157 - int err;
15158 -
15159 - /* prepare command */
15160 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_MASK,
15161 - cmd_flags, token);
15162 - cmd_params = (struct dprc_cmd_get_irq_mask *)cmd.params;
15163 - cmd_params->irq_index = irq_index;
15164 -
15165 - /* send command to mc*/
15166 - err = mc_send_command(mc_io, &cmd);
15167 - if (err)
15168 - return err;
15169 -
15170 - /* retrieve response parameters */
15171 - rsp_params = (struct dprc_rsp_get_irq_mask *)cmd.params;
15172 - *mask = le32_to_cpu(rsp_params->mask);
15173 -
15174 - return 0;
15175 -}
15176 -
15177 -/**
15178 - * dprc_set_irq_mask() - Set interrupt mask.
15179 - * @mc_io: Pointer to MC portal's I/O object
15180 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
15181 - * @token: Token of DPRC object
15182 - * @irq_index: The interrupt index to configure
15183 - * @mask: event mask to trigger interrupt;
15184 - * each bit:
15185 - * 0 = ignore event
15186 - * 1 = consider event for asserting irq
15187 - *
15188 - * Every interrupt can have up to 32 causes and the interrupt model supports
15189 - * masking/unmasking each cause independently
15190 - *
15191 - * Return: '0' on Success; Error code otherwise.
15192 - */
15193 -int dprc_set_irq_mask(struct fsl_mc_io *mc_io,
15194 - u32 cmd_flags,
15195 - u16 token,
15196 - u8 irq_index,
15197 - u32 mask)
15198 -{
15199 - struct mc_command cmd = { 0 };
15200 - struct dprc_cmd_set_irq_mask *cmd_params;
15201 -
15202 - /* prepare command */
15203 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_MASK,
15204 - cmd_flags, token);
15205 - cmd_params = (struct dprc_cmd_set_irq_mask *)cmd.params;
15206 - cmd_params->mask = cpu_to_le32(mask);
15207 - cmd_params->irq_index = irq_index;
15208 -
15209 - /* send command to mc*/
15210 - return mc_send_command(mc_io, &cmd);
15211 -}
15212 -
15213 -/**
15214 - * dprc_get_irq_status() - Get the current status of any pending interrupts.
15215 - * @mc_io: Pointer to MC portal's I/O object
15216 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
15217 - * @token: Token of DPRC object
15218 - * @irq_index: The interrupt index to configure
15219 - * @status: Returned interrupts status - one bit per cause:
15220 - * 0 = no interrupt pending
15221 - * 1 = interrupt pending
15222 - *
15223 - * Return: '0' on Success; Error code otherwise.
15224 - */
15225 -int dprc_get_irq_status(struct fsl_mc_io *mc_io,
15226 - u32 cmd_flags,
15227 - u16 token,
15228 - u8 irq_index,
15229 - u32 *status)
15230 -{
15231 - struct mc_command cmd = { 0 };
15232 - struct dprc_cmd_get_irq_status *cmd_params;
15233 - struct dprc_rsp_get_irq_status *rsp_params;
15234 - int err;
15235 -
15236 - /* prepare command */
15237 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_STATUS,
15238 - cmd_flags, token);
15239 - cmd_params = (struct dprc_cmd_get_irq_status *)cmd.params;
15240 - cmd_params->status = cpu_to_le32(*status);
15241 - cmd_params->irq_index = irq_index;
15242 -
15243 - /* send command to mc*/
15244 - err = mc_send_command(mc_io, &cmd);
15245 - if (err)
15246 - return err;
15247 -
15248 - /* retrieve response parameters */
15249 - rsp_params = (struct dprc_rsp_get_irq_status *)cmd.params;
15250 - *status = le32_to_cpu(rsp_params->status);
15251 -
15252 - return 0;
15253 -}
15254 -
15255 -/**
15256 - * dprc_clear_irq_status() - Clear a pending interrupt's status
15257 - * @mc_io: Pointer to MC portal's I/O object
15258 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
15259 - * @token: Token of DPRC object
15260 - * @irq_index: The interrupt index to configure
15261 - * @status: bits to clear (W1C) - one bit per cause:
15262 - * 0 = don't change
15263 - * 1 = clear status bit
15264 - *
15265 - * Return: '0' on Success; Error code otherwise.
15266 - */
15267 -int dprc_clear_irq_status(struct fsl_mc_io *mc_io,
15268 - u32 cmd_flags,
15269 - u16 token,
15270 - u8 irq_index,
15271 - u32 status)
15272 -{
15273 - struct mc_command cmd = { 0 };
15274 - struct dprc_cmd_clear_irq_status *cmd_params;
15275 -
15276 - /* prepare command */
15277 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLEAR_IRQ_STATUS,
15278 - cmd_flags, token);
15279 - cmd_params = (struct dprc_cmd_clear_irq_status *)cmd.params;
15280 - cmd_params->status = cpu_to_le32(status);
15281 - cmd_params->irq_index = irq_index;
15282 -
15283 - /* send command to mc*/
15284 - return mc_send_command(mc_io, &cmd);
15285 -}
15286 -
15287 -/**
15288 - * dprc_get_attributes() - Obtains container attributes
15289 - * @mc_io: Pointer to MC portal's I/O object
15290 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
15291 - * @token: Token of DPRC object
15292 - * @attributes Returned container attributes
15293 - *
15294 - * Return: '0' on Success; Error code otherwise.
15295 - */
15296 -int dprc_get_attributes(struct fsl_mc_io *mc_io,
15297 - u32 cmd_flags,
15298 - u16 token,
15299 - struct dprc_attributes *attr)
15300 -{
15301 - struct mc_command cmd = { 0 };
15302 - struct dprc_rsp_get_attributes *rsp_params;
15303 - int err;
15304 -
15305 - /* prepare command */
15306 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_ATTR,
15307 - cmd_flags,
15308 - token);
15309 -
15310 - /* send command to mc*/
15311 - err = mc_send_command(mc_io, &cmd);
15312 - if (err)
15313 - return err;
15314 -
15315 - /* retrieve response parameters */
15316 - rsp_params = (struct dprc_rsp_get_attributes *)cmd.params;
15317 - attr->container_id = le32_to_cpu(rsp_params->container_id);
15318 - attr->icid = le16_to_cpu(rsp_params->icid);
15319 - attr->options = le32_to_cpu(rsp_params->options);
15320 - attr->portal_id = le32_to_cpu(rsp_params->portal_id);
15321 - attr->version.major = le16_to_cpu(rsp_params->version_major);
15322 - attr->version.minor = le16_to_cpu(rsp_params->version_minor);
15323 -
15324 - return 0;
15325 -}
15326 -
15327 -/**
15328 - * dprc_set_res_quota() - Set allocation policy for a specific resource/object
15329 - * type in a child container
15330 - * @mc_io: Pointer to MC portal's I/O object
15331 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
15332 - * @token: Token of DPRC object
15333 - * @child_container_id: ID of the child container
15334 - * @type: Resource/object type
15335 - * @quota: Sets the maximum number of resources of the selected type
15336 - * that the child container is allowed to allocate from its parent;
15337 - * when quota is set to -1, the policy is the same as container's
15338 - * general policy.
15339 - *
15340 - * Allocation policy determines whether or not a container may allocate
15341 - * resources from its parent. Each container has a 'global' allocation policy
15342 - * that is set when the container is created.
15343 - *
15344 - * This function sets allocation policy for a specific resource type.
15345 - * The default policy for all resource types matches the container's 'global'
15346 - * allocation policy.
15347 - *
15348 - * Return: '0' on Success; Error code otherwise.
15349 - *
15350 - * @warning Only the parent container is allowed to change a child policy.
15351 - */
15352 -int dprc_set_res_quota(struct fsl_mc_io *mc_io,
15353 - u32 cmd_flags,
15354 - u16 token,
15355 - int child_container_id,
15356 - char *type,
15357 - u16 quota)
15358 -{
15359 - struct mc_command cmd = { 0 };
15360 - struct dprc_cmd_set_res_quota *cmd_params;
15361 -
15362 - /* prepare command */
15363 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_RES_QUOTA,
15364 - cmd_flags, token);
15365 - cmd_params = (struct dprc_cmd_set_res_quota *)cmd.params;
15366 - cmd_params->child_container_id = cpu_to_le32(child_container_id);
15367 - cmd_params->quota = cpu_to_le16(quota);
15368 - strncpy(cmd_params->type, type, 16);
15369 - cmd_params->type[15] = '\0';
15370 -
15371 - /* send command to mc*/
15372 - return mc_send_command(mc_io, &cmd);
15373 -}
15374 -
15375 -/**
15376 - * dprc_get_res_quota() - Gets the allocation policy of a specific
15377 - * resource/object type in a child container
15378 - * @mc_io: Pointer to MC portal's I/O object
15379 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
15380 - * @token: Token of DPRC object
15381 - * @child_container_id; ID of the child container
15382 - * @type: resource/object type
15383 - * @quota: Returnes the maximum number of resources of the selected type
15384 - * that the child container is allowed to allocate from the parent;
15385 - * when quota is set to -1, the policy is the same as container's
15386 - * general policy.
15387 - *
15388 - * Return: '0' on Success; Error code otherwise.
15389 - */
15390 -int dprc_get_res_quota(struct fsl_mc_io *mc_io,
15391 - u32 cmd_flags,
15392 - u16 token,
15393 - int child_container_id,
15394 - char *type,
15395 - u16 *quota)
15396 -{
15397 - struct mc_command cmd = { 0 };
15398 - struct dprc_cmd_get_res_quota *cmd_params;
15399 - struct dprc_rsp_get_res_quota *rsp_params;
15400 - int err;
15401 -
15402 - /* prepare command */
15403 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_QUOTA,
15404 - cmd_flags, token);
15405 - cmd_params = (struct dprc_cmd_get_res_quota *)cmd.params;
15406 - cmd_params->child_container_id = cpu_to_le32(child_container_id);
15407 - strncpy(cmd_params->type, type, 16);
15408 - cmd_params->type[15] = '\0';
15409 -
15410 - /* send command to mc*/
15411 - err = mc_send_command(mc_io, &cmd);
15412 - if (err)
15413 - return err;
15414 -
15415 - /* retrieve response parameters */
15416 - rsp_params = (struct dprc_rsp_get_res_quota *)cmd.params;
15417 - *quota = le16_to_cpu(rsp_params->quota);
15418 -
15419 - return 0;
15420 -}
15421 -
15422 -/**
15423 - * dprc_assign() - Assigns objects or resource to a child container.
15424 - * @mc_io: Pointer to MC portal's I/O object
15425 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
15426 - * @token: Token of DPRC object
15427 - * @container_id: ID of the child container
15428 - * @res_req: Describes the type and amount of resources to
15429 - * assign to the given container
15430 - *
15431 - * Assignment is usually done by a parent (this DPRC) to one of its child
15432 - * containers.
15433 - *
15434 - * According to the DPRC allocation policy, the assigned resources may be taken
15435 - * (allocated) from the container's ancestors, if not enough resources are
15436 - * available in the container itself.
15437 - *
15438 - * The type of assignment depends on the dprc_res_req options, as follows:
15439 - * - DPRC_RES_REQ_OPT_EXPLICIT: indicates that assigned resources should have
15440 - * the explicit base ID specified at the id_base_align field of res_req.
15441 - * - DPRC_RES_REQ_OPT_ALIGNED: indicates that the assigned resources should be
15442 - * aligned to the value given at id_base_align field of res_req.
15443 - * - DPRC_RES_REQ_OPT_PLUGGED: Relevant only for object assignment,
15444 - * and indicates that the object must be set to the plugged state.
15445 - *
15446 - * A container may use this function with its own ID in order to change a
15447 - * object state to plugged or unplugged.
15448 - *
15449 - * If IRQ information has been set in the child DPRC, it will signal an
15450 - * interrupt following every change in its object assignment.
15451 - *
15452 - * Return: '0' on Success; Error code otherwise.
15453 - */
15454 -int dprc_assign(struct fsl_mc_io *mc_io,
15455 - u32 cmd_flags,
15456 - u16 token,
15457 - int container_id,
15458 - struct dprc_res_req *res_req)
15459 -{
15460 - struct mc_command cmd = { 0 };
15461 - struct dprc_cmd_assign *cmd_params;
15462 -
15463 - /* prepare command */
15464 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_ASSIGN,
15465 - cmd_flags, token);
15466 - cmd_params = (struct dprc_cmd_assign *)cmd.params;
15467 - cmd_params->container_id = cpu_to_le32(container_id);
15468 - cmd_params->options = cpu_to_le32(res_req->options);
15469 - cmd_params->num = cpu_to_le32(res_req->num);
15470 - cmd_params->id_base_align = cpu_to_le32(res_req->id_base_align);
15471 - strncpy(cmd_params->type, res_req->type, 16);
15472 - cmd_params->type[15] = '\0';
15473 -
15474 - /* send command to mc*/
15475 - return mc_send_command(mc_io, &cmd);
15476 -}
15477 -
15478 -/**
15479 - * dprc_unassign() - Un-assigns objects or resources from a child container
15480 - * and moves them into this (parent) DPRC.
15481 - * @mc_io: Pointer to MC portal's I/O object
15482 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
15483 - * @token: Token of DPRC object
15484 - * @child_container_id: ID of the child container
15485 - * @res_req: Describes the type and amount of resources to un-assign from
15486 - * the child container
15487 - *
15488 - * Un-assignment of objects can succeed only if the object is not in the
15489 - * plugged or opened state.
15490 - *
15491 - * Return: '0' on Success; Error code otherwise.
15492 - */
15493 -int dprc_unassign(struct fsl_mc_io *mc_io,
15494 - u32 cmd_flags,
15495 - u16 token,
15496 - int child_container_id,
15497 - struct dprc_res_req *res_req)
15498 -{
15499 - struct mc_command cmd = { 0 };
15500 - struct dprc_cmd_unassign *cmd_params;
15501 -
15502 - /* prepare command */
15503 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_UNASSIGN,
15504 - cmd_flags,
15505 - token);
15506 - cmd_params = (struct dprc_cmd_unassign *)cmd.params;
15507 - cmd_params->child_container_id = cpu_to_le32(child_container_id);
15508 - cmd_params->options = cpu_to_le32(res_req->options);
15509 - cmd_params->num = cpu_to_le32(res_req->num);
15510 - cmd_params->id_base_align = cpu_to_le32(res_req->id_base_align);
15511 - strncpy(cmd_params->type, res_req->type, 16);
15512 - cmd_params->type[15] = '\0';
15513 -
15514 - /* send command to mc*/
15515 - return mc_send_command(mc_io, &cmd);
15516 -}
15517 -
15518 -/**
15519 - * dprc_get_pool_count() - Get the number of dprc's pools
15520 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
15521 - * @mc_io: Pointer to MC portal's I/O object
15522 - * @token: Token of DPRC object
15523 - * @pool_count: Returned number of resource pools in the dprc
15524 - *
15525 - * Return: '0' on Success; Error code otherwise.
15526 - */
15527 -int dprc_get_pool_count(struct fsl_mc_io *mc_io,
15528 - u32 cmd_flags,
15529 - u16 token,
15530 - int *pool_count)
15531 -{
15532 - struct mc_command cmd = { 0 };
15533 - struct dprc_rsp_get_pool_count *rsp_params;
15534 - int err;
15535 -
15536 - /* prepare command */
15537 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_POOL_COUNT,
15538 - cmd_flags, token);
15539 -
15540 - /* send command to mc*/
15541 - err = mc_send_command(mc_io, &cmd);
15542 - if (err)
15543 - return err;
15544 -
15545 - /* retrieve response parameters */
15546 - rsp_params = (struct dprc_rsp_get_pool_count *)cmd.params;
15547 - *pool_count = le32_to_cpu(rsp_params->pool_count);
15548 -
15549 - return 0;
15550 -}
15551 -
15552 -/**
15553 - * dprc_get_pool() - Get the type (string) of a certain dprc's pool
15554 - * @mc_io: Pointer to MC portal's I/O object
15555 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
15556 - * @token: Token of DPRC object
15557 - * @pool_index; Index of the pool to be queried (< pool_count)
15558 - * @type: The type of the pool
15559 - *
15560 - * The pool types retrieved one by one by incrementing
15561 - * pool_index up to (not including) the value of pool_count returned
15562 - * from dprc_get_pool_count(). dprc_get_pool_count() must
15563 - * be called prior to dprc_get_pool().
15564 - *
15565 - * Return: '0' on Success; Error code otherwise.
15566 - */
15567 -int dprc_get_pool(struct fsl_mc_io *mc_io,
15568 - u32 cmd_flags,
15569 - u16 token,
15570 - int pool_index,
15571 - char *type)
15572 -{
15573 - struct mc_command cmd = { 0 };
15574 - struct dprc_cmd_get_pool *cmd_params;
15575 - struct dprc_rsp_get_pool *rsp_params;
15576 - int err;
15577 -
15578 - /* prepare command */
15579 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_POOL,
15580 - cmd_flags,
15581 - token);
15582 - cmd_params = (struct dprc_cmd_get_pool *)cmd.params;
15583 - cmd_params->pool_index = cpu_to_le32(pool_index);
15584 -
15585 - /* send command to mc*/
15586 - err = mc_send_command(mc_io, &cmd);
15587 - if (err)
15588 - return err;
15589 -
15590 - /* retrieve response parameters */
15591 - rsp_params = (struct dprc_rsp_get_pool *)cmd.params;
15592 - strncpy(type, rsp_params->type, 16);
15593 - type[15] = '\0';
15594 -
15595 - return 0;
15596 -}
15597 -
15598 -/**
15599 - * dprc_get_obj_count() - Obtains the number of objects in the DPRC
15600 - * @mc_io: Pointer to MC portal's I/O object
15601 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
15602 - * @token: Token of DPRC object
15603 - * @obj_count: Number of objects assigned to the DPRC
15604 - *
15605 - * Return: '0' on Success; Error code otherwise.
15606 - */
15607 -int dprc_get_obj_count(struct fsl_mc_io *mc_io,
15608 - u32 cmd_flags,
15609 - u16 token,
15610 - int *obj_count)
15611 -{
15612 - struct mc_command cmd = { 0 };
15613 - struct dprc_rsp_get_obj_count *rsp_params;
15614 - int err;
15615 -
15616 - /* prepare command */
15617 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_COUNT,
15618 - cmd_flags, token);
15619 -
15620 - /* send command to mc*/
15621 - err = mc_send_command(mc_io, &cmd);
15622 - if (err)
15623 - return err;
15624 -
15625 - /* retrieve response parameters */
15626 - rsp_params = (struct dprc_rsp_get_obj_count *)cmd.params;
15627 - *obj_count = le32_to_cpu(rsp_params->obj_count);
15628 -
15629 - return 0;
15630 -}
15631 -EXPORT_SYMBOL(dprc_get_obj_count);
15632 -
15633 -/**
15634 - * dprc_get_obj() - Get general information on an object
15635 - * @mc_io: Pointer to MC portal's I/O object
15636 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
15637 - * @token: Token of DPRC object
15638 - * @obj_index: Index of the object to be queried (< obj_count)
15639 - * @obj_desc: Returns the requested object descriptor
15640 - *
15641 - * The object descriptors are retrieved one by one by incrementing
15642 - * obj_index up to (not including) the value of obj_count returned
15643 - * from dprc_get_obj_count(). dprc_get_obj_count() must
15644 - * be called prior to dprc_get_obj().
15645 - *
15646 - * Return: '0' on Success; Error code otherwise.
15647 - */
15648 -int dprc_get_obj(struct fsl_mc_io *mc_io,
15649 - u32 cmd_flags,
15650 - u16 token,
15651 - int obj_index,
15652 - struct dprc_obj_desc *obj_desc)
15653 -{
15654 - struct mc_command cmd = { 0 };
15655 - struct dprc_cmd_get_obj *cmd_params;
15656 - struct dprc_rsp_get_obj *rsp_params;
15657 - int err;
15658 -
15659 - /* prepare command */
15660 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ,
15661 - cmd_flags,
15662 - token);
15663 - cmd_params = (struct dprc_cmd_get_obj *)cmd.params;
15664 - cmd_params->obj_index = cpu_to_le32(obj_index);
15665 -
15666 - /* send command to mc*/
15667 - err = mc_send_command(mc_io, &cmd);
15668 - if (err)
15669 - return err;
15670 -
15671 - /* retrieve response parameters */
15672 - rsp_params = (struct dprc_rsp_get_obj *)cmd.params;
15673 - obj_desc->id = le32_to_cpu(rsp_params->id);
15674 - obj_desc->vendor = le16_to_cpu(rsp_params->vendor);
15675 - obj_desc->irq_count = rsp_params->irq_count;
15676 - obj_desc->region_count = rsp_params->region_count;
15677 - obj_desc->state = le32_to_cpu(rsp_params->state);
15678 - obj_desc->ver_major = le16_to_cpu(rsp_params->version_major);
15679 - obj_desc->ver_minor = le16_to_cpu(rsp_params->version_minor);
15680 - obj_desc->flags = le16_to_cpu(rsp_params->flags);
15681 - strncpy(obj_desc->type, rsp_params->type, 16);
15682 - obj_desc->type[15] = '\0';
15683 - strncpy(obj_desc->label, rsp_params->label, 16);
15684 - obj_desc->label[15] = '\0';
15685 - return 0;
15686 -}
15687 -EXPORT_SYMBOL(dprc_get_obj);
15688 -
15689 -/**
15690 - * dprc_get_obj_desc() - Get object descriptor.
15691 - *
15692 - * @mc_io: Pointer to MC portal's I/O object
15693 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
15694 - * @token: Token of DPRC object
15695 - * @obj_type: The type of the object to get its descriptor.
15696 - * @obj_id: The id of the object to get its descriptor
15697 - * @obj_desc: The returned descriptor to fill and return to the user
15698 - *
15699 - * Return: '0' on Success; Error code otherwise.
15700 - *
15701 - */
15702 -int dprc_get_obj_desc(struct fsl_mc_io *mc_io,
15703 - u32 cmd_flags,
15704 - u16 token,
15705 - char *obj_type,
15706 - int obj_id,
15707 - struct dprc_obj_desc *obj_desc)
15708 -{
15709 - struct mc_command cmd = { 0 };
15710 - struct dprc_cmd_get_obj_desc *cmd_params;
15711 - struct dprc_rsp_get_obj_desc *rsp_params;
15712 - int err;
15713 -
15714 - /* prepare command */
15715 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_DESC,
15716 - cmd_flags,
15717 - token);
15718 - cmd_params = (struct dprc_cmd_get_obj_desc *)cmd.params;
15719 - cmd_params->obj_id = cpu_to_le32(obj_id);
15720 - strncpy(cmd_params->type, obj_type, 16);
15721 - cmd_params->type[15] = '\0';
15722 -
15723 - /* send command to mc*/
15724 - err = mc_send_command(mc_io, &cmd);
15725 - if (err)
15726 - return err;
15727 -
15728 - /* retrieve response parameters */
15729 - rsp_params = (struct dprc_rsp_get_obj_desc *)cmd.params;
15730 - obj_desc->id = le32_to_cpu(rsp_params->id);
15731 - obj_desc->vendor = le16_to_cpu(rsp_params->vendor);
15732 - obj_desc->irq_count = rsp_params->irq_count;
15733 - obj_desc->region_count = rsp_params->region_count;
15734 - obj_desc->state = le32_to_cpu(rsp_params->state);
15735 - obj_desc->ver_major = le16_to_cpu(rsp_params->version_major);
15736 - obj_desc->ver_minor = le16_to_cpu(rsp_params->version_minor);
15737 - obj_desc->flags = le16_to_cpu(rsp_params->flags);
15738 - strncpy(obj_desc->type, rsp_params->type, 16);
15739 - obj_desc->type[15] = '\0';
15740 - strncpy(obj_desc->label, rsp_params->label, 16);
15741 - obj_desc->label[15] = '\0';
15742 -
15743 - return 0;
15744 -}
15745 -EXPORT_SYMBOL(dprc_get_obj_desc);
15746 -
15747 -/**
15748 - * dprc_set_obj_irq() - Set IRQ information for object to trigger an interrupt.
15749 - * @mc_io: Pointer to MC portal's I/O object
15750 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
15751 - * @token: Token of DPRC object
15752 - * @obj_type: Type of the object to set its IRQ
15753 - * @obj_id: ID of the object to set its IRQ
15754 - * @irq_index: The interrupt index to configure
15755 - * @irq_cfg: IRQ configuration
15756 - *
15757 - * Return: '0' on Success; Error code otherwise.
15758 - */
15759 -int dprc_set_obj_irq(struct fsl_mc_io *mc_io,
15760 - u32 cmd_flags,
15761 - u16 token,
15762 - char *obj_type,
15763 - int obj_id,
15764 - u8 irq_index,
15765 - struct dprc_irq_cfg *irq_cfg)
15766 -{
15767 - struct mc_command cmd = { 0 };
15768 - struct dprc_cmd_set_obj_irq *cmd_params;
15769 -
15770 - /* prepare command */
15771 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_OBJ_IRQ,
15772 - cmd_flags,
15773 - token);
15774 - cmd_params = (struct dprc_cmd_set_obj_irq *)cmd.params;
15775 - cmd_params->irq_val = cpu_to_le32(irq_cfg->val);
15776 - cmd_params->irq_index = irq_index;
15777 - cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr);
15778 - cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num);
15779 - cmd_params->obj_id = cpu_to_le32(obj_id);
15780 - strncpy(cmd_params->obj_type, obj_type, 16);
15781 - cmd_params->obj_type[15] = '\0';
15782 -
15783 - /* send command to mc*/
15784 - return mc_send_command(mc_io, &cmd);
15785 -}
15786 -EXPORT_SYMBOL(dprc_set_obj_irq);
15787 -
15788 -/**
15789 - * dprc_get_obj_irq() - Get IRQ information from object.
15790 - * @mc_io: Pointer to MC portal's I/O object
15791 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
15792 - * @token: Token of DPRC object
15793 - * @obj_type: Type od the object to get its IRQ
15794 - * @obj_id: ID of the object to get its IRQ
15795 - * @irq_index: The interrupt index to configure
15796 - * @type: Interrupt type: 0 represents message interrupt
15797 - * type (both irq_addr and irq_val are valid)
15798 - * @irq_cfg: The returned IRQ attributes
15799 - *
15800 - * Return: '0' on Success; Error code otherwise.
15801 - */
15802 -int dprc_get_obj_irq(struct fsl_mc_io *mc_io,
15803 - u32 cmd_flags,
15804 - u16 token,
15805 - char *obj_type,
15806 - int obj_id,
15807 - u8 irq_index,
15808 - int *type,
15809 - struct dprc_irq_cfg *irq_cfg)
15810 -{
15811 - struct mc_command cmd = { 0 };
15812 - struct dprc_cmd_get_obj_irq *cmd_params;
15813 - struct dprc_rsp_get_obj_irq *rsp_params;
15814 - int err;
15815 -
15816 - /* prepare command */
15817 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_IRQ,
15818 - cmd_flags,
15819 - token);
15820 - cmd_params = (struct dprc_cmd_get_obj_irq *)cmd.params;
15821 - cmd_params->obj_id = cpu_to_le32(obj_id);
15822 - cmd_params->irq_index = irq_index;
15823 - strncpy(cmd_params->obj_type, obj_type, 16);
15824 - cmd_params->obj_type[15] = '\0';
15825 -
15826 - /* send command to mc*/
15827 - err = mc_send_command(mc_io, &cmd);
15828 - if (err)
15829 - return err;
15830 -
15831 - /* retrieve response parameters */
15832 - rsp_params = (struct dprc_rsp_get_obj_irq *)cmd.params;
15833 - irq_cfg->val = le32_to_cpu(rsp_params->irq_val);
15834 - irq_cfg->paddr = le64_to_cpu(rsp_params->irq_addr);
15835 - irq_cfg->irq_num = le32_to_cpu(rsp_params->irq_num);
15836 - *type = le32_to_cpu(rsp_params->type);
15837 -
15838 - return 0;
15839 -}
15840 -EXPORT_SYMBOL(dprc_get_obj_irq);
15841 -
15842 -/**
15843 - * dprc_get_res_count() - Obtains the number of free resources that are assigned
15844 - * to this container, by pool type
15845 - * @mc_io: Pointer to MC portal's I/O object
15846 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
15847 - * @token: Token of DPRC object
15848 - * @type: pool type
15849 - * @res_count: Returned number of free resources of the given
15850 - * resource type that are assigned to this DPRC
15851 - *
15852 - * Return: '0' on Success; Error code otherwise.
15853 - */
15854 -int dprc_get_res_count(struct fsl_mc_io *mc_io,
15855 - u32 cmd_flags,
15856 - u16 token,
15857 - char *type,
15858 - int *res_count)
15859 -{
15860 - struct mc_command cmd = { 0 };
15861 - struct dprc_cmd_get_res_count *cmd_params;
15862 - struct dprc_rsp_get_res_count *rsp_params;
15863 - int err;
15864 -
15865 - /* prepare command */
15866 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_COUNT,
15867 - cmd_flags, token);
15868 - cmd_params = (struct dprc_cmd_get_res_count *)cmd.params;
15869 - strncpy(cmd_params->type, type, 16);
15870 - cmd_params->type[15] = '\0';
15871 -
15872 - /* send command to mc*/
15873 - err = mc_send_command(mc_io, &cmd);
15874 - if (err)
15875 - return err;
15876 -
15877 - /* retrieve response parameters */
15878 - rsp_params = (struct dprc_rsp_get_res_count *)cmd.params;
15879 - *res_count = le32_to_cpu(rsp_params->res_count);
15880 -
15881 - return 0;
15882 -}
15883 -EXPORT_SYMBOL(dprc_get_res_count);
15884 -
15885 -/**
15886 - * dprc_get_res_ids() - Obtains IDs of free resources in the container
15887 - * @mc_io: Pointer to MC portal's I/O object
15888 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
15889 - * @token: Token of DPRC object
15890 - * @type: pool type
15891 - * @range_desc: range descriptor
15892 - *
15893 - * Return: '0' on Success; Error code otherwise.
15894 - */
15895 -int dprc_get_res_ids(struct fsl_mc_io *mc_io,
15896 - u32 cmd_flags,
15897 - u16 token,
15898 - char *type,
15899 - struct dprc_res_ids_range_desc *range_desc)
15900 -{
15901 - struct mc_command cmd = { 0 };
15902 - struct dprc_cmd_get_res_ids *cmd_params;
15903 - struct dprc_rsp_get_res_ids *rsp_params;
15904 - int err;
15905 -
15906 - /* prepare command */
15907 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_IDS,
15908 - cmd_flags, token);
15909 - cmd_params = (struct dprc_cmd_get_res_ids *)cmd.params;
15910 - cmd_params->iter_status = range_desc->iter_status;
15911 - cmd_params->base_id = cpu_to_le32(range_desc->base_id);
15912 - cmd_params->last_id = cpu_to_le32(range_desc->last_id);
15913 - strncpy(cmd_params->type, type, 16);
15914 - cmd_params->type[15] = '\0';
15915 -
15916 - /* send command to mc*/
15917 - err = mc_send_command(mc_io, &cmd);
15918 - if (err)
15919 - return err;
15920 -
15921 - /* retrieve response parameters */
15922 - rsp_params = (struct dprc_rsp_get_res_ids *)cmd.params;
15923 - range_desc->iter_status = rsp_params->iter_status;
15924 - range_desc->base_id = le32_to_cpu(rsp_params->base_id);
15925 - range_desc->last_id = le32_to_cpu(rsp_params->last_id);
15926 -
15927 - return 0;
15928 -}
15929 -EXPORT_SYMBOL(dprc_get_res_ids);
15930 -
15931 -/**
15932 - * dprc_get_obj_region() - Get region information for a specified object.
15933 - * @mc_io: Pointer to MC portal's I/O object
15934 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
15935 - * @token: Token of DPRC object
15936 - * @obj_type; Object type as returned in dprc_get_obj()
15937 - * @obj_id: Unique object instance as returned in dprc_get_obj()
15938 - * @region_index: The specific region to query
15939 - * @region_desc: Returns the requested region descriptor
15940 - *
15941 - * Return: '0' on Success; Error code otherwise.
15942 - */
15943 -int dprc_get_obj_region(struct fsl_mc_io *mc_io,
15944 - u32 cmd_flags,
15945 - u16 token,
15946 - char *obj_type,
15947 - int obj_id,
15948 - u8 region_index,
15949 - struct dprc_region_desc *region_desc)
15950 -{
15951 - struct mc_command cmd = { 0 };
15952 - struct dprc_cmd_get_obj_region *cmd_params;
15953 - struct dprc_rsp_get_obj_region *rsp_params;
15954 - int err;
15955 -
15956 - /* prepare command */
15957 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG,
15958 - cmd_flags, token);
15959 - cmd_params = (struct dprc_cmd_get_obj_region *)cmd.params;
15960 - cmd_params->obj_id = cpu_to_le32(obj_id);
15961 - cmd_params->region_index = region_index;
15962 - strncpy(cmd_params->obj_type, obj_type, 16);
15963 - cmd_params->obj_type[15] = '\0';
15964 -
15965 - /* send command to mc*/
15966 - err = mc_send_command(mc_io, &cmd);
15967 - if (err)
15968 - return err;
15969 -
15970 - /* retrieve response parameters */
15971 - rsp_params = (struct dprc_rsp_get_obj_region *)cmd.params;
15972 - region_desc->base_offset = le64_to_cpu(rsp_params->base_addr);
15973 - region_desc->size = le32_to_cpu(rsp_params->size);
15974 -
15975 - return 0;
15976 -}
15977 -EXPORT_SYMBOL(dprc_get_obj_region);
15978 -
15979 -/**
15980 - * dprc_set_obj_label() - Set object label.
15981 - * @mc_io: Pointer to MC portal's I/O object
15982 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
15983 - * @token: Token of DPRC object
15984 - * @obj_type: Object's type
15985 - * @obj_id: Object's ID
15986 - * @label: The required label. The maximum length is 16 chars.
15987 - *
15988 - * Return: '0' on Success; Error code otherwise.
15989 - */
15990 -int dprc_set_obj_label(struct fsl_mc_io *mc_io,
15991 - u32 cmd_flags,
15992 - u16 token,
15993 - char *obj_type,
15994 - int obj_id,
15995 - char *label)
15996 -{
15997 - struct mc_command cmd = { 0 };
15998 - struct dprc_cmd_set_obj_label *cmd_params;
15999 -
16000 - /* prepare command */
16001 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_OBJ_LABEL,
16002 - cmd_flags,
16003 - token);
16004 - cmd_params = (struct dprc_cmd_set_obj_label *)cmd.params;
16005 - cmd_params->obj_id = cpu_to_le32(obj_id);
16006 - strncpy(cmd_params->label, label, 16);
16007 - cmd_params->label[15] = '\0';
16008 - strncpy(cmd_params->obj_type, obj_type, 16);
16009 - cmd_params->obj_type[15] = '\0';
16010 -
16011 - /* send command to mc*/
16012 - return mc_send_command(mc_io, &cmd);
16013 -}
16014 -EXPORT_SYMBOL(dprc_set_obj_label);
16015 -
16016 -/**
16017 - * dprc_connect() - Connect two endpoints to create a network link between them
16018 - * @mc_io: Pointer to MC portal's I/O object
16019 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
16020 - * @token: Token of DPRC object
16021 - * @endpoint1: Endpoint 1 configuration parameters
16022 - * @endpoint2: Endpoint 2 configuration parameters
16023 - * @cfg: Connection configuration. The connection configuration is ignored for
16024 - * connections made to DPMAC objects, where rate is retrieved from the
16025 - * MAC configuration.
16026 - *
16027 - * Return: '0' on Success; Error code otherwise.
16028 - */
16029 -int dprc_connect(struct fsl_mc_io *mc_io,
16030 - u32 cmd_flags,
16031 - u16 token,
16032 - const struct dprc_endpoint *endpoint1,
16033 - const struct dprc_endpoint *endpoint2,
16034 - const struct dprc_connection_cfg *cfg)
16035 -{
16036 - struct mc_command cmd = { 0 };
16037 - struct dprc_cmd_connect *cmd_params;
16038 -
16039 - /* prepare command */
16040 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_CONNECT,
16041 - cmd_flags,
16042 - token);
16043 - cmd_params = (struct dprc_cmd_connect *)cmd.params;
16044 - cmd_params->ep1_id = cpu_to_le32(endpoint1->id);
16045 - cmd_params->ep1_interface_id = cpu_to_le32(endpoint1->if_id);
16046 - cmd_params->ep2_id = cpu_to_le32(endpoint2->id);
16047 - cmd_params->ep2_interface_id = cpu_to_le32(endpoint2->if_id);
16048 - strncpy(cmd_params->ep1_type, endpoint1->type, 16);
16049 - cmd_params->ep1_type[15] = '\0';
16050 - cmd_params->max_rate = cpu_to_le32(cfg->max_rate);
16051 - cmd_params->committed_rate = cpu_to_le32(cfg->committed_rate);
16052 - strncpy(cmd_params->ep2_type, endpoint2->type, 16);
16053 - cmd_params->ep2_type[15] = '\0';
16054 -
16055 - /* send command to mc*/
16056 - return mc_send_command(mc_io, &cmd);
16057 -}
16058 -
16059 -/**
16060 - * dprc_disconnect() - Disconnect one endpoint to remove its network connection
16061 - * @mc_io: Pointer to MC portal's I/O object
16062 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
16063 - * @token: Token of DPRC object
16064 - * @endpoint: Endpoint configuration parameters
16065 - *
16066 - * Return: '0' on Success; Error code otherwise.
16067 - */
16068 -int dprc_disconnect(struct fsl_mc_io *mc_io,
16069 - u32 cmd_flags,
16070 - u16 token,
16071 - const struct dprc_endpoint *endpoint)
16072 -{
16073 - struct mc_command cmd = { 0 };
16074 - struct dprc_cmd_disconnect *cmd_params;
16075 -
16076 - /* prepare command */
16077 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_DISCONNECT,
16078 - cmd_flags,
16079 - token);
16080 - cmd_params = (struct dprc_cmd_disconnect *)cmd.params;
16081 - cmd_params->id = cpu_to_le32(endpoint->id);
16082 - cmd_params->interface_id = cpu_to_le32(endpoint->if_id);
16083 - strncpy(cmd_params->type, endpoint->type, 16);
16084 - cmd_params->type[15] = '\0';
16085 -
16086 - /* send command to mc*/
16087 - return mc_send_command(mc_io, &cmd);
16088 -}
16089 -
16090 -/**
16091 - * dprc_get_connection() - Get connected endpoint and link status if connection
16092 - * exists.
16093 - * @mc_io: Pointer to MC portal's I/O object
16094 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
16095 - * @token: Token of DPRC object
16096 - * @endpoint1: Endpoint 1 configuration parameters
16097 - * @endpoint2: Returned endpoint 2 configuration parameters
16098 - * @state: Returned link state:
16099 - * 1 - link is up;
16100 - * 0 - link is down;
16101 - * -1 - no connection (endpoint2 information is irrelevant)
16102 - *
16103 - * Return: '0' on Success; -ENAVAIL if connection does not exist.
16104 - */
16105 -int dprc_get_connection(struct fsl_mc_io *mc_io,
16106 - u32 cmd_flags,
16107 - u16 token,
16108 - const struct dprc_endpoint *endpoint1,
16109 - struct dprc_endpoint *endpoint2,
16110 - int *state)
16111 -{
16112 - struct mc_command cmd = { 0 };
16113 - struct dprc_cmd_get_connection *cmd_params;
16114 - struct dprc_rsp_get_connection *rsp_params;
16115 - int err;
16116 -
16117 - /* prepare command */
16118 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONNECTION,
16119 - cmd_flags,
16120 - token);
16121 - cmd_params = (struct dprc_cmd_get_connection *)cmd.params;
16122 - cmd_params->ep1_id = cpu_to_le32(endpoint1->id);
16123 - cmd_params->ep1_interface_id = cpu_to_le32(endpoint1->if_id);
16124 - strncpy(cmd_params->ep1_type, endpoint1->type, 16);
16125 - cmd_params->ep1_type[15] = '\0';
16126 -
16127 - /* send command to mc*/
16128 - err = mc_send_command(mc_io, &cmd);
16129 - if (err)
16130 - return err;
16131 -
16132 - /* retrieve response parameters */
16133 - rsp_params = (struct dprc_rsp_get_connection *)cmd.params;
16134 - endpoint2->id = le32_to_cpu(rsp_params->ep2_id);
16135 - endpoint2->if_id = le32_to_cpu(rsp_params->ep2_interface_id);
16136 - strncpy(endpoint2->type, rsp_params->ep2_type, 16);
16137 - endpoint2->type[15] = '\0';
16138 - *state = le32_to_cpu(rsp_params->state);
16139 -
16140 - return 0;
16141 -}
16142 --- a/drivers/staging/fsl-mc/bus/fsl-mc-private.h
16143 +++ /dev/null
16144 @@ -1,52 +0,0 @@
16145 -/*
16146 - * Freescale Management Complex (MC) bus private declarations
16147 - *
16148 - * Copyright (C) 2016 Freescale Semiconductor, Inc.
16149 - *
16150 - * This file is licensed under the terms of the GNU General Public
16151 - * License version 2. This program is licensed "as is" without any
16152 - * warranty of any kind, whether express or implied.
16153 - */
16154 -#ifndef _FSL_MC_PRIVATE_H_
16155 -#define _FSL_MC_PRIVATE_H_
16156 -
16157 -int __must_check fsl_mc_device_add(struct dprc_obj_desc *obj_desc,
16158 - struct fsl_mc_io *mc_io,
16159 - struct device *parent_dev,
16160 - struct fsl_mc_device **new_mc_dev);
16161 -
16162 -void fsl_mc_device_remove(struct fsl_mc_device *mc_dev);
16163 -
16164 -int __init dprc_driver_init(void);
16165 -
16166 -void dprc_driver_exit(void);
16167 -
16168 -int __init fsl_mc_allocator_driver_init(void);
16169 -
16170 -void fsl_mc_allocator_driver_exit(void);
16171 -
16172 -int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus,
16173 - enum fsl_mc_pool_type pool_type,
16174 - struct fsl_mc_resource
16175 - **new_resource);
16176 -
16177 -void fsl_mc_resource_free(struct fsl_mc_resource *resource);
16178 -
16179 -int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
16180 - unsigned int irq_count);
16181 -
16182 -void fsl_mc_msi_domain_free_irqs(struct device *dev);
16183 -
16184 -int __init its_fsl_mc_msi_init(void);
16185 -
16186 -void its_fsl_mc_msi_cleanup(void);
16187 -
16188 -int __must_check fsl_create_mc_io(struct device *dev,
16189 - phys_addr_t mc_portal_phys_addr,
16190 - u32 mc_portal_size,
16191 - struct fsl_mc_device *dpmcp_dev,
16192 - u32 flags, struct fsl_mc_io **new_mc_io);
16193 -
16194 -void fsl_destroy_mc_io(struct fsl_mc_io *mc_io);
16195 -
16196 -#endif /* _FSL_MC_PRIVATE_H_ */
16197 --- /dev/null
16198 +++ b/drivers/staging/fsl-mc/include/dpaa2-fd.h
16199 @@ -0,0 +1,681 @@
16200 +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
16201 +/*
16202 + * Copyright 2014-2016 Freescale Semiconductor Inc.
16203 + * Copyright 2016 NXP
16204 + *
16205 + */
16206 +#ifndef __FSL_DPAA2_FD_H
16207 +#define __FSL_DPAA2_FD_H
16208 +
16209 +#include <linux/kernel.h>
16210 +
16211 +/**
16212 + * DOC: DPAA2 FD - Frame Descriptor APIs for DPAA2
16213 + *
16214 + * Frame Descriptors (FDs) are used to describe frame data in the DPAA2.
16215 + * Frames can be enqueued and dequeued to Frame Queues (FQs) which are consumed
16216 + * by the various DPAA accelerators (WRIOP, SEC, PME, DCE)
16217 + *
16218 + * There are three types of frames: single, scatter gather, and frame lists.
16219 + *
16220 + * The set of APIs in this file must be used to create, manipulate and
16221 + * query Frame Descriptors.
16222 + */
16223 +
16224 +/**
16225 + * struct dpaa2_fd - Struct describing FDs
16226 + * @words: for easier/faster copying the whole FD structure
16227 + * @addr: address in the FD
16228 + * @len: length in the FD
16229 + * @bpid: buffer pool ID
16230 + * @format_offset: format, offset, and short-length fields
16231 + * @frc: frame context
16232 + * @ctrl: control bits...including dd, sc, va, err, etc
16233 + * @flc: flow context address
16234 + *
16235 + * This structure represents the basic Frame Descriptor used in the system.
16236 + */
16237 +struct dpaa2_fd {
16238 + union {
16239 + u32 words[8];
16240 + struct dpaa2_fd_simple {
16241 + __le64 addr;
16242 + __le32 len;
16243 + __le16 bpid;
16244 + __le16 format_offset;
16245 + __le32 frc;
16246 + __le32 ctrl;
16247 + __le64 flc;
16248 + } simple;
16249 + };
16250 +};
16251 +
16252 +#define FD_SHORT_LEN_FLAG_MASK 0x1
16253 +#define FD_SHORT_LEN_FLAG_SHIFT 14
16254 +#define FD_SHORT_LEN_MASK 0x3FFFF
16255 +#define FD_OFFSET_MASK 0x0FFF
16256 +#define FD_FORMAT_MASK 0x3
16257 +#define FD_FORMAT_SHIFT 12
16258 +#define FD_BPID_MASK 0x3FFF
16259 +#define SG_SHORT_LEN_FLAG_MASK 0x1
16260 +#define SG_SHORT_LEN_FLAG_SHIFT 14
16261 +#define SG_SHORT_LEN_MASK 0x1FFFF
16262 +#define SG_OFFSET_MASK 0x0FFF
16263 +#define SG_FORMAT_MASK 0x3
16264 +#define SG_FORMAT_SHIFT 12
16265 +#define SG_BPID_MASK 0x3FFF
16266 +#define SG_FINAL_FLAG_MASK 0x1
16267 +#define SG_FINAL_FLAG_SHIFT 15
16268 +#define FL_SHORT_LEN_FLAG_MASK 0x1
16269 +#define FL_SHORT_LEN_FLAG_SHIFT 14
16270 +#define FL_SHORT_LEN_MASK 0x3FFFF
16271 +#define FL_OFFSET_MASK 0x0FFF
16272 +#define FL_FORMAT_MASK 0x3
16273 +#define FL_FORMAT_SHIFT 12
16274 +#define FL_BPID_MASK 0x3FFF
16275 +#define FL_FINAL_FLAG_MASK 0x1
16276 +#define FL_FINAL_FLAG_SHIFT 15
16277 +
16278 +/* Error bits in FD CTRL */
16279 +#define FD_CTRL_ERR_MASK 0x000000FF
16280 +#define FD_CTRL_UFD 0x00000004
16281 +#define FD_CTRL_SBE 0x00000008
16282 +#define FD_CTRL_FLC 0x00000010
16283 +#define FD_CTRL_FSE 0x00000020
16284 +#define FD_CTRL_FAERR 0x00000040
16285 +
16286 +/* Annotation bits in FD CTRL */
16287 +#define FD_CTRL_PTA 0x00800000
16288 +#define FD_CTRL_PTV1 0x00400000
16289 +
16290 +enum dpaa2_fd_format {
16291 + dpaa2_fd_single = 0,
16292 + dpaa2_fd_list,
16293 + dpaa2_fd_sg
16294 +};
16295 +
16296 +/**
16297 + * dpaa2_fd_get_addr() - get the addr field of frame descriptor
16298 + * @fd: the given frame descriptor
16299 + *
16300 + * Return the address in the frame descriptor.
16301 + */
16302 +static inline dma_addr_t dpaa2_fd_get_addr(const struct dpaa2_fd *fd)
16303 +{
16304 + return (dma_addr_t)le64_to_cpu(fd->simple.addr);
16305 +}
16306 +
16307 +/**
16308 + * dpaa2_fd_set_addr() - Set the addr field of frame descriptor
16309 + * @fd: the given frame descriptor
16310 + * @addr: the address needs to be set in frame descriptor
16311 + */
16312 +static inline void dpaa2_fd_set_addr(struct dpaa2_fd *fd, dma_addr_t addr)
16313 +{
16314 + fd->simple.addr = cpu_to_le64(addr);
16315 +}
16316 +
16317 +/**
16318 + * dpaa2_fd_get_frc() - Get the frame context in the frame descriptor
16319 + * @fd: the given frame descriptor
16320 + *
16321 + * Return the frame context field in the frame descriptor.
16322 + */
16323 +static inline u32 dpaa2_fd_get_frc(const struct dpaa2_fd *fd)
16324 +{
16325 + return le32_to_cpu(fd->simple.frc);
16326 +}
16327 +
16328 +/**
16329 + * dpaa2_fd_set_frc() - Set the frame context in the frame descriptor
16330 + * @fd: the given frame descriptor
16331 + * @frc: the frame context needs to be set in frame descriptor
16332 + */
16333 +static inline void dpaa2_fd_set_frc(struct dpaa2_fd *fd, u32 frc)
16334 +{
16335 + fd->simple.frc = cpu_to_le32(frc);
16336 +}
16337 +
16338 +/**
16339 + * dpaa2_fd_get_ctrl() - Get the control bits in the frame descriptor
16340 + * @fd: the given frame descriptor
16341 + *
16342 + * Return the control bits field in the frame descriptor.
16343 + */
16344 +static inline u32 dpaa2_fd_get_ctrl(const struct dpaa2_fd *fd)
16345 +{
16346 + return le32_to_cpu(fd->simple.ctrl);
16347 +}
16348 +
16349 +/**
16350 + * dpaa2_fd_set_ctrl() - Set the control bits in the frame descriptor
16351 + * @fd: the given frame descriptor
16352 + * @ctrl: the control bits to be set in the frame descriptor
16353 + */
16354 +static inline void dpaa2_fd_set_ctrl(struct dpaa2_fd *fd, u32 ctrl)
16355 +{
16356 + fd->simple.ctrl = cpu_to_le32(ctrl);
16357 +}
16358 +
16359 +/**
16360 + * dpaa2_fd_get_flc() - Get the flow context in the frame descriptor
16361 + * @fd: the given frame descriptor
16362 + *
16363 + * Return the flow context in the frame descriptor.
16364 + */
16365 +static inline dma_addr_t dpaa2_fd_get_flc(const struct dpaa2_fd *fd)
16366 +{
16367 + return (dma_addr_t)le64_to_cpu(fd->simple.flc);
16368 +}
16369 +
16370 +/**
16371 + * dpaa2_fd_set_flc() - Set the flow context field of frame descriptor
16372 + * @fd: the given frame descriptor
16373 + * @flc_addr: the flow context needs to be set in frame descriptor
16374 + */
16375 +static inline void dpaa2_fd_set_flc(struct dpaa2_fd *fd, dma_addr_t flc_addr)
16376 +{
16377 + fd->simple.flc = cpu_to_le64(flc_addr);
16378 +}
16379 +
16380 +static inline bool dpaa2_fd_short_len(const struct dpaa2_fd *fd)
16381 +{
16382 + return !!((le16_to_cpu(fd->simple.format_offset) >>
16383 + FD_SHORT_LEN_FLAG_SHIFT) & FD_SHORT_LEN_FLAG_MASK);
16384 +}
16385 +
16386 +/**
16387 + * dpaa2_fd_get_len() - Get the length in the frame descriptor
16388 + * @fd: the given frame descriptor
16389 + *
16390 + * Return the length field in the frame descriptor.
16391 + */
16392 +static inline u32 dpaa2_fd_get_len(const struct dpaa2_fd *fd)
16393 +{
16394 + if (dpaa2_fd_short_len(fd))
16395 + return le32_to_cpu(fd->simple.len) & FD_SHORT_LEN_MASK;
16396 +
16397 + return le32_to_cpu(fd->simple.len);
16398 +}
16399 +
16400 +/**
16401 + * dpaa2_fd_set_len() - Set the length field of frame descriptor
16402 + * @fd: the given frame descriptor
16403 + * @len: the length needs to be set in frame descriptor
16404 + */
16405 +static inline void dpaa2_fd_set_len(struct dpaa2_fd *fd, u32 len)
16406 +{
16407 + fd->simple.len = cpu_to_le32(len);
16408 +}
16409 +
16410 +/**
16411 + * dpaa2_fd_get_offset() - Get the offset field in the frame descriptor
16412 + * @fd: the given frame descriptor
16413 + *
16414 + * Return the offset.
16415 + */
16416 +static inline uint16_t dpaa2_fd_get_offset(const struct dpaa2_fd *fd)
16417 +{
16418 + return le16_to_cpu(fd->simple.format_offset) & FD_OFFSET_MASK;
16419 +}
16420 +
16421 +/**
16422 + * dpaa2_fd_set_offset() - Set the offset field of frame descriptor
16423 + * @fd: the given frame descriptor
16424 + * @offset: the offset needs to be set in frame descriptor
16425 + */
16426 +static inline void dpaa2_fd_set_offset(struct dpaa2_fd *fd, uint16_t offset)
16427 +{
16428 + fd->simple.format_offset &= cpu_to_le16(~FD_OFFSET_MASK);
16429 + fd->simple.format_offset |= cpu_to_le16(offset);
16430 +}
16431 +
16432 +/**
16433 + * dpaa2_fd_get_format() - Get the format field in the frame descriptor
16434 + * @fd: the given frame descriptor
16435 + *
16436 + * Return the format.
16437 + */
16438 +static inline enum dpaa2_fd_format dpaa2_fd_get_format(
16439 + const struct dpaa2_fd *fd)
16440 +{
16441 + return (enum dpaa2_fd_format)((le16_to_cpu(fd->simple.format_offset)
16442 + >> FD_FORMAT_SHIFT) & FD_FORMAT_MASK);
16443 +}
16444 +
16445 +/**
16446 + * dpaa2_fd_set_format() - Set the format field of frame descriptor
16447 + * @fd: the given frame descriptor
16448 + * @format: the format needs to be set in frame descriptor
16449 + */
16450 +static inline void dpaa2_fd_set_format(struct dpaa2_fd *fd,
16451 + enum dpaa2_fd_format format)
16452 +{
16453 + fd->simple.format_offset &=
16454 + cpu_to_le16(~(FD_FORMAT_MASK << FD_FORMAT_SHIFT));
16455 + fd->simple.format_offset |= cpu_to_le16(format << FD_FORMAT_SHIFT);
16456 +}
16457 +
16458 +/**
16459 + * dpaa2_fd_get_bpid() - Get the bpid field in the frame descriptor
16460 + * @fd: the given frame descriptor
16461 + *
16462 + * Return the buffer pool id.
16463 + */
16464 +static inline uint16_t dpaa2_fd_get_bpid(const struct dpaa2_fd *fd)
16465 +{
16466 + return le16_to_cpu(fd->simple.bpid) & FD_BPID_MASK;
16467 +}
16468 +
16469 +/**
16470 + * dpaa2_fd_set_bpid() - Set the bpid field of frame descriptor
16471 + * @fd: the given frame descriptor
16472 + * @bpid: buffer pool id to be set
16473 + */
16474 +static inline void dpaa2_fd_set_bpid(struct dpaa2_fd *fd, uint16_t bpid)
16475 +{
16476 + fd->simple.bpid &= cpu_to_le16(~(FD_BPID_MASK));
16477 + fd->simple.bpid |= cpu_to_le16(bpid);
16478 +}
16479 +
16480 +/**
16481 + * struct dpaa2_sg_entry - the scatter-gathering structure
16482 + * @addr: address of the sg entry
16483 + * @len: length in this sg entry
16484 + * @bpid: buffer pool id
16485 + * @format_offset: format and offset fields
16486 + */
16487 +struct dpaa2_sg_entry {
16488 + __le64 addr;
16489 + __le32 len;
16490 + __le16 bpid;
16491 + __le16 format_offset;
16492 +};
16493 +
16494 +enum dpaa2_sg_format {
16495 + dpaa2_sg_single = 0,
16496 + dpaa2_sg_frame_data,
16497 + dpaa2_sg_sgt_ext
16498 +};
16499 +
16500 +/* Accessors for SG entry fields */
16501 +
16502 +/**
16503 + * dpaa2_sg_get_addr() - Get the address from SG entry
16504 + * @sg: the given scatter-gathering object
16505 + *
16506 + * Return the address.
16507 + */
16508 +static inline dma_addr_t dpaa2_sg_get_addr(const struct dpaa2_sg_entry *sg)
16509 +{
16510 + return (dma_addr_t)le64_to_cpu(sg->addr);
16511 +}
16512 +
16513 +/**
16514 + * dpaa2_sg_set_addr() - Set the address in SG entry
16515 + * @sg: the given scatter-gathering object
16516 + * @addr: the address to be set
16517 + */
16518 +static inline void dpaa2_sg_set_addr(struct dpaa2_sg_entry *sg, dma_addr_t addr)
16519 +{
16520 + sg->addr = cpu_to_le64(addr);
16521 +}
16522 +
16523 +static inline bool dpaa2_sg_short_len(const struct dpaa2_sg_entry *sg)
16524 +{
16525 + return !!((le16_to_cpu(sg->format_offset) >> SG_SHORT_LEN_FLAG_SHIFT)
16526 + & SG_SHORT_LEN_FLAG_MASK);
16527 +}
16528 +
16529 +/**
16530 + * dpaa2_sg_get_len() - Get the length in SG entry
16531 + * @sg: the given scatter-gathering object
16532 + *
16533 + * Return the length.
16534 + */
16535 +static inline u32 dpaa2_sg_get_len(const struct dpaa2_sg_entry *sg)
16536 +{
16537 + if (dpaa2_sg_short_len(sg))
16538 + return le32_to_cpu(sg->len) & SG_SHORT_LEN_MASK;
16539 +
16540 + return le32_to_cpu(sg->len);
16541 +}
16542 +
16543 +/**
16544 + * dpaa2_sg_set_len() - Set the length in SG entry
16545 + * @sg: the given scatter-gathering object
16546 + * @len: the length to be set
16547 + */
16548 +static inline void dpaa2_sg_set_len(struct dpaa2_sg_entry *sg, u32 len)
16549 +{
16550 + sg->len = cpu_to_le32(len);
16551 +}
16552 +
16553 +/**
16554 + * dpaa2_sg_get_offset() - Get the offset in SG entry
16555 + * @sg: the given scatter-gathering object
16556 + *
16557 + * Return the offset.
16558 + */
16559 +static inline u16 dpaa2_sg_get_offset(const struct dpaa2_sg_entry *sg)
16560 +{
16561 + return le16_to_cpu(sg->format_offset) & SG_OFFSET_MASK;
16562 +}
16563 +
16564 +/**
16565 + * dpaa2_sg_set_offset() - Set the offset in SG entry
16566 + * @sg: the given scatter-gathering object
16567 + * @offset: the offset to be set
16568 + */
16569 +static inline void dpaa2_sg_set_offset(struct dpaa2_sg_entry *sg,
16570 + u16 offset)
16571 +{
16572 + sg->format_offset &= cpu_to_le16(~SG_OFFSET_MASK);
16573 + sg->format_offset |= cpu_to_le16(offset);
16574 +}
16575 +
16576 +/**
16577 + * dpaa2_sg_get_format() - Get the SG format in SG entry
16578 + * @sg: the given scatter-gathering object
16579 + *
16580 + * Return the format.
16581 + */
16582 +static inline enum dpaa2_sg_format
16583 + dpaa2_sg_get_format(const struct dpaa2_sg_entry *sg)
16584 +{
16585 + return (enum dpaa2_sg_format)((le16_to_cpu(sg->format_offset)
16586 + >> SG_FORMAT_SHIFT) & SG_FORMAT_MASK);
16587 +}
16588 +
16589 +/**
16590 + * dpaa2_sg_set_format() - Set the SG format in SG entry
16591 + * @sg: the given scatter-gathering object
16592 + * @format: the format to be set
16593 + */
16594 +static inline void dpaa2_sg_set_format(struct dpaa2_sg_entry *sg,
16595 + enum dpaa2_sg_format format)
16596 +{
16597 + sg->format_offset &= cpu_to_le16(~(SG_FORMAT_MASK << SG_FORMAT_SHIFT));
16598 + sg->format_offset |= cpu_to_le16(format << SG_FORMAT_SHIFT);
16599 +}
16600 +
16601 +/**
16602 + * dpaa2_sg_get_bpid() - Get the buffer pool id in SG entry
16603 + * @sg: the given scatter-gathering object
16604 + *
16605 + * Return the bpid.
16606 + */
16607 +static inline u16 dpaa2_sg_get_bpid(const struct dpaa2_sg_entry *sg)
16608 +{
16609 + return le16_to_cpu(sg->bpid) & SG_BPID_MASK;
16610 +}
16611 +
16612 +/**
16613 + * dpaa2_sg_set_bpid() - Set the buffer pool id in SG entry
16614 + * @sg: the given scatter-gathering object
16615 + * @bpid: the bpid to be set
16616 + */
16617 +static inline void dpaa2_sg_set_bpid(struct dpaa2_sg_entry *sg, u16 bpid)
16618 +{
16619 + sg->bpid &= cpu_to_le16(~(SG_BPID_MASK));
16620 + sg->bpid |= cpu_to_le16(bpid);
16621 +}
16622 +
16623 +/**
16624 + * dpaa2_sg_is_final() - Check final bit in SG entry
16625 + * @sg: the given scatter-gathering object
16626 + *
16627 + * Return bool.
16628 + */
16629 +static inline bool dpaa2_sg_is_final(const struct dpaa2_sg_entry *sg)
16630 +{
16631 + return !!(le16_to_cpu(sg->format_offset) >> SG_FINAL_FLAG_SHIFT);
16632 +}
16633 +
16634 +/**
16635 + * dpaa2_sg_set_final() - Set the final bit in SG entry
16636 + * @sg: the given scatter-gathering object
16637 + * @final: the final boolean to be set
16638 + */
16639 +static inline void dpaa2_sg_set_final(struct dpaa2_sg_entry *sg, bool final)
16640 +{
16641 + sg->format_offset &= cpu_to_le16((~(SG_FINAL_FLAG_MASK
16642 + << SG_FINAL_FLAG_SHIFT)) & 0xFFFF);
16643 + sg->format_offset |= cpu_to_le16(final << SG_FINAL_FLAG_SHIFT);
16644 +}
16645 +
16646 +/**
16647 + * struct dpaa2_fl_entry - structure for frame list entry.
16648 + * @addr: address in the FLE
16649 + * @len: length in the FLE
16650 + * @bpid: buffer pool ID
16651 + * @format_offset: format, offset, and short-length fields
16652 + * @frc: frame context
16653 + * @ctrl: control bits...including pta, pvt1, pvt2, err, etc
16654 + * @flc: flow context address
16655 + */
16656 +struct dpaa2_fl_entry {
16657 + __le64 addr;
16658 + __le32 len;
16659 + __le16 bpid;
16660 + __le16 format_offset;
16661 + __le32 frc;
16662 + __le32 ctrl;
16663 + __le64 flc;
16664 +};
16665 +
16666 +enum dpaa2_fl_format {
16667 + dpaa2_fl_single = 0,
16668 + dpaa2_fl_res,
16669 + dpaa2_fl_sg
16670 +};
16671 +
16672 +/**
16673 + * dpaa2_fl_get_addr() - get the addr field of FLE
16674 + * @fle: the given frame list entry
16675 + *
16676 + * Return the address in the frame list entry.
16677 + */
16678 +static inline dma_addr_t dpaa2_fl_get_addr(const struct dpaa2_fl_entry *fle)
16679 +{
16680 + return (dma_addr_t)le64_to_cpu(fle->addr);
16681 +}
16682 +
16683 +/**
16684 + * dpaa2_fl_set_addr() - Set the addr field of FLE
16685 + * @fle: the given frame list entry
16686 + * @addr: the address needs to be set in frame list entry
16687 + */
16688 +static inline void dpaa2_fl_set_addr(struct dpaa2_fl_entry *fle,
16689 + dma_addr_t addr)
16690 +{
16691 + fle->addr = cpu_to_le64(addr);
16692 +}
16693 +
16694 +/**
16695 + * dpaa2_fl_get_frc() - Get the frame context in the FLE
16696 + * @fle: the given frame list entry
16697 + *
16698 + * Return the frame context field in the frame lsit entry.
16699 + */
16700 +static inline u32 dpaa2_fl_get_frc(const struct dpaa2_fl_entry *fle)
16701 +{
16702 + return le32_to_cpu(fle->frc);
16703 +}
16704 +
16705 +/**
16706 + * dpaa2_fl_set_frc() - Set the frame context in the FLE
16707 + * @fle: the given frame list entry
16708 + * @frc: the frame context needs to be set in frame list entry
16709 + */
16710 +static inline void dpaa2_fl_set_frc(struct dpaa2_fl_entry *fle, u32 frc)
16711 +{
16712 + fle->frc = cpu_to_le32(frc);
16713 +}
16714 +
16715 +/**
16716 + * dpaa2_fl_get_ctrl() - Get the control bits in the FLE
16717 + * @fle: the given frame list entry
16718 + *
16719 + * Return the control bits field in the frame list entry.
16720 + */
16721 +static inline u32 dpaa2_fl_get_ctrl(const struct dpaa2_fl_entry *fle)
16722 +{
16723 + return le32_to_cpu(fle->ctrl);
16724 +}
16725 +
16726 +/**
16727 + * dpaa2_fl_set_ctrl() - Set the control bits in the FLE
16728 + * @fle: the given frame list entry
16729 + * @ctrl: the control bits to be set in the frame list entry
16730 + */
16731 +static inline void dpaa2_fl_set_ctrl(struct dpaa2_fl_entry *fle, u32 ctrl)
16732 +{
16733 + fle->ctrl = cpu_to_le32(ctrl);
16734 +}
16735 +
16736 +/**
16737 + * dpaa2_fl_get_flc() - Get the flow context in the FLE
16738 + * @fle: the given frame list entry
16739 + *
16740 + * Return the flow context in the frame list entry.
16741 + */
16742 +static inline dma_addr_t dpaa2_fl_get_flc(const struct dpaa2_fl_entry *fle)
16743 +{
16744 + return (dma_addr_t)le64_to_cpu(fle->flc);
16745 +}
16746 +
16747 +/**
16748 + * dpaa2_fl_set_flc() - Set the flow context field of FLE
16749 + * @fle: the given frame list entry
16750 + * @flc_addr: the flow context needs to be set in frame list entry
16751 + */
16752 +static inline void dpaa2_fl_set_flc(struct dpaa2_fl_entry *fle,
16753 + dma_addr_t flc_addr)
16754 +{
16755 + fle->flc = cpu_to_le64(flc_addr);
16756 +}
16757 +
16758 +static inline bool dpaa2_fl_short_len(const struct dpaa2_fl_entry *fle)
16759 +{
16760 + return !!((le16_to_cpu(fle->format_offset) >>
16761 + FL_SHORT_LEN_FLAG_SHIFT) & FL_SHORT_LEN_FLAG_MASK);
16762 +}
16763 +
16764 +/**
16765 + * dpaa2_fl_get_len() - Get the length in the FLE
16766 + * @fle: the given frame list entry
16767 + *
16768 + * Return the length field in the frame list entry.
16769 + */
16770 +static inline u32 dpaa2_fl_get_len(const struct dpaa2_fl_entry *fle)
16771 +{
16772 + if (dpaa2_fl_short_len(fle))
16773 + return le32_to_cpu(fle->len) & FL_SHORT_LEN_MASK;
16774 +
16775 + return le32_to_cpu(fle->len);
16776 +}
16777 +
16778 +/**
16779 + * dpaa2_fl_set_len() - Set the length field of FLE
16780 + * @fle: the given frame list entry
16781 + * @len: the length needs to be set in frame list entry
16782 + */
16783 +static inline void dpaa2_fl_set_len(struct dpaa2_fl_entry *fle, u32 len)
16784 +{
16785 + fle->len = cpu_to_le32(len);
16786 +}
16787 +
16788 +/**
16789 + * dpaa2_fl_get_offset() - Get the offset field in the frame list entry
16790 + * @fle: the given frame list entry
16791 + *
16792 + * Return the offset.
16793 + */
16794 +static inline u16 dpaa2_fl_get_offset(const struct dpaa2_fl_entry *fle)
16795 +{
16796 + return le16_to_cpu(fle->format_offset) & FL_OFFSET_MASK;
16797 +}
16798 +
16799 +/**
16800 + * dpaa2_fl_set_offset() - Set the offset field of FLE
16801 + * @fle: the given frame list entry
16802 + * @offset: the offset needs to be set in frame list entry
16803 + */
16804 +static inline void dpaa2_fl_set_offset(struct dpaa2_fl_entry *fle, u16 offset)
16805 +{
16806 + fle->format_offset &= cpu_to_le16(~FL_OFFSET_MASK);
16807 + fle->format_offset |= cpu_to_le16(offset);
16808 +}
16809 +
16810 +/**
16811 + * dpaa2_fl_get_format() - Get the format field in the FLE
16812 + * @fle: the given frame list entry
16813 + *
16814 + * Return the format.
16815 + */
16816 +static inline enum dpaa2_fl_format dpaa2_fl_get_format(
16817 + const struct dpaa2_fl_entry *fle)
16818 +{
16819 + return (enum dpaa2_fl_format)((le16_to_cpu(fle->format_offset) >>
16820 + FL_FORMAT_SHIFT) & FL_FORMAT_MASK);
16821 +}
16822 +
16823 +/**
16824 + * dpaa2_fl_set_format() - Set the format field of FLE
16825 + * @fle: the given frame list entry
16826 + * @format: the format needs to be set in frame list entry
16827 + */
16828 +static inline void dpaa2_fl_set_format(struct dpaa2_fl_entry *fle,
16829 + enum dpaa2_fl_format format)
16830 +{
16831 + fle->format_offset &= cpu_to_le16(~(FL_FORMAT_MASK << FL_FORMAT_SHIFT));
16832 + fle->format_offset |= cpu_to_le16(format << FL_FORMAT_SHIFT);
16833 +}
16834 +
16835 +/**
16836 + * dpaa2_fl_get_bpid() - Get the bpid field in the FLE
16837 + * @fle: the given frame list entry
16838 + *
16839 + * Return the buffer pool id.
16840 + */
16841 +static inline u16 dpaa2_fl_get_bpid(const struct dpaa2_fl_entry *fle)
16842 +{
16843 + return le16_to_cpu(fle->bpid) & FL_BPID_MASK;
16844 +}
16845 +
16846 +/**
16847 + * dpaa2_fl_set_bpid() - Set the bpid field of FLE
16848 + * @fle: the given frame list entry
16849 + * @bpid: buffer pool id to be set
16850 + */
16851 +static inline void dpaa2_fl_set_bpid(struct dpaa2_fl_entry *fle, u16 bpid)
16852 +{
16853 + fle->bpid &= cpu_to_le16(~(FL_BPID_MASK));
16854 + fle->bpid |= cpu_to_le16(bpid);
16855 +}
16856 +
16857 +/**
16858 + * dpaa2_fl_is_final() - Check final bit in FLE
16859 + * @fle: the given frame list entry
16860 + *
16861 + * Return bool.
16862 + */
16863 +static inline bool dpaa2_fl_is_final(const struct dpaa2_fl_entry *fle)
16864 +{
16865 + return !!(le16_to_cpu(fle->format_offset) >> FL_FINAL_FLAG_SHIFT);
16866 +}
16867 +
16868 +/**
16869 + * dpaa2_fl_set_final() - Set the final bit in FLE
16870 + * @fle: the given frame list entry
16871 + * @final: the final boolean to be set
16872 + */
16873 +static inline void dpaa2_fl_set_final(struct dpaa2_fl_entry *fle, bool final)
16874 +{
16875 + fle->format_offset &= cpu_to_le16(~(FL_FINAL_FLAG_MASK <<
16876 + FL_FINAL_FLAG_SHIFT));
16877 + fle->format_offset |= cpu_to_le16(final << FL_FINAL_FLAG_SHIFT);
16878 +}
16879 +
16880 +#endif /* __FSL_DPAA2_FD_H */
16881 --- /dev/null
16882 +++ b/drivers/staging/fsl-mc/include/dpaa2-global.h
16883 @@ -0,0 +1,177 @@
16884 +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
16885 +/*
16886 + * Copyright 2014-2016 Freescale Semiconductor Inc.
16887 + * Copyright 2016 NXP
16888 + *
16889 + */
16890 +#ifndef __FSL_DPAA2_GLOBAL_H
16891 +#define __FSL_DPAA2_GLOBAL_H
16892 +
16893 +#include <linux/types.h>
16894 +#include <linux/cpumask.h>
16895 +#include "dpaa2-fd.h"
16896 +
16897 +struct dpaa2_dq {
16898 + union {
16899 + struct common {
16900 + u8 verb;
16901 + u8 reserved[63];
16902 + } common;
16903 + struct dq {
16904 + u8 verb;
16905 + u8 stat;
16906 + __le16 seqnum;
16907 + __le16 oprid;
16908 + u8 reserved;
16909 + u8 tok;
16910 + __le32 fqid;
16911 + u32 reserved2;
16912 + __le32 fq_byte_cnt;
16913 + __le32 fq_frm_cnt;
16914 + __le64 fqd_ctx;
16915 + u8 fd[32];
16916 + } dq;
16917 + struct scn {
16918 + u8 verb;
16919 + u8 stat;
16920 + u8 state;
16921 + u8 reserved;
16922 + __le32 rid_tok;
16923 + __le64 ctx;
16924 + } scn;
16925 + };
16926 +};
16927 +
16928 +/* Parsing frame dequeue results */
16929 +/* FQ empty */
16930 +#define DPAA2_DQ_STAT_FQEMPTY 0x80
16931 +/* FQ held active */
16932 +#define DPAA2_DQ_STAT_HELDACTIVE 0x40
16933 +/* FQ force eligible */
16934 +#define DPAA2_DQ_STAT_FORCEELIGIBLE 0x20
16935 +/* valid frame */
16936 +#define DPAA2_DQ_STAT_VALIDFRAME 0x10
16937 +/* FQ ODP enable */
16938 +#define DPAA2_DQ_STAT_ODPVALID 0x04
16939 +/* volatile dequeue */
16940 +#define DPAA2_DQ_STAT_VOLATILE 0x02
16941 +/* volatile dequeue command is expired */
16942 +#define DPAA2_DQ_STAT_EXPIRED 0x01
16943 +
16944 +#define DQ_FQID_MASK 0x00FFFFFF
16945 +#define DQ_FRAME_COUNT_MASK 0x00FFFFFF
16946 +
16947 +/**
16948 + * dpaa2_dq_flags() - Get the stat field of dequeue response
16949 + * @dq: the dequeue result.
16950 + */
16951 +static inline u32 dpaa2_dq_flags(const struct dpaa2_dq *dq)
16952 +{
16953 + return dq->dq.stat;
16954 +}
16955 +
16956 +/**
16957 + * dpaa2_dq_is_pull() - Check whether the dq response is from a pull
16958 + * command.
16959 + * @dq: the dequeue result
16960 + *
16961 + * Return 1 for volatile(pull) dequeue, 0 for static dequeue.
16962 + */
16963 +static inline int dpaa2_dq_is_pull(const struct dpaa2_dq *dq)
16964 +{
16965 + return (int)(dpaa2_dq_flags(dq) & DPAA2_DQ_STAT_VOLATILE);
16966 +}
16967 +
16968 +/**
16969 + * dpaa2_dq_is_pull_complete() - Check whether the pull command is completed.
16970 + * @dq: the dequeue result
16971 + *
16972 + * Return boolean.
16973 + */
16974 +static inline bool dpaa2_dq_is_pull_complete(const struct dpaa2_dq *dq)
16975 +{
16976 + return !!(dpaa2_dq_flags(dq) & DPAA2_DQ_STAT_EXPIRED);
16977 +}
16978 +
16979 +/**
16980 + * dpaa2_dq_seqnum() - Get the seqnum field in dequeue response
16981 + * @dq: the dequeue result
16982 + *
16983 + * seqnum is valid only if VALIDFRAME flag is TRUE
16984 + *
16985 + * Return seqnum.
16986 + */
16987 +static inline u16 dpaa2_dq_seqnum(const struct dpaa2_dq *dq)
16988 +{
16989 + return le16_to_cpu(dq->dq.seqnum);
16990 +}
16991 +
16992 +/**
16993 + * dpaa2_dq_odpid() - Get the odpid field in dequeue response
16994 + * @dq: the dequeue result
16995 + *
16996 + * odpid is valid only if ODPVALID flag is TRUE.
16997 + *
16998 + * Return odpid.
16999 + */
17000 +static inline u16 dpaa2_dq_odpid(const struct dpaa2_dq *dq)
17001 +{
17002 + return le16_to_cpu(dq->dq.oprid);
17003 +}
17004 +
17005 +/**
17006 + * dpaa2_dq_fqid() - Get the fqid in dequeue response
17007 + * @dq: the dequeue result
17008 + *
17009 + * Return fqid.
17010 + */
17011 +static inline u32 dpaa2_dq_fqid(const struct dpaa2_dq *dq)
17012 +{
17013 + return le32_to_cpu(dq->dq.fqid) & DQ_FQID_MASK;
17014 +}
17015 +
17016 +/**
17017 + * dpaa2_dq_byte_count() - Get the byte count in dequeue response
17018 + * @dq: the dequeue result
17019 + *
17020 + * Return the byte count remaining in the FQ.
17021 + */
17022 +static inline u32 dpaa2_dq_byte_count(const struct dpaa2_dq *dq)
17023 +{
17024 + return le32_to_cpu(dq->dq.fq_byte_cnt);
17025 +}
17026 +
17027 +/**
17028 + * dpaa2_dq_frame_count() - Get the frame count in dequeue response
17029 + * @dq: the dequeue result
17030 + *
17031 + * Return the frame count remaining in the FQ.
17032 + */
17033 +static inline u32 dpaa2_dq_frame_count(const struct dpaa2_dq *dq)
17034 +{
17035 + return le32_to_cpu(dq->dq.fq_frm_cnt) & DQ_FRAME_COUNT_MASK;
17036 +}
17037 +
17038 +/**
17039 + * dpaa2_dq_fd_ctx() - Get the frame queue context in dequeue response
17040 + * @dq: the dequeue result
17041 + *
17042 + * Return the frame queue context.
17043 + */
17044 +static inline u64 dpaa2_dq_fqd_ctx(const struct dpaa2_dq *dq)
17045 +{
17046 + return le64_to_cpu(dq->dq.fqd_ctx);
17047 +}
17048 +
17049 +/**
17050 + * dpaa2_dq_fd() - Get the frame descriptor in dequeue response
17051 + * @dq: the dequeue result
17052 + *
17053 + * Return the frame descriptor.
17054 + */
17055 +static inline const struct dpaa2_fd *dpaa2_dq_fd(const struct dpaa2_dq *dq)
17056 +{
17057 + return (const struct dpaa2_fd *)&dq->dq.fd[0];
17058 +}
17059 +
17060 +#endif /* __FSL_DPAA2_GLOBAL_H */
17061 --- /dev/null
17062 +++ b/drivers/staging/fsl-mc/include/dpaa2-io.h
17063 @@ -0,0 +1,178 @@
17064 +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
17065 +/*
17066 + * Copyright 2014-2016 Freescale Semiconductor Inc.
17067 + * Copyright 2017 NXP
17068 + *
17069 + */
17070 +#ifndef __FSL_DPAA2_IO_H
17071 +#define __FSL_DPAA2_IO_H
17072 +
17073 +#include <linux/types.h>
17074 +#include <linux/cpumask.h>
17075 +
17076 +#include "dpaa2-fd.h"
17077 +#include "dpaa2-global.h"
17078 +
17079 +struct dpaa2_io;
17080 +struct dpaa2_io_store;
17081 +struct device;
17082 +
17083 +/**
17084 + * DOC: DPIO Service
17085 + *
17086 + * The DPIO service provides APIs for users to interact with the datapath
17087 + * by enqueueing and dequeing frame descriptors.
17088 + *
17089 + * The following set of APIs can be used to enqueue and dequeue frames
17090 + * as well as producing notification callbacks when data is available
17091 + * for dequeue.
17092 + */
17093 +
17094 +#define DPAA2_IO_ANY_CPU -1
17095 +
17096 +/**
17097 + * struct dpaa2_io_desc - The DPIO descriptor
17098 + * @receives_notifications: Use notificaton mode. Non-zero if the DPIO
17099 + * has a channel.
17100 + * @has_8prio: Set to non-zero for channel with 8 priority WQs. Ignored
17101 + * unless receives_notification is TRUE.
17102 + * @cpu: The cpu index that at least interrupt handlers will
17103 + * execute on.
17104 + * @stash_affinity: The stash affinity for this portal favour 'cpu'
17105 + * @regs_cena: The cache enabled regs.
17106 + * @regs_cinh: The cache inhibited regs
17107 + * @dpio_id: The dpio index
17108 + * @qman_version: The qman version
17109 + *
17110 + * Describes the attributes and features of the DPIO object.
17111 + */
17112 +struct dpaa2_io_desc {
17113 + int receives_notifications;
17114 + int has_8prio;
17115 + int cpu;
17116 + void *regs_cena;
17117 + void *regs_cinh;
17118 + int dpio_id;
17119 + u32 qman_version;
17120 +};
17121 +
17122 +struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc);
17123 +
17124 +void dpaa2_io_down(struct dpaa2_io *d);
17125 +
17126 +irqreturn_t dpaa2_io_irq(struct dpaa2_io *obj);
17127 +
17128 +struct dpaa2_io *dpaa2_io_service_select(int cpu);
17129 +
17130 +/**
17131 + * struct dpaa2_io_notification_ctx - The DPIO notification context structure
17132 + * @cb: The callback to be invoked when the notification arrives
17133 + * @is_cdan: Zero for FQDAN, non-zero for CDAN
17134 + * @id: FQID or channel ID, needed for rearm
17135 + * @desired_cpu: The cpu on which the notifications will show up. Use
17136 + * DPAA2_IO_ANY_CPU if don't care
17137 + * @dpio_id: The dpio index
17138 + * @qman64: The 64-bit context value shows up in the FQDAN/CDAN.
17139 + * @node: The list node
17140 + * @dpio_private: The dpio object internal to dpio_service
17141 + *
17142 + * Used when a FQDAN/CDAN registration is made by drivers.
17143 + */
17144 +struct dpaa2_io_notification_ctx {
17145 + void (*cb)(struct dpaa2_io_notification_ctx *ctx);
17146 + int is_cdan;
17147 + u32 id;
17148 + int desired_cpu;
17149 + int dpio_id;
17150 + u64 qman64;
17151 + struct list_head node;
17152 + void *dpio_private;
17153 +};
17154 +
17155 +int dpaa2_io_service_register(struct dpaa2_io *service,
17156 + struct dpaa2_io_notification_ctx *ctx);
17157 +void dpaa2_io_service_deregister(struct dpaa2_io *service,
17158 + struct dpaa2_io_notification_ctx *ctx);
17159 +int dpaa2_io_service_rearm(struct dpaa2_io *service,
17160 + struct dpaa2_io_notification_ctx *ctx);
17161 +
17162 +int dpaa2_io_service_pull_fq(struct dpaa2_io *d, u32 fqid,
17163 + struct dpaa2_io_store *s);
17164 +int dpaa2_io_service_pull_channel(struct dpaa2_io *d, u32 channelid,
17165 + struct dpaa2_io_store *s);
17166 +
17167 +int dpaa2_io_service_enqueue_fq(struct dpaa2_io *d, u32 fqid,
17168 + const struct dpaa2_fd *fd);
17169 +int dpaa2_io_service_enqueue_qd(struct dpaa2_io *d, u32 qdid, u8 prio,
17170 + u16 qdbin, const struct dpaa2_fd *fd);
17171 +int dpaa2_io_service_release(struct dpaa2_io *d, u32 bpid,
17172 + const u64 *buffers, unsigned int num_buffers);
17173 +int dpaa2_io_service_acquire(struct dpaa2_io *d, u32 bpid,
17174 + u64 *buffers, unsigned int num_buffers);
17175 +
17176 +struct dpaa2_io_store *dpaa2_io_store_create(unsigned int max_frames,
17177 + struct device *dev);
17178 +void dpaa2_io_store_destroy(struct dpaa2_io_store *s);
17179 +struct dpaa2_dq *dpaa2_io_store_next(struct dpaa2_io_store *s, int *is_last);
17180 +
17181 +/* Order Restoration Support */
17182 +int dpaa2_io_service_enqueue_orp_fq(struct dpaa2_io *d, u32 fqid,
17183 + const struct dpaa2_fd *fd, u16 orpid,
17184 + u16 seqnum, int last);
17185 +
17186 +int dpaa2_io_service_enqueue_orp_qd(struct dpaa2_io *d, u32 qdid, u8 prio,
17187 + u16 qdbin, const struct dpaa2_fd *fd,
17188 + u16 orpid, u16 seqnum, int last);
17189 +
17190 +int dpaa2_io_service_orp_seqnum_drop(struct dpaa2_io *d, u16 orpid,
17191 + u16 seqnum);
17192 +
17193 +/***************/
17194 +/* CSCN */
17195 +/***************/
17196 +
17197 +/**
17198 + * struct dpaa2_cscn - The CSCN message format
17199 + * @verb: identifies the type of message (should be 0x27).
17200 + * @stat: status bits related to dequeuing response (not used)
17201 + * @state: bit 0 = 0/1 if CG is no/is congested
17202 + * @reserved: reserved byte
17203 + * @cgid: congest grp ID - the first 16 bits
17204 + * @ctx: context data
17205 + *
17206 + * Congestion management can be implemented in software through
17207 + * the use of Congestion State Change Notifications (CSCN). These
17208 + * are messages written by DPAA2 hardware to memory whenever the
17209 + * instantaneous count (I_CNT field in the CG) exceeds the
17210 + * Congestion State (CS) entrance threshold, signifying congestion
17211 + * entrance, or when the instantaneous count returns below exit
17212 + * threshold, signifying congestion exit. The format of the message
17213 + * is given by the dpaa2_cscn structure. Bit 0 of the state field
17214 + * represents congestion state written by the hardware.
17215 + */
17216 +struct dpaa2_cscn {
17217 + u8 verb;
17218 + u8 stat;
17219 + u8 state;
17220 + u8 reserved;
17221 + __le32 cgid;
17222 + __le64 ctx;
17223 +};
17224 +
17225 +#define DPAA2_CSCN_SIZE 64
17226 +#define DPAA2_CSCN_ALIGN 16
17227 +
17228 +#define DPAA2_CSCN_STATE_MASK 0x1
17229 +#define DPAA2_CSCN_CONGESTED 1
17230 +
17231 +static inline bool dpaa2_cscn_state_congested(struct dpaa2_cscn *cscn)
17232 +{
17233 + return ((cscn->state & DPAA2_CSCN_STATE_MASK) == DPAA2_CSCN_CONGESTED);
17234 +}
17235 +
17236 +int dpaa2_io_query_fq_count(struct dpaa2_io *d, u32 fqid,
17237 + u32 *fcnt, u32 *bcnt);
17238 +int dpaa2_io_query_bp_count(struct dpaa2_io *d, u32 bpid,
17239 + u32 *num);
17240 +
17241 +#endif /* __FSL_DPAA2_IO_H */
17242 --- a/drivers/staging/fsl-mc/include/dpbp-cmd.h
17243 +++ /dev/null
17244 @@ -1,185 +0,0 @@
17245 -/* Copyright 2013-2016 Freescale Semiconductor Inc.
17246 - *
17247 - * Redistribution and use in source and binary forms, with or without
17248 - * modification, are permitted provided that the following conditions are met:
17249 - * * Redistributions of source code must retain the above copyright
17250 - * notice, this list of conditions and the following disclaimer.
17251 - * * Redistributions in binary form must reproduce the above copyright
17252 - * notice, this list of conditions and the following disclaimer in the
17253 - * documentation and/or other materials provided with the distribution.
17254 - * * Neither the name of the above-listed copyright holders nor the
17255 - * names of any contributors may be used to endorse or promote products
17256 - * derived from this software without specific prior written permission.
17257 - *
17258 - *
17259 - * ALTERNATIVELY, this software may be distributed under the terms of the
17260 - * GNU General Public License ("GPL") as published by the Free Software
17261 - * Foundation, either version 2 of that License or (at your option) any
17262 - * later version.
17263 - *
17264 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17265 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17266 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17267 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
17268 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
17269 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
17270 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
17271 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
17272 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
17273 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
17274 - * POSSIBILITY OF SUCH DAMAGE.
17275 - */
17276 -#ifndef _FSL_DPBP_CMD_H
17277 -#define _FSL_DPBP_CMD_H
17278 -
17279 -/* DPBP Version */
17280 -#define DPBP_VER_MAJOR 2
17281 -#define DPBP_VER_MINOR 2
17282 -
17283 -/* Command IDs */
17284 -#define DPBP_CMDID_CLOSE 0x800
17285 -#define DPBP_CMDID_OPEN 0x804
17286 -#define DPBP_CMDID_CREATE 0x904
17287 -#define DPBP_CMDID_DESTROY 0x900
17288 -
17289 -#define DPBP_CMDID_ENABLE 0x002
17290 -#define DPBP_CMDID_DISABLE 0x003
17291 -#define DPBP_CMDID_GET_ATTR 0x004
17292 -#define DPBP_CMDID_RESET 0x005
17293 -#define DPBP_CMDID_IS_ENABLED 0x006
17294 -
17295 -#define DPBP_CMDID_SET_IRQ 0x010
17296 -#define DPBP_CMDID_GET_IRQ 0x011
17297 -#define DPBP_CMDID_SET_IRQ_ENABLE 0x012
17298 -#define DPBP_CMDID_GET_IRQ_ENABLE 0x013
17299 -#define DPBP_CMDID_SET_IRQ_MASK 0x014
17300 -#define DPBP_CMDID_GET_IRQ_MASK 0x015
17301 -#define DPBP_CMDID_GET_IRQ_STATUS 0x016
17302 -#define DPBP_CMDID_CLEAR_IRQ_STATUS 0x017
17303 -
17304 -#define DPBP_CMDID_SET_NOTIFICATIONS 0x01b0
17305 -#define DPBP_CMDID_GET_NOTIFICATIONS 0x01b1
17306 -
17307 -struct dpbp_cmd_open {
17308 - __le32 dpbp_id;
17309 -};
17310 -
17311 -#define DPBP_ENABLE 0x1
17312 -
17313 -struct dpbp_rsp_is_enabled {
17314 - u8 enabled;
17315 -};
17316 -
17317 -struct dpbp_cmd_set_irq {
17318 - /* cmd word 0 */
17319 - u8 irq_index;
17320 - u8 pad[3];
17321 - __le32 irq_val;
17322 - /* cmd word 1 */
17323 - __le64 irq_addr;
17324 - /* cmd word 2 */
17325 - __le32 irq_num;
17326 -};
17327 -
17328 -struct dpbp_cmd_get_irq {
17329 - __le32 pad;
17330 - u8 irq_index;
17331 -};
17332 -
17333 -struct dpbp_rsp_get_irq {
17334 - /* response word 0 */
17335 - __le32 irq_val;
17336 - __le32 pad;
17337 - /* response word 1 */
17338 - __le64 irq_addr;
17339 - /* response word 2 */
17340 - __le32 irq_num;
17341 - __le32 type;
17342 -};
17343 -
17344 -struct dpbp_cmd_set_irq_enable {
17345 - u8 enable;
17346 - u8 pad[3];
17347 - u8 irq_index;
17348 -};
17349 -
17350 -struct dpbp_cmd_get_irq_enable {
17351 - __le32 pad;
17352 - u8 irq_index;
17353 -};
17354 -
17355 -struct dpbp_rsp_get_irq_enable {
17356 - u8 enabled;
17357 -};
17358 -
17359 -struct dpbp_cmd_set_irq_mask {
17360 - __le32 mask;
17361 - u8 irq_index;
17362 -};
17363 -
17364 -struct dpbp_cmd_get_irq_mask {
17365 - __le32 pad;
17366 - u8 irq_index;
17367 -};
17368 -
17369 -struct dpbp_rsp_get_irq_mask {
17370 - __le32 mask;
17371 -};
17372 -
17373 -struct dpbp_cmd_get_irq_status {
17374 - __le32 status;
17375 - u8 irq_index;
17376 -};
17377 -
17378 -struct dpbp_rsp_get_irq_status {
17379 - __le32 status;
17380 -};
17381 -
17382 -struct dpbp_cmd_clear_irq_status {
17383 - __le32 status;
17384 - u8 irq_index;
17385 -};
17386 -
17387 -struct dpbp_rsp_get_attributes {
17388 - /* response word 0 */
17389 - __le16 pad;
17390 - __le16 bpid;
17391 - __le32 id;
17392 - /* response word 1 */
17393 - __le16 version_major;
17394 - __le16 version_minor;
17395 -};
17396 -
17397 -struct dpbp_cmd_set_notifications {
17398 - /* cmd word 0 */
17399 - __le32 depletion_entry;
17400 - __le32 depletion_exit;
17401 - /* cmd word 1 */
17402 - __le32 surplus_entry;
17403 - __le32 surplus_exit;
17404 - /* cmd word 2 */
17405 - __le16 options;
17406 - __le16 pad[3];
17407 - /* cmd word 3 */
17408 - __le64 message_ctx;
17409 - /* cmd word 4 */
17410 - __le64 message_iova;
17411 -};
17412 -
17413 -struct dpbp_rsp_get_notifications {
17414 - /* response word 0 */
17415 - __le32 depletion_entry;
17416 - __le32 depletion_exit;
17417 - /* response word 1 */
17418 - __le32 surplus_entry;
17419 - __le32 surplus_exit;
17420 - /* response word 2 */
17421 - __le16 options;
17422 - __le16 pad[3];
17423 - /* response word 3 */
17424 - __le64 message_ctx;
17425 - /* response word 4 */
17426 - __le64 message_iova;
17427 -};
17428 -
17429 -#endif /* _FSL_DPBP_CMD_H */
17430 --- a/drivers/staging/fsl-mc/include/dpbp.h
17431 +++ /dev/null
17432 @@ -1,220 +0,0 @@
17433 -/* Copyright 2013-2015 Freescale Semiconductor Inc.
17434 - *
17435 - * Redistribution and use in source and binary forms, with or without
17436 - * modification, are permitted provided that the following conditions are met:
17437 - * * Redistributions of source code must retain the above copyright
17438 - * notice, this list of conditions and the following disclaimer.
17439 - * * Redistributions in binary form must reproduce the above copyright
17440 - * notice, this list of conditions and the following disclaimer in the
17441 - * documentation and/or other materials provided with the distribution.
17442 - * * Neither the name of the above-listed copyright holders nor the
17443 - * names of any contributors may be used to endorse or promote products
17444 - * derived from this software without specific prior written permission.
17445 - *
17446 - *
17447 - * ALTERNATIVELY, this software may be distributed under the terms of the
17448 - * GNU General Public License ("GPL") as published by the Free Software
17449 - * Foundation, either version 2 of that License or (at your option) any
17450 - * later version.
17451 - *
17452 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17453 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17454 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17455 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
17456 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
17457 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
17458 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
17459 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
17460 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
17461 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
17462 - * POSSIBILITY OF SUCH DAMAGE.
17463 - */
17464 -#ifndef __FSL_DPBP_H
17465 -#define __FSL_DPBP_H
17466 -
17467 -/* Data Path Buffer Pool API
17468 - * Contains initialization APIs and runtime control APIs for DPBP
17469 - */
17470 -
17471 -struct fsl_mc_io;
17472 -
17473 -int dpbp_open(struct fsl_mc_io *mc_io,
17474 - u32 cmd_flags,
17475 - int dpbp_id,
17476 - u16 *token);
17477 -
17478 -int dpbp_close(struct fsl_mc_io *mc_io,
17479 - u32 cmd_flags,
17480 - u16 token);
17481 -
17482 -/**
17483 - * struct dpbp_cfg - Structure representing DPBP configuration
17484 - * @options: place holder
17485 - */
17486 -struct dpbp_cfg {
17487 - u32 options;
17488 -};
17489 -
17490 -int dpbp_create(struct fsl_mc_io *mc_io,
17491 - u32 cmd_flags,
17492 - const struct dpbp_cfg *cfg,
17493 - u16 *token);
17494 -
17495 -int dpbp_destroy(struct fsl_mc_io *mc_io,
17496 - u32 cmd_flags,
17497 - u16 token);
17498 -
17499 -int dpbp_enable(struct fsl_mc_io *mc_io,
17500 - u32 cmd_flags,
17501 - u16 token);
17502 -
17503 -int dpbp_disable(struct fsl_mc_io *mc_io,
17504 - u32 cmd_flags,
17505 - u16 token);
17506 -
17507 -int dpbp_is_enabled(struct fsl_mc_io *mc_io,
17508 - u32 cmd_flags,
17509 - u16 token,
17510 - int *en);
17511 -
17512 -int dpbp_reset(struct fsl_mc_io *mc_io,
17513 - u32 cmd_flags,
17514 - u16 token);
17515 -
17516 -/**
17517 - * struct dpbp_irq_cfg - IRQ configuration
17518 - * @addr: Address that must be written to signal a message-based interrupt
17519 - * @val: Value to write into irq_addr address
17520 - * @irq_num: A user defined number associated with this IRQ
17521 - */
17522 -struct dpbp_irq_cfg {
17523 - u64 addr;
17524 - u32 val;
17525 - int irq_num;
17526 -};
17527 -
17528 -int dpbp_set_irq(struct fsl_mc_io *mc_io,
17529 - u32 cmd_flags,
17530 - u16 token,
17531 - u8 irq_index,
17532 - struct dpbp_irq_cfg *irq_cfg);
17533 -
17534 -int dpbp_get_irq(struct fsl_mc_io *mc_io,
17535 - u32 cmd_flags,
17536 - u16 token,
17537 - u8 irq_index,
17538 - int *type,
17539 - struct dpbp_irq_cfg *irq_cfg);
17540 -
17541 -int dpbp_set_irq_enable(struct fsl_mc_io *mc_io,
17542 - u32 cmd_flags,
17543 - u16 token,
17544 - u8 irq_index,
17545 - u8 en);
17546 -
17547 -int dpbp_get_irq_enable(struct fsl_mc_io *mc_io,
17548 - u32 cmd_flags,
17549 - u16 token,
17550 - u8 irq_index,
17551 - u8 *en);
17552 -
17553 -int dpbp_set_irq_mask(struct fsl_mc_io *mc_io,
17554 - u32 cmd_flags,
17555 - u16 token,
17556 - u8 irq_index,
17557 - u32 mask);
17558 -
17559 -int dpbp_get_irq_mask(struct fsl_mc_io *mc_io,
17560 - u32 cmd_flags,
17561 - u16 token,
17562 - u8 irq_index,
17563 - u32 *mask);
17564 -
17565 -int dpbp_get_irq_status(struct fsl_mc_io *mc_io,
17566 - u32 cmd_flags,
17567 - u16 token,
17568 - u8 irq_index,
17569 - u32 *status);
17570 -
17571 -int dpbp_clear_irq_status(struct fsl_mc_io *mc_io,
17572 - u32 cmd_flags,
17573 - u16 token,
17574 - u8 irq_index,
17575 - u32 status);
17576 -
17577 -/**
17578 - * struct dpbp_attr - Structure representing DPBP attributes
17579 - * @id: DPBP object ID
17580 - * @version: DPBP version
17581 - * @bpid: Hardware buffer pool ID; should be used as an argument in
17582 - * acquire/release operations on buffers
17583 - */
17584 -struct dpbp_attr {
17585 - int id;
17586 - /**
17587 - * struct version - Structure representing DPBP version
17588 - * @major: DPBP major version
17589 - * @minor: DPBP minor version
17590 - */
17591 - struct {
17592 - u16 major;
17593 - u16 minor;
17594 - } version;
17595 - u16 bpid;
17596 -};
17597 -
17598 -int dpbp_get_attributes(struct fsl_mc_io *mc_io,
17599 - u32 cmd_flags,
17600 - u16 token,
17601 - struct dpbp_attr *attr);
17602 -
17603 -/**
17604 - * DPBP notifications options
17605 - */
17606 -
17607 -/**
17608 - * BPSCN write will attempt to allocate into a cache (coherent write)
17609 - */
17610 -#define DPBP_NOTIF_OPT_COHERENT_WRITE 0x00000001
17611 -
17612 -/**
17613 - * struct dpbp_notification_cfg - Structure representing DPBP notifications
17614 - * towards software
17615 - * @depletion_entry: below this threshold the pool is "depleted";
17616 - * set it to '0' to disable it
17617 - * @depletion_exit: greater than or equal to this threshold the pool exit its
17618 - * "depleted" state
17619 - * @surplus_entry: above this threshold the pool is in "surplus" state;
17620 - * set it to '0' to disable it
17621 - * @surplus_exit: less than or equal to this threshold the pool exit its
17622 - * "surplus" state
17623 - * @message_iova: MUST be given if either 'depletion_entry' or 'surplus_entry'
17624 - * is not '0' (enable); I/O virtual address (must be in DMA-able memory),
17625 - * must be 16B aligned.
17626 - * @message_ctx: The context that will be part of the BPSCN message and will
17627 - * be written to 'message_iova'
17628 - * @options: Mask of available options; use 'DPBP_NOTIF_OPT_<X>' values
17629 - */
17630 -struct dpbp_notification_cfg {
17631 - u32 depletion_entry;
17632 - u32 depletion_exit;
17633 - u32 surplus_entry;
17634 - u32 surplus_exit;
17635 - u64 message_iova;
17636 - u64 message_ctx;
17637 - u16 options;
17638 -};
17639 -
17640 -int dpbp_set_notifications(struct fsl_mc_io *mc_io,
17641 - u32 cmd_flags,
17642 - u16 token,
17643 - struct dpbp_notification_cfg *cfg);
17644 -
17645 -int dpbp_get_notifications(struct fsl_mc_io *mc_io,
17646 - u32 cmd_flags,
17647 - u16 token,
17648 - struct dpbp_notification_cfg *cfg);
17649 -
17650 -/** @} */
17651 -
17652 -#endif /* __FSL_DPBP_H */
17653 --- a/drivers/staging/fsl-mc/include/dpcon-cmd.h
17654 +++ /dev/null
17655 @@ -1,62 +0,0 @@
17656 -/* Copyright 2013-2015 Freescale Semiconductor Inc.
17657 - *
17658 - * Redistribution and use in source and binary forms, with or without
17659 - * modification, are permitted provided that the following conditions are met:
17660 - * * Redistributions of source code must retain the above copyright
17661 - * notice, this list of conditions and the following disclaimer.
17662 - * * Redistributions in binary form must reproduce the above copyright
17663 - * notice, this list of conditions and the following disclaimer in the
17664 - * documentation and/or other materials provided with the distribution.
17665 - * * Neither the name of the above-listed copyright holders nor the
17666 - * names of any contributors may be used to endorse or promote products
17667 - * derived from this software without specific prior written permission.
17668 - *
17669 - *
17670 - * ALTERNATIVELY, this software may be distributed under the terms of the
17671 - * GNU General Public License ("GPL") as published by the Free Software
17672 - * Foundation, either version 2 of that License or (at your option) any
17673 - * later version.
17674 - *
17675 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17676 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17677 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17678 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
17679 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
17680 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
17681 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
17682 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
17683 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
17684 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
17685 - * POSSIBILITY OF SUCH DAMAGE.
17686 - */
17687 -#ifndef _FSL_DPCON_CMD_H
17688 -#define _FSL_DPCON_CMD_H
17689 -
17690 -/* DPCON Version */
17691 -#define DPCON_VER_MAJOR 2
17692 -#define DPCON_VER_MINOR 1
17693 -
17694 -/* Command IDs */
17695 -#define DPCON_CMDID_CLOSE 0x800
17696 -#define DPCON_CMDID_OPEN 0x808
17697 -#define DPCON_CMDID_CREATE 0x908
17698 -#define DPCON_CMDID_DESTROY 0x900
17699 -
17700 -#define DPCON_CMDID_ENABLE 0x002
17701 -#define DPCON_CMDID_DISABLE 0x003
17702 -#define DPCON_CMDID_GET_ATTR 0x004
17703 -#define DPCON_CMDID_RESET 0x005
17704 -#define DPCON_CMDID_IS_ENABLED 0x006
17705 -
17706 -#define DPCON_CMDID_SET_IRQ 0x010
17707 -#define DPCON_CMDID_GET_IRQ 0x011
17708 -#define DPCON_CMDID_SET_IRQ_ENABLE 0x012
17709 -#define DPCON_CMDID_GET_IRQ_ENABLE 0x013
17710 -#define DPCON_CMDID_SET_IRQ_MASK 0x014
17711 -#define DPCON_CMDID_GET_IRQ_MASK 0x015
17712 -#define DPCON_CMDID_GET_IRQ_STATUS 0x016
17713 -#define DPCON_CMDID_CLEAR_IRQ_STATUS 0x017
17714 -
17715 -#define DPCON_CMDID_SET_NOTIFICATION 0x100
17716 -
17717 -#endif /* _FSL_DPCON_CMD_H */
17718 --- a/drivers/staging/fsl-mc/include/dpmng.h
17719 +++ /dev/null
17720 @@ -1,69 +0,0 @@
17721 -/* Copyright 2013-2015 Freescale Semiconductor Inc.
17722 - *
17723 - * Redistribution and use in source and binary forms, with or without
17724 - * modification, are permitted provided that the following conditions are met:
17725 - * * Redistributions of source code must retain the above copyright
17726 - * notice, this list of conditions and the following disclaimer.
17727 - * * Redistributions in binary form must reproduce the above copyright
17728 - * notice, this list of conditions and the following disclaimer in the
17729 - * documentation and/or other materials provided with the distribution.
17730 - * * Neither the name of the above-listed copyright holders nor the
17731 - * names of any contributors may be used to endorse or promote products
17732 - * derived from this software without specific prior written permission.
17733 - *
17734 - *
17735 - * ALTERNATIVELY, this software may be distributed under the terms of the
17736 - * GNU General Public License ("GPL") as published by the Free Software
17737 - * Foundation, either version 2 of that License or (at your option) any
17738 - * later version.
17739 - *
17740 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17741 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17742 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17743 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
17744 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
17745 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
17746 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
17747 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
17748 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
17749 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
17750 - * POSSIBILITY OF SUCH DAMAGE.
17751 - */
17752 -#ifndef __FSL_DPMNG_H
17753 -#define __FSL_DPMNG_H
17754 -
17755 -/* Management Complex General API
17756 - * Contains general API for the Management Complex firmware
17757 - */
17758 -
17759 -struct fsl_mc_io;
17760 -
17761 -/**
17762 - * Management Complex firmware version information
17763 - */
17764 -#define MC_VER_MAJOR 8
17765 -#define MC_VER_MINOR 0
17766 -
17767 -/**
17768 - * struct mc_version
17769 - * @major: Major version number: incremented on API compatibility changes
17770 - * @minor: Minor version number: incremented on API additions (that are
17771 - * backward compatible); reset when major version is incremented
17772 - * @revision: Internal revision number: incremented on implementation changes
17773 - * and/or bug fixes that have no impact on API
17774 - */
17775 -struct mc_version {
17776 - u32 major;
17777 - u32 minor;
17778 - u32 revision;
17779 -};
17780 -
17781 -int mc_get_version(struct fsl_mc_io *mc_io,
17782 - u32 cmd_flags,
17783 - struct mc_version *mc_ver_info);
17784 -
17785 -int dpmng_get_container_id(struct fsl_mc_io *mc_io,
17786 - u32 cmd_flags,
17787 - int *container_id);
17788 -
17789 -#endif /* __FSL_DPMNG_H */
17790 --- /dev/null
17791 +++ b/drivers/staging/fsl-mc/include/dpopr.h
17792 @@ -0,0 +1,112 @@
17793 +/*
17794 + * Copyright 2017 NXP
17795 + *
17796 + * Redistribution and use in source and binary forms, with or without
17797 + * modification, are permitted provided that the following conditions are met:
17798 + * * Redistributions of source code must retain the above copyright
17799 + * notice, this list of conditions and the following disclaimer.
17800 + * * Redistributions in binary form must reproduce the above copyright
17801 + * notice, this list of conditions and the following disclaimer in the
17802 + * documentation and/or other materials provided with the distribution.
17803 + * * Neither the name of the above-listed copyright holders nor the
17804 + * names of any contributors may be used to endorse or promote products
17805 + * derived from this software without specific prior written permission.
17806 + *
17807 + *
17808 + * ALTERNATIVELY, this software may be distributed under the terms of the
17809 + * GNU General Public License ("GPL") as published by the Free Software
17810 + * Foundation, either version 2 of that License or (at your option) any
17811 + * later version.
17812 + *
17813 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17814 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17815 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17816 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
17817 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
17818 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
17819 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
17820 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
17821 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
17822 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
17823 + * POSSIBILITY OF SUCH DAMAGE.
17824 + */
17825 +#ifndef __FSL_DPOPR_H_
17826 +#define __FSL_DPOPR_H_
17827 +
17828 +#include <linux/types.h>
17829 +
17830 +/* Data Path Order Restoration API
17831 + * Contains initialization APIs and runtime APIs for the Order Restoration
17832 + */
17833 +
17834 +/** Order Restoration properties */
17835 +
17836 +/**
17837 + * Create a new Order Point Record option
17838 + */
17839 +#define OPR_OPT_CREATE 0x1
17840 +/**
17841 + * Retire an existing Order Point Record option
17842 + */
17843 +#define OPR_OPT_RETIRE 0x2
17844 +
17845 +/**
17846 + * struct opr_cfg - Structure representing OPR configuration
17847 + * @oprrws: Order point record (OPR) restoration window size (0 to 5)
17848 + * 0 - Window size is 32 frames.
17849 + * 1 - Window size is 64 frames.
17850 + * 2 - Window size is 128 frames.
17851 + * 3 - Window size is 256 frames.
17852 + * 4 - Window size is 512 frames.
17853 + * 5 - Window size is 1024 frames.
17854 + * @oa: OPR auto advance NESN window size (0 disabled, 1 enabled)
17855 + * @olws: OPR acceptable late arrival window size (0 to 3)
17856 + * 0 - Disabled. Late arrivals are always rejected.
17857 + * 1 - Window size is 32 frames.
17858 + * 2 - Window size is the same as the OPR restoration
17859 + * window size configured in the OPRRWS field.
17860 + * 3 - Window size is 8192 frames. Late arrivals are
17861 + * always accepted.
17862 + * @oeane: Order restoration list (ORL) resource exhaustion
17863 + * advance NESN enable (0 disabled, 1 enabled)
17864 + * @oloe: OPR loose ordering enable (0 disabled, 1 enabled)
17865 + */
17866 +struct opr_cfg {
17867 + u8 oprrws;
17868 + u8 oa;
17869 + u8 olws;
17870 + u8 oeane;
17871 + u8 oloe;
17872 +};
17873 +
17874 +/**
17875 + * struct opr_qry - Structure representing OPR configuration
17876 + * @enable: Enabled state
17877 + * @rip: Retirement In Progress
17878 + * @ndsn: Next dispensed sequence number
17879 + * @nesn: Next expected sequence number
17880 + * @ea_hseq: Early arrival head sequence number
17881 + * @hseq_nlis: HSEQ not last in sequence
17882 + * @ea_tseq: Early arrival tail sequence number
17883 + * @tseq_nlis: TSEQ not last in sequence
17884 + * @ea_tptr: Early arrival tail pointer
17885 + * @ea_hptr: Early arrival head pointer
17886 + * @opr_id: Order Point Record ID
17887 + * @opr_vid: Order Point Record Virtual ID
17888 + */
17889 +struct opr_qry {
17890 + char enable;
17891 + char rip;
17892 + u16 ndsn;
17893 + u16 nesn;
17894 + u16 ea_hseq;
17895 + char hseq_nlis;
17896 + u16 ea_tseq;
17897 + char tseq_nlis;
17898 + u16 ea_tptr;
17899 + u16 ea_hptr;
17900 + u16 opr_id;
17901 + u16 opr_vid;
17902 +};
17903 +
17904 +#endif /* __FSL_DPOPR_H_ */
17905 --- a/drivers/staging/fsl-mc/include/dprc.h
17906 +++ /dev/null
17907 @@ -1,544 +0,0 @@
17908 -/* Copyright 2013-2015 Freescale Semiconductor Inc.
17909 - *
17910 - * Redistribution and use in source and binary forms, with or without
17911 - * modification, are permitted provided that the following conditions are met:
17912 - * * Redistributions of source code must retain the above copyright
17913 - * notice, this list of conditions and the following disclaimer.
17914 - * * Redistributions in binary form must reproduce the above copyright
17915 - * notice, this list of conditions and the following disclaimer in the
17916 - * documentation and/or other materials provided with the distribution.
17917 - * * Neither the name of the above-listed copyright holders nor the
17918 - * names of any contributors may be used to endorse or promote products
17919 - * derived from this software without specific prior written permission.
17920 - *
17921 - *
17922 - * ALTERNATIVELY, this software may be distributed under the terms of the
17923 - * GNU General Public License ("GPL") as published by the Free Software
17924 - * Foundation, either version 2 of that License or (at your option) any
17925 - * later version.
17926 - *
17927 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17928 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17929 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17930 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
17931 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
17932 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
17933 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
17934 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
17935 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
17936 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
17937 - * POSSIBILITY OF SUCH DAMAGE.
17938 - */
17939 -#ifndef _FSL_DPRC_H
17940 -#define _FSL_DPRC_H
17941 -
17942 -#include "mc-cmd.h"
17943 -
17944 -/* Data Path Resource Container API
17945 - * Contains DPRC API for managing and querying DPAA resources
17946 - */
17947 -
17948 -struct fsl_mc_io;
17949 -
17950 -/**
17951 - * Set this value as the icid value in dprc_cfg structure when creating a
17952 - * container, in case the ICID is not selected by the user and should be
17953 - * allocated by the DPRC from the pool of ICIDs.
17954 - */
17955 -#define DPRC_GET_ICID_FROM_POOL (u16)(~(0))
17956 -
17957 -/**
17958 - * Set this value as the portal_id value in dprc_cfg structure when creating a
17959 - * container, in case the portal ID is not specifically selected by the
17960 - * user and should be allocated by the DPRC from the pool of portal ids.
17961 - */
17962 -#define DPRC_GET_PORTAL_ID_FROM_POOL (int)(~(0))
17963 -
17964 -int dprc_open(struct fsl_mc_io *mc_io,
17965 - u32 cmd_flags,
17966 - int container_id,
17967 - u16 *token);
17968 -
17969 -int dprc_close(struct fsl_mc_io *mc_io,
17970 - u32 cmd_flags,
17971 - u16 token);
17972 -
17973 -/**
17974 - * Container general options
17975 - *
17976 - * These options may be selected at container creation by the container creator
17977 - * and can be retrieved using dprc_get_attributes()
17978 - */
17979 -
17980 -/* Spawn Policy Option allowed - Indicates that the new container is allowed
17981 - * to spawn and have its own child containers.
17982 - */
17983 -#define DPRC_CFG_OPT_SPAWN_ALLOWED 0x00000001
17984 -
17985 -/* General Container allocation policy - Indicates that the new container is
17986 - * allowed to allocate requested resources from its parent container; if not
17987 - * set, the container is only allowed to use resources in its own pools; Note
17988 - * that this is a container's global policy, but the parent container may
17989 - * override it and set specific quota per resource type.
17990 - */
17991 -#define DPRC_CFG_OPT_ALLOC_ALLOWED 0x00000002
17992 -
17993 -/* Object initialization allowed - software context associated with this
17994 - * container is allowed to invoke object initialization operations.
17995 - */
17996 -#define DPRC_CFG_OPT_OBJ_CREATE_ALLOWED 0x00000004
17997 -
17998 -/* Topology change allowed - software context associated with this
17999 - * container is allowed to invoke topology operations, such as attach/detach
18000 - * of network objects.
18001 - */
18002 -#define DPRC_CFG_OPT_TOPOLOGY_CHANGES_ALLOWED 0x00000008
18003 -
18004 -/* AIOP - Indicates that container belongs to AIOP. */
18005 -#define DPRC_CFG_OPT_AIOP 0x00000020
18006 -
18007 -/* IRQ Config - Indicates that the container allowed to configure its IRQs. */
18008 -#define DPRC_CFG_OPT_IRQ_CFG_ALLOWED 0x00000040
18009 -
18010 -/**
18011 - * struct dprc_cfg - Container configuration options
18012 - * @icid: Container's ICID; if set to 'DPRC_GET_ICID_FROM_POOL', a free
18013 - * ICID value is allocated by the DPRC
18014 - * @portal_id: Portal ID; if set to 'DPRC_GET_PORTAL_ID_FROM_POOL', a free
18015 - * portal ID is allocated by the DPRC
18016 - * @options: Combination of 'DPRC_CFG_OPT_<X>' options
18017 - * @label: Object's label
18018 - */
18019 -struct dprc_cfg {
18020 - u16 icid;
18021 - int portal_id;
18022 - u64 options;
18023 - char label[16];
18024 -};
18025 -
18026 -int dprc_create_container(struct fsl_mc_io *mc_io,
18027 - u32 cmd_flags,
18028 - u16 token,
18029 - struct dprc_cfg *cfg,
18030 - int *child_container_id,
18031 - u64 *child_portal_offset);
18032 -
18033 -int dprc_destroy_container(struct fsl_mc_io *mc_io,
18034 - u32 cmd_flags,
18035 - u16 token,
18036 - int child_container_id);
18037 -
18038 -int dprc_reset_container(struct fsl_mc_io *mc_io,
18039 - u32 cmd_flags,
18040 - u16 token,
18041 - int child_container_id);
18042 -
18043 -/* IRQ */
18044 -
18045 -/* IRQ index */
18046 -#define DPRC_IRQ_INDEX 0
18047 -
18048 -/* Number of dprc's IRQs */
18049 -#define DPRC_NUM_OF_IRQS 1
18050 -
18051 -/* DPRC IRQ events */
18052 -
18053 -/* IRQ event - Indicates that a new object added to the container */
18054 -#define DPRC_IRQ_EVENT_OBJ_ADDED 0x00000001
18055 -/* IRQ event - Indicates that an object was removed from the container */
18056 -#define DPRC_IRQ_EVENT_OBJ_REMOVED 0x00000002
18057 -/* IRQ event - Indicates that resources added to the container */
18058 -#define DPRC_IRQ_EVENT_RES_ADDED 0x00000004
18059 -/* IRQ event - Indicates that resources removed from the container */
18060 -#define DPRC_IRQ_EVENT_RES_REMOVED 0x00000008
18061 -/* IRQ event - Indicates that one of the descendant containers that opened by
18062 - * this container is destroyed
18063 - */
18064 -#define DPRC_IRQ_EVENT_CONTAINER_DESTROYED 0x00000010
18065 -
18066 -/* IRQ event - Indicates that on one of the container's opened object is
18067 - * destroyed
18068 - */
18069 -#define DPRC_IRQ_EVENT_OBJ_DESTROYED 0x00000020
18070 -
18071 -/* Irq event - Indicates that object is created at the container */
18072 -#define DPRC_IRQ_EVENT_OBJ_CREATED 0x00000040
18073 -
18074 -/**
18075 - * struct dprc_irq_cfg - IRQ configuration
18076 - * @paddr: Address that must be written to signal a message-based interrupt
18077 - * @val: Value to write into irq_addr address
18078 - * @irq_num: A user defined number associated with this IRQ
18079 - */
18080 -struct dprc_irq_cfg {
18081 - phys_addr_t paddr;
18082 - u32 val;
18083 - int irq_num;
18084 -};
18085 -
18086 -int dprc_set_irq(struct fsl_mc_io *mc_io,
18087 - u32 cmd_flags,
18088 - u16 token,
18089 - u8 irq_index,
18090 - struct dprc_irq_cfg *irq_cfg);
18091 -
18092 -int dprc_get_irq(struct fsl_mc_io *mc_io,
18093 - u32 cmd_flags,
18094 - u16 token,
18095 - u8 irq_index,
18096 - int *type,
18097 - struct dprc_irq_cfg *irq_cfg);
18098 -
18099 -int dprc_set_irq_enable(struct fsl_mc_io *mc_io,
18100 - u32 cmd_flags,
18101 - u16 token,
18102 - u8 irq_index,
18103 - u8 en);
18104 -
18105 -int dprc_get_irq_enable(struct fsl_mc_io *mc_io,
18106 - u32 cmd_flags,
18107 - u16 token,
18108 - u8 irq_index,
18109 - u8 *en);
18110 -
18111 -int dprc_set_irq_mask(struct fsl_mc_io *mc_io,
18112 - u32 cmd_flags,
18113 - u16 token,
18114 - u8 irq_index,
18115 - u32 mask);
18116 -
18117 -int dprc_get_irq_mask(struct fsl_mc_io *mc_io,
18118 - u32 cmd_flags,
18119 - u16 token,
18120 - u8 irq_index,
18121 - u32 *mask);
18122 -
18123 -int dprc_get_irq_status(struct fsl_mc_io *mc_io,
18124 - u32 cmd_flags,
18125 - u16 token,
18126 - u8 irq_index,
18127 - u32 *status);
18128 -
18129 -int dprc_clear_irq_status(struct fsl_mc_io *mc_io,
18130 - u32 cmd_flags,
18131 - u16 token,
18132 - u8 irq_index,
18133 - u32 status);
18134 -
18135 -/**
18136 - * struct dprc_attributes - Container attributes
18137 - * @container_id: Container's ID
18138 - * @icid: Container's ICID
18139 - * @portal_id: Container's portal ID
18140 - * @options: Container's options as set at container's creation
18141 - * @version: DPRC version
18142 - */
18143 -struct dprc_attributes {
18144 - int container_id;
18145 - u16 icid;
18146 - int portal_id;
18147 - u64 options;
18148 - /**
18149 - * struct version - DPRC version
18150 - * @major: DPRC major version
18151 - * @minor: DPRC minor version
18152 - */
18153 - struct {
18154 - u16 major;
18155 - u16 minor;
18156 - } version;
18157 -};
18158 -
18159 -int dprc_get_attributes(struct fsl_mc_io *mc_io,
18160 - u32 cmd_flags,
18161 - u16 token,
18162 - struct dprc_attributes *attributes);
18163 -
18164 -int dprc_set_res_quota(struct fsl_mc_io *mc_io,
18165 - u32 cmd_flags,
18166 - u16 token,
18167 - int child_container_id,
18168 - char *type,
18169 - u16 quota);
18170 -
18171 -int dprc_get_res_quota(struct fsl_mc_io *mc_io,
18172 - u32 cmd_flags,
18173 - u16 token,
18174 - int child_container_id,
18175 - char *type,
18176 - u16 *quota);
18177 -
18178 -/* Resource request options */
18179 -
18180 -/* Explicit resource ID request - The requested objects/resources
18181 - * are explicit and sequential (in case of resources).
18182 - * The base ID is given at res_req at base_align field
18183 - */
18184 -#define DPRC_RES_REQ_OPT_EXPLICIT 0x00000001
18185 -
18186 -/* Aligned resources request - Relevant only for resources
18187 - * request (and not objects). Indicates that resources base ID should be
18188 - * sequential and aligned to the value given at dprc_res_req base_align field
18189 - */
18190 -#define DPRC_RES_REQ_OPT_ALIGNED 0x00000002
18191 -
18192 -/* Plugged Flag - Relevant only for object assignment request.
18193 - * Indicates that after all objects assigned. An interrupt will be invoked at
18194 - * the relevant GPP. The assigned object will be marked as plugged.
18195 - * plugged objects can't be assigned from their container
18196 - */
18197 -#define DPRC_RES_REQ_OPT_PLUGGED 0x00000004
18198 -
18199 -/**
18200 - * struct dprc_res_req - Resource request descriptor, to be used in assignment
18201 - * or un-assignment of resources and objects.
18202 - * @type: Resource/object type: Represent as a NULL terminated string.
18203 - * This string may received by using dprc_get_pool() to get resource
18204 - * type and dprc_get_obj() to get object type;
18205 - * Note: it is not possible to assign/un-assign DPRC objects
18206 - * @num: Number of resources
18207 - * @options: Request options: combination of DPRC_RES_REQ_OPT_ options
18208 - * @id_base_align: In case of explicit assignment (DPRC_RES_REQ_OPT_EXPLICIT
18209 - * is set at option), this field represents the required base ID
18210 - * for resource allocation; In case of aligned assignment
18211 - * (DPRC_RES_REQ_OPT_ALIGNED is set at option), this field
18212 - * indicates the required alignment for the resource ID(s) -
18213 - * use 0 if there is no alignment or explicit ID requirements
18214 - */
18215 -struct dprc_res_req {
18216 - char type[16];
18217 - u32 num;
18218 - u32 options;
18219 - int id_base_align;
18220 -};
18221 -
18222 -int dprc_assign(struct fsl_mc_io *mc_io,
18223 - u32 cmd_flags,
18224 - u16 token,
18225 - int container_id,
18226 - struct dprc_res_req *res_req);
18227 -
18228 -int dprc_unassign(struct fsl_mc_io *mc_io,
18229 - u32 cmd_flags,
18230 - u16 token,
18231 - int child_container_id,
18232 - struct dprc_res_req *res_req);
18233 -
18234 -int dprc_get_pool_count(struct fsl_mc_io *mc_io,
18235 - u32 cmd_flags,
18236 - u16 token,
18237 - int *pool_count);
18238 -
18239 -int dprc_get_pool(struct fsl_mc_io *mc_io,
18240 - u32 cmd_flags,
18241 - u16 token,
18242 - int pool_index,
18243 - char *type);
18244 -
18245 -int dprc_get_obj_count(struct fsl_mc_io *mc_io,
18246 - u32 cmd_flags,
18247 - u16 token,
18248 - int *obj_count);
18249 -
18250 -/* Objects Attributes Flags */
18251 -
18252 -/* Opened state - Indicates that an object is open by at least one owner */
18253 -#define DPRC_OBJ_STATE_OPEN 0x00000001
18254 -/* Plugged state - Indicates that the object is plugged */
18255 -#define DPRC_OBJ_STATE_PLUGGED 0x00000002
18256 -
18257 -/**
18258 - * Shareability flag - Object flag indicating no memory shareability.
18259 - * the object generates memory accesses that are non coherent with other
18260 - * masters;
18261 - * user is responsible for proper memory handling through IOMMU configuration.
18262 - */
18263 -#define DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY 0x0001
18264 -
18265 -/**
18266 - * struct dprc_obj_desc - Object descriptor, returned from dprc_get_obj()
18267 - * @type: Type of object: NULL terminated string
18268 - * @id: ID of logical object resource
18269 - * @vendor: Object vendor identifier
18270 - * @ver_major: Major version number
18271 - * @ver_minor: Minor version number
18272 - * @irq_count: Number of interrupts supported by the object
18273 - * @region_count: Number of mappable regions supported by the object
18274 - * @state: Object state: combination of DPRC_OBJ_STATE_ states
18275 - * @label: Object label
18276 - * @flags: Object's flags
18277 - */
18278 -struct dprc_obj_desc {
18279 - char type[16];
18280 - int id;
18281 - u16 vendor;
18282 - u16 ver_major;
18283 - u16 ver_minor;
18284 - u8 irq_count;
18285 - u8 region_count;
18286 - u32 state;
18287 - char label[16];
18288 - u16 flags;
18289 -};
18290 -
18291 -int dprc_get_obj(struct fsl_mc_io *mc_io,
18292 - u32 cmd_flags,
18293 - u16 token,
18294 - int obj_index,
18295 - struct dprc_obj_desc *obj_desc);
18296 -
18297 -int dprc_get_obj_desc(struct fsl_mc_io *mc_io,
18298 - u32 cmd_flags,
18299 - u16 token,
18300 - char *obj_type,
18301 - int obj_id,
18302 - struct dprc_obj_desc *obj_desc);
18303 -
18304 -int dprc_set_obj_irq(struct fsl_mc_io *mc_io,
18305 - u32 cmd_flags,
18306 - u16 token,
18307 - char *obj_type,
18308 - int obj_id,
18309 - u8 irq_index,
18310 - struct dprc_irq_cfg *irq_cfg);
18311 -
18312 -int dprc_get_obj_irq(struct fsl_mc_io *mc_io,
18313 - u32 cmd_flags,
18314 - u16 token,
18315 - char *obj_type,
18316 - int obj_id,
18317 - u8 irq_index,
18318 - int *type,
18319 - struct dprc_irq_cfg *irq_cfg);
18320 -
18321 -int dprc_get_res_count(struct fsl_mc_io *mc_io,
18322 - u32 cmd_flags,
18323 - u16 token,
18324 - char *type,
18325 - int *res_count);
18326 -
18327 -/**
18328 - * enum dprc_iter_status - Iteration status
18329 - * @DPRC_ITER_STATUS_FIRST: Perform first iteration
18330 - * @DPRC_ITER_STATUS_MORE: Indicates more/next iteration is needed
18331 - * @DPRC_ITER_STATUS_LAST: Indicates last iteration
18332 - */
18333 -enum dprc_iter_status {
18334 - DPRC_ITER_STATUS_FIRST = 0,
18335 - DPRC_ITER_STATUS_MORE = 1,
18336 - DPRC_ITER_STATUS_LAST = 2
18337 -};
18338 -
18339 -/**
18340 - * struct dprc_res_ids_range_desc - Resource ID range descriptor
18341 - * @base_id: Base resource ID of this range
18342 - * @last_id: Last resource ID of this range
18343 - * @iter_status: Iteration status - should be set to DPRC_ITER_STATUS_FIRST at
18344 - * first iteration; while the returned marker is DPRC_ITER_STATUS_MORE,
18345 - * additional iterations are needed, until the returned marker is
18346 - * DPRC_ITER_STATUS_LAST
18347 - */
18348 -struct dprc_res_ids_range_desc {
18349 - int base_id;
18350 - int last_id;
18351 - enum dprc_iter_status iter_status;
18352 -};
18353 -
18354 -int dprc_get_res_ids(struct fsl_mc_io *mc_io,
18355 - u32 cmd_flags,
18356 - u16 token,
18357 - char *type,
18358 - struct dprc_res_ids_range_desc *range_desc);
18359 -
18360 -/* Region flags */
18361 -/* Cacheable - Indicates that region should be mapped as cacheable */
18362 -#define DPRC_REGION_CACHEABLE 0x00000001
18363 -
18364 -/**
18365 - * enum dprc_region_type - Region type
18366 - * @DPRC_REGION_TYPE_MC_PORTAL: MC portal region
18367 - * @DPRC_REGION_TYPE_QBMAN_PORTAL: Qbman portal region
18368 - */
18369 -enum dprc_region_type {
18370 - DPRC_REGION_TYPE_MC_PORTAL,
18371 - DPRC_REGION_TYPE_QBMAN_PORTAL
18372 -};
18373 -
18374 -/**
18375 - * struct dprc_region_desc - Mappable region descriptor
18376 - * @base_offset: Region offset from region's base address.
18377 - * For DPMCP and DPRC objects, region base is offset from SoC MC portals
18378 - * base address; For DPIO, region base is offset from SoC QMan portals
18379 - * base address
18380 - * @size: Region size (in bytes)
18381 - * @flags: Region attributes
18382 - * @type: Portal region type
18383 - */
18384 -struct dprc_region_desc {
18385 - u32 base_offset;
18386 - u32 size;
18387 - u32 flags;
18388 - enum dprc_region_type type;
18389 -};
18390 -
18391 -int dprc_get_obj_region(struct fsl_mc_io *mc_io,
18392 - u32 cmd_flags,
18393 - u16 token,
18394 - char *obj_type,
18395 - int obj_id,
18396 - u8 region_index,
18397 - struct dprc_region_desc *region_desc);
18398 -
18399 -int dprc_set_obj_label(struct fsl_mc_io *mc_io,
18400 - u32 cmd_flags,
18401 - u16 token,
18402 - char *obj_type,
18403 - int obj_id,
18404 - char *label);
18405 -
18406 -/**
18407 - * struct dprc_endpoint - Endpoint description for link connect/disconnect
18408 - * operations
18409 - * @type: Endpoint object type: NULL terminated string
18410 - * @id: Endpoint object ID
18411 - * @if_id: Interface ID; should be set for endpoints with multiple
18412 - * interfaces ("dpsw", "dpdmux"); for others, always set to 0
18413 - */
18414 -struct dprc_endpoint {
18415 - char type[16];
18416 - int id;
18417 - int if_id;
18418 -};
18419 -
18420 -/**
18421 - * struct dprc_connection_cfg - Connection configuration.
18422 - * Used for virtual connections only
18423 - * @committed_rate: Committed rate (Mbits/s)
18424 - * @max_rate: Maximum rate (Mbits/s)
18425 - */
18426 -struct dprc_connection_cfg {
18427 - u32 committed_rate;
18428 - u32 max_rate;
18429 -};
18430 -
18431 -int dprc_connect(struct fsl_mc_io *mc_io,
18432 - u32 cmd_flags,
18433 - u16 token,
18434 - const struct dprc_endpoint *endpoint1,
18435 - const struct dprc_endpoint *endpoint2,
18436 - const struct dprc_connection_cfg *cfg);
18437 -
18438 -int dprc_disconnect(struct fsl_mc_io *mc_io,
18439 - u32 cmd_flags,
18440 - u16 token,
18441 - const struct dprc_endpoint *endpoint);
18442 -
18443 -int dprc_get_connection(struct fsl_mc_io *mc_io,
18444 - u32 cmd_flags,
18445 - u16 token,
18446 - const struct dprc_endpoint *endpoint1,
18447 - struct dprc_endpoint *endpoint2,
18448 - int *state);
18449 -
18450 -#endif /* _FSL_DPRC_H */
18451 -
18452 --- a/drivers/staging/fsl-mc/include/mc-bus.h
18453 +++ /dev/null
18454 @@ -1,111 +0,0 @@
18455 -/*
18456 - * Freescale Management Complex (MC) bus declarations
18457 - *
18458 - * Copyright (C) 2014 Freescale Semiconductor, Inc.
18459 - * Author: German Rivera <German.Rivera@freescale.com>
18460 - *
18461 - * This file is licensed under the terms of the GNU General Public
18462 - * License version 2. This program is licensed "as is" without any
18463 - * warranty of any kind, whether express or implied.
18464 - */
18465 -#ifndef _FSL_MC_MCBUS_H_
18466 -#define _FSL_MC_MCBUS_H_
18467 -
18468 -#include "../include/mc.h"
18469 -#include <linux/mutex.h>
18470 -
18471 -struct irq_domain;
18472 -struct msi_domain_info;
18473 -
18474 -/**
18475 - * Maximum number of total IRQs that can be pre-allocated for an MC bus'
18476 - * IRQ pool
18477 - */
18478 -#define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256
18479 -
18480 -#ifdef CONFIG_FSL_MC_BUS
18481 -#define dev_is_fsl_mc(_dev) ((_dev)->bus == &fsl_mc_bus_type)
18482 -#else
18483 -/* If fsl-mc bus is not present device cannot belong to fsl-mc bus */
18484 -#define dev_is_fsl_mc(_dev) (0)
18485 -#endif
18486 -
18487 -/**
18488 - * struct fsl_mc_resource_pool - Pool of MC resources of a given
18489 - * type
18490 - * @type: type of resources in the pool
18491 - * @max_count: maximum number of resources in the pool
18492 - * @free_count: number of free resources in the pool
18493 - * @mutex: mutex to serialize access to the pool's free list
18494 - * @free_list: anchor node of list of free resources in the pool
18495 - * @mc_bus: pointer to the MC bus that owns this resource pool
18496 - */
18497 -struct fsl_mc_resource_pool {
18498 - enum fsl_mc_pool_type type;
18499 - int16_t max_count;
18500 - int16_t free_count;
18501 - struct mutex mutex; /* serializes access to free_list */
18502 - struct list_head free_list;
18503 - struct fsl_mc_bus *mc_bus;
18504 -};
18505 -
18506 -/**
18507 - * struct fsl_mc_bus - logical bus that corresponds to a physical DPRC
18508 - * @mc_dev: fsl-mc device for the bus device itself.
18509 - * @resource_pools: array of resource pools (one pool per resource type)
18510 - * for this MC bus. These resources represent allocatable entities
18511 - * from the physical DPRC.
18512 - * @irq_resources: Pointer to array of IRQ objects for the IRQ pool
18513 - * @scan_mutex: Serializes bus scanning
18514 - * @dprc_attr: DPRC attributes
18515 - */
18516 -struct fsl_mc_bus {
18517 - struct fsl_mc_device mc_dev;
18518 - struct fsl_mc_resource_pool resource_pools[FSL_MC_NUM_POOL_TYPES];
18519 - struct fsl_mc_device_irq *irq_resources;
18520 - struct mutex scan_mutex; /* serializes bus scanning */
18521 - struct dprc_attributes dprc_attr;
18522 -};
18523 -
18524 -#define to_fsl_mc_bus(_mc_dev) \
18525 - container_of(_mc_dev, struct fsl_mc_bus, mc_dev)
18526 -
18527 -int dprc_scan_container(struct fsl_mc_device *mc_bus_dev);
18528 -
18529 -int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
18530 - unsigned int *total_irq_count);
18531 -
18532 -int __init dprc_driver_init(void);
18533 -
18534 -void dprc_driver_exit(void);
18535 -
18536 -int __init fsl_mc_allocator_driver_init(void);
18537 -
18538 -void fsl_mc_allocator_driver_exit(void);
18539 -
18540 -struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode,
18541 - struct msi_domain_info *info,
18542 - struct irq_domain *parent);
18543 -
18544 -int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
18545 - struct irq_domain **mc_msi_domain);
18546 -
18547 -int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
18548 - unsigned int irq_count);
18549 -
18550 -void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus);
18551 -
18552 -void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev);
18553 -
18554 -void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev);
18555 -
18556 -bool fsl_mc_bus_exists(void);
18557 -
18558 -void fsl_mc_get_root_dprc(struct device *dev,
18559 - struct device **root_dprc_dev);
18560 -
18561 -bool fsl_mc_is_root_dprc(struct device *dev);
18562 -
18563 -extern struct bus_type fsl_mc_bus_type;
18564 -
18565 -#endif /* _FSL_MC_MCBUS_H_ */
18566 --- a/drivers/staging/fsl-mc/include/mc-cmd.h
18567 +++ /dev/null
18568 @@ -1,108 +0,0 @@
18569 -/* Copyright 2013-2015 Freescale Semiconductor Inc.
18570 - *
18571 - * Redistribution and use in source and binary forms, with or without
18572 - * modification, are permitted provided that the following conditions are met:
18573 - * * Redistributions of source code must retain the above copyright
18574 - * notice, this list of conditions and the following disclaimer.
18575 - * * Redistributions in binary form must reproduce the above copyright
18576 - * notice, this list of conditions and the following disclaimer in the
18577 - * documentation and/or other materials provided with the distribution.
18578 - * * Neither the name of the above-listed copyright holders nor the
18579 - * names of any contributors may be used to endorse or promote products
18580 - * derived from this software without specific prior written permission.
18581 - *
18582 - *
18583 - * ALTERNATIVELY, this software may be distributed under the terms of the
18584 - * GNU General Public License ("GPL") as published by the Free Software
18585 - * Foundation, either version 2 of that License or (at your option) any
18586 - * later version.
18587 - *
18588 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18589 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18590 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18591 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
18592 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18593 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
18594 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
18595 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
18596 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
18597 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
18598 - * POSSIBILITY OF SUCH DAMAGE.
18599 - */
18600 -#ifndef __FSL_MC_CMD_H
18601 -#define __FSL_MC_CMD_H
18602 -
18603 -#define MC_CMD_NUM_OF_PARAMS 7
18604 -
18605 -struct mc_cmd_header {
18606 - u8 src_id;
18607 - u8 flags_hw;
18608 - u8 status;
18609 - u8 flags_sw;
18610 - __le16 token;
18611 - __le16 cmd_id;
18612 -};
18613 -
18614 -struct mc_command {
18615 - u64 header;
18616 - u64 params[MC_CMD_NUM_OF_PARAMS];
18617 -};
18618 -
18619 -enum mc_cmd_status {
18620 - MC_CMD_STATUS_OK = 0x0, /* Completed successfully */
18621 - MC_CMD_STATUS_READY = 0x1, /* Ready to be processed */
18622 - MC_CMD_STATUS_AUTH_ERR = 0x3, /* Authentication error */
18623 - MC_CMD_STATUS_NO_PRIVILEGE = 0x4, /* No privilege */
18624 - MC_CMD_STATUS_DMA_ERR = 0x5, /* DMA or I/O error */
18625 - MC_CMD_STATUS_CONFIG_ERR = 0x6, /* Configuration error */
18626 - MC_CMD_STATUS_TIMEOUT = 0x7, /* Operation timed out */
18627 - MC_CMD_STATUS_NO_RESOURCE = 0x8, /* No resources */
18628 - MC_CMD_STATUS_NO_MEMORY = 0x9, /* No memory available */
18629 - MC_CMD_STATUS_BUSY = 0xA, /* Device is busy */
18630 - MC_CMD_STATUS_UNSUPPORTED_OP = 0xB, /* Unsupported operation */
18631 - MC_CMD_STATUS_INVALID_STATE = 0xC /* Invalid state */
18632 -};
18633 -
18634 -/*
18635 - * MC command flags
18636 - */
18637 -
18638 -/* High priority flag */
18639 -#define MC_CMD_FLAG_PRI 0x80
18640 -/* Command completion flag */
18641 -#define MC_CMD_FLAG_INTR_DIS 0x01
18642 -
18643 -#define MC_CMD_HDR_CMDID_MASK 0xFFF0
18644 -#define MC_CMD_HDR_CMDID_SHIFT 4
18645 -#define MC_CMD_HDR_TOKEN_MASK 0xFFC0
18646 -#define MC_CMD_HDR_TOKEN_SHIFT 6
18647 -
18648 -static inline u64 mc_encode_cmd_header(u16 cmd_id,
18649 - u32 cmd_flags,
18650 - u16 token)
18651 -{
18652 - u64 header = 0;
18653 - struct mc_cmd_header *hdr = (struct mc_cmd_header *)&header;
18654 -
18655 - hdr->cmd_id = cpu_to_le16((cmd_id << MC_CMD_HDR_CMDID_SHIFT) &
18656 - MC_CMD_HDR_CMDID_MASK);
18657 - hdr->token = cpu_to_le16((token << MC_CMD_HDR_TOKEN_SHIFT) &
18658 - MC_CMD_HDR_TOKEN_MASK);
18659 - hdr->status = MC_CMD_STATUS_READY;
18660 - if (cmd_flags & MC_CMD_FLAG_PRI)
18661 - hdr->flags_hw = MC_CMD_FLAG_PRI;
18662 - if (cmd_flags & MC_CMD_FLAG_INTR_DIS)
18663 - hdr->flags_sw = MC_CMD_FLAG_INTR_DIS;
18664 -
18665 - return header;
18666 -}
18667 -
18668 -static inline u16 mc_cmd_hdr_read_token(struct mc_command *cmd)
18669 -{
18670 - struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
18671 - u16 token = le16_to_cpu(hdr->token);
18672 -
18673 - return (token & MC_CMD_HDR_TOKEN_MASK) >> MC_CMD_HDR_TOKEN_SHIFT;
18674 -}
18675 -
18676 -#endif /* __FSL_MC_CMD_H */
18677 --- a/drivers/staging/fsl-mc/include/mc-sys.h
18678 +++ /dev/null
18679 @@ -1,98 +0,0 @@
18680 -/* Copyright 2013-2014 Freescale Semiconductor Inc.
18681 - *
18682 - * Interface of the I/O services to send MC commands to the MC hardware
18683 - *
18684 - * Redistribution and use in source and binary forms, with or without
18685 - * modification, are permitted provided that the following conditions are met:
18686 - * * Redistributions of source code must retain the above copyright
18687 - * notice, this list of conditions and the following disclaimer.
18688 - * * Redistributions in binary form must reproduce the above copyright
18689 - * notice, this list of conditions and the following disclaimer in the
18690 - * documentation and/or other materials provided with the distribution.
18691 - * * Neither the name of the above-listed copyright holders nor the
18692 - * names of any contributors may be used to endorse or promote products
18693 - * derived from this software without specific prior written permission.
18694 - *
18695 - *
18696 - * ALTERNATIVELY, this software may be distributed under the terms of the
18697 - * GNU General Public License ("GPL") as published by the Free Software
18698 - * Foundation, either version 2 of that License or (at your option) any
18699 - * later version.
18700 - *
18701 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18702 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18703 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18704 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
18705 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18706 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
18707 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
18708 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
18709 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
18710 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
18711 - * POSSIBILITY OF SUCH DAMAGE.
18712 - */
18713 -
18714 -#ifndef _FSL_MC_SYS_H
18715 -#define _FSL_MC_SYS_H
18716 -
18717 -#include <linux/types.h>
18718 -#include <linux/errno.h>
18719 -#include <linux/mutex.h>
18720 -#include <linux/spinlock.h>
18721 -
18722 -/**
18723 - * Bit masks for a MC I/O object (struct fsl_mc_io) flags
18724 - */
18725 -#define FSL_MC_IO_ATOMIC_CONTEXT_PORTAL 0x0001
18726 -
18727 -struct fsl_mc_resource;
18728 -struct mc_command;
18729 -
18730 -/**
18731 - * struct fsl_mc_io - MC I/O object to be passed-in to mc_send_command()
18732 - * @dev: device associated with this Mc I/O object
18733 - * @flags: flags for mc_send_command()
18734 - * @portal_size: MC command portal size in bytes
18735 - * @portal_phys_addr: MC command portal physical address
18736 - * @portal_virt_addr: MC command portal virtual address
18737 - * @dpmcp_dev: pointer to the DPMCP device associated with the MC portal.
18738 - *
18739 - * Fields are only meaningful if the FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is not
18740 - * set:
18741 - * @mutex: Mutex to serialize mc_send_command() calls that use the same MC
18742 - * portal, if the fsl_mc_io object was created with the
18743 - * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag off. mc_send_command() calls for this
18744 - * fsl_mc_io object must be made only from non-atomic context.
18745 - *
18746 - * Fields are only meaningful if the FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is
18747 - * set:
18748 - * @spinlock: Spinlock to serialize mc_send_command() calls that use the same MC
18749 - * portal, if the fsl_mc_io object was created with the
18750 - * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag on. mc_send_command() calls for this
18751 - * fsl_mc_io object can be made from atomic or non-atomic context.
18752 - */
18753 -struct fsl_mc_io {
18754 - struct device *dev;
18755 - u16 flags;
18756 - u16 portal_size;
18757 - phys_addr_t portal_phys_addr;
18758 - void __iomem *portal_virt_addr;
18759 - struct fsl_mc_device *dpmcp_dev;
18760 - union {
18761 - /*
18762 - * This field is only meaningful if the
18763 - * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is not set
18764 - */
18765 - struct mutex mutex; /* serializes mc_send_command() */
18766 -
18767 - /*
18768 - * This field is only meaningful if the
18769 - * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is set
18770 - */
18771 - spinlock_t spinlock; /* serializes mc_send_command() */
18772 - };
18773 -};
18774 -
18775 -int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd);
18776 -
18777 -#endif /* _FSL_MC_SYS_H */
18778 --- a/drivers/staging/fsl-mc/include/mc.h
18779 +++ /dev/null
18780 @@ -1,201 +0,0 @@
18781 -/*
18782 - * Freescale Management Complex (MC) bus public interface
18783 - *
18784 - * Copyright (C) 2014 Freescale Semiconductor, Inc.
18785 - * Author: German Rivera <German.Rivera@freescale.com>
18786 - *
18787 - * This file is licensed under the terms of the GNU General Public
18788 - * License version 2. This program is licensed "as is" without any
18789 - * warranty of any kind, whether express or implied.
18790 - */
18791 -#ifndef _FSL_MC_H_
18792 -#define _FSL_MC_H_
18793 -
18794 -#include <linux/device.h>
18795 -#include <linux/mod_devicetable.h>
18796 -#include <linux/interrupt.h>
18797 -#include "../include/dprc.h"
18798 -
18799 -#define FSL_MC_VENDOR_FREESCALE 0x1957
18800 -
18801 -struct fsl_mc_device;
18802 -struct fsl_mc_io;
18803 -
18804 -/**
18805 - * struct fsl_mc_driver - MC object device driver object
18806 - * @driver: Generic device driver
18807 - * @match_id_table: table of supported device matching Ids
18808 - * @probe: Function called when a device is added
18809 - * @remove: Function called when a device is removed
18810 - * @shutdown: Function called at shutdown time to quiesce the device
18811 - * @suspend: Function called when a device is stopped
18812 - * @resume: Function called when a device is resumed
18813 - *
18814 - * Generic DPAA device driver object for device drivers that are registered
18815 - * with a DPRC bus. This structure is to be embedded in each device-specific
18816 - * driver structure.
18817 - */
18818 -struct fsl_mc_driver {
18819 - struct device_driver driver;
18820 - const struct fsl_mc_device_id *match_id_table;
18821 - int (*probe)(struct fsl_mc_device *dev);
18822 - int (*remove)(struct fsl_mc_device *dev);
18823 - void (*shutdown)(struct fsl_mc_device *dev);
18824 - int (*suspend)(struct fsl_mc_device *dev, pm_message_t state);
18825 - int (*resume)(struct fsl_mc_device *dev);
18826 -};
18827 -
18828 -#define to_fsl_mc_driver(_drv) \
18829 - container_of(_drv, struct fsl_mc_driver, driver)
18830 -
18831 -/**
18832 - * enum fsl_mc_pool_type - Types of allocatable MC bus resources
18833 - *
18834 - * Entries in these enum are used as indices in the array of resource
18835 - * pools of an fsl_mc_bus object.
18836 - */
18837 -enum fsl_mc_pool_type {
18838 - FSL_MC_POOL_DPMCP = 0x0, /* corresponds to "dpmcp" in the MC */
18839 - FSL_MC_POOL_DPBP, /* corresponds to "dpbp" in the MC */
18840 - FSL_MC_POOL_DPCON, /* corresponds to "dpcon" in the MC */
18841 - FSL_MC_POOL_IRQ,
18842 -
18843 - /*
18844 - * NOTE: New resource pool types must be added before this entry
18845 - */
18846 - FSL_MC_NUM_POOL_TYPES
18847 -};
18848 -
18849 -/**
18850 - * struct fsl_mc_resource - MC generic resource
18851 - * @type: type of resource
18852 - * @id: unique MC resource Id within the resources of the same type
18853 - * @data: pointer to resource-specific data if the resource is currently
18854 - * allocated, or NULL if the resource is not currently allocated.
18855 - * @parent_pool: pointer to the parent resource pool from which this
18856 - * resource is allocated from.
18857 - * @node: Node in the free list of the corresponding resource pool
18858 - *
18859 - * NOTE: This structure is to be embedded as a field of specific
18860 - * MC resource structures.
18861 - */
18862 -struct fsl_mc_resource {
18863 - enum fsl_mc_pool_type type;
18864 - int32_t id;
18865 - void *data;
18866 - struct fsl_mc_resource_pool *parent_pool;
18867 - struct list_head node;
18868 -};
18869 -
18870 -/**
18871 - * struct fsl_mc_device_irq - MC object device message-based interrupt
18872 - * @msi_desc: pointer to MSI descriptor allocated by fsl_mc_msi_alloc_descs()
18873 - * @mc_dev: MC object device that owns this interrupt
18874 - * @dev_irq_index: device-relative IRQ index
18875 - * @resource: MC generic resource associated with the interrupt
18876 - */
18877 -struct fsl_mc_device_irq {
18878 - struct msi_desc *msi_desc;
18879 - struct fsl_mc_device *mc_dev;
18880 - u8 dev_irq_index;
18881 - struct fsl_mc_resource resource;
18882 -};
18883 -
18884 -#define to_fsl_mc_irq(_mc_resource) \
18885 - container_of(_mc_resource, struct fsl_mc_device_irq, resource)
18886 -
18887 -/**
18888 - * Bit masks for a MC object device (struct fsl_mc_device) flags
18889 - */
18890 -#define FSL_MC_IS_DPRC 0x0001
18891 -
18892 -/**
18893 - * struct fsl_mc_device - MC object device object
18894 - * @dev: Linux driver model device object
18895 - * @dma_mask: Default DMA mask
18896 - * @flags: MC object device flags
18897 - * @icid: Isolation context ID for the device
18898 - * @mc_handle: MC handle for the corresponding MC object opened
18899 - * @mc_io: Pointer to MC IO object assigned to this device or
18900 - * NULL if none.
18901 - * @obj_desc: MC description of the DPAA device
18902 - * @regions: pointer to array of MMIO region entries
18903 - * @irqs: pointer to array of pointers to interrupts allocated to this device
18904 - * @resource: generic resource associated with this MC object device, if any.
18905 - *
18906 - * Generic device object for MC object devices that are "attached" to a
18907 - * MC bus.
18908 - *
18909 - * NOTES:
18910 - * - For a non-DPRC object its icid is the same as its parent DPRC's icid.
18911 - * - The SMMU notifier callback gets invoked after device_add() has been
18912 - * called for an MC object device, but before the device-specific probe
18913 - * callback gets called.
18914 - * - DP_OBJ_DPRC objects are the only MC objects that have built-in MC
18915 - * portals. For all other MC objects, their device drivers are responsible for
18916 - * allocating MC portals for them by calling fsl_mc_portal_allocate().
18917 - * - Some types of MC objects (e.g., DP_OBJ_DPBP, DP_OBJ_DPCON) are
18918 - * treated as resources that can be allocated/deallocated from the
18919 - * corresponding resource pool in the object's parent DPRC, using the
18920 - * fsl_mc_object_allocate()/fsl_mc_object_free() functions. These MC objects
18921 - * are known as "allocatable" objects. For them, the corresponding
18922 - * fsl_mc_device's 'resource' points to the associated resource object.
18923 - * For MC objects that are not allocatable (e.g., DP_OBJ_DPRC, DP_OBJ_DPNI),
18924 - * 'resource' is NULL.
18925 - */
18926 -struct fsl_mc_device {
18927 - struct device dev;
18928 - u64 dma_mask;
18929 - u16 flags;
18930 - u16 icid;
18931 - u16 mc_handle;
18932 - struct fsl_mc_io *mc_io;
18933 - struct dprc_obj_desc obj_desc;
18934 - struct resource *regions;
18935 - struct fsl_mc_device_irq **irqs;
18936 - struct fsl_mc_resource *resource;
18937 -};
18938 -
18939 -#define to_fsl_mc_device(_dev) \
18940 - container_of(_dev, struct fsl_mc_device, dev)
18941 -
18942 -/*
18943 - * module_fsl_mc_driver() - Helper macro for drivers that don't do
18944 - * anything special in module init/exit. This eliminates a lot of
18945 - * boilerplate. Each module may only use this macro once, and
18946 - * calling it replaces module_init() and module_exit()
18947 - */
18948 -#define module_fsl_mc_driver(__fsl_mc_driver) \
18949 - module_driver(__fsl_mc_driver, fsl_mc_driver_register, \
18950 - fsl_mc_driver_unregister)
18951 -
18952 -/*
18953 - * Macro to avoid include chaining to get THIS_MODULE
18954 - */
18955 -#define fsl_mc_driver_register(drv) \
18956 - __fsl_mc_driver_register(drv, THIS_MODULE)
18957 -
18958 -int __must_check __fsl_mc_driver_register(struct fsl_mc_driver *fsl_mc_driver,
18959 - struct module *owner);
18960 -
18961 -void fsl_mc_driver_unregister(struct fsl_mc_driver *driver);
18962 -
18963 -int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
18964 - u16 mc_io_flags,
18965 - struct fsl_mc_io **new_mc_io);
18966 -
18967 -void fsl_mc_portal_free(struct fsl_mc_io *mc_io);
18968 -
18969 -int fsl_mc_portal_reset(struct fsl_mc_io *mc_io);
18970 -
18971 -int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
18972 - enum fsl_mc_pool_type pool_type,
18973 - struct fsl_mc_device **new_mc_adev);
18974 -
18975 -void fsl_mc_object_free(struct fsl_mc_device *mc_adev);
18976 -
18977 -int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev);
18978 -
18979 -void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev);
18980 -
18981 -#endif /* _FSL_MC_H_ */
18982 --- /dev/null
18983 +++ b/include/linux/fsl/mc.h
18984 @@ -0,0 +1,1025 @@
18985 +/* SPDX-License-Identifier: GPL-2.0 */
18986 +/*
18987 + * Freescale Management Complex (MC) bus public interface
18988 + *
18989 + * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
18990 + * Author: German Rivera <German.Rivera@freescale.com>
18991 + *
18992 + */
18993 +#ifndef _FSL_MC_H_
18994 +#define _FSL_MC_H_
18995 +
18996 +#include <linux/device.h>
18997 +#include <linux/mod_devicetable.h>
18998 +#include <linux/interrupt.h>
18999 +#include <linux/cdev.h>
19000 +#include <uapi/linux/fsl_mc.h>
19001 +
19002 +#define FSL_MC_VENDOR_FREESCALE 0x1957
19003 +
19004 +struct irq_domain;
19005 +struct msi_domain_info;
19006 +
19007 +struct fsl_mc_device;
19008 +struct fsl_mc_io;
19009 +
19010 +/**
19011 + * struct fsl_mc_driver - MC object device driver object
19012 + * @driver: Generic device driver
19013 + * @match_id_table: table of supported device matching Ids
19014 + * @probe: Function called when a device is added
19015 + * @remove: Function called when a device is removed
19016 + * @shutdown: Function called at shutdown time to quiesce the device
19017 + * @suspend: Function called when a device is stopped
19018 + * @resume: Function called when a device is resumed
19019 + *
19020 + * Generic DPAA device driver object for device drivers that are registered
19021 + * with a DPRC bus. This structure is to be embedded in each device-specific
19022 + * driver structure.
19023 + */
19024 +struct fsl_mc_driver {
19025 + struct device_driver driver;
19026 + const struct fsl_mc_device_id *match_id_table;
19027 + int (*probe)(struct fsl_mc_device *dev);
19028 + int (*remove)(struct fsl_mc_device *dev);
19029 + void (*shutdown)(struct fsl_mc_device *dev);
19030 + int (*suspend)(struct fsl_mc_device *dev, pm_message_t state);
19031 + int (*resume)(struct fsl_mc_device *dev);
19032 +};
19033 +
19034 +#define to_fsl_mc_driver(_drv) \
19035 + container_of(_drv, struct fsl_mc_driver, driver)
19036 +
19037 +#define to_fsl_mc_bus(_mc_dev) \
19038 + container_of(_mc_dev, struct fsl_mc_bus, mc_dev)
19039 +
19040 +/**
19041 + * enum fsl_mc_pool_type - Types of allocatable MC bus resources
19042 + *
19043 + * Entries in these enum are used as indices in the array of resource
19044 + * pools of an fsl_mc_bus object.
19045 + */
19046 +enum fsl_mc_pool_type {
19047 + FSL_MC_POOL_DPMCP = 0x0, /* corresponds to "dpmcp" in the MC */
19048 + FSL_MC_POOL_DPBP, /* corresponds to "dpbp" in the MC */
19049 + FSL_MC_POOL_DPCON, /* corresponds to "dpcon" in the MC */
19050 + FSL_MC_POOL_IRQ,
19051 +
19052 + /*
19053 + * NOTE: New resource pool types must be added before this entry
19054 + */
19055 + FSL_MC_NUM_POOL_TYPES
19056 +};
19057 +
19058 +/**
19059 + * struct fsl_mc_resource - MC generic resource
19060 + * @type: type of resource
19061 + * @id: unique MC resource Id within the resources of the same type
19062 + * @data: pointer to resource-specific data if the resource is currently
19063 + * allocated, or NULL if the resource is not currently allocated.
19064 + * @parent_pool: pointer to the parent resource pool from which this
19065 + * resource is allocated from.
19066 + * @node: Node in the free list of the corresponding resource pool
19067 + *
19068 + * NOTE: This structure is to be embedded as a field of specific
19069 + * MC resource structures.
19070 + */
19071 +struct fsl_mc_resource {
19072 + enum fsl_mc_pool_type type;
19073 + s32 id;
19074 + void *data;
19075 + struct fsl_mc_resource_pool *parent_pool;
19076 + struct list_head node;
19077 +};
19078 +
19079 +/**
19080 + * struct fsl_mc_device_irq - MC object device message-based interrupt
19081 + * @msi_desc: pointer to MSI descriptor allocated by fsl_mc_msi_alloc_descs()
19082 + * @mc_dev: MC object device that owns this interrupt
19083 + * @dev_irq_index: device-relative IRQ index
19084 + * @resource: MC generic resource associated with the interrupt
19085 + */
19086 +struct fsl_mc_device_irq {
19087 + struct msi_desc *msi_desc;
19088 + struct fsl_mc_device *mc_dev;
19089 + u8 dev_irq_index;
19090 + struct fsl_mc_resource resource;
19091 +};
19092 +
19093 +#define to_fsl_mc_irq(_mc_resource) \
19094 + container_of(_mc_resource, struct fsl_mc_device_irq, resource)
19095 +
19096 +/* Opened state - Indicates that an object is open by at least one owner */
19097 +#define FSL_MC_OBJ_STATE_OPEN 0x00000001
19098 +/* Plugged state - Indicates that the object is plugged */
19099 +#define FSL_MC_OBJ_STATE_PLUGGED 0x00000002
19100 +
19101 +/**
19102 + * Shareability flag - Object flag indicating no memory shareability.
19103 + * the object generates memory accesses that are non coherent with other
19104 + * masters;
19105 + * user is responsible for proper memory handling through IOMMU configuration.
19106 + */
19107 +#define FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY 0x0001
19108 +
19109 +/**
19110 + * struct fsl_mc_obj_desc - Object descriptor
19111 + * @type: Type of object: NULL terminated string
19112 + * @id: ID of logical object resource
19113 + * @vendor: Object vendor identifier
19114 + * @ver_major: Major version number
19115 + * @ver_minor: Minor version number
19116 + * @irq_count: Number of interrupts supported by the object
19117 + * @region_count: Number of mappable regions supported by the object
19118 + * @state: Object state: combination of FSL_MC_OBJ_STATE_ states
19119 + * @label: Object label: NULL terminated string
19120 + * @flags: Object's flags
19121 + */
19122 +struct fsl_mc_obj_desc {
19123 + char type[16];
19124 + int id;
19125 + u16 vendor;
19126 + u16 ver_major;
19127 + u16 ver_minor;
19128 + u8 irq_count;
19129 + u8 region_count;
19130 + u32 state;
19131 + char label[16];
19132 + u16 flags;
19133 +};
19134 +
19135 +/**
19136 + * Bit masks for a MC object device (struct fsl_mc_device) flags
19137 + */
19138 +#define FSL_MC_IS_DPRC 0x0001
19139 +
19140 +/**
19141 + * struct fsl_mc_device - MC object device object
19142 + * @dev: Linux driver model device object
19143 + * @dma_mask: Default DMA mask
19144 + * @flags: MC object device flags
19145 + * @icid: Isolation context ID for the device
19146 + * @mc_handle: MC handle for the corresponding MC object opened
19147 + * @mc_io: Pointer to MC IO object assigned to this device or
19148 + * NULL if none.
19149 + * @obj_desc: MC description of the DPAA device
19150 + * @regions: pointer to array of MMIO region entries
19151 + * @irqs: pointer to array of pointers to interrupts allocated to this device
19152 + * @resource: generic resource associated with this MC object device, if any.
19153 + * @driver_override: Driver name to force a match
19154 + *
19155 + * Generic device object for MC object devices that are "attached" to a
19156 + * MC bus.
19157 + *
19158 + * NOTES:
19159 + * - For a non-DPRC object its icid is the same as its parent DPRC's icid.
19160 + * - The SMMU notifier callback gets invoked after device_add() has been
19161 + * called for an MC object device, but before the device-specific probe
19162 + * callback gets called.
19163 + * - DP_OBJ_DPRC objects are the only MC objects that have built-in MC
19164 + * portals. For all other MC objects, their device drivers are responsible for
19165 + * allocating MC portals for them by calling fsl_mc_portal_allocate().
19166 + * - Some types of MC objects (e.g., DP_OBJ_DPBP, DP_OBJ_DPCON) are
19167 + * treated as resources that can be allocated/deallocated from the
19168 + * corresponding resource pool in the object's parent DPRC, using the
19169 + * fsl_mc_object_allocate()/fsl_mc_object_free() functions. These MC objects
19170 + * are known as "allocatable" objects. For them, the corresponding
19171 + * fsl_mc_device's 'resource' points to the associated resource object.
19172 + * For MC objects that are not allocatable (e.g., DP_OBJ_DPRC, DP_OBJ_DPNI),
19173 + * 'resource' is NULL.
19174 + */
19175 +struct fsl_mc_device {
19176 + struct device dev;
19177 + u64 dma_mask;
19178 + u16 flags;
19179 + u32 icid;
19180 + u16 mc_handle;
19181 + struct fsl_mc_io *mc_io;
19182 + struct fsl_mc_obj_desc obj_desc;
19183 + struct resource *regions;
19184 + struct fsl_mc_device_irq **irqs;
19185 + struct fsl_mc_resource *resource;
19186 + const char *driver_override;
19187 +};
19188 +
19189 +#define to_fsl_mc_device(_dev) \
19190 + container_of(_dev, struct fsl_mc_device, dev)
19191 +
19192 +struct mc_cmd_header {
19193 + u8 src_id;
19194 + u8 flags_hw;
19195 + u8 status;
19196 + u8 flags_sw;
19197 + __le16 token;
19198 + __le16 cmd_id;
19199 +};
19200 +
19201 +enum mc_cmd_status {
19202 + MC_CMD_STATUS_OK = 0x0, /* Completed successfully */
19203 + MC_CMD_STATUS_READY = 0x1, /* Ready to be processed */
19204 + MC_CMD_STATUS_AUTH_ERR = 0x3, /* Authentication error */
19205 + MC_CMD_STATUS_NO_PRIVILEGE = 0x4, /* No privilege */
19206 + MC_CMD_STATUS_DMA_ERR = 0x5, /* DMA or I/O error */
19207 + MC_CMD_STATUS_CONFIG_ERR = 0x6, /* Configuration error */
19208 + MC_CMD_STATUS_TIMEOUT = 0x7, /* Operation timed out */
19209 + MC_CMD_STATUS_NO_RESOURCE = 0x8, /* No resources */
19210 + MC_CMD_STATUS_NO_MEMORY = 0x9, /* No memory available */
19211 + MC_CMD_STATUS_BUSY = 0xA, /* Device is busy */
19212 + MC_CMD_STATUS_UNSUPPORTED_OP = 0xB, /* Unsupported operation */
19213 + MC_CMD_STATUS_INVALID_STATE = 0xC /* Invalid state */
19214 +};
19215 +
19216 +/*
19217 + * MC command flags
19218 + */
19219 +
19220 +/* High priority flag */
19221 +#define MC_CMD_FLAG_PRI 0x80
19222 +/* Command completion flag */
19223 +#define MC_CMD_FLAG_INTR_DIS 0x01
19224 +
19225 +static inline u64 mc_encode_cmd_header(u16 cmd_id,
19226 + u32 cmd_flags,
19227 + u16 token)
19228 +{
19229 + u64 header = 0;
19230 + struct mc_cmd_header *hdr = (struct mc_cmd_header *)&header;
19231 +
19232 + hdr->cmd_id = cpu_to_le16(cmd_id);
19233 + hdr->token = cpu_to_le16(token);
19234 + hdr->status = MC_CMD_STATUS_READY;
19235 + if (cmd_flags & MC_CMD_FLAG_PRI)
19236 + hdr->flags_hw = MC_CMD_FLAG_PRI;
19237 + if (cmd_flags & MC_CMD_FLAG_INTR_DIS)
19238 + hdr->flags_sw = MC_CMD_FLAG_INTR_DIS;
19239 +
19240 + return header;
19241 +}
19242 +
19243 +static inline u16 mc_cmd_hdr_read_token(struct fsl_mc_command *cmd)
19244 +{
19245 + struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
19246 + u16 token = le16_to_cpu(hdr->token);
19247 +
19248 + return token;
19249 +}
19250 +
19251 +struct mc_rsp_create {
19252 + __le32 object_id;
19253 +};
19254 +
19255 +struct mc_rsp_api_ver {
19256 + __le16 major_ver;
19257 + __le16 minor_ver;
19258 +};
19259 +
19260 +static inline u32 mc_cmd_read_object_id(struct fsl_mc_command *cmd)
19261 +{
19262 + struct mc_rsp_create *rsp_params;
19263 +
19264 + rsp_params = (struct mc_rsp_create *)cmd->params;
19265 + return le32_to_cpu(rsp_params->object_id);
19266 +}
19267 +
19268 +static inline void mc_cmd_read_api_version(struct fsl_mc_command *cmd,
19269 + u16 *major_ver,
19270 + u16 *minor_ver)
19271 +{
19272 + struct mc_rsp_api_ver *rsp_params;
19273 +
19274 + rsp_params = (struct mc_rsp_api_ver *)cmd->params;
19275 + *major_ver = le16_to_cpu(rsp_params->major_ver);
19276 + *minor_ver = le16_to_cpu(rsp_params->minor_ver);
19277 +}
19278 +
19279 +/**
19280 + * Bit masks for a MC I/O object (struct fsl_mc_io) flags
19281 + */
19282 +#define FSL_MC_IO_ATOMIC_CONTEXT_PORTAL 0x0001
19283 +
19284 +/**
19285 + * struct fsl_mc_io - MC I/O object to be passed-in to mc_send_command()
19286 + * @dev: device associated with this Mc I/O object
19287 + * @flags: flags for mc_send_command()
19288 + * @portal_size: MC command portal size in bytes
19289 + * @portal_phys_addr: MC command portal physical address
19290 + * @portal_virt_addr: MC command portal virtual address
19291 + * @dpmcp_dev: pointer to the DPMCP device associated with the MC portal.
19292 + *
19293 + * Fields are only meaningful if the FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is not
19294 + * set:
19295 + * @mutex: Mutex to serialize mc_send_command() calls that use the same MC
19296 + * portal, if the fsl_mc_io object was created with the
19297 + * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag off. mc_send_command() calls for this
19298 + * fsl_mc_io object must be made only from non-atomic context.
19299 + *
19300 + * Fields are only meaningful if the FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is
19301 + * set:
19302 + * @spinlock: Spinlock to serialize mc_send_command() calls that use the same MC
19303 + * portal, if the fsl_mc_io object was created with the
19304 + * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag on. mc_send_command() calls for this
19305 + * fsl_mc_io object can be made from atomic or non-atomic context.
19306 + */
19307 +struct fsl_mc_io {
19308 + struct device *dev;
19309 + u16 flags;
19310 + u32 portal_size;
19311 + phys_addr_t portal_phys_addr;
19312 + void __iomem *portal_virt_addr;
19313 + struct fsl_mc_device *dpmcp_dev;
19314 + union {
19315 + /*
19316 + * This field is only meaningful if the
19317 + * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is not set
19318 + */
19319 + struct mutex mutex; /* serializes mc_send_command() */
19320 +
19321 + /*
19322 + * This field is only meaningful if the
19323 + * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is set
19324 + */
19325 + spinlock_t spinlock; /* serializes mc_send_command() */
19326 + };
19327 +};
19328 +
19329 +int mc_send_command(struct fsl_mc_io *mc_io, struct fsl_mc_command *cmd);
19330 +
19331 +#ifdef CONFIG_FSL_MC_BUS
19332 +#define dev_is_fsl_mc(_dev) ((_dev)->bus == &fsl_mc_bus_type)
19333 +#else
19334 +/* If fsl-mc bus is not present device cannot belong to fsl-mc bus */
19335 +#define dev_is_fsl_mc(_dev) (0)
19336 +#endif
19337 +
19338 +/* Macro to check if a device is a container device */
19339 +#define fsl_mc_is_cont_dev(_dev) (to_fsl_mc_device(_dev)->flags & \
19340 + FSL_MC_IS_DPRC)
19341 +
19342 +/* Macro to get the container device of a MC device */
19343 +#define fsl_mc_cont_dev(_dev) (fsl_mc_is_cont_dev(_dev) ? \
19344 + (_dev) : (_dev)->parent)
19345 +
19346 +#define fsl_mc_is_dev_coherent(_dev) \
19347 + (!((to_fsl_mc_device(_dev))->obj_desc.flags & \
19348 + FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY))
19349 +
19350 +/*
19351 + * module_fsl_mc_driver() - Helper macro for drivers that don't do
19352 + * anything special in module init/exit. This eliminates a lot of
19353 + * boilerplate. Each module may only use this macro once, and
19354 + * calling it replaces module_init() and module_exit()
19355 + */
19356 +#define module_fsl_mc_driver(__fsl_mc_driver) \
19357 + module_driver(__fsl_mc_driver, fsl_mc_driver_register, \
19358 + fsl_mc_driver_unregister)
19359 +
19360 +void fsl_mc_device_remove(struct fsl_mc_device *mc_dev);
19361 +
19362 +/*
19363 + * Macro to avoid include chaining to get THIS_MODULE
19364 + */
19365 +#define fsl_mc_driver_register(drv) \
19366 + __fsl_mc_driver_register(drv, THIS_MODULE)
19367 +
19368 +int __must_check __fsl_mc_driver_register(struct fsl_mc_driver *fsl_mc_driver,
19369 + struct module *owner);
19370 +
19371 +void fsl_mc_driver_unregister(struct fsl_mc_driver *driver);
19372 +
19373 +int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
19374 + u16 mc_io_flags,
19375 + struct fsl_mc_io **new_mc_io);
19376 +
19377 +void fsl_mc_portal_free(struct fsl_mc_io *mc_io);
19378 +
19379 +int fsl_mc_portal_reset(struct fsl_mc_io *mc_io);
19380 +
19381 +int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
19382 + enum fsl_mc_pool_type pool_type,
19383 + struct fsl_mc_device **new_mc_adev);
19384 +
19385 +void fsl_mc_object_free(struct fsl_mc_device *mc_adev);
19386 +
19387 +struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode,
19388 + struct msi_domain_info *info,
19389 + struct irq_domain *parent);
19390 +
19391 +int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev);
19392 +
19393 +void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev);
19394 +
19395 +void fsl_mc_dma_configure(struct fsl_mc_device *mc_dev,
19396 + struct device_node *fsl_mc_platform_node, int coherent);
19397 +
19398 +extern struct bus_type fsl_mc_bus_type;
19399 +
19400 +extern struct device_type fsl_mc_bus_dprc_type;
19401 +extern struct device_type fsl_mc_bus_dpni_type;
19402 +extern struct device_type fsl_mc_bus_dpio_type;
19403 +extern struct device_type fsl_mc_bus_dpsw_type;
19404 +extern struct device_type fsl_mc_bus_dpdmux_type;
19405 +extern struct device_type fsl_mc_bus_dpbp_type;
19406 +extern struct device_type fsl_mc_bus_dpcon_type;
19407 +extern struct device_type fsl_mc_bus_dpmcp_type;
19408 +extern struct device_type fsl_mc_bus_dpmac_type;
19409 +extern struct device_type fsl_mc_bus_dprtc_type;
19410 +extern struct device_type fsl_mc_bus_dpseci_type;
19411 +extern struct device_type fsl_mc_bus_dpdcei_type;
19412 +extern struct device_type fsl_mc_bus_dpaiop_type;
19413 +extern struct device_type fsl_mc_bus_dpci_type;
19414 +extern struct device_type fsl_mc_bus_dpdmai_type;
19415 +
19416 +static inline bool is_fsl_mc_bus_dprc(const struct fsl_mc_device *mc_dev)
19417 +{
19418 + return mc_dev->dev.type == &fsl_mc_bus_dprc_type;
19419 +}
19420 +
19421 +static inline bool is_fsl_mc_bus_dpni(const struct fsl_mc_device *mc_dev)
19422 +{
19423 + return mc_dev->dev.type == &fsl_mc_bus_dpni_type;
19424 +}
19425 +
19426 +static inline bool is_fsl_mc_bus_dpio(const struct fsl_mc_device *mc_dev)
19427 +{
19428 + return mc_dev->dev.type == &fsl_mc_bus_dpio_type;
19429 +}
19430 +
19431 +static inline bool is_fsl_mc_bus_dpsw(const struct fsl_mc_device *mc_dev)
19432 +{
19433 + return mc_dev->dev.type == &fsl_mc_bus_dpsw_type;
19434 +}
19435 +
19436 +static inline bool is_fsl_mc_bus_dpdmux(const struct fsl_mc_device *mc_dev)
19437 +{
19438 + return mc_dev->dev.type == &fsl_mc_bus_dpdmux_type;
19439 +}
19440 +
19441 +static inline bool is_fsl_mc_bus_dpbp(const struct fsl_mc_device *mc_dev)
19442 +{
19443 + return mc_dev->dev.type == &fsl_mc_bus_dpbp_type;
19444 +}
19445 +
19446 +static inline bool is_fsl_mc_bus_dpcon(const struct fsl_mc_device *mc_dev)
19447 +{
19448 + return mc_dev->dev.type == &fsl_mc_bus_dpcon_type;
19449 +}
19450 +
19451 +static inline bool is_fsl_mc_bus_dpmcp(const struct fsl_mc_device *mc_dev)
19452 +{
19453 + return mc_dev->dev.type == &fsl_mc_bus_dpmcp_type;
19454 +}
19455 +
19456 +static inline bool is_fsl_mc_bus_dpmac(const struct fsl_mc_device *mc_dev)
19457 +{
19458 + return mc_dev->dev.type == &fsl_mc_bus_dpmac_type;
19459 +}
19460 +
19461 +static inline bool is_fsl_mc_bus_dprtc(const struct fsl_mc_device *mc_dev)
19462 +{
19463 + return mc_dev->dev.type == &fsl_mc_bus_dprtc_type;
19464 +}
19465 +
19466 +static inline bool is_fsl_mc_bus_dpseci(const struct fsl_mc_device *mc_dev)
19467 +{
19468 + return mc_dev->dev.type == &fsl_mc_bus_dpseci_type;
19469 +}
19470 +
19471 +static inline bool is_fsl_mc_bus_dpdcei(const struct fsl_mc_device *mc_dev)
19472 +{
19473 + return mc_dev->dev.type == &fsl_mc_bus_dpdcei_type;
19474 +}
19475 +
19476 +static inline bool is_fsl_mc_bus_dpaiop(const struct fsl_mc_device *mc_dev)
19477 +{
19478 + return mc_dev->dev.type == &fsl_mc_bus_dpaiop_type;
19479 +}
19480 +
19481 +static inline bool is_fsl_mc_bus_dpci(const struct fsl_mc_device *mc_dev)
19482 +{
19483 + return mc_dev->dev.type == &fsl_mc_bus_dpci_type;
19484 +}
19485 +
19486 +static inline bool is_fsl_mc_bus_dpdmai(const struct fsl_mc_device *mc_dev)
19487 +{
19488 + return mc_dev->dev.type == &fsl_mc_bus_dpdmai_type;
19489 +}
19490 +
19491 +/*
19492 + * Data Path Resource Container (DPRC) API
19493 + */
19494 +
19495 +/* Minimal supported DPRC Version */
19496 +#define DPRC_MIN_VER_MAJOR 6
19497 +#define DPRC_MIN_VER_MINOR 0
19498 +
19499 +/* DPRC command versioning */
19500 +#define DPRC_CMD_BASE_VERSION 1
19501 +#define DPRC_CMD_ID_OFFSET 4
19502 +
19503 +#define DPRC_CMD(id) (((id) << DPRC_CMD_ID_OFFSET) | DPRC_CMD_BASE_VERSION)
19504 +
19505 +/* DPRC command IDs */
19506 +#define DPRC_CMDID_CLOSE DPRC_CMD(0x800)
19507 +#define DPRC_CMDID_OPEN DPRC_CMD(0x805)
19508 +#define DPRC_CMDID_GET_API_VERSION DPRC_CMD(0xa05)
19509 +
19510 +#define DPRC_CMDID_GET_ATTR DPRC_CMD(0x004)
19511 +#define DPRC_CMDID_RESET_CONT DPRC_CMD(0x005)
19512 +
19513 +#define DPRC_CMDID_SET_IRQ DPRC_CMD(0x010)
19514 +#define DPRC_CMDID_SET_IRQ_ENABLE DPRC_CMD(0x012)
19515 +#define DPRC_CMDID_SET_IRQ_MASK DPRC_CMD(0x014)
19516 +#define DPRC_CMDID_GET_IRQ_STATUS DPRC_CMD(0x016)
19517 +#define DPRC_CMDID_CLEAR_IRQ_STATUS DPRC_CMD(0x017)
19518 +
19519 +#define DPRC_CMDID_GET_CONT_ID DPRC_CMD(0x830)
19520 +#define DPRC_CMDID_GET_OBJ_COUNT DPRC_CMD(0x159)
19521 +#define DPRC_CMDID_GET_OBJ DPRC_CMD(0x15A)
19522 +#define DPRC_CMDID_GET_OBJ_REG DPRC_CMD(0x15E)
19523 +#define DPRC_CMDID_SET_OBJ_IRQ DPRC_CMD(0x15F)
19524 +
19525 +struct dprc_cmd_open {
19526 + __le32 container_id;
19527 +};
19528 +
19529 +struct dprc_cmd_reset_container {
19530 + __le32 child_container_id;
19531 +};
19532 +
19533 +struct dprc_cmd_set_irq {
19534 + /* cmd word 0 */
19535 + __le32 irq_val;
19536 + u8 irq_index;
19537 + u8 pad[3];
19538 + /* cmd word 1 */
19539 + __le64 irq_addr;
19540 + /* cmd word 2 */
19541 + __le32 irq_num;
19542 +};
19543 +
19544 +#define DPRC_ENABLE 0x1
19545 +
19546 +struct dprc_cmd_set_irq_enable {
19547 + u8 enable;
19548 + u8 pad[3];
19549 + u8 irq_index;
19550 +};
19551 +
19552 +struct dprc_cmd_set_irq_mask {
19553 + __le32 mask;
19554 + u8 irq_index;
19555 +};
19556 +
19557 +struct dprc_cmd_get_irq_status {
19558 + __le32 status;
19559 + u8 irq_index;
19560 +};
19561 +
19562 +struct dprc_rsp_get_irq_status {
19563 + __le32 status;
19564 +};
19565 +
19566 +struct dprc_cmd_clear_irq_status {
19567 + __le32 status;
19568 + u8 irq_index;
19569 +};
19570 +
19571 +struct dprc_rsp_get_attributes {
19572 + /* response word 0 */
19573 + __le32 container_id;
19574 + __le32 icid;
19575 + /* response word 1 */
19576 + __le32 options;
19577 + __le32 portal_id;
19578 +};
19579 +
19580 +struct dprc_rsp_get_obj_count {
19581 + __le32 pad;
19582 + __le32 obj_count;
19583 +};
19584 +
19585 +struct dprc_cmd_get_obj {
19586 + __le32 obj_index;
19587 +};
19588 +
19589 +struct dprc_rsp_get_obj {
19590 + /* response word 0 */
19591 + __le32 pad0;
19592 + __le32 id;
19593 + /* response word 1 */
19594 + __le16 vendor;
19595 + u8 irq_count;
19596 + u8 region_count;
19597 + __le32 state;
19598 + /* response word 2 */
19599 + __le16 version_major;
19600 + __le16 version_minor;
19601 + __le16 flags;
19602 + __le16 pad1;
19603 + /* response word 3-4 */
19604 + u8 type[16];
19605 + /* response word 5-6 */
19606 + u8 label[16];
19607 +};
19608 +
19609 +struct dprc_cmd_get_obj_region {
19610 + /* cmd word 0 */
19611 + __le32 obj_id;
19612 + __le16 pad0;
19613 + u8 region_index;
19614 + u8 pad1;
19615 + /* cmd word 1-2 */
19616 + __le64 pad2[2];
19617 + /* cmd word 3-4 */
19618 + u8 obj_type[16];
19619 +};
19620 +
19621 +struct dprc_rsp_get_obj_region {
19622 + /* response word 0 */
19623 + __le64 pad0;
19624 + /* response word 1 */
19625 + __le32 base_addr;
19626 + __le32 pad1;
19627 + /* response word 2 */
19628 + __le32 size;
19629 + u8 type;
19630 + u8 pad2[3];
19631 + /* response word 3 */
19632 + __le32 flags;
19633 +};
19634 +
19635 +struct dprc_cmd_set_obj_irq {
19636 + /* cmd word 0 */
19637 + __le32 irq_val;
19638 + u8 irq_index;
19639 + u8 pad[3];
19640 + /* cmd word 1 */
19641 + __le64 irq_addr;
19642 + /* cmd word 2 */
19643 + __le32 irq_num;
19644 + __le32 obj_id;
19645 + /* cmd word 3-4 */
19646 + u8 obj_type[16];
19647 +};
19648 +
19649 +/*
19650 + * DPRC API for managing and querying DPAA resources
19651 + */
19652 +int dprc_open(struct fsl_mc_io *mc_io,
19653 + u32 cmd_flags,
19654 + int container_id,
19655 + u16 *token);
19656 +
19657 +int dprc_close(struct fsl_mc_io *mc_io,
19658 + u32 cmd_flags,
19659 + u16 token);
19660 +
19661 +/* DPRC IRQ events */
19662 +
19663 +/* IRQ event - Indicates that a new object added to the container */
19664 +#define DPRC_IRQ_EVENT_OBJ_ADDED 0x00000001
19665 +/* IRQ event - Indicates that an object was removed from the container */
19666 +#define DPRC_IRQ_EVENT_OBJ_REMOVED 0x00000002
19667 +/*
19668 + * IRQ event - Indicates that one of the descendant containers that opened by
19669 + * this container is destroyed
19670 + */
19671 +#define DPRC_IRQ_EVENT_CONTAINER_DESTROYED 0x00000010
19672 +
19673 +/*
19674 + * IRQ event - Indicates that on one of the container's opened object is
19675 + * destroyed
19676 + */
19677 +#define DPRC_IRQ_EVENT_OBJ_DESTROYED 0x00000020
19678 +
19679 +/* Irq event - Indicates that object is created at the container */
19680 +#define DPRC_IRQ_EVENT_OBJ_CREATED 0x00000040
19681 +
19682 +/**
19683 + * struct dprc_irq_cfg - IRQ configuration
19684 + * @paddr: Address that must be written to signal a message-based interrupt
19685 + * @val: Value to write into irq_addr address
19686 + * @irq_num: A user defined number associated with this IRQ
19687 + */
19688 +struct dprc_irq_cfg {
19689 + phys_addr_t paddr;
19690 + u32 val;
19691 + int irq_num;
19692 +};
19693 +
19694 +int dprc_set_irq(struct fsl_mc_io *mc_io,
19695 + u32 cmd_flags,
19696 + u16 token,
19697 + u8 irq_index,
19698 + struct dprc_irq_cfg *irq_cfg);
19699 +
19700 +int dprc_set_irq_enable(struct fsl_mc_io *mc_io,
19701 + u32 cmd_flags,
19702 + u16 token,
19703 + u8 irq_index,
19704 + u8 en);
19705 +
19706 +int dprc_set_irq_mask(struct fsl_mc_io *mc_io,
19707 + u32 cmd_flags,
19708 + u16 token,
19709 + u8 irq_index,
19710 + u32 mask);
19711 +
19712 +int dprc_get_irq_status(struct fsl_mc_io *mc_io,
19713 + u32 cmd_flags,
19714 + u16 token,
19715 + u8 irq_index,
19716 + u32 *status);
19717 +
19718 +int dprc_clear_irq_status(struct fsl_mc_io *mc_io,
19719 + u32 cmd_flags,
19720 + u16 token,
19721 + u8 irq_index,
19722 + u32 status);
19723 +
19724 +/**
19725 + * struct dprc_attributes - Container attributes
19726 + * @container_id: Container's ID
19727 + * @icid: Container's ICID
19728 + * @portal_id: Container's portal ID
19729 + * @options: Container's options as set at container's creation
19730 + */
19731 +struct dprc_attributes {
19732 + int container_id;
19733 + u32 icid;
19734 + int portal_id;
19735 + u64 options;
19736 +};
19737 +
19738 +int dprc_get_attributes(struct fsl_mc_io *mc_io,
19739 + u32 cmd_flags,
19740 + u16 token,
19741 + struct dprc_attributes *attributes);
19742 +
19743 +int dprc_get_obj_count(struct fsl_mc_io *mc_io,
19744 + u32 cmd_flags,
19745 + u16 token,
19746 + int *obj_count);
19747 +
19748 +int dprc_get_obj(struct fsl_mc_io *mc_io,
19749 + u32 cmd_flags,
19750 + u16 token,
19751 + int obj_index,
19752 + struct fsl_mc_obj_desc *obj_desc);
19753 +
19754 +int dprc_set_obj_irq(struct fsl_mc_io *mc_io,
19755 + u32 cmd_flags,
19756 + u16 token,
19757 + char *obj_type,
19758 + int obj_id,
19759 + u8 irq_index,
19760 + struct dprc_irq_cfg *irq_cfg);
19761 +
19762 +/* Region flags */
19763 +/* Cacheable - Indicates that region should be mapped as cacheable */
19764 +#define DPRC_REGION_CACHEABLE 0x00000001
19765 +
19766 +/**
19767 + * enum dprc_region_type - Region type
19768 + * @DPRC_REGION_TYPE_MC_PORTAL: MC portal region
19769 + * @DPRC_REGION_TYPE_QBMAN_PORTAL: Qbman portal region
19770 + */
19771 +enum dprc_region_type {
19772 + DPRC_REGION_TYPE_MC_PORTAL,
19773 + DPRC_REGION_TYPE_QBMAN_PORTAL
19774 +};
19775 +
19776 +#define DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY 0x0001
19777 +
19778 +/**
19779 + * struct dprc_region_desc - Mappable region descriptor
19780 + * @base_offset: Region offset from region's base address.
19781 + * For DPMCP and DPRC objects, region base is offset from SoC MC portals
19782 + * base address; For DPIO, region base is offset from SoC QMan portals
19783 + * base address
19784 + * @size: Region size (in bytes)
19785 + * @flags: Region attributes
19786 + * @type: Portal region type
19787 + */
19788 +struct dprc_region_desc {
19789 + u32 base_offset;
19790 + u32 size;
19791 + u32 flags;
19792 + enum dprc_region_type type;
19793 +};
19794 +
19795 +int dprc_get_obj_region(struct fsl_mc_io *mc_io,
19796 + u32 cmd_flags,
19797 + u16 token,
19798 + char *obj_type,
19799 + int obj_id,
19800 + u8 region_index,
19801 + struct dprc_region_desc *region_desc);
19802 +
19803 +int dprc_get_api_version(struct fsl_mc_io *mc_io,
19804 + u32 cmd_flags,
19805 + u16 *major_ver,
19806 + u16 *minor_ver);
19807 +
19808 +int dprc_get_container_id(struct fsl_mc_io *mc_io,
19809 + u32 cmd_flags,
19810 + int *container_id);
19811 +
19812 +int dprc_reset_container(struct fsl_mc_io *mc_io,
19813 + u32 cmd_flags,
19814 + u16 token,
19815 + int child_container_id);
19816 +
19817 +/*
19818 + * Data Path Buffer Pool (DPBP) API
19819 + * Contains initialization APIs and runtime control APIs for DPBP
19820 + */
19821 +
19822 +int dpbp_open(struct fsl_mc_io *mc_io,
19823 + u32 cmd_flags,
19824 + int dpbp_id,
19825 + u16 *token);
19826 +
19827 +int dpbp_close(struct fsl_mc_io *mc_io,
19828 + u32 cmd_flags,
19829 + u16 token);
19830 +
19831 +int dpbp_enable(struct fsl_mc_io *mc_io,
19832 + u32 cmd_flags,
19833 + u16 token);
19834 +
19835 +int dpbp_disable(struct fsl_mc_io *mc_io,
19836 + u32 cmd_flags,
19837 + u16 token);
19838 +
19839 +int dpbp_reset(struct fsl_mc_io *mc_io,
19840 + u32 cmd_flags,
19841 + u16 token);
19842 +
19843 +/**
19844 + * struct dpbp_attr - Structure representing DPBP attributes
19845 + * @id: DPBP object ID
19846 + * @bpid: Hardware buffer pool ID; should be used as an argument in
19847 + * acquire/release operations on buffers
19848 + */
19849 +struct dpbp_attr {
19850 + int id;
19851 + u16 bpid;
19852 +};
19853 +
19854 +int dpbp_get_attributes(struct fsl_mc_io *mc_io,
19855 + u32 cmd_flags,
19856 + u16 token,
19857 + struct dpbp_attr *attr);
19858 +
19859 +/* Data Path Concentrator (DPCON) API
19860 + * Contains initialization APIs and runtime control APIs for DPCON
19861 + */
19862 +
19863 +/**
19864 + * Use it to disable notifications; see dpcon_set_notification()
19865 + */
19866 +#define DPCON_INVALID_DPIO_ID (int)(-1)
19867 +
19868 +int dpcon_open(struct fsl_mc_io *mc_io,
19869 + u32 cmd_flags,
19870 + int dpcon_id,
19871 + u16 *token);
19872 +
19873 +int dpcon_close(struct fsl_mc_io *mc_io,
19874 + u32 cmd_flags,
19875 + u16 token);
19876 +
19877 +int dpcon_enable(struct fsl_mc_io *mc_io,
19878 + u32 cmd_flags,
19879 + u16 token);
19880 +
19881 +int dpcon_disable(struct fsl_mc_io *mc_io,
19882 + u32 cmd_flags,
19883 + u16 token);
19884 +
19885 +int dpcon_reset(struct fsl_mc_io *mc_io,
19886 + u32 cmd_flags,
19887 + u16 token);
19888 +
19889 +/**
19890 + * struct dpcon_attr - Structure representing DPCON attributes
19891 + * @id: DPCON object ID
19892 + * @qbman_ch_id: Channel ID to be used by dequeue operation
19893 + * @num_priorities: Number of priorities for the DPCON channel (1-8)
19894 + */
19895 +struct dpcon_attr {
19896 + int id;
19897 + u16 qbman_ch_id;
19898 + u8 num_priorities;
19899 +};
19900 +
19901 +int dpcon_get_attributes(struct fsl_mc_io *mc_io,
19902 + u32 cmd_flags,
19903 + u16 token,
19904 + struct dpcon_attr *attr);
19905 +
19906 +/**
19907 + * struct dpcon_notification_cfg - Structure representing notification params
19908 + * @dpio_id: DPIO object ID; must be configured with a notification channel;
19909 + * to disable notifications set it to 'DPCON_INVALID_DPIO_ID';
19910 + * @priority: Priority selection within the DPIO channel; valid values
19911 + * are 0-7, depending on the number of priorities in that channel
19912 + * @user_ctx: User context value provided with each CDAN message
19913 + */
19914 +struct dpcon_notification_cfg {
19915 + int dpio_id;
19916 + u8 priority;
19917 + u64 user_ctx;
19918 +};
19919 +
19920 +int dpcon_set_notification(struct fsl_mc_io *mc_io,
19921 + u32 cmd_flags,
19922 + u16 token,
19923 + struct dpcon_notification_cfg *cfg);
19924 +
19925 +struct irq_domain;
19926 +struct msi_domain_info;
19927 +
19928 +/**
19929 + * Maximum number of total IRQs that can be pre-allocated for an MC bus'
19930 + * IRQ pool
19931 + */
19932 +#define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256
19933 +
19934 +/**
19935 + * struct fsl_mc_resource_pool - Pool of MC resources of a given
19936 + * type
19937 + * @type: type of resources in the pool
19938 + * @max_count: maximum number of resources in the pool
19939 + * @free_count: number of free resources in the pool
19940 + * @mutex: mutex to serialize access to the pool's free list
19941 + * @free_list: anchor node of list of free resources in the pool
19942 + * @mc_bus: pointer to the MC bus that owns this resource pool
19943 + */
19944 +struct fsl_mc_resource_pool {
19945 + enum fsl_mc_pool_type type;
19946 + int max_count;
19947 + int free_count;
19948 + struct mutex mutex; /* serializes access to free_list */
19949 + struct list_head free_list;
19950 + struct fsl_mc_bus *mc_bus;
19951 +};
19952 +
19953 +/**
19954 + * struct fsl_mc_restool - information associated with a restool device file
19955 + * @cdev: struct char device linked to the root dprc
19956 + * @dev: dev_t for the char device to be added
19957 + * @device: newly created device in /dev
19958 + * @mutex: mutex lock to serialize the open/release operations
19959 + * @local_instance_in_use: local MC I/O instance in use or not
19960 + * @dynamic_instance_count: number of dynamically created MC I/O instances
19961 + */
19962 +struct fsl_mc_restool {
19963 + struct cdev cdev;
19964 + dev_t dev;
19965 + struct device *device;
19966 + struct mutex mutex; /* serialize open/release operations */
19967 + bool local_instance_in_use;
19968 + u32 dynamic_instance_count;
19969 +};
19970 +
19971 +/**
19972 + * struct fsl_mc_bus - logical bus that corresponds to a physical DPRC
19973 + * @mc_dev: fsl-mc device for the bus device itself.
19974 + * @resource_pools: array of resource pools (one pool per resource type)
19975 + * for this MC bus. These resources represent allocatable entities
19976 + * from the physical DPRC.
19977 + * @irq_resources: Pointer to array of IRQ objects for the IRQ pool
19978 + * @scan_mutex: Serializes bus scanning
19979 + * @dprc_attr: DPRC attributes
19980 + * @restool_misc: struct that abstracts the interaction with userspace restool
19981 + */
19982 +struct fsl_mc_bus {
19983 + struct fsl_mc_device mc_dev;
19984 + struct fsl_mc_resource_pool resource_pools[FSL_MC_NUM_POOL_TYPES];
19985 + struct fsl_mc_device_irq *irq_resources;
19986 + struct mutex scan_mutex; /* serializes bus scanning */
19987 + struct dprc_attributes dprc_attr;
19988 + struct fsl_mc_restool restool_misc;
19989 +};
19990 +
19991 +int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
19992 + const char *driver_override,
19993 + unsigned int *total_irq_count);
19994 +
19995 +int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
19996 + struct irq_domain **mc_msi_domain);
19997 +
19998 +int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
19999 + unsigned int irq_count);
20000 +
20001 +void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus);
20002 +
20003 +void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev);
20004 +
20005 +void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev);
20006 +
20007 +void fsl_mc_get_root_dprc(struct device *dev, struct device **root_dprc_dev);
20008 +
20009 +#endif /* _FSL_MC_H_ */
20010 --- /dev/null
20011 +++ b/include/uapi/linux/fsl_mc.h
20012 @@ -0,0 +1,31 @@
20013 +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
20014 +/*
20015 + * Management Complex (MC) userspace public interface
20016 + *
20017 + * Copyright 2018 NXP
20018 + *
20019 + */
20020 +#ifndef _UAPI_FSL_MC_H_
20021 +#define _UAPI_FSL_MC_H_
20022 +
20023 +#define MC_CMD_NUM_OF_PARAMS 7
20024 +
20025 +/**
20026 + * struct fsl_mc_command - Management Complex (MC) command structure
20027 + * @header: MC command header
20028 + * @params: MC command parameters
20029 + *
20030 + * Used by RESTOOL_SEND_MC_COMMAND
20031 + */
20032 +struct fsl_mc_command {
20033 + __u64 header;
20034 + __u64 params[MC_CMD_NUM_OF_PARAMS];
20035 +};
20036 +
20037 +#define RESTOOL_IOCTL_TYPE 'R'
20038 +#define RESTOOL_IOCTL_SEQ 0xE0
20039 +
20040 +#define RESTOOL_SEND_MC_COMMAND \
20041 + _IOWR(RESTOOL_IOCTL_TYPE, RESTOOL_IOCTL_SEQ, struct fsl_mc_command)
20042 +
20043 +#endif /* _UAPI_FSL_MC_H_ */