diff options
Diffstat (limited to 'target/linux/layerscape/patches-4.9/704-fsl-mc-layerscape-support.patch')
-rw-r--r-- | target/linux/layerscape/patches-4.9/704-fsl-mc-layerscape-support.patch | 20043 |
1 files changed, 0 insertions, 20043 deletions
diff --git a/target/linux/layerscape/patches-4.9/704-fsl-mc-layerscape-support.patch b/target/linux/layerscape/patches-4.9/704-fsl-mc-layerscape-support.patch deleted file mode 100644 index 52c099203c..0000000000 --- a/target/linux/layerscape/patches-4.9/704-fsl-mc-layerscape-support.patch +++ /dev/null @@ -1,20043 +0,0 @@ -From ab7b47676f9334bb55f80e0ac096c7aa289810e2 Mon Sep 17 00:00:00 2001 -From: Yangbo Lu <yangbo.lu@nxp.com> -Date: Thu, 5 Jul 2018 16:44:34 +0800 -Subject: [PATCH 10/32] fsl-mc: layerscape support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This is an integrated patch for layerscape mc-bus support. - -Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com> -Signed-off-by: Bharat Bhushan <Bharat.Bhushan@nxp.com> -Signed-off-by: Arnd Bergmann <arnd@arndb.de> -Signed-off-by: Laurentiu Tudor <laurentiu.tudor@nxp.com> -Signed-off-by: Roy Pledge <roy.pledge@nxp.com> -Signed-off-by: Shiva Kerdel <shiva@exdev.nl> -Signed-off-by: Nipun Gupta <nipun.gupta@nxp.com> -Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com> -Signed-off-by: Horia Geantă <horia.geanta@nxp.com> -Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> ---- - Documentation/ABI/stable/sysfs-bus-fsl-mc | 13 + - Documentation/ioctl/ioctl-number.txt | 1 + - Documentation/networking/dpaa2/index.rst | 8 + - Documentation/networking/dpaa2/overview.rst | 408 +++++ - MAINTAINERS | 11 +- - drivers/bus/Kconfig | 3 + - drivers/bus/Makefile | 4 + - drivers/bus/fsl-mc/Kconfig | 23 + - drivers/bus/fsl-mc/Makefile | 22 + - drivers/bus/fsl-mc/dpbp.c | 186 +++ - drivers/bus/fsl-mc/dpcon.c | 222 +++ - drivers/bus/fsl-mc/dpmcp.c | 99 ++ - .../fsl-mc/bus => bus/fsl-mc}/dprc-driver.c | 180 ++- - drivers/bus/fsl-mc/dprc.c | 575 +++++++ - .../bus => bus/fsl-mc}/fsl-mc-allocator.c | 195 ++- - .../fsl-mc/bus => bus/fsl-mc}/fsl-mc-bus.c | 523 +++++-- - drivers/bus/fsl-mc/fsl-mc-iommu.c | 78 + - .../fsl-mc/bus => bus/fsl-mc}/fsl-mc-msi.c | 34 +- - drivers/bus/fsl-mc/fsl-mc-private.h | 223 +++ - drivers/bus/fsl-mc/fsl-mc-restool.c | 219 +++ - .../fsl-mc/bus => bus/fsl-mc}/mc-io.c | 80 +- - .../fsl-mc/bus => bus/fsl-mc}/mc-sys.c | 105 +- - drivers/irqchip/Kconfig | 6 + - drivers/irqchip/Makefile | 1 + - .../irq-gic-v3-its-fsl-mc-msi.c | 52 +- - drivers/staging/fsl-mc/Kconfig | 1 + - drivers/staging/fsl-mc/Makefile | 1 + - drivers/staging/fsl-mc/TODO | 18 - - drivers/staging/fsl-mc/bus/Kconfig | 37 +- - drivers/staging/fsl-mc/bus/Makefile | 17 +- - drivers/staging/fsl-mc/bus/dpbp.c | 691 -------- - drivers/staging/fsl-mc/bus/dpio/Makefile | 8 + - drivers/staging/fsl-mc/bus/dpio/dpio-cmd.h | 50 + - drivers/staging/fsl-mc/bus/dpio/dpio-driver.c | 278 ++++ - .../staging/fsl-mc/bus/dpio/dpio-service.c | 780 +++++++++ - drivers/staging/fsl-mc/bus/dpio/dpio.c | 221 +++ - drivers/staging/fsl-mc/bus/dpio/dpio.h | 87 ++ - .../staging/fsl-mc/bus/dpio/qbman-portal.c | 1164 ++++++++++++++ - .../staging/fsl-mc/bus/dpio/qbman-portal.h | 505 ++++++ - drivers/staging/fsl-mc/bus/dpmcp-cmd.h | 140 -- - drivers/staging/fsl-mc/bus/dpmcp.c | 504 ------ - drivers/staging/fsl-mc/bus/dpmcp.h | 159 -- - drivers/staging/fsl-mc/bus/dpmng-cmd.h | 58 - - drivers/staging/fsl-mc/bus/dpmng.c | 107 -- - drivers/staging/fsl-mc/bus/dprc-cmd.h | 465 ------ - drivers/staging/fsl-mc/bus/dprc.c | 1388 ----------------- - drivers/staging/fsl-mc/bus/fsl-mc-private.h | 52 - - drivers/staging/fsl-mc/include/dpaa2-fd.h | 681 ++++++++ - drivers/staging/fsl-mc/include/dpaa2-global.h | 177 +++ - drivers/staging/fsl-mc/include/dpaa2-io.h | 178 +++ - drivers/staging/fsl-mc/include/dpbp-cmd.h | 185 --- - drivers/staging/fsl-mc/include/dpbp.h | 220 --- - drivers/staging/fsl-mc/include/dpcon-cmd.h | 62 - - drivers/staging/fsl-mc/include/dpmng.h | 69 - - drivers/staging/fsl-mc/include/dpopr.h | 112 ++ - drivers/staging/fsl-mc/include/dprc.h | 544 ------- - drivers/staging/fsl-mc/include/mc-bus.h | 111 -- - drivers/staging/fsl-mc/include/mc-cmd.h | 108 -- - drivers/staging/fsl-mc/include/mc-sys.h | 98 -- - drivers/staging/fsl-mc/include/mc.h | 201 --- - include/linux/fsl/mc.h | 1025 ++++++++++++ - include/uapi/linux/fsl_mc.h | 31 + - 62 files changed, 8068 insertions(+), 5736 deletions(-) - create mode 100644 Documentation/ABI/stable/sysfs-bus-fsl-mc - create mode 100644 Documentation/networking/dpaa2/index.rst - create mode 100644 Documentation/networking/dpaa2/overview.rst - create mode 100644 drivers/bus/fsl-mc/Kconfig - create mode 100644 drivers/bus/fsl-mc/Makefile - create mode 100644 drivers/bus/fsl-mc/dpbp.c - create mode 100644 drivers/bus/fsl-mc/dpcon.c - create mode 100644 drivers/bus/fsl-mc/dpmcp.c - rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dprc-driver.c (84%) - create mode 100644 drivers/bus/fsl-mc/dprc.c - rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-allocator.c (71%) - rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-bus.c (64%) - create mode 100644 drivers/bus/fsl-mc/fsl-mc-iommu.c - rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-msi.c (89%) - create mode 100644 drivers/bus/fsl-mc/fsl-mc-private.h - create mode 100644 drivers/bus/fsl-mc/fsl-mc-restool.c - rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/mc-io.c (68%) - rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/mc-sys.c (66%) - rename drivers/{staging/fsl-mc/bus => irqchip}/irq-gic-v3-its-fsl-mc-msi.c (60%) - delete mode 100644 drivers/staging/fsl-mc/TODO - delete mode 100644 drivers/staging/fsl-mc/bus/dpbp.c - create mode 100644 drivers/staging/fsl-mc/bus/dpio/Makefile - create mode 100644 drivers/staging/fsl-mc/bus/dpio/dpio-cmd.h - create mode 100644 drivers/staging/fsl-mc/bus/dpio/dpio-driver.c - create mode 100644 drivers/staging/fsl-mc/bus/dpio/dpio-service.c - create mode 100644 drivers/staging/fsl-mc/bus/dpio/dpio.c - create mode 100644 drivers/staging/fsl-mc/bus/dpio/dpio.h - create mode 100644 drivers/staging/fsl-mc/bus/dpio/qbman-portal.c - create mode 100644 drivers/staging/fsl-mc/bus/dpio/qbman-portal.h - delete mode 100644 drivers/staging/fsl-mc/bus/dpmcp-cmd.h - delete mode 100644 drivers/staging/fsl-mc/bus/dpmcp.c - delete mode 100644 drivers/staging/fsl-mc/bus/dpmcp.h - delete mode 100644 drivers/staging/fsl-mc/bus/dpmng-cmd.h - delete mode 100644 drivers/staging/fsl-mc/bus/dpmng.c - delete mode 100644 drivers/staging/fsl-mc/bus/dprc-cmd.h - delete mode 100644 drivers/staging/fsl-mc/bus/dprc.c - delete mode 100644 drivers/staging/fsl-mc/bus/fsl-mc-private.h - create mode 100644 drivers/staging/fsl-mc/include/dpaa2-fd.h - create mode 100644 drivers/staging/fsl-mc/include/dpaa2-global.h - create mode 100644 drivers/staging/fsl-mc/include/dpaa2-io.h - delete mode 100644 drivers/staging/fsl-mc/include/dpbp-cmd.h - delete mode 100644 drivers/staging/fsl-mc/include/dpbp.h - delete mode 100644 drivers/staging/fsl-mc/include/dpcon-cmd.h - delete mode 100644 drivers/staging/fsl-mc/include/dpmng.h - create mode 100644 drivers/staging/fsl-mc/include/dpopr.h - delete mode 100644 drivers/staging/fsl-mc/include/dprc.h - delete mode 100644 drivers/staging/fsl-mc/include/mc-bus.h - delete mode 100644 drivers/staging/fsl-mc/include/mc-cmd.h - delete mode 100644 drivers/staging/fsl-mc/include/mc-sys.h - delete mode 100644 drivers/staging/fsl-mc/include/mc.h - create mode 100644 include/linux/fsl/mc.h - create mode 100644 include/uapi/linux/fsl_mc.h - ---- /dev/null -+++ b/Documentation/ABI/stable/sysfs-bus-fsl-mc -@@ -0,0 +1,13 @@ -+What: /sys/bus/fsl-mc/devices/dprc.*/rescan -+Date: March. 2018 -+KernelVersion: 4.16 -+Contact: Ioana Ciornei <ioana.ciornei@nxp.com> -+Description: Root dprc rescan attribute -+Users: Userspace drivers and management tools -+ -+What: /sys/bus/fsl-mc/rescan -+Date: March. 2018 -+KernelVersion: 4.16 -+Contact: Ioana Ciornei <ioana.ciornei@nxp.com> -+Description: Bus rescan attribute -+Users: Userspace drivers and management tools ---- a/Documentation/ioctl/ioctl-number.txt -+++ b/Documentation/ioctl/ioctl-number.txt -@@ -170,6 +170,7 @@ Code Seq#(hex) Include File Comments - 'R' 00-1F linux/random.h conflict! - 'R' 01 linux/rfkill.h conflict! - 'R' C0-DF net/bluetooth/rfcomm.h -+'R' E0 uapi/linux/fsl_mc.h - 'S' all linux/cdrom.h conflict! - 'S' 80-81 scsi/scsi_ioctl.h conflict! - 'S' 82-FF scsi/scsi.h conflict! ---- /dev/null -+++ b/Documentation/networking/dpaa2/index.rst -@@ -0,0 +1,8 @@ -+=================== -+DPAA2 Documentation -+=================== -+ -+.. toctree:: -+ :maxdepth: 1 -+ -+ overview ---- /dev/null -+++ b/Documentation/networking/dpaa2/overview.rst -@@ -0,0 +1,408 @@ -+.. include:: <isonum.txt> -+ -+DPAA2 (Data Path Acceleration Architecture Gen2) Overview -+========================================================= -+ -+:Copyright: |copy| 2015 Freescale Semiconductor Inc. -+:Copyright: |copy| 2018 NXP -+ -+This document provides an overview of the Freescale DPAA2 architecture -+and how it is integrated into the Linux kernel. -+ -+Introduction -+============ -+ -+DPAA2 is a hardware architecture designed for high-speeed network -+packet processing. DPAA2 consists of sophisticated mechanisms for -+processing Ethernet packets, queue management, buffer management, -+autonomous L2 switching, virtual Ethernet bridging, and accelerator -+(e.g. crypto) sharing. -+ -+A DPAA2 hardware component called the Management Complex (or MC) manages the -+DPAA2 hardware resources. The MC provides an object-based abstraction for -+software drivers to use the DPAA2 hardware. -+The MC uses DPAA2 hardware resources such as queues, buffer pools, and -+network ports to create functional objects/devices such as network -+interfaces, an L2 switch, or accelerator instances. -+The MC provides memory-mapped I/O command interfaces (MC portals) -+which DPAA2 software drivers use to operate on DPAA2 objects. -+ -+The diagram below shows an overview of the DPAA2 resource management -+architecture:: -+ -+ +--------------------------------------+ -+ | OS | -+ | DPAA2 drivers | -+ | | | -+ +-----------------------------|--------+ -+ | -+ | (create,discover,connect -+ | config,use,destroy) -+ | -+ DPAA2 | -+ +------------------------| mc portal |-+ -+ | | | -+ | +- - - - - - - - - - - - -V- - -+ | -+ | | | | -+ | | Management Complex (MC) | | -+ | | | | -+ | +- - - - - - - - - - - - - - - -+ | -+ | | -+ | Hardware Hardware | -+ | Resources Objects | -+ | --------- ------- | -+ | -queues -DPRC | -+ | -buffer pools -DPMCP | -+ | -Eth MACs/ports -DPIO | -+ | -network interface -DPNI | -+ | profiles -DPMAC | -+ | -queue portals -DPBP | -+ | -MC portals ... | -+ | ... | -+ | | -+ +--------------------------------------+ -+ -+ -+The MC mediates operations such as create, discover, -+connect, configuration, and destroy. Fast-path operations -+on data, such as packet transmit/receive, are not mediated by -+the MC and are done directly using memory mapped regions in -+DPIO objects. -+ -+Overview of DPAA2 Objects -+========================= -+ -+The section provides a brief overview of some key DPAA2 objects. -+A simple scenario is described illustrating the objects involved -+in creating a network interfaces. -+ -+DPRC (Datapath Resource Container) -+---------------------------------- -+ -+A DPRC is a container object that holds all the other -+types of DPAA2 objects. In the example diagram below there -+are 8 objects of 5 types (DPMCP, DPIO, DPBP, DPNI, and DPMAC) -+in the container. -+ -+:: -+ -+ +---------------------------------------------------------+ -+ | DPRC | -+ | | -+ | +-------+ +-------+ +-------+ +-------+ +-------+ | -+ | | DPMCP | | DPIO | | DPBP | | DPNI | | DPMAC | | -+ | +-------+ +-------+ +-------+ +---+---+ +---+---+ | -+ | | DPMCP | | DPIO | | -+ | +-------+ +-------+ | -+ | | DPMCP | | -+ | +-------+ | -+ | | -+ +---------------------------------------------------------+ -+ -+From the point of view of an OS, a DPRC behaves similar to a plug and -+play bus, like PCI. DPRC commands can be used to enumerate the contents -+of the DPRC, discover the hardware objects present (including mappable -+regions and interrupts). -+ -+:: -+ -+ DPRC.1 (bus) -+ | -+ +--+--------+-------+-------+-------+ -+ | | | | | -+ DPMCP.1 DPIO.1 DPBP.1 DPNI.1 DPMAC.1 -+ DPMCP.2 DPIO.2 -+ DPMCP.3 -+ -+Hardware objects can be created and destroyed dynamically, providing -+the ability to hot plug/unplug objects in and out of the DPRC. -+ -+A DPRC has a mappable MMIO region (an MC portal) that can be used -+to send MC commands. It has an interrupt for status events (like -+hotplug). -+All objects in a container share the same hardware "isolation context". -+This means that with respect to an IOMMU the isolation granularity -+is at the DPRC (container) level, not at the individual object -+level. -+ -+DPRCs can be defined statically and populated with objects -+via a config file passed to the MC when firmware starts it. -+There is also a Linux user space tool called "restool" that can be -+used to create/destroy containers and objects dynamically. The latest -+version of restool can be found at: -+ https://github.com/qoriq-open-source/restool -+ -+DPAA2 Objects for an Ethernet Network Interface -+----------------------------------------------- -+ -+A typical Ethernet NIC is monolithic-- the NIC device contains TX/RX -+queuing mechanisms, configuration mechanisms, buffer management, -+physical ports, and interrupts. DPAA2 uses a more granular approach -+utilizing multiple hardware objects. Each object provides specialized -+functions. Groups of these objects are used by software to provide -+Ethernet network interface functionality. This approach provides -+efficient use of finite hardware resources, flexibility, and -+performance advantages. -+ -+The diagram below shows the objects needed for a simple -+network interface configuration on a system with 2 CPUs. -+ -+:: -+ -+ +---+---+ +---+---+ -+ CPU0 CPU1 -+ +---+---+ +---+---+ -+ | | -+ +---+---+ +---+---+ -+ DPIO DPIO -+ +---+---+ +---+---+ -+ \ / -+ \ / -+ \ / -+ +---+---+ -+ DPNI --- DPBP,DPMCP -+ +---+---+ -+ | -+ | -+ +---+---+ -+ DPMAC -+ +---+---+ -+ | -+ port/PHY -+ -+Below the objects are described. For each object a brief description -+is provided along with a summary of the kinds of operations the object -+supports and a summary of key resources of the object (MMIO regions -+and IRQs). -+ -+DPMAC (Datapath Ethernet MAC) -+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -+Represents an Ethernet MAC, a hardware device that connects to an Ethernet -+PHY and allows physical transmission and reception of Ethernet frames. -+ -+- MMIO regions: none -+- IRQs: DPNI link change -+- commands: set link up/down, link config, get stats, -+ IRQ config, enable, reset -+ -+DPNI (Datapath Network Interface) -+Contains TX/RX queues, network interface configuration, and RX buffer pool -+configuration mechanisms. The TX/RX queues are in memory and are identified -+by queue number. -+ -+- MMIO regions: none -+- IRQs: link state -+- commands: port config, offload config, queue config, -+ parse/classify config, IRQ config, enable, reset -+ -+DPIO (Datapath I/O) -+~~~~~~~~~~~~~~~~~~~ -+Provides interfaces to enqueue and dequeue -+packets and do hardware buffer pool management operations. The DPAA2 -+architecture separates the mechanism to access queues (the DPIO object) -+from the queues themselves. The DPIO provides an MMIO interface to -+enqueue/dequeue packets. To enqueue something a descriptor is written -+to the DPIO MMIO region, which includes the target queue number. -+There will typically be one DPIO assigned to each CPU. This allows all -+CPUs to simultaneously perform enqueue/dequeued operations. DPIOs are -+expected to be shared by different DPAA2 drivers. -+ -+- MMIO regions: queue operations, buffer management -+- IRQs: data availability, congestion notification, buffer -+ pool depletion -+- commands: IRQ config, enable, reset -+ -+DPBP (Datapath Buffer Pool) -+~~~~~~~~~~~~~~~~~~~~~~~~~~~ -+Represents a hardware buffer pool. -+ -+- MMIO regions: none -+- IRQs: none -+- commands: enable, reset -+ -+DPMCP (Datapath MC Portal) -+~~~~~~~~~~~~~~~~~~~~~~~~~~ -+Provides an MC command portal. -+Used by drivers to send commands to the MC to manage -+objects. -+ -+- MMIO regions: MC command portal -+- IRQs: command completion -+- commands: IRQ config, enable, reset -+ -+Object Connections -+================== -+Some objects have explicit relationships that must -+be configured: -+ -+- DPNI <--> DPMAC -+- DPNI <--> DPNI -+- DPNI <--> L2-switch-port -+ -+ A DPNI must be connected to something such as a DPMAC, -+ another DPNI, or L2 switch port. The DPNI connection -+ is made via a DPRC command. -+ -+:: -+ -+ +-------+ +-------+ -+ | DPNI | | DPMAC | -+ +---+---+ +---+---+ -+ | | -+ +==========+ -+ -+- DPNI <--> DPBP -+ -+ A network interface requires a 'buffer pool' (DPBP -+ object) which provides a list of pointers to memory -+ where received Ethernet data is to be copied. The -+ Ethernet driver configures the DPBPs associated with -+ the network interface. -+ -+Interrupts -+========== -+All interrupts generated by DPAA2 objects are message -+interrupts. At the hardware level message interrupts -+generated by devices will normally have 3 components-- -+1) a non-spoofable 'device-id' expressed on the hardware -+bus, 2) an address, 3) a data value. -+ -+In the case of DPAA2 devices/objects, all objects in the -+same container/DPRC share the same 'device-id'. -+For ARM-based SoC this is the same as the stream ID. -+ -+ -+DPAA2 Linux Drivers Overview -+============================ -+ -+This section provides an overview of the Linux kernel drivers for -+DPAA2-- 1) the bus driver and associated "DPAA2 infrastructure" -+drivers and 2) functional object drivers (such as Ethernet). -+ -+As described previously, a DPRC is a container that holds the other -+types of DPAA2 objects. It is functionally similar to a plug-and-play -+bus controller. -+Each object in the DPRC is a Linux "device" and is bound to a driver. -+The diagram below shows the Linux drivers involved in a networking -+scenario and the objects bound to each driver. A brief description -+of each driver follows. -+ -+:: -+ -+ +------------+ -+ | OS Network | -+ | Stack | -+ +------------+ +------------+ -+ | Allocator |. . . . . . . | Ethernet | -+ |(DPMCP,DPBP)| | (DPNI) | -+ +-.----------+ +---+---+----+ -+ . . ^ | -+ . . <data avail, | | <enqueue, -+ . . tx confirm> | | dequeue> -+ +-------------+ . | | -+ | DPRC driver | . +---+---V----+ +---------+ -+ | (DPRC) | . . . . . .| DPIO driver| | MAC | -+ +----------+--+ | (DPIO) | | (DPMAC) | -+ | +------+-----+ +-----+---+ -+ |<dev add/remove> | | -+ | | | -+ +--------+----------+ | +--+---+ -+ | MC-bus driver | | | PHY | -+ | | | |driver| -+ | /bus/fsl-mc | | +--+---+ -+ +-------------------+ | | -+ | | -+ ========================= HARDWARE =========|=================|====== -+ DPIO | -+ | | -+ DPNI---DPBP | -+ | | -+ DPMAC | -+ | | -+ PHY ---------------+ -+ ============================================|======================== -+ -+A brief description of each driver is provided below. -+ -+MC-bus driver -+------------- -+The MC-bus driver is a platform driver and is probed from a -+node in the device tree (compatible "fsl,qoriq-mc") passed in by boot -+firmware. It is responsible for bootstrapping the DPAA2 kernel -+infrastructure. -+Key functions include: -+ -+- registering a new bus type named "fsl-mc" with the kernel, -+ and implementing bus call-backs (e.g. match/uevent/dev_groups) -+- implementing APIs for DPAA2 driver registration and for device -+ add/remove -+- creates an MSI IRQ domain -+- doing a 'device add' to expose the 'root' DPRC, in turn triggering -+ a bind of the root DPRC to the DPRC driver -+ -+The binding for the MC-bus device-tree node can be consulted at -+*Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt*. -+The sysfs bind/unbind interfaces for the MC-bus can be consulted at -+*Documentation/ABI/testing/sysfs-bus-fsl-mc*. -+ -+DPRC driver -+----------- -+The DPRC driver is bound to DPRC objects and does runtime management -+of a bus instance. It performs the initial bus scan of the DPRC -+and handles interrupts for container events such as hot plug by -+re-scanning the DPRC. -+ -+Allocator -+--------- -+Certain objects such as DPMCP and DPBP are generic and fungible, -+and are intended to be used by other drivers. For example, -+the DPAA2 Ethernet driver needs: -+ -+- DPMCPs to send MC commands, to configure network interfaces -+- DPBPs for network buffer pools -+ -+The allocator driver registers for these allocatable object types -+and those objects are bound to the allocator when the bus is probed. -+The allocator maintains a pool of objects that are available for -+allocation by other DPAA2 drivers. -+ -+DPIO driver -+----------- -+The DPIO driver is bound to DPIO objects and provides services that allow -+other drivers such as the Ethernet driver to enqueue and dequeue data for -+their respective objects. -+Key services include: -+ -+- data availability notifications -+- hardware queuing operations (enqueue and dequeue of data) -+- hardware buffer pool management -+ -+To transmit a packet the Ethernet driver puts data on a queue and -+invokes a DPIO API. For receive, the Ethernet driver registers -+a data availability notification callback. To dequeue a packet -+a DPIO API is used. -+There is typically one DPIO object per physical CPU for optimum -+performance, allowing different CPUs to simultaneously enqueue -+and dequeue data. -+ -+The DPIO driver operates on behalf of all DPAA2 drivers -+active in the kernel-- Ethernet, crypto, compression, -+etc. -+ -+Ethernet driver -+--------------- -+The Ethernet driver is bound to a DPNI and implements the kernel -+interfaces needed to connect the DPAA2 network interface to -+the network stack. -+Each DPNI corresponds to a Linux network interface. -+ -+MAC driver -+---------- -+An Ethernet PHY is an off-chip, board specific component and is managed -+by the appropriate PHY driver via an mdio bus. The MAC driver -+plays a role of being a proxy between the PHY driver and the -+MC. It does this proxy via the MC commands to a DPMAC object. -+If the PHY driver signals a link change, the MAC driver notifies -+the MC via a DPMAC command. If a network interface is brought -+up or down, the MC notifies the DPMAC driver via an interrupt and -+the driver can take appropriate action. ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -3980,6 +3980,12 @@ S: Maintained - F: drivers/char/dtlk.c - F: include/linux/dtlk.h - -+DPAA2 DATAPATH I/O (DPIO) DRIVER -+M: Roy Pledge <Roy.Pledge@nxp.com> -+L: linux-kernel@vger.kernel.org -+S: Maintained -+F: drivers/staging/fsl-mc/bus/dpio -+ - DPT_I2O SCSI RAID DRIVER - M: Adaptec OEM Raid Solutions <aacraid@adaptec.com> - L: linux-scsi@vger.kernel.org -@@ -5110,7 +5116,10 @@ M: "J. German Rivera" <German.Rivera@fre - M: Stuart Yoder <stuart.yoder@nxp.com> - L: linux-kernel@vger.kernel.org - S: Maintained --F: drivers/staging/fsl-mc/ -+F: drivers/bus/fsl-mc/ -+F: Documentation/networking/dpaa2/overview.rst -+F: include/uapi/linux/fsl_mc.h -+F: Documentation/ABI/stable/sysfs-bus-fsl-mc - - FREEVXFS FILESYSTEM - M: Christoph Hellwig <hch@infradead.org> ---- a/drivers/bus/Kconfig -+++ b/drivers/bus/Kconfig -@@ -167,4 +167,7 @@ config VEXPRESS_CONFIG - help - Platform configuration infrastructure for the ARM Ltd. - Versatile Express. -+ -+source "drivers/bus/fsl-mc/Kconfig" -+ - endmenu ---- a/drivers/bus/Makefile -+++ b/drivers/bus/Makefile -@@ -7,6 +7,10 @@ obj-$(CONFIG_ARM_CCI) += arm-cci.o - obj-$(CONFIG_ARM_CCN) += arm-ccn.o - - obj-$(CONFIG_BRCMSTB_GISB_ARB) += brcmstb_gisb.o -+ -+# DPAA2 fsl-mc bus -+obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/ -+ - obj-$(CONFIG_IMX_WEIM) += imx-weim.o - obj-$(CONFIG_MIPS_CDMM) += mips_cdmm.o - obj-$(CONFIG_MVEBU_MBUS) += mvebu-mbus.o ---- /dev/null -+++ b/drivers/bus/fsl-mc/Kconfig -@@ -0,0 +1,23 @@ -+# SPDX-License-Identifier: GPL-2.0 -+# -+# DPAA2 fsl-mc bus -+# -+# Copyright (C) 2014-2016 Freescale Semiconductor, Inc. -+# -+ -+config FSL_MC_BUS -+ bool "QorIQ DPAA2 fsl-mc bus driver" -+ depends on OF && (ARCH_LAYERSCAPE || (COMPILE_TEST && (ARM || ARM64 || X86 || PPC))) -+ select GENERIC_MSI_IRQ_DOMAIN -+ help -+ Driver to enable the bus infrastructure for the QorIQ DPAA2 -+ architecture. The fsl-mc bus driver handles discovery of -+ DPAA2 objects (which are represented as Linux devices) and -+ binding objects to drivers. -+ -+config FSL_MC_RESTOOL -+ bool "Management Complex (MC) restool support" -+ depends on FSL_MC_BUS -+ help -+ Provides kernel support for the Management Complex resource -+ manager user-space tool - restool. ---- /dev/null -+++ b/drivers/bus/fsl-mc/Makefile -@@ -0,0 +1,22 @@ -+# SPDX-License-Identifier: GPL-2.0 -+# -+# Freescale Management Complex (MC) bus drivers -+# -+# Copyright (C) 2014 Freescale Semiconductor, Inc. -+# -+obj-$(CONFIG_FSL_MC_BUS) += mc-bus-driver.o -+ -+mc-bus-driver-objs := fsl-mc-bus.o \ -+ mc-sys.o \ -+ mc-io.o \ -+ dpbp.o \ -+ dpcon.o \ -+ dprc.o \ -+ dprc-driver.o \ -+ fsl-mc-allocator.o \ -+ fsl-mc-msi.o \ -+ dpmcp.o \ -+ fsl-mc-iommu.o -+ -+# MC restool kernel support -+obj-$(CONFIG_FSL_MC_RESTOOL) += fsl-mc-restool.o ---- /dev/null -+++ b/drivers/bus/fsl-mc/dpbp.c -@@ -0,0 +1,186 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright 2013-2016 Freescale Semiconductor Inc. -+ * -+ */ -+#include <linux/kernel.h> -+#include <linux/fsl/mc.h> -+#include <linux/fsl/mc.h> -+ -+#include "fsl-mc-private.h" -+ -+/** -+ * dpbp_open() - Open a control session for the specified object. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @dpbp_id: DPBP unique ID -+ * @token: Returned token; use in subsequent API calls -+ * -+ * This function can be used to open a control session for an -+ * already created object; an object may have been declared in -+ * the DPL or by calling the dpbp_create function. -+ * This function returns a unique authentication token, -+ * associated with the specific object ID and the specific MC -+ * portal; this token must be used in all subsequent commands for -+ * this specific object -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpbp_open(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ int dpbp_id, -+ u16 *token) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpbp_cmd_open *cmd_params; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPBP_CMDID_OPEN, -+ cmd_flags, 0); -+ cmd_params = (struct dpbp_cmd_open *)cmd.params; -+ cmd_params->dpbp_id = cpu_to_le32(dpbp_id); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ *token = mc_cmd_hdr_read_token(&cmd); -+ -+ return err; -+} -+EXPORT_SYMBOL_GPL(dpbp_open); -+ -+/** -+ * dpbp_close() - Close the control session of the object -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPBP object -+ * -+ * After this function is called, no further operations are -+ * allowed on the object without opening a new control session. -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpbp_close(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLOSE, cmd_flags, -+ token); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+EXPORT_SYMBOL_GPL(dpbp_close); -+ -+/** -+ * dpbp_enable() - Enable the DPBP. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPBP object -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpbp_enable(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPBP_CMDID_ENABLE, cmd_flags, -+ token); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+EXPORT_SYMBOL_GPL(dpbp_enable); -+ -+/** -+ * dpbp_disable() - Disable the DPBP. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPBP object -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpbp_disable(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPBP_CMDID_DISABLE, -+ cmd_flags, token); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+EXPORT_SYMBOL_GPL(dpbp_disable); -+ -+/** -+ * dpbp_reset() - Reset the DPBP, returns the object to initial state. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPBP object -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpbp_reset(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPBP_CMDID_RESET, -+ cmd_flags, token); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+EXPORT_SYMBOL_GPL(dpbp_reset); -+ -+/** -+ * dpbp_get_attributes - Retrieve DPBP attributes. -+ * -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPBP object -+ * @attr: Returned object's attributes -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpbp_get_attributes(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ struct dpbp_attr *attr) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpbp_rsp_get_attributes *rsp_params; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_ATTR, -+ cmd_flags, token); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ rsp_params = (struct dpbp_rsp_get_attributes *)cmd.params; -+ attr->bpid = le16_to_cpu(rsp_params->bpid); -+ attr->id = le32_to_cpu(rsp_params->id); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(dpbp_get_attributes); ---- /dev/null -+++ b/drivers/bus/fsl-mc/dpcon.c -@@ -0,0 +1,222 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright 2013-2016 Freescale Semiconductor Inc. -+ * -+ */ -+#include <linux/kernel.h> -+#include <linux/fsl/mc.h> -+#include <linux/fsl/mc.h> -+ -+#include "fsl-mc-private.h" -+ -+/** -+ * dpcon_open() - Open a control session for the specified object -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @dpcon_id: DPCON unique ID -+ * @token: Returned token; use in subsequent API calls -+ * -+ * This function can be used to open a control session for an -+ * already created object; an object may have been declared in -+ * the DPL or by calling the dpcon_create() function. -+ * This function returns a unique authentication token, -+ * associated with the specific object ID and the specific MC -+ * portal; this token must be used in all subsequent commands for -+ * this specific object. -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpcon_open(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ int dpcon_id, -+ u16 *token) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpcon_cmd_open *dpcon_cmd; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPCON_CMDID_OPEN, -+ cmd_flags, -+ 0); -+ dpcon_cmd = (struct dpcon_cmd_open *)cmd.params; -+ dpcon_cmd->dpcon_id = cpu_to_le32(dpcon_id); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ *token = mc_cmd_hdr_read_token(&cmd); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(dpcon_open); -+ -+/** -+ * dpcon_close() - Close the control session of the object -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPCON object -+ * -+ * After this function is called, no further operations are -+ * allowed on the object without opening a new control session. -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpcon_close(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPCON_CMDID_CLOSE, -+ cmd_flags, -+ token); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+EXPORT_SYMBOL_GPL(dpcon_close); -+ -+/** -+ * dpcon_enable() - Enable the DPCON -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPCON object -+ * -+ * Return: '0' on Success; Error code otherwise -+ */ -+int dpcon_enable(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPCON_CMDID_ENABLE, -+ cmd_flags, -+ token); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+EXPORT_SYMBOL_GPL(dpcon_enable); -+ -+/** -+ * dpcon_disable() - Disable the DPCON -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPCON object -+ * -+ * Return: '0' on Success; Error code otherwise -+ */ -+int dpcon_disable(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPCON_CMDID_DISABLE, -+ cmd_flags, -+ token); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+EXPORT_SYMBOL_GPL(dpcon_disable); -+ -+/** -+ * dpcon_reset() - Reset the DPCON, returns the object to initial state. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPCON object -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpcon_reset(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPCON_CMDID_RESET, -+ cmd_flags, token); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+EXPORT_SYMBOL_GPL(dpcon_reset); -+ -+/** -+ * dpcon_get_attributes() - Retrieve DPCON attributes. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPCON object -+ * @attr: Object's attributes -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpcon_get_attributes(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ struct dpcon_attr *attr) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpcon_rsp_get_attr *dpcon_rsp; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_ATTR, -+ cmd_flags, -+ token); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ dpcon_rsp = (struct dpcon_rsp_get_attr *)cmd.params; -+ attr->id = le32_to_cpu(dpcon_rsp->id); -+ attr->qbman_ch_id = le16_to_cpu(dpcon_rsp->qbman_ch_id); -+ attr->num_priorities = dpcon_rsp->num_priorities; -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(dpcon_get_attributes); -+ -+/** -+ * dpcon_set_notification() - Set DPCON notification destination -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPCON object -+ * @cfg: Notification parameters -+ * -+ * Return: '0' on Success; Error code otherwise -+ */ -+int dpcon_set_notification(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ struct dpcon_notification_cfg *cfg) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpcon_cmd_set_notification *dpcon_cmd; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPCON_CMDID_SET_NOTIFICATION, -+ cmd_flags, -+ token); -+ dpcon_cmd = (struct dpcon_cmd_set_notification *)cmd.params; -+ dpcon_cmd->dpio_id = cpu_to_le32(cfg->dpio_id); -+ dpcon_cmd->priority = cfg->priority; -+ dpcon_cmd->user_ctx = cpu_to_le64(cfg->user_ctx); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+EXPORT_SYMBOL_GPL(dpcon_set_notification); ---- /dev/null -+++ b/drivers/bus/fsl-mc/dpmcp.c -@@ -0,0 +1,99 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright 2013-2016 Freescale Semiconductor Inc. -+ * -+ */ -+#include <linux/kernel.h> -+#include <linux/fsl/mc.h> -+ -+#include "fsl-mc-private.h" -+ -+/** -+ * dpmcp_open() - Open a control session for the specified object. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @dpmcp_id: DPMCP unique ID -+ * @token: Returned token; use in subsequent API calls -+ * -+ * This function can be used to open a control session for an -+ * already created object; an object may have been declared in -+ * the DPL or by calling the dpmcp_create function. -+ * This function returns a unique authentication token, -+ * associated with the specific object ID and the specific MC -+ * portal; this token must be used in all subsequent commands for -+ * this specific object -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpmcp_open(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ int dpmcp_id, -+ u16 *token) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpmcp_cmd_open *cmd_params; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_OPEN, -+ cmd_flags, 0); -+ cmd_params = (struct dpmcp_cmd_open *)cmd.params; -+ cmd_params->dpmcp_id = cpu_to_le32(dpmcp_id); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ *token = mc_cmd_hdr_read_token(&cmd); -+ -+ return err; -+} -+ -+/** -+ * dpmcp_close() - Close the control session of the object -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPMCP object -+ * -+ * After this function is called, no further operations are -+ * allowed on the object without opening a new control session. -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpmcp_close(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CLOSE, -+ cmd_flags, token); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpmcp_reset() - Reset the DPMCP, returns the object to initial state. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPMCP object -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpmcp_reset(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_RESET, -+ cmd_flags, token); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} ---- a/drivers/staging/fsl-mc/bus/dprc-driver.c -+++ /dev/null -@@ -1,805 +0,0 @@ --/* -- * Freescale data path resource container (DPRC) driver -- * -- * Copyright (C) 2014 Freescale Semiconductor, Inc. -- * Author: German Rivera <German.Rivera@freescale.com> -- * -- * This file is licensed under the terms of the GNU General Public -- * License version 2. This program is licensed "as is" without any -- * warranty of any kind, whether express or implied. -- */ -- --#include <linux/module.h> --#include <linux/slab.h> --#include <linux/interrupt.h> --#include <linux/msi.h> --#include "../include/mc-bus.h" --#include "../include/mc-sys.h" -- --#include "dprc-cmd.h" --#include "fsl-mc-private.h" -- --#define FSL_MC_DPRC_DRIVER_NAME "fsl_mc_dprc" -- --#define FSL_MC_DEVICE_MATCH(_mc_dev, _obj_desc) \ -- (strcmp((_mc_dev)->obj_desc.type, (_obj_desc)->type) == 0 && \ -- (_mc_dev)->obj_desc.id == (_obj_desc)->id) -- --struct dprc_child_objs { -- int child_count; -- struct dprc_obj_desc *child_array; --}; -- --static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data) --{ -- int i; -- struct dprc_child_objs *objs; -- struct fsl_mc_device *mc_dev; -- -- WARN_ON(!dev); -- WARN_ON(!data); -- mc_dev = to_fsl_mc_device(dev); -- objs = data; -- -- for (i = 0; i < objs->child_count; i++) { -- struct dprc_obj_desc *obj_desc = &objs->child_array[i]; -- -- if (strlen(obj_desc->type) != 0 && -- FSL_MC_DEVICE_MATCH(mc_dev, obj_desc)) -- break; -- } -- -- if (i == objs->child_count) -- fsl_mc_device_remove(mc_dev); -- -- return 0; --} -- --static int __fsl_mc_device_remove(struct device *dev, void *data) --{ -- WARN_ON(!dev); -- WARN_ON(data); -- fsl_mc_device_remove(to_fsl_mc_device(dev)); -- return 0; --} -- --/** -- * dprc_remove_devices - Removes devices for objects removed from a DPRC -- * -- * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object -- * @obj_desc_array: array of object descriptors for child objects currently -- * present in the DPRC in the MC. -- * @num_child_objects_in_mc: number of entries in obj_desc_array -- * -- * Synchronizes the state of the Linux bus driver with the actual state of -- * the MC by removing devices that represent MC objects that have -- * been dynamically removed in the physical DPRC. -- */ --static void dprc_remove_devices(struct fsl_mc_device *mc_bus_dev, -- struct dprc_obj_desc *obj_desc_array, -- int num_child_objects_in_mc) --{ -- if (num_child_objects_in_mc != 0) { -- /* -- * Remove child objects that are in the DPRC in Linux, -- * but not in the MC: -- */ -- struct dprc_child_objs objs; -- -- objs.child_count = num_child_objects_in_mc; -- objs.child_array = obj_desc_array; -- device_for_each_child(&mc_bus_dev->dev, &objs, -- __fsl_mc_device_remove_if_not_in_mc); -- } else { -- /* -- * There are no child objects for this DPRC in the MC. -- * So, remove all the child devices from Linux: -- */ -- device_for_each_child(&mc_bus_dev->dev, NULL, -- __fsl_mc_device_remove); -- } --} -- --static int __fsl_mc_device_match(struct device *dev, void *data) --{ -- struct dprc_obj_desc *obj_desc = data; -- struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); -- -- return FSL_MC_DEVICE_MATCH(mc_dev, obj_desc); --} -- --static struct fsl_mc_device *fsl_mc_device_lookup(struct dprc_obj_desc -- *obj_desc, -- struct fsl_mc_device -- *mc_bus_dev) --{ -- struct device *dev; -- -- dev = device_find_child(&mc_bus_dev->dev, obj_desc, -- __fsl_mc_device_match); -- -- return dev ? to_fsl_mc_device(dev) : NULL; --} -- --/** -- * check_plugged_state_change - Check change in an MC object's plugged state -- * -- * @mc_dev: pointer to the fsl-mc device for a given MC object -- * @obj_desc: pointer to the MC object's descriptor in the MC -- * -- * If the plugged state has changed from unplugged to plugged, the fsl-mc -- * device is bound to the corresponding device driver. -- * If the plugged state has changed from plugged to unplugged, the fsl-mc -- * device is unbound from the corresponding device driver. -- */ --static void check_plugged_state_change(struct fsl_mc_device *mc_dev, -- struct dprc_obj_desc *obj_desc) --{ -- int error; -- u32 plugged_flag_at_mc = -- obj_desc->state & DPRC_OBJ_STATE_PLUGGED; -- -- if (plugged_flag_at_mc != -- (mc_dev->obj_desc.state & DPRC_OBJ_STATE_PLUGGED)) { -- if (plugged_flag_at_mc) { -- mc_dev->obj_desc.state |= DPRC_OBJ_STATE_PLUGGED; -- error = device_attach(&mc_dev->dev); -- if (error < 0) { -- dev_err(&mc_dev->dev, -- "device_attach() failed: %d\n", -- error); -- } -- } else { -- mc_dev->obj_desc.state &= ~DPRC_OBJ_STATE_PLUGGED; -- device_release_driver(&mc_dev->dev); -- } -- } --} -- --/** -- * dprc_add_new_devices - Adds devices to the logical bus for a DPRC -- * -- * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object -- * @obj_desc_array: array of device descriptors for child devices currently -- * present in the physical DPRC. -- * @num_child_objects_in_mc: number of entries in obj_desc_array -- * -- * Synchronizes the state of the Linux bus driver with the actual -- * state of the MC by adding objects that have been newly discovered -- * in the physical DPRC. -- */ --static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev, -- struct dprc_obj_desc *obj_desc_array, -- int num_child_objects_in_mc) --{ -- int error; -- int i; -- -- for (i = 0; i < num_child_objects_in_mc; i++) { -- struct fsl_mc_device *child_dev; -- struct dprc_obj_desc *obj_desc = &obj_desc_array[i]; -- -- if (strlen(obj_desc->type) == 0) -- continue; -- -- /* -- * Check if device is already known to Linux: -- */ -- child_dev = fsl_mc_device_lookup(obj_desc, mc_bus_dev); -- if (child_dev) { -- check_plugged_state_change(child_dev, obj_desc); -- continue; -- } -- -- error = fsl_mc_device_add(obj_desc, NULL, &mc_bus_dev->dev, -- &child_dev); -- if (error < 0) -- continue; -- } --} -- --/** -- * dprc_scan_objects - Discover objects in a DPRC -- * -- * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object -- * @total_irq_count: total number of IRQs needed by objects in the DPRC. -- * -- * Detects objects added and removed from a DPRC and synchronizes the -- * state of the Linux bus driver, MC by adding and removing -- * devices accordingly. -- * Two types of devices can be found in a DPRC: allocatable objects (e.g., -- * dpbp, dpmcp) and non-allocatable devices (e.g., dprc, dpni). -- * All allocatable devices needed to be probed before all non-allocatable -- * devices, to ensure that device drivers for non-allocatable -- * devices can allocate any type of allocatable devices. -- * That is, we need to ensure that the corresponding resource pools are -- * populated before they can get allocation requests from probe callbacks -- * of the device drivers for the non-allocatable devices. -- */ --int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, -- unsigned int *total_irq_count) --{ -- int num_child_objects; -- int dprc_get_obj_failures; -- int error; -- unsigned int irq_count = mc_bus_dev->obj_desc.irq_count; -- struct dprc_obj_desc *child_obj_desc_array = NULL; -- -- error = dprc_get_obj_count(mc_bus_dev->mc_io, -- 0, -- mc_bus_dev->mc_handle, -- &num_child_objects); -- if (error < 0) { -- dev_err(&mc_bus_dev->dev, "dprc_get_obj_count() failed: %d\n", -- error); -- return error; -- } -- -- if (num_child_objects != 0) { -- int i; -- -- child_obj_desc_array = -- devm_kmalloc_array(&mc_bus_dev->dev, num_child_objects, -- sizeof(*child_obj_desc_array), -- GFP_KERNEL); -- if (!child_obj_desc_array) -- return -ENOMEM; -- -- /* -- * Discover objects currently present in the physical DPRC: -- */ -- dprc_get_obj_failures = 0; -- for (i = 0; i < num_child_objects; i++) { -- struct dprc_obj_desc *obj_desc = -- &child_obj_desc_array[i]; -- -- error = dprc_get_obj(mc_bus_dev->mc_io, -- 0, -- mc_bus_dev->mc_handle, -- i, obj_desc); -- if (error < 0) { -- dev_err(&mc_bus_dev->dev, -- "dprc_get_obj(i=%d) failed: %d\n", -- i, error); -- /* -- * Mark the obj entry as "invalid", by using the -- * empty string as obj type: -- */ -- obj_desc->type[0] = '\0'; -- obj_desc->id = error; -- dprc_get_obj_failures++; -- continue; -- } -- -- /* -- * add a quirk for all versions of dpsec < 4.0...none -- * are coherent regardless of what the MC reports. -- */ -- if ((strcmp(obj_desc->type, "dpseci") == 0) && -- (obj_desc->ver_major < 4)) -- obj_desc->flags |= -- DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY; -- -- irq_count += obj_desc->irq_count; -- dev_dbg(&mc_bus_dev->dev, -- "Discovered object: type %s, id %d\n", -- obj_desc->type, obj_desc->id); -- } -- -- if (dprc_get_obj_failures != 0) { -- dev_err(&mc_bus_dev->dev, -- "%d out of %d devices could not be retrieved\n", -- dprc_get_obj_failures, num_child_objects); -- } -- } -- -- *total_irq_count = irq_count; -- dprc_remove_devices(mc_bus_dev, child_obj_desc_array, -- num_child_objects); -- -- dprc_add_new_devices(mc_bus_dev, child_obj_desc_array, -- num_child_objects); -- -- if (child_obj_desc_array) -- devm_kfree(&mc_bus_dev->dev, child_obj_desc_array); -- -- return 0; --} --EXPORT_SYMBOL_GPL(dprc_scan_objects); -- --/** -- * dprc_scan_container - Scans a physical DPRC and synchronizes Linux bus state -- * -- * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object -- * -- * Scans the physical DPRC and synchronizes the state of the Linux -- * bus driver with the actual state of the MC by adding and removing -- * devices as appropriate. -- */ --int dprc_scan_container(struct fsl_mc_device *mc_bus_dev) --{ -- int error; -- unsigned int irq_count; -- struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); -- -- fsl_mc_init_all_resource_pools(mc_bus_dev); -- -- /* -- * Discover objects in the DPRC: -- */ -- mutex_lock(&mc_bus->scan_mutex); -- error = dprc_scan_objects(mc_bus_dev, &irq_count); -- mutex_unlock(&mc_bus->scan_mutex); -- if (error < 0) -- goto error; -- -- if (dev_get_msi_domain(&mc_bus_dev->dev) && !mc_bus->irq_resources) { -- if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) { -- dev_warn(&mc_bus_dev->dev, -- "IRQs needed (%u) exceed IRQs preallocated (%u)\n", -- irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); -- } -- -- error = fsl_mc_populate_irq_pool( -- mc_bus, -- FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); -- if (error < 0) -- goto error; -- } -- -- return 0; --error: -- fsl_mc_cleanup_all_resource_pools(mc_bus_dev); -- return error; --} --EXPORT_SYMBOL_GPL(dprc_scan_container); -- --/** -- * dprc_irq0_handler - Regular ISR for DPRC interrupt 0 -- * -- * @irq: IRQ number of the interrupt being handled -- * @arg: Pointer to device structure -- */ --static irqreturn_t dprc_irq0_handler(int irq_num, void *arg) --{ -- return IRQ_WAKE_THREAD; --} -- --/** -- * dprc_irq0_handler_thread - Handler thread function for DPRC interrupt 0 -- * -- * @irq: IRQ number of the interrupt being handled -- * @arg: Pointer to device structure -- */ --static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg) --{ -- int error; -- u32 status; -- struct device *dev = arg; -- struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); -- struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); -- struct fsl_mc_io *mc_io = mc_dev->mc_io; -- struct msi_desc *msi_desc = mc_dev->irqs[0]->msi_desc; -- -- dev_dbg(dev, "DPRC IRQ %d triggered on CPU %u\n", -- irq_num, smp_processor_id()); -- -- if (WARN_ON(!(mc_dev->flags & FSL_MC_IS_DPRC))) -- return IRQ_HANDLED; -- -- mutex_lock(&mc_bus->scan_mutex); -- if (WARN_ON(!msi_desc || msi_desc->irq != (u32)irq_num)) -- goto out; -- -- status = 0; -- error = dprc_get_irq_status(mc_io, 0, mc_dev->mc_handle, 0, -- &status); -- if (error < 0) { -- dev_err(dev, -- "dprc_get_irq_status() failed: %d\n", error); -- goto out; -- } -- -- error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, -- status); -- if (error < 0) { -- dev_err(dev, -- "dprc_clear_irq_status() failed: %d\n", error); -- goto out; -- } -- -- if (status & (DPRC_IRQ_EVENT_OBJ_ADDED | -- DPRC_IRQ_EVENT_OBJ_REMOVED | -- DPRC_IRQ_EVENT_CONTAINER_DESTROYED | -- DPRC_IRQ_EVENT_OBJ_DESTROYED | -- DPRC_IRQ_EVENT_OBJ_CREATED)) { -- unsigned int irq_count; -- -- error = dprc_scan_objects(mc_dev, &irq_count); -- if (error < 0) { -- /* -- * If the error is -ENXIO, we ignore it, as it indicates -- * that the object scan was aborted, as we detected that -- * an object was removed from the DPRC in the MC, while -- * we were scanning the DPRC. -- */ -- if (error != -ENXIO) { -- dev_err(dev, "dprc_scan_objects() failed: %d\n", -- error); -- } -- -- goto out; -- } -- -- if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) { -- dev_warn(dev, -- "IRQs needed (%u) exceed IRQs preallocated (%u)\n", -- irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); -- } -- } -- --out: -- mutex_unlock(&mc_bus->scan_mutex); -- return IRQ_HANDLED; --} -- --/* -- * Disable and clear interrupt for a given DPRC object -- */ --static int disable_dprc_irq(struct fsl_mc_device *mc_dev) --{ -- int error; -- struct fsl_mc_io *mc_io = mc_dev->mc_io; -- -- WARN_ON(mc_dev->obj_desc.irq_count != 1); -- -- /* -- * Disable generation of interrupt, while we configure it: -- */ -- error = dprc_set_irq_enable(mc_io, 0, mc_dev->mc_handle, 0, 0); -- if (error < 0) { -- dev_err(&mc_dev->dev, -- "Disabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n", -- error); -- return error; -- } -- -- /* -- * Disable all interrupt causes for the interrupt: -- */ -- error = dprc_set_irq_mask(mc_io, 0, mc_dev->mc_handle, 0, 0x0); -- if (error < 0) { -- dev_err(&mc_dev->dev, -- "Disabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n", -- error); -- return error; -- } -- -- /* -- * Clear any leftover interrupts: -- */ -- error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, ~0x0U); -- if (error < 0) { -- dev_err(&mc_dev->dev, -- "Disabling DPRC IRQ failed: dprc_clear_irq_status() failed: %d\n", -- error); -- return error; -- } -- -- return 0; --} -- --static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev) --{ -- int error; -- struct fsl_mc_device_irq *irq = mc_dev->irqs[0]; -- -- WARN_ON(mc_dev->obj_desc.irq_count != 1); -- -- /* -- * NOTE: devm_request_threaded_irq() invokes the device-specific -- * function that programs the MSI physically in the device -- */ -- error = devm_request_threaded_irq(&mc_dev->dev, -- irq->msi_desc->irq, -- dprc_irq0_handler, -- dprc_irq0_handler_thread, -- IRQF_NO_SUSPEND | IRQF_ONESHOT, -- "FSL MC DPRC irq0", -- &mc_dev->dev); -- if (error < 0) { -- dev_err(&mc_dev->dev, -- "devm_request_threaded_irq() failed: %d\n", -- error); -- return error; -- } -- -- return 0; --} -- --static int enable_dprc_irq(struct fsl_mc_device *mc_dev) --{ -- int error; -- -- /* -- * Enable all interrupt causes for the interrupt: -- */ -- error = dprc_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, -- ~0x0u); -- if (error < 0) { -- dev_err(&mc_dev->dev, -- "Enabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n", -- error); -- -- return error; -- } -- -- /* -- * Enable generation of the interrupt: -- */ -- error = dprc_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, 1); -- if (error < 0) { -- dev_err(&mc_dev->dev, -- "Enabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n", -- error); -- -- return error; -- } -- -- return 0; --} -- --/* -- * Setup interrupt for a given DPRC device -- */ --static int dprc_setup_irq(struct fsl_mc_device *mc_dev) --{ -- int error; -- -- error = fsl_mc_allocate_irqs(mc_dev); -- if (error < 0) -- return error; -- -- error = disable_dprc_irq(mc_dev); -- if (error < 0) -- goto error_free_irqs; -- -- error = register_dprc_irq_handler(mc_dev); -- if (error < 0) -- goto error_free_irqs; -- -- error = enable_dprc_irq(mc_dev); -- if (error < 0) -- goto error_free_irqs; -- -- return 0; -- --error_free_irqs: -- fsl_mc_free_irqs(mc_dev); -- return error; --} -- --/** -- * dprc_probe - callback invoked when a DPRC is being bound to this driver -- * -- * @mc_dev: Pointer to fsl-mc device representing a DPRC -- * -- * It opens the physical DPRC in the MC. -- * It scans the DPRC to discover the MC objects contained in it. -- * It creates the interrupt pool for the MC bus associated with the DPRC. -- * It configures the interrupts for the DPRC device itself. -- */ --static int dprc_probe(struct fsl_mc_device *mc_dev) --{ -- int error; -- size_t region_size; -- struct device *parent_dev = mc_dev->dev.parent; -- struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); -- bool mc_io_created = false; -- bool msi_domain_set = false; -- -- if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0)) -- return -EINVAL; -- -- if (WARN_ON(dev_get_msi_domain(&mc_dev->dev))) -- return -EINVAL; -- -- if (!mc_dev->mc_io) { -- /* -- * This is a child DPRC: -- */ -- if (WARN_ON(!dev_is_fsl_mc(parent_dev))) -- return -EINVAL; -- -- if (WARN_ON(mc_dev->obj_desc.region_count == 0)) -- return -EINVAL; -- -- region_size = mc_dev->regions[0].end - -- mc_dev->regions[0].start + 1; -- -- error = fsl_create_mc_io(&mc_dev->dev, -- mc_dev->regions[0].start, -- region_size, -- NULL, -- FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, -- &mc_dev->mc_io); -- if (error < 0) -- return error; -- -- mc_io_created = true; -- -- /* -- * Inherit parent MSI domain: -- */ -- dev_set_msi_domain(&mc_dev->dev, -- dev_get_msi_domain(parent_dev)); -- msi_domain_set = true; -- } else { -- /* -- * This is a root DPRC -- */ -- struct irq_domain *mc_msi_domain; -- -- if (WARN_ON(dev_is_fsl_mc(parent_dev))) -- return -EINVAL; -- -- error = fsl_mc_find_msi_domain(parent_dev, -- &mc_msi_domain); -- if (error < 0) { -- dev_warn(&mc_dev->dev, -- "WARNING: MC bus without interrupt support\n"); -- } else { -- dev_set_msi_domain(&mc_dev->dev, mc_msi_domain); -- msi_domain_set = true; -- } -- } -- -- error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id, -- &mc_dev->mc_handle); -- if (error < 0) { -- dev_err(&mc_dev->dev, "dprc_open() failed: %d\n", error); -- goto error_cleanup_msi_domain; -- } -- -- error = dprc_get_attributes(mc_dev->mc_io, 0, mc_dev->mc_handle, -- &mc_bus->dprc_attr); -- if (error < 0) { -- dev_err(&mc_dev->dev, "dprc_get_attributes() failed: %d\n", -- error); -- goto error_cleanup_open; -- } -- -- if (mc_bus->dprc_attr.version.major < DPRC_MIN_VER_MAJOR || -- (mc_bus->dprc_attr.version.major == DPRC_MIN_VER_MAJOR && -- mc_bus->dprc_attr.version.minor < DPRC_MIN_VER_MINOR)) { -- dev_err(&mc_dev->dev, -- "ERROR: DPRC version %d.%d not supported\n", -- mc_bus->dprc_attr.version.major, -- mc_bus->dprc_attr.version.minor); -- error = -ENOTSUPP; -- goto error_cleanup_open; -- } -- -- mutex_init(&mc_bus->scan_mutex); -- -- /* -- * Discover MC objects in DPRC object: -- */ -- error = dprc_scan_container(mc_dev); -- if (error < 0) -- goto error_cleanup_open; -- -- /* -- * Configure interrupt for the DPRC object associated with this MC bus: -- */ -- error = dprc_setup_irq(mc_dev); -- if (error < 0) -- goto error_cleanup_open; -- -- dev_info(&mc_dev->dev, "DPRC device bound to driver"); -- return 0; -- --error_cleanup_open: -- (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); -- --error_cleanup_msi_domain: -- if (msi_domain_set) -- dev_set_msi_domain(&mc_dev->dev, NULL); -- -- if (mc_io_created) { -- fsl_destroy_mc_io(mc_dev->mc_io); -- mc_dev->mc_io = NULL; -- } -- -- return error; --} -- --/* -- * Tear down interrupt for a given DPRC object -- */ --static void dprc_teardown_irq(struct fsl_mc_device *mc_dev) --{ -- struct fsl_mc_device_irq *irq = mc_dev->irqs[0]; -- -- (void)disable_dprc_irq(mc_dev); -- -- devm_free_irq(&mc_dev->dev, irq->msi_desc->irq, &mc_dev->dev); -- -- fsl_mc_free_irqs(mc_dev); --} -- --/** -- * dprc_remove - callback invoked when a DPRC is being unbound from this driver -- * -- * @mc_dev: Pointer to fsl-mc device representing the DPRC -- * -- * It removes the DPRC's child objects from Linux (not from the MC) and -- * closes the DPRC device in the MC. -- * It tears down the interrupts that were configured for the DPRC device. -- * It destroys the interrupt pool associated with this MC bus. -- */ --static int dprc_remove(struct fsl_mc_device *mc_dev) --{ -- int error; -- struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); -- -- if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0)) -- return -EINVAL; -- if (WARN_ON(!mc_dev->mc_io)) -- return -EINVAL; -- -- if (WARN_ON(!mc_bus->irq_resources)) -- return -EINVAL; -- -- if (dev_get_msi_domain(&mc_dev->dev)) -- dprc_teardown_irq(mc_dev); -- -- device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove); -- -- if (dev_get_msi_domain(&mc_dev->dev)) { -- fsl_mc_cleanup_irq_pool(mc_bus); -- dev_set_msi_domain(&mc_dev->dev, NULL); -- } -- -- fsl_mc_cleanup_all_resource_pools(mc_dev); -- -- error = dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); -- if (error < 0) -- dev_err(&mc_dev->dev, "dprc_close() failed: %d\n", error); -- -- if (!fsl_mc_is_root_dprc(&mc_dev->dev)) { -- fsl_destroy_mc_io(mc_dev->mc_io); -- mc_dev->mc_io = NULL; -- } -- -- dev_info(&mc_dev->dev, "DPRC device unbound from driver"); -- return 0; --} -- --static const struct fsl_mc_device_id match_id_table[] = { -- { -- .vendor = FSL_MC_VENDOR_FREESCALE, -- .obj_type = "dprc"}, -- {.vendor = 0x0}, --}; -- --static struct fsl_mc_driver dprc_driver = { -- .driver = { -- .name = FSL_MC_DPRC_DRIVER_NAME, -- .owner = THIS_MODULE, -- .pm = NULL, -- }, -- .match_id_table = match_id_table, -- .probe = dprc_probe, -- .remove = dprc_remove, --}; -- --int __init dprc_driver_init(void) --{ -- return fsl_mc_driver_register(&dprc_driver); --} -- --void dprc_driver_exit(void) --{ -- fsl_mc_driver_unregister(&dprc_driver); --} ---- /dev/null -+++ b/drivers/bus/fsl-mc/dprc-driver.c -@@ -0,0 +1,815 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Freescale data path resource container (DPRC) driver -+ * -+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. -+ * Author: German Rivera <German.Rivera@freescale.com> -+ * -+ */ -+ -+#include <linux/module.h> -+#include <linux/slab.h> -+#include <linux/interrupt.h> -+#include <linux/msi.h> -+#include <linux/fsl/mc.h> -+ -+#include "fsl-mc-private.h" -+ -+#define FSL_MC_DPRC_DRIVER_NAME "fsl_mc_dprc" -+ -+struct fsl_mc_child_objs { -+ int child_count; -+ struct fsl_mc_obj_desc *child_array; -+}; -+ -+static bool fsl_mc_device_match(struct fsl_mc_device *mc_dev, -+ struct fsl_mc_obj_desc *obj_desc) -+{ -+ return mc_dev->obj_desc.id == obj_desc->id && -+ strcmp(mc_dev->obj_desc.type, obj_desc->type) == 0; -+ -+} -+ -+static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data) -+{ -+ int i; -+ struct fsl_mc_child_objs *objs; -+ struct fsl_mc_device *mc_dev; -+ -+ mc_dev = to_fsl_mc_device(dev); -+ objs = data; -+ -+ for (i = 0; i < objs->child_count; i++) { -+ struct fsl_mc_obj_desc *obj_desc = &objs->child_array[i]; -+ -+ if (strlen(obj_desc->type) != 0 && -+ fsl_mc_device_match(mc_dev, obj_desc)) -+ break; -+ } -+ -+ if (i == objs->child_count) -+ fsl_mc_device_remove(mc_dev); -+ -+ return 0; -+} -+ -+static int __fsl_mc_device_remove(struct device *dev, void *data) -+{ -+ fsl_mc_device_remove(to_fsl_mc_device(dev)); -+ return 0; -+} -+ -+/** -+ * dprc_remove_devices - Removes devices for objects removed from a DPRC -+ * -+ * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object -+ * @obj_desc_array: array of object descriptors for child objects currently -+ * present in the DPRC in the MC. -+ * @num_child_objects_in_mc: number of entries in obj_desc_array -+ * -+ * Synchronizes the state of the Linux bus driver with the actual state of -+ * the MC by removing devices that represent MC objects that have -+ * been dynamically removed in the physical DPRC. -+ */ -+static void dprc_remove_devices(struct fsl_mc_device *mc_bus_dev, -+ struct fsl_mc_obj_desc *obj_desc_array, -+ int num_child_objects_in_mc) -+{ -+ if (num_child_objects_in_mc != 0) { -+ /* -+ * Remove child objects that are in the DPRC in Linux, -+ * but not in the MC: -+ */ -+ struct fsl_mc_child_objs objs; -+ -+ objs.child_count = num_child_objects_in_mc; -+ objs.child_array = obj_desc_array; -+ device_for_each_child(&mc_bus_dev->dev, &objs, -+ __fsl_mc_device_remove_if_not_in_mc); -+ } else { -+ /* -+ * There are no child objects for this DPRC in the MC. -+ * So, remove all the child devices from Linux: -+ */ -+ device_for_each_child(&mc_bus_dev->dev, NULL, -+ __fsl_mc_device_remove); -+ } -+} -+ -+static int __fsl_mc_device_match(struct device *dev, void *data) -+{ -+ struct fsl_mc_obj_desc *obj_desc = data; -+ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); -+ -+ return fsl_mc_device_match(mc_dev, obj_desc); -+} -+ -+static struct fsl_mc_device *fsl_mc_device_lookup(struct fsl_mc_obj_desc -+ *obj_desc, -+ struct fsl_mc_device -+ *mc_bus_dev) -+{ -+ struct device *dev; -+ -+ dev = device_find_child(&mc_bus_dev->dev, obj_desc, -+ __fsl_mc_device_match); -+ -+ return dev ? to_fsl_mc_device(dev) : NULL; -+} -+ -+/** -+ * check_plugged_state_change - Check change in an MC object's plugged state -+ * -+ * @mc_dev: pointer to the fsl-mc device for a given MC object -+ * @obj_desc: pointer to the MC object's descriptor in the MC -+ * -+ * If the plugged state has changed from unplugged to plugged, the fsl-mc -+ * device is bound to the corresponding device driver. -+ * If the plugged state has changed from plugged to unplugged, the fsl-mc -+ * device is unbound from the corresponding device driver. -+ */ -+static void check_plugged_state_change(struct fsl_mc_device *mc_dev, -+ struct fsl_mc_obj_desc *obj_desc) -+{ -+ int error; -+ u32 plugged_flag_at_mc = -+ obj_desc->state & FSL_MC_OBJ_STATE_PLUGGED; -+ -+ if (plugged_flag_at_mc != -+ (mc_dev->obj_desc.state & FSL_MC_OBJ_STATE_PLUGGED)) { -+ if (plugged_flag_at_mc) { -+ mc_dev->obj_desc.state |= FSL_MC_OBJ_STATE_PLUGGED; -+ error = device_attach(&mc_dev->dev); -+ if (error < 0) { -+ dev_err(&mc_dev->dev, -+ "device_attach() failed: %d\n", -+ error); -+ } -+ } else { -+ mc_dev->obj_desc.state &= ~FSL_MC_OBJ_STATE_PLUGGED; -+ device_release_driver(&mc_dev->dev); -+ } -+ } -+} -+ -+/** -+ * dprc_add_new_devices - Adds devices to the logical bus for a DPRC -+ * -+ * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object -+ * @driver_override: driver override to apply to new objects found in the -+ * DPRC, or NULL, if none. -+ * @obj_desc_array: array of device descriptors for child devices currently -+ * present in the physical DPRC. -+ * @num_child_objects_in_mc: number of entries in obj_desc_array -+ * -+ * Synchronizes the state of the Linux bus driver with the actual -+ * state of the MC by adding objects that have been newly discovered -+ * in the physical DPRC. -+ */ -+static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev, -+ const char *driver_override, -+ struct fsl_mc_obj_desc *obj_desc_array, -+ int num_child_objects_in_mc) -+{ -+ int error; -+ int i; -+ -+ for (i = 0; i < num_child_objects_in_mc; i++) { -+ struct fsl_mc_device *child_dev; -+ struct fsl_mc_obj_desc *obj_desc = &obj_desc_array[i]; -+ -+ if (strlen(obj_desc->type) == 0) -+ continue; -+ -+ /* -+ * Check if device is already known to Linux: -+ */ -+ child_dev = fsl_mc_device_lookup(obj_desc, mc_bus_dev); -+ if (child_dev) { -+ check_plugged_state_change(child_dev, obj_desc); -+ put_device(&child_dev->dev); -+ continue; -+ } -+ -+ error = fsl_mc_device_add(obj_desc, NULL, &mc_bus_dev->dev, -+ driver_override, &child_dev); -+ if (error < 0) -+ continue; -+ } -+} -+ -+/** -+ * dprc_scan_objects - Discover objects in a DPRC -+ * -+ * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object -+ * @driver_override: driver override to apply to new objects found in the -+ * DPRC, or NULL, if none. -+ * @total_irq_count: If argument is provided the function populates the -+ * total number of IRQs created by objects in the DPRC. -+ * -+ * Detects objects added and removed from a DPRC and synchronizes the -+ * state of the Linux bus driver, MC by adding and removing -+ * devices accordingly. -+ * Two types of devices can be found in a DPRC: allocatable objects (e.g., -+ * dpbp, dpmcp) and non-allocatable devices (e.g., dprc, dpni). -+ * All allocatable devices needed to be probed before all non-allocatable -+ * devices, to ensure that device drivers for non-allocatable -+ * devices can allocate any type of allocatable devices. -+ * That is, we need to ensure that the corresponding resource pools are -+ * populated before they can get allocation requests from probe callbacks -+ * of the device drivers for the non-allocatable devices. -+ */ -+int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, -+ const char *driver_override, -+ unsigned int *total_irq_count) -+{ -+ int num_child_objects; -+ int dprc_get_obj_failures; -+ int error; -+ unsigned int irq_count = mc_bus_dev->obj_desc.irq_count; -+ struct fsl_mc_obj_desc *child_obj_desc_array = NULL; -+ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); -+ -+ error = dprc_get_obj_count(mc_bus_dev->mc_io, -+ 0, -+ mc_bus_dev->mc_handle, -+ &num_child_objects); -+ if (error < 0) { -+ dev_err(&mc_bus_dev->dev, "dprc_get_obj_count() failed: %d\n", -+ error); -+ return error; -+ } -+ -+ if (num_child_objects != 0) { -+ int i; -+ -+ child_obj_desc_array = -+ devm_kmalloc_array(&mc_bus_dev->dev, num_child_objects, -+ sizeof(*child_obj_desc_array), -+ GFP_KERNEL); -+ if (!child_obj_desc_array) -+ return -ENOMEM; -+ -+ /* -+ * Discover objects currently present in the physical DPRC: -+ */ -+ dprc_get_obj_failures = 0; -+ for (i = 0; i < num_child_objects; i++) { -+ struct fsl_mc_obj_desc *obj_desc = -+ &child_obj_desc_array[i]; -+ -+ error = dprc_get_obj(mc_bus_dev->mc_io, -+ 0, -+ mc_bus_dev->mc_handle, -+ i, obj_desc); -+ if (error < 0) { -+ dev_err(&mc_bus_dev->dev, -+ "dprc_get_obj(i=%d) failed: %d\n", -+ i, error); -+ /* -+ * Mark the obj entry as "invalid", by using the -+ * empty string as obj type: -+ */ -+ obj_desc->type[0] = '\0'; -+ obj_desc->id = error; -+ dprc_get_obj_failures++; -+ continue; -+ } -+ -+ /* -+ * add a quirk for all versions of dpsec < 4.0...none -+ * are coherent regardless of what the MC reports. -+ */ -+ if ((strcmp(obj_desc->type, "dpseci") == 0) && -+ (obj_desc->ver_major < 4)) -+ obj_desc->flags |= -+ FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY; -+ -+ irq_count += obj_desc->irq_count; -+ dev_dbg(&mc_bus_dev->dev, -+ "Discovered object: type %s, id %d\n", -+ obj_desc->type, obj_desc->id); -+ } -+ -+ if (dprc_get_obj_failures != 0) { -+ dev_err(&mc_bus_dev->dev, -+ "%d out of %d devices could not be retrieved\n", -+ dprc_get_obj_failures, num_child_objects); -+ } -+ } -+ -+ /* -+ * Allocate IRQ's before binding the scanned devices with their -+ * respective drivers. -+ */ -+ if (dev_get_msi_domain(&mc_bus_dev->dev) && !mc_bus->irq_resources) { -+ if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) { -+ dev_warn(&mc_bus_dev->dev, -+ "IRQs needed (%u) exceed IRQs preallocated (%u)\n", -+ irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); -+ } -+ -+ error = fsl_mc_populate_irq_pool(mc_bus, -+ FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); -+ if (error < 0) -+ return error; -+ } -+ -+ if (total_irq_count) -+ *total_irq_count = irq_count; -+ -+ dprc_remove_devices(mc_bus_dev, child_obj_desc_array, -+ num_child_objects); -+ -+ dprc_add_new_devices(mc_bus_dev, driver_override, child_obj_desc_array, -+ num_child_objects); -+ -+ if (child_obj_desc_array) -+ devm_kfree(&mc_bus_dev->dev, child_obj_desc_array); -+ -+ return 0; -+} -+ -+/** -+ * dprc_scan_container - Scans a physical DPRC and synchronizes Linux bus state -+ * -+ * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object -+ * -+ * Scans the physical DPRC and synchronizes the state of the Linux -+ * bus driver with the actual state of the MC by adding and removing -+ * devices as appropriate. -+ */ -+static int dprc_scan_container(struct fsl_mc_device *mc_bus_dev) -+{ -+ int error; -+ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); -+ -+ fsl_mc_init_all_resource_pools(mc_bus_dev); -+ -+ /* -+ * Discover objects in the DPRC: -+ */ -+ mutex_lock(&mc_bus->scan_mutex); -+ error = dprc_scan_objects(mc_bus_dev, NULL, NULL); -+ mutex_unlock(&mc_bus->scan_mutex); -+ if (error < 0) { -+ fsl_mc_cleanup_all_resource_pools(mc_bus_dev); -+ return error; -+ } -+ -+ return 0; -+} -+ -+/** -+ * dprc_irq0_handler - Regular ISR for DPRC interrupt 0 -+ * -+ * @irq: IRQ number of the interrupt being handled -+ * @arg: Pointer to device structure -+ */ -+static irqreturn_t dprc_irq0_handler(int irq_num, void *arg) -+{ -+ return IRQ_WAKE_THREAD; -+} -+ -+/** -+ * dprc_irq0_handler_thread - Handler thread function for DPRC interrupt 0 -+ * -+ * @irq: IRQ number of the interrupt being handled -+ * @arg: Pointer to device structure -+ */ -+static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg) -+{ -+ int error; -+ u32 status; -+ struct device *dev = arg; -+ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); -+ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); -+ struct fsl_mc_io *mc_io = mc_dev->mc_io; -+ struct msi_desc *msi_desc = mc_dev->irqs[0]->msi_desc; -+ -+ dev_dbg(dev, "DPRC IRQ %d triggered on CPU %u\n", -+ irq_num, smp_processor_id()); -+ -+ if (!(mc_dev->flags & FSL_MC_IS_DPRC)) -+ return IRQ_HANDLED; -+ -+ mutex_lock(&mc_bus->scan_mutex); -+ if (!msi_desc || msi_desc->irq != (u32)irq_num) -+ goto out; -+ -+ status = 0; -+ error = dprc_get_irq_status(mc_io, 0, mc_dev->mc_handle, 0, -+ &status); -+ if (error < 0) { -+ dev_err(dev, -+ "dprc_get_irq_status() failed: %d\n", error); -+ goto out; -+ } -+ -+ error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, -+ status); -+ if (error < 0) { -+ dev_err(dev, -+ "dprc_clear_irq_status() failed: %d\n", error); -+ goto out; -+ } -+ -+ if (status & (DPRC_IRQ_EVENT_OBJ_ADDED | -+ DPRC_IRQ_EVENT_OBJ_REMOVED | -+ DPRC_IRQ_EVENT_CONTAINER_DESTROYED | -+ DPRC_IRQ_EVENT_OBJ_DESTROYED | -+ DPRC_IRQ_EVENT_OBJ_CREATED)) { -+ unsigned int irq_count; -+ -+ error = dprc_scan_objects(mc_dev, NULL, &irq_count); -+ if (error < 0) { -+ /* -+ * If the error is -ENXIO, we ignore it, as it indicates -+ * that the object scan was aborted, as we detected that -+ * an object was removed from the DPRC in the MC, while -+ * we were scanning the DPRC. -+ */ -+ if (error != -ENXIO) { -+ dev_err(dev, "dprc_scan_objects() failed: %d\n", -+ error); -+ } -+ -+ goto out; -+ } -+ -+ if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) { -+ dev_warn(dev, -+ "IRQs needed (%u) exceed IRQs preallocated (%u)\n", -+ irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); -+ } -+ } -+ -+out: -+ mutex_unlock(&mc_bus->scan_mutex); -+ return IRQ_HANDLED; -+} -+ -+/* -+ * Disable and clear interrupt for a given DPRC object -+ */ -+static int disable_dprc_irq(struct fsl_mc_device *mc_dev) -+{ -+ int error; -+ struct fsl_mc_io *mc_io = mc_dev->mc_io; -+ -+ /* -+ * Disable generation of interrupt, while we configure it: -+ */ -+ error = dprc_set_irq_enable(mc_io, 0, mc_dev->mc_handle, 0, 0); -+ if (error < 0) { -+ dev_err(&mc_dev->dev, -+ "Disabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n", -+ error); -+ return error; -+ } -+ -+ /* -+ * Disable all interrupt causes for the interrupt: -+ */ -+ error = dprc_set_irq_mask(mc_io, 0, mc_dev->mc_handle, 0, 0x0); -+ if (error < 0) { -+ dev_err(&mc_dev->dev, -+ "Disabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n", -+ error); -+ return error; -+ } -+ -+ /* -+ * Clear any leftover interrupts: -+ */ -+ error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, ~0x0U); -+ if (error < 0) { -+ dev_err(&mc_dev->dev, -+ "Disabling DPRC IRQ failed: dprc_clear_irq_status() failed: %d\n", -+ error); -+ return error; -+ } -+ -+ return 0; -+} -+ -+static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev) -+{ -+ int error; -+ struct fsl_mc_device_irq *irq = mc_dev->irqs[0]; -+ -+ /* -+ * NOTE: devm_request_threaded_irq() invokes the device-specific -+ * function that programs the MSI physically in the device -+ */ -+ error = devm_request_threaded_irq(&mc_dev->dev, -+ irq->msi_desc->irq, -+ dprc_irq0_handler, -+ dprc_irq0_handler_thread, -+ IRQF_NO_SUSPEND | IRQF_ONESHOT, -+ dev_name(&mc_dev->dev), -+ &mc_dev->dev); -+ if (error < 0) { -+ dev_err(&mc_dev->dev, -+ "devm_request_threaded_irq() failed: %d\n", -+ error); -+ return error; -+ } -+ -+ return 0; -+} -+ -+static int enable_dprc_irq(struct fsl_mc_device *mc_dev) -+{ -+ int error; -+ -+ /* -+ * Enable all interrupt causes for the interrupt: -+ */ -+ error = dprc_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, -+ ~0x0u); -+ if (error < 0) { -+ dev_err(&mc_dev->dev, -+ "Enabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n", -+ error); -+ -+ return error; -+ } -+ -+ /* -+ * Enable generation of the interrupt: -+ */ -+ error = dprc_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, 1); -+ if (error < 0) { -+ dev_err(&mc_dev->dev, -+ "Enabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n", -+ error); -+ -+ return error; -+ } -+ -+ return 0; -+} -+ -+/* -+ * Setup interrupt for a given DPRC device -+ */ -+static int dprc_setup_irq(struct fsl_mc_device *mc_dev) -+{ -+ int error; -+ -+ error = fsl_mc_allocate_irqs(mc_dev); -+ if (error < 0) -+ return error; -+ -+ error = disable_dprc_irq(mc_dev); -+ if (error < 0) -+ goto error_free_irqs; -+ -+ error = register_dprc_irq_handler(mc_dev); -+ if (error < 0) -+ goto error_free_irqs; -+ -+ error = enable_dprc_irq(mc_dev); -+ if (error < 0) -+ goto error_free_irqs; -+ -+ return 0; -+ -+error_free_irqs: -+ fsl_mc_free_irqs(mc_dev); -+ return error; -+} -+ -+/** -+ * dprc_probe - callback invoked when a DPRC is being bound to this driver -+ * -+ * @mc_dev: Pointer to fsl-mc device representing a DPRC -+ * -+ * It opens the physical DPRC in the MC. -+ * It scans the DPRC to discover the MC objects contained in it. -+ * It creates the interrupt pool for the MC bus associated with the DPRC. -+ * It configures the interrupts for the DPRC device itself. -+ */ -+static int dprc_probe(struct fsl_mc_device *mc_dev) -+{ -+ int error; -+ size_t region_size; -+ struct device *parent_dev = mc_dev->dev.parent; -+ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); -+ bool mc_io_created = false; -+ bool msi_domain_set = false; -+ u16 major_ver, minor_ver; -+ -+ if (!is_fsl_mc_bus_dprc(mc_dev)) -+ return -EINVAL; -+ -+ if (dev_get_msi_domain(&mc_dev->dev)) -+ return -EINVAL; -+ -+ if (!mc_dev->mc_io) { -+ /* -+ * This is a child DPRC: -+ */ -+ if (!dev_is_fsl_mc(parent_dev)) -+ return -EINVAL; -+ -+ if (mc_dev->obj_desc.region_count == 0) -+ return -EINVAL; -+ -+ region_size = resource_size(mc_dev->regions); -+ -+ error = fsl_create_mc_io(&mc_dev->dev, -+ mc_dev->regions[0].start, -+ region_size, -+ NULL, -+ FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, -+ &mc_dev->mc_io); -+ if (error < 0) -+ return error; -+ -+ mc_io_created = true; -+ -+ /* -+ * Inherit parent MSI domain: -+ */ -+ dev_set_msi_domain(&mc_dev->dev, -+ dev_get_msi_domain(parent_dev)); -+ msi_domain_set = true; -+ } else { -+ /* -+ * This is a root DPRC -+ */ -+ struct irq_domain *mc_msi_domain; -+ -+ if (dev_is_fsl_mc(parent_dev)) -+ return -EINVAL; -+ -+ error = fsl_mc_find_msi_domain(parent_dev, -+ &mc_msi_domain); -+ if (error < 0) { -+ dev_warn(&mc_dev->dev, -+ "WARNING: MC bus without interrupt support\n"); -+ } else { -+ dev_set_msi_domain(&mc_dev->dev, mc_msi_domain); -+ msi_domain_set = true; -+ } -+ } -+ -+ error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id, -+ &mc_dev->mc_handle); -+ if (error < 0) { -+ dev_err(&mc_dev->dev, "dprc_open() failed: %d\n", error); -+ goto error_cleanup_msi_domain; -+ } -+ -+ error = dprc_get_attributes(mc_dev->mc_io, 0, mc_dev->mc_handle, -+ &mc_bus->dprc_attr); -+ if (error < 0) { -+ dev_err(&mc_dev->dev, "dprc_get_attributes() failed: %d\n", -+ error); -+ goto error_cleanup_open; -+ } -+ -+ error = dprc_get_api_version(mc_dev->mc_io, 0, -+ &major_ver, -+ &minor_ver); -+ if (error < 0) { -+ dev_err(&mc_dev->dev, "dprc_get_api_version() failed: %d\n", -+ error); -+ goto error_cleanup_open; -+ } -+ -+ if (major_ver < DPRC_MIN_VER_MAJOR || -+ (major_ver == DPRC_MIN_VER_MAJOR && -+ minor_ver < DPRC_MIN_VER_MINOR)) { -+ dev_err(&mc_dev->dev, -+ "ERROR: DPRC version %d.%d not supported\n", -+ major_ver, minor_ver); -+ error = -ENOTSUPP; -+ goto error_cleanup_open; -+ } -+ -+ mutex_init(&mc_bus->scan_mutex); -+ -+ /* -+ * Discover MC objects in DPRC object: -+ */ -+ error = dprc_scan_container(mc_dev); -+ if (error < 0) -+ goto error_cleanup_open; -+ -+ /* -+ * Configure interrupt for the DPRC object associated with this MC bus: -+ */ -+ error = dprc_setup_irq(mc_dev); -+ if (error < 0) -+ goto error_cleanup_open; -+ -+ dev_info(&mc_dev->dev, "DPRC device bound to driver"); -+ return 0; -+ -+error_cleanup_open: -+ (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); -+ -+error_cleanup_msi_domain: -+ if (msi_domain_set) -+ dev_set_msi_domain(&mc_dev->dev, NULL); -+ -+ if (mc_io_created) { -+ fsl_destroy_mc_io(mc_dev->mc_io); -+ mc_dev->mc_io = NULL; -+ } -+ -+ return error; -+} -+ -+/* -+ * Tear down interrupt for a given DPRC object -+ */ -+static void dprc_teardown_irq(struct fsl_mc_device *mc_dev) -+{ -+ struct fsl_mc_device_irq *irq = mc_dev->irqs[0]; -+ -+ (void)disable_dprc_irq(mc_dev); -+ -+ devm_free_irq(&mc_dev->dev, irq->msi_desc->irq, &mc_dev->dev); -+ -+ fsl_mc_free_irqs(mc_dev); -+} -+ -+/** -+ * dprc_remove - callback invoked when a DPRC is being unbound from this driver -+ * -+ * @mc_dev: Pointer to fsl-mc device representing the DPRC -+ * -+ * It removes the DPRC's child objects from Linux (not from the MC) and -+ * closes the DPRC device in the MC. -+ * It tears down the interrupts that were configured for the DPRC device. -+ * It destroys the interrupt pool associated with this MC bus. -+ */ -+static int dprc_remove(struct fsl_mc_device *mc_dev) -+{ -+ int error; -+ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); -+ -+ if (!is_fsl_mc_bus_dprc(mc_dev)) -+ return -EINVAL; -+ if (!mc_dev->mc_io) -+ return -EINVAL; -+ -+ if (!mc_bus->irq_resources) -+ return -EINVAL; -+ -+ if (dev_get_msi_domain(&mc_dev->dev)) -+ dprc_teardown_irq(mc_dev); -+ -+ device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove); -+ -+ if (dev_get_msi_domain(&mc_dev->dev)) { -+ fsl_mc_cleanup_irq_pool(mc_bus); -+ dev_set_msi_domain(&mc_dev->dev, NULL); -+ } -+ -+ fsl_mc_cleanup_all_resource_pools(mc_dev); -+ -+ error = dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); -+ if (error < 0) -+ dev_err(&mc_dev->dev, "dprc_close() failed: %d\n", error); -+ -+ if (!fsl_mc_is_root_dprc(&mc_dev->dev)) { -+ fsl_destroy_mc_io(mc_dev->mc_io); -+ mc_dev->mc_io = NULL; -+ } -+ -+ dev_info(&mc_dev->dev, "DPRC device unbound from driver"); -+ return 0; -+} -+ -+static const struct fsl_mc_device_id match_id_table[] = { -+ { -+ .vendor = FSL_MC_VENDOR_FREESCALE, -+ .obj_type = "dprc"}, -+ {.vendor = 0x0}, -+}; -+ -+static struct fsl_mc_driver dprc_driver = { -+ .driver = { -+ .name = FSL_MC_DPRC_DRIVER_NAME, -+ .owner = THIS_MODULE, -+ .pm = NULL, -+ }, -+ .match_id_table = match_id_table, -+ .probe = dprc_probe, -+ .remove = dprc_remove, -+}; -+ -+int __init dprc_driver_init(void) -+{ -+ return fsl_mc_driver_register(&dprc_driver); -+} -+ -+void dprc_driver_exit(void) -+{ -+ fsl_mc_driver_unregister(&dprc_driver); -+} ---- /dev/null -+++ b/drivers/bus/fsl-mc/dprc.c -@@ -0,0 +1,575 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright 2013-2016 Freescale Semiconductor Inc. -+ * -+ */ -+#include <linux/kernel.h> -+#include <linux/fsl/mc.h> -+ -+#include "fsl-mc-private.h" -+ -+/** -+ * dprc_open() - Open DPRC object for use -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @container_id: Container ID to open -+ * @token: Returned token of DPRC object -+ * -+ * Return: '0' on Success; Error code otherwise. -+ * -+ * @warning Required before any operation on the object. -+ */ -+int dprc_open(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ int container_id, -+ u16 *token) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dprc_cmd_open *cmd_params; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_OPEN, cmd_flags, -+ 0); -+ cmd_params = (struct dprc_cmd_open *)cmd.params; -+ cmd_params->container_id = cpu_to_le32(container_id); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ *token = mc_cmd_hdr_read_token(&cmd); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(dprc_open); -+ -+/** -+ * dprc_close() - Close the control session of the object -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPRC object -+ * -+ * After this function is called, no further operations are -+ * allowed on the object without opening a new control session. -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dprc_close(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLOSE, cmd_flags, -+ token); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+EXPORT_SYMBOL_GPL(dprc_close); -+ -+/** -+ * dprc_reset_container - Reset child container. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPRC object -+ * @child_container_id: ID of the container to reset -+ * -+ * In case a software context crashes or becomes non-responsive, the parent -+ * may wish to reset its resources container before the software context is -+ * restarted. -+ * -+ * This routine informs all objects assigned to the child container that the -+ * container is being reset, so they may perform any cleanup operations that are -+ * needed. All objects handles that were owned by the child container shall be -+ * closed. -+ * -+ * Note that such request may be submitted even if the child software context -+ * has not crashed, but the resulting object cleanup operations will not be -+ * aware of that. -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dprc_reset_container(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ int child_container_id) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dprc_cmd_reset_container *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_RESET_CONT, -+ cmd_flags, token); -+ cmd_params = (struct dprc_cmd_reset_container *)cmd.params; -+ cmd_params->child_container_id = cpu_to_le32(child_container_id); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+EXPORT_SYMBOL_GPL(dprc_reset_container); -+ -+/** -+ * dprc_set_irq() - Set IRQ information for the DPRC to trigger an interrupt. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPRC object -+ * @irq_index: Identifies the interrupt index to configure -+ * @irq_cfg: IRQ configuration -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dprc_set_irq(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u8 irq_index, -+ struct dprc_irq_cfg *irq_cfg) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dprc_cmd_set_irq *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ, -+ cmd_flags, -+ token); -+ cmd_params = (struct dprc_cmd_set_irq *)cmd.params; -+ cmd_params->irq_val = cpu_to_le32(irq_cfg->val); -+ cmd_params->irq_index = irq_index; -+ cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr); -+ cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dprc_set_irq_enable() - Set overall interrupt state. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPRC object -+ * @irq_index: The interrupt index to configure -+ * @en: Interrupt state - enable = 1, disable = 0 -+ * -+ * Allows GPP software to control when interrupts are generated. -+ * Each interrupt can have up to 32 causes. The enable/disable control's the -+ * overall interrupt state. if the interrupt is disabled no causes will cause -+ * an interrupt. -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dprc_set_irq_enable(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u8 irq_index, -+ u8 en) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dprc_cmd_set_irq_enable *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_ENABLE, -+ cmd_flags, token); -+ cmd_params = (struct dprc_cmd_set_irq_enable *)cmd.params; -+ cmd_params->enable = en & DPRC_ENABLE; -+ cmd_params->irq_index = irq_index; -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dprc_set_irq_mask() - Set interrupt mask. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPRC object -+ * @irq_index: The interrupt index to configure -+ * @mask: event mask to trigger interrupt; -+ * each bit: -+ * 0 = ignore event -+ * 1 = consider event for asserting irq -+ * -+ * Every interrupt can have up to 32 causes and the interrupt model supports -+ * masking/unmasking each cause independently -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dprc_set_irq_mask(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u8 irq_index, -+ u32 mask) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dprc_cmd_set_irq_mask *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_MASK, -+ cmd_flags, token); -+ cmd_params = (struct dprc_cmd_set_irq_mask *)cmd.params; -+ cmd_params->mask = cpu_to_le32(mask); -+ cmd_params->irq_index = irq_index; -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dprc_get_irq_status() - Get the current status of any pending interrupts. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPRC object -+ * @irq_index: The interrupt index to configure -+ * @status: Returned interrupts status - one bit per cause: -+ * 0 = no interrupt pending -+ * 1 = interrupt pending -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dprc_get_irq_status(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u8 irq_index, -+ u32 *status) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dprc_cmd_get_irq_status *cmd_params; -+ struct dprc_rsp_get_irq_status *rsp_params; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_STATUS, -+ cmd_flags, token); -+ cmd_params = (struct dprc_cmd_get_irq_status *)cmd.params; -+ cmd_params->status = cpu_to_le32(*status); -+ cmd_params->irq_index = irq_index; -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ rsp_params = (struct dprc_rsp_get_irq_status *)cmd.params; -+ *status = le32_to_cpu(rsp_params->status); -+ -+ return 0; -+} -+ -+/** -+ * dprc_clear_irq_status() - Clear a pending interrupt's status -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPRC object -+ * @irq_index: The interrupt index to configure -+ * @status: bits to clear (W1C) - one bit per cause: -+ * 0 = don't change -+ * 1 = clear status bit -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dprc_clear_irq_status(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u8 irq_index, -+ u32 status) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dprc_cmd_clear_irq_status *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLEAR_IRQ_STATUS, -+ cmd_flags, token); -+ cmd_params = (struct dprc_cmd_clear_irq_status *)cmd.params; -+ cmd_params->status = cpu_to_le32(status); -+ cmd_params->irq_index = irq_index; -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dprc_get_attributes() - Obtains container attributes -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPRC object -+ * @attributes Returned container attributes -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dprc_get_attributes(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ struct dprc_attributes *attr) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dprc_rsp_get_attributes *rsp_params; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_ATTR, -+ cmd_flags, -+ token); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ rsp_params = (struct dprc_rsp_get_attributes *)cmd.params; -+ attr->container_id = le32_to_cpu(rsp_params->container_id); -+ attr->icid = le32_to_cpu(rsp_params->icid); -+ attr->options = le32_to_cpu(rsp_params->options); -+ attr->portal_id = le32_to_cpu(rsp_params->portal_id); -+ -+ return 0; -+} -+ -+/** -+ * dprc_get_obj_count() - Obtains the number of objects in the DPRC -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPRC object -+ * @obj_count: Number of objects assigned to the DPRC -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dprc_get_obj_count(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ int *obj_count) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dprc_rsp_get_obj_count *rsp_params; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_COUNT, -+ cmd_flags, token); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ rsp_params = (struct dprc_rsp_get_obj_count *)cmd.params; -+ *obj_count = le32_to_cpu(rsp_params->obj_count); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(dprc_get_obj_count); -+ -+/** -+ * dprc_get_obj() - Get general information on an object -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPRC object -+ * @obj_index: Index of the object to be queried (< obj_count) -+ * @obj_desc: Returns the requested object descriptor -+ * -+ * The object descriptors are retrieved one by one by incrementing -+ * obj_index up to (not including) the value of obj_count returned -+ * from dprc_get_obj_count(). dprc_get_obj_count() must -+ * be called prior to dprc_get_obj(). -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dprc_get_obj(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ int obj_index, -+ struct fsl_mc_obj_desc *obj_desc) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dprc_cmd_get_obj *cmd_params; -+ struct dprc_rsp_get_obj *rsp_params; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ, -+ cmd_flags, -+ token); -+ cmd_params = (struct dprc_cmd_get_obj *)cmd.params; -+ cmd_params->obj_index = cpu_to_le32(obj_index); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ rsp_params = (struct dprc_rsp_get_obj *)cmd.params; -+ obj_desc->id = le32_to_cpu(rsp_params->id); -+ obj_desc->vendor = le16_to_cpu(rsp_params->vendor); -+ obj_desc->irq_count = rsp_params->irq_count; -+ obj_desc->region_count = rsp_params->region_count; -+ obj_desc->state = le32_to_cpu(rsp_params->state); -+ obj_desc->ver_major = le16_to_cpu(rsp_params->version_major); -+ obj_desc->ver_minor = le16_to_cpu(rsp_params->version_minor); -+ obj_desc->flags = le16_to_cpu(rsp_params->flags); -+ strncpy(obj_desc->type, rsp_params->type, 16); -+ obj_desc->type[15] = '\0'; -+ strncpy(obj_desc->label, rsp_params->label, 16); -+ obj_desc->label[15] = '\0'; -+ return 0; -+} -+EXPORT_SYMBOL_GPL(dprc_get_obj); -+ -+/** -+ * dprc_set_obj_irq() - Set IRQ information for object to trigger an interrupt. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPRC object -+ * @obj_type: Type of the object to set its IRQ -+ * @obj_id: ID of the object to set its IRQ -+ * @irq_index: The interrupt index to configure -+ * @irq_cfg: IRQ configuration -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dprc_set_obj_irq(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ char *obj_type, -+ int obj_id, -+ u8 irq_index, -+ struct dprc_irq_cfg *irq_cfg) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dprc_cmd_set_obj_irq *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_OBJ_IRQ, -+ cmd_flags, -+ token); -+ cmd_params = (struct dprc_cmd_set_obj_irq *)cmd.params; -+ cmd_params->irq_val = cpu_to_le32(irq_cfg->val); -+ cmd_params->irq_index = irq_index; -+ cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr); -+ cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num); -+ cmd_params->obj_id = cpu_to_le32(obj_id); -+ strncpy(cmd_params->obj_type, obj_type, 16); -+ cmd_params->obj_type[15] = '\0'; -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+EXPORT_SYMBOL_GPL(dprc_set_obj_irq); -+ -+/** -+ * dprc_get_obj_region() - Get region information for a specified object. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPRC object -+ * @obj_type; Object type as returned in dprc_get_obj() -+ * @obj_id: Unique object instance as returned in dprc_get_obj() -+ * @region_index: The specific region to query -+ * @region_desc: Returns the requested region descriptor -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dprc_get_obj_region(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ char *obj_type, -+ int obj_id, -+ u8 region_index, -+ struct dprc_region_desc *region_desc) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dprc_cmd_get_obj_region *cmd_params; -+ struct dprc_rsp_get_obj_region *rsp_params; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG, -+ cmd_flags, token); -+ cmd_params = (struct dprc_cmd_get_obj_region *)cmd.params; -+ cmd_params->obj_id = cpu_to_le32(obj_id); -+ cmd_params->region_index = region_index; -+ strncpy(cmd_params->obj_type, obj_type, 16); -+ cmd_params->obj_type[15] = '\0'; -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ rsp_params = (struct dprc_rsp_get_obj_region *)cmd.params; -+ region_desc->base_offset = le32_to_cpu(rsp_params->base_addr); -+ region_desc->size = le32_to_cpu(rsp_params->size); -+ region_desc->type = rsp_params->type; -+ region_desc->flags = le32_to_cpu(rsp_params->flags); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(dprc_get_obj_region); -+ -+/** -+ * dprc_get_api_version - Get Data Path Resource Container API version -+ * @mc_io: Pointer to Mc portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @major_ver: Major version of Data Path Resource Container API -+ * @minor_ver: Minor version of Data Path Resource Container API -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dprc_get_api_version(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 *major_ver, -+ u16 *minor_ver) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_API_VERSION, -+ cmd_flags, 0); -+ -+ /* send command to mc */ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ mc_cmd_read_api_version(&cmd, major_ver, minor_ver); -+ -+ return 0; -+} -+ -+/** -+ * dprc_get_container_id - Get container ID associated with a given portal. -+ * @mc_io: Pointer to Mc portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @container_id: Requested container id -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dprc_get_container_id(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ int *container_id) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONT_ID, -+ cmd_flags, -+ 0); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ *container_id = (int)mc_cmd_read_object_id(&cmd); -+ -+ return 0; -+} ---- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c -+++ /dev/null -@@ -1,668 +0,0 @@ --/* -- * Freescale MC object device allocator driver -- * -- * Copyright (C) 2013 Freescale Semiconductor, Inc. -- * -- * This file is licensed under the terms of the GNU General Public -- * License version 2. This program is licensed "as is" without any -- * warranty of any kind, whether express or implied. -- */ -- --#include <linux/module.h> --#include <linux/msi.h> --#include "../include/mc-bus.h" --#include "../include/mc-sys.h" --#include "../include/dpbp-cmd.h" --#include "../include/dpcon-cmd.h" -- --#include "fsl-mc-private.h" -- --#define FSL_MC_IS_ALLOCATABLE(_obj_type) \ -- (strcmp(_obj_type, "dpbp") == 0 || \ -- strcmp(_obj_type, "dpmcp") == 0 || \ -- strcmp(_obj_type, "dpcon") == 0) -- --/** -- * fsl_mc_resource_pool_add_device - add allocatable device to a resource -- * pool of a given MC bus -- * -- * @mc_bus: pointer to the MC bus -- * @pool_type: MC bus pool type -- * @mc_dev: Pointer to allocatable MC object device -- * -- * It adds an allocatable MC object device to a container's resource pool of -- * the given resource type -- */ --static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus -- *mc_bus, -- enum fsl_mc_pool_type -- pool_type, -- struct fsl_mc_device -- *mc_dev) --{ -- struct fsl_mc_resource_pool *res_pool; -- struct fsl_mc_resource *resource; -- struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; -- int error = -EINVAL; -- -- if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)) -- goto out; -- if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type))) -- goto out; -- if (WARN_ON(mc_dev->resource)) -- goto out; -- -- res_pool = &mc_bus->resource_pools[pool_type]; -- if (WARN_ON(res_pool->type != pool_type)) -- goto out; -- if (WARN_ON(res_pool->mc_bus != mc_bus)) -- goto out; -- -- mutex_lock(&res_pool->mutex); -- -- if (WARN_ON(res_pool->max_count < 0)) -- goto out_unlock; -- if (WARN_ON(res_pool->free_count < 0 || -- res_pool->free_count > res_pool->max_count)) -- goto out_unlock; -- -- resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource), -- GFP_KERNEL); -- if (!resource) { -- error = -ENOMEM; -- dev_err(&mc_bus_dev->dev, -- "Failed to allocate memory for fsl_mc_resource\n"); -- goto out_unlock; -- } -- -- resource->type = pool_type; -- resource->id = mc_dev->obj_desc.id; -- resource->data = mc_dev; -- resource->parent_pool = res_pool; -- INIT_LIST_HEAD(&resource->node); -- list_add_tail(&resource->node, &res_pool->free_list); -- mc_dev->resource = resource; -- res_pool->free_count++; -- res_pool->max_count++; -- error = 0; --out_unlock: -- mutex_unlock(&res_pool->mutex); --out: -- return error; --} -- --/** -- * fsl_mc_resource_pool_remove_device - remove an allocatable device from a -- * resource pool -- * -- * @mc_dev: Pointer to allocatable MC object device -- * -- * It permanently removes an allocatable MC object device from the resource -- * pool, the device is currently in, as long as it is in the pool's free list. -- */ --static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device -- *mc_dev) --{ -- struct fsl_mc_device *mc_bus_dev; -- struct fsl_mc_bus *mc_bus; -- struct fsl_mc_resource_pool *res_pool; -- struct fsl_mc_resource *resource; -- int error = -EINVAL; -- -- if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type))) -- goto out; -- -- resource = mc_dev->resource; -- if (WARN_ON(!resource || resource->data != mc_dev)) -- goto out; -- -- mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); -- mc_bus = to_fsl_mc_bus(mc_bus_dev); -- res_pool = resource->parent_pool; -- if (WARN_ON(res_pool != &mc_bus->resource_pools[resource->type])) -- goto out; -- -- mutex_lock(&res_pool->mutex); -- -- if (WARN_ON(res_pool->max_count <= 0)) -- goto out_unlock; -- if (WARN_ON(res_pool->free_count <= 0 || -- res_pool->free_count > res_pool->max_count)) -- goto out_unlock; -- -- /* -- * If the device is currently allocated, its resource is not -- * in the free list and thus, the device cannot be removed. -- */ -- if (list_empty(&resource->node)) { -- error = -EBUSY; -- dev_err(&mc_bus_dev->dev, -- "Device %s cannot be removed from resource pool\n", -- dev_name(&mc_dev->dev)); -- goto out_unlock; -- } -- -- list_del_init(&resource->node); -- res_pool->free_count--; -- res_pool->max_count--; -- -- devm_kfree(&mc_bus_dev->dev, resource); -- mc_dev->resource = NULL; -- error = 0; --out_unlock: -- mutex_unlock(&res_pool->mutex); --out: -- return error; --} -- --static const char *const fsl_mc_pool_type_strings[] = { -- [FSL_MC_POOL_DPMCP] = "dpmcp", -- [FSL_MC_POOL_DPBP] = "dpbp", -- [FSL_MC_POOL_DPCON] = "dpcon", -- [FSL_MC_POOL_IRQ] = "irq", --}; -- --static int __must_check object_type_to_pool_type(const char *object_type, -- enum fsl_mc_pool_type -- *pool_type) --{ -- unsigned int i; -- -- for (i = 0; i < ARRAY_SIZE(fsl_mc_pool_type_strings); i++) { -- if (strcmp(object_type, fsl_mc_pool_type_strings[i]) == 0) { -- *pool_type = i; -- return 0; -- } -- } -- -- return -EINVAL; --} -- --int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, -- enum fsl_mc_pool_type pool_type, -- struct fsl_mc_resource **new_resource) --{ -- struct fsl_mc_resource_pool *res_pool; -- struct fsl_mc_resource *resource; -- struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; -- int error = -EINVAL; -- -- BUILD_BUG_ON(ARRAY_SIZE(fsl_mc_pool_type_strings) != -- FSL_MC_NUM_POOL_TYPES); -- -- *new_resource = NULL; -- if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)) -- goto out; -- -- res_pool = &mc_bus->resource_pools[pool_type]; -- if (WARN_ON(res_pool->mc_bus != mc_bus)) -- goto out; -- -- mutex_lock(&res_pool->mutex); -- resource = list_first_entry_or_null(&res_pool->free_list, -- struct fsl_mc_resource, node); -- -- if (!resource) { -- WARN_ON(res_pool->free_count != 0); -- error = -ENXIO; -- dev_err(&mc_bus_dev->dev, -- "No more resources of type %s left\n", -- fsl_mc_pool_type_strings[pool_type]); -- goto out_unlock; -- } -- -- if (WARN_ON(resource->type != pool_type)) -- goto out_unlock; -- if (WARN_ON(resource->parent_pool != res_pool)) -- goto out_unlock; -- if (WARN_ON(res_pool->free_count <= 0 || -- res_pool->free_count > res_pool->max_count)) -- goto out_unlock; -- -- list_del_init(&resource->node); -- -- res_pool->free_count--; -- error = 0; --out_unlock: -- mutex_unlock(&res_pool->mutex); -- *new_resource = resource; --out: -- return error; --} --EXPORT_SYMBOL_GPL(fsl_mc_resource_allocate); -- --void fsl_mc_resource_free(struct fsl_mc_resource *resource) --{ -- struct fsl_mc_resource_pool *res_pool; -- -- res_pool = resource->parent_pool; -- if (WARN_ON(resource->type != res_pool->type)) -- return; -- -- mutex_lock(&res_pool->mutex); -- if (WARN_ON(res_pool->free_count < 0 || -- res_pool->free_count >= res_pool->max_count)) -- goto out_unlock; -- -- if (WARN_ON(!list_empty(&resource->node))) -- goto out_unlock; -- -- list_add_tail(&resource->node, &res_pool->free_list); -- res_pool->free_count++; --out_unlock: -- mutex_unlock(&res_pool->mutex); --} --EXPORT_SYMBOL_GPL(fsl_mc_resource_free); -- --/** -- * fsl_mc_object_allocate - Allocates a MC object device of the given -- * pool type from a given MC bus -- * -- * @mc_dev: MC device for which the MC object device is to be allocated -- * @pool_type: MC bus resource pool type -- * @new_mc_dev: Pointer to area where the pointer to the allocated -- * MC object device is to be returned -- * -- * This function allocates a MC object device from the device's parent DPRC, -- * from the corresponding MC bus' pool of allocatable MC object devices of -- * the given resource type. mc_dev cannot be a DPRC itself. -- * -- * NOTE: pool_type must be different from FSL_MC_POOL_MCP, since MC -- * portals are allocated using fsl_mc_portal_allocate(), instead of -- * this function. -- */ --int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev, -- enum fsl_mc_pool_type pool_type, -- struct fsl_mc_device **new_mc_adev) --{ -- struct fsl_mc_device *mc_bus_dev; -- struct fsl_mc_bus *mc_bus; -- struct fsl_mc_device *mc_adev; -- int error = -EINVAL; -- struct fsl_mc_resource *resource = NULL; -- -- *new_mc_adev = NULL; -- if (WARN_ON(mc_dev->flags & FSL_MC_IS_DPRC)) -- goto error; -- -- if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent))) -- goto error; -- -- if (WARN_ON(pool_type == FSL_MC_POOL_DPMCP)) -- goto error; -- -- mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); -- mc_bus = to_fsl_mc_bus(mc_bus_dev); -- error = fsl_mc_resource_allocate(mc_bus, pool_type, &resource); -- if (error < 0) -- goto error; -- -- mc_adev = resource->data; -- if (WARN_ON(!mc_adev)) -- goto error; -- -- *new_mc_adev = mc_adev; -- return 0; --error: -- if (resource) -- fsl_mc_resource_free(resource); -- -- return error; --} --EXPORT_SYMBOL_GPL(fsl_mc_object_allocate); -- --/** -- * fsl_mc_object_free - Returns an allocatable MC object device to the -- * corresponding resource pool of a given MC bus. -- * -- * @mc_adev: Pointer to the MC object device -- */ --void fsl_mc_object_free(struct fsl_mc_device *mc_adev) --{ -- struct fsl_mc_resource *resource; -- -- resource = mc_adev->resource; -- if (WARN_ON(resource->type == FSL_MC_POOL_DPMCP)) -- return; -- if (WARN_ON(resource->data != mc_adev)) -- return; -- -- fsl_mc_resource_free(resource); --} --EXPORT_SYMBOL_GPL(fsl_mc_object_free); -- --/* -- * Initialize the interrupt pool associated with a MC bus. -- * It allocates a block of IRQs from the GIC-ITS -- */ --int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, -- unsigned int irq_count) --{ -- unsigned int i; -- struct msi_desc *msi_desc; -- struct fsl_mc_device_irq *irq_resources; -- struct fsl_mc_device_irq *mc_dev_irq; -- int error; -- struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; -- struct fsl_mc_resource_pool *res_pool = -- &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; -- -- if (WARN_ON(irq_count == 0 || -- irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS)) -- return -EINVAL; -- -- error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count); -- if (error < 0) -- return error; -- -- irq_resources = devm_kzalloc(&mc_bus_dev->dev, -- sizeof(*irq_resources) * irq_count, -- GFP_KERNEL); -- if (!irq_resources) { -- error = -ENOMEM; -- goto cleanup_msi_irqs; -- } -- -- for (i = 0; i < irq_count; i++) { -- mc_dev_irq = &irq_resources[i]; -- -- /* -- * NOTE: This mc_dev_irq's MSI addr/value pair will be set -- * by the fsl_mc_msi_write_msg() callback -- */ -- mc_dev_irq->resource.type = res_pool->type; -- mc_dev_irq->resource.data = mc_dev_irq; -- mc_dev_irq->resource.parent_pool = res_pool; -- INIT_LIST_HEAD(&mc_dev_irq->resource.node); -- list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list); -- } -- -- for_each_msi_entry(msi_desc, &mc_bus_dev->dev) { -- mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index]; -- mc_dev_irq->msi_desc = msi_desc; -- mc_dev_irq->resource.id = msi_desc->irq; -- } -- -- res_pool->max_count = irq_count; -- res_pool->free_count = irq_count; -- mc_bus->irq_resources = irq_resources; -- return 0; -- --cleanup_msi_irqs: -- fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); -- return error; --} --EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool); -- --/** -- * Teardown the interrupt pool associated with an MC bus. -- * It frees the IRQs that were allocated to the pool, back to the GIC-ITS. -- */ --void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus) --{ -- struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; -- struct fsl_mc_resource_pool *res_pool = -- &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; -- -- if (WARN_ON(!mc_bus->irq_resources)) -- return; -- -- if (WARN_ON(res_pool->max_count == 0)) -- return; -- -- if (WARN_ON(res_pool->free_count != res_pool->max_count)) -- return; -- -- INIT_LIST_HEAD(&res_pool->free_list); -- res_pool->max_count = 0; -- res_pool->free_count = 0; -- mc_bus->irq_resources = NULL; -- fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); --} --EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool); -- --/** -- * It allocates the IRQs required by a given MC object device. The -- * IRQs are allocated from the interrupt pool associated with the -- * MC bus that contains the device, if the device is not a DPRC device. -- * Otherwise, the IRQs are allocated from the interrupt pool associated -- * with the MC bus that represents the DPRC device itself. -- */ --int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev) --{ -- int i; -- int irq_count; -- int res_allocated_count = 0; -- int error = -EINVAL; -- struct fsl_mc_device_irq **irqs = NULL; -- struct fsl_mc_bus *mc_bus; -- struct fsl_mc_resource_pool *res_pool; -- -- if (WARN_ON(mc_dev->irqs)) -- return -EINVAL; -- -- irq_count = mc_dev->obj_desc.irq_count; -- if (WARN_ON(irq_count == 0)) -- return -EINVAL; -- -- if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) -- mc_bus = to_fsl_mc_bus(mc_dev); -- else -- mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); -- -- if (WARN_ON(!mc_bus->irq_resources)) -- return -EINVAL; -- -- res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; -- if (res_pool->free_count < irq_count) { -- dev_err(&mc_dev->dev, -- "Not able to allocate %u irqs for device\n", irq_count); -- return -ENOSPC; -- } -- -- irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]), -- GFP_KERNEL); -- if (!irqs) -- return -ENOMEM; -- -- for (i = 0; i < irq_count; i++) { -- struct fsl_mc_resource *resource; -- -- error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ, -- &resource); -- if (error < 0) -- goto error_resource_alloc; -- -- irqs[i] = to_fsl_mc_irq(resource); -- res_allocated_count++; -- -- WARN_ON(irqs[i]->mc_dev); -- irqs[i]->mc_dev = mc_dev; -- irqs[i]->dev_irq_index = i; -- } -- -- mc_dev->irqs = irqs; -- return 0; -- --error_resource_alloc: -- for (i = 0; i < res_allocated_count; i++) { -- irqs[i]->mc_dev = NULL; -- fsl_mc_resource_free(&irqs[i]->resource); -- } -- -- return error; --} --EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs); -- --/* -- * It frees the IRQs that were allocated for a MC object device, by -- * returning them to the corresponding interrupt pool. -- */ --void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev) --{ -- int i; -- int irq_count; -- struct fsl_mc_bus *mc_bus; -- struct fsl_mc_device_irq **irqs = mc_dev->irqs; -- -- if (WARN_ON(!irqs)) -- return; -- -- irq_count = mc_dev->obj_desc.irq_count; -- -- if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) -- mc_bus = to_fsl_mc_bus(mc_dev); -- else -- mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); -- -- if (WARN_ON(!mc_bus->irq_resources)) -- return; -- -- for (i = 0; i < irq_count; i++) { -- WARN_ON(!irqs[i]->mc_dev); -- irqs[i]->mc_dev = NULL; -- fsl_mc_resource_free(&irqs[i]->resource); -- } -- -- mc_dev->irqs = NULL; --} --EXPORT_SYMBOL_GPL(fsl_mc_free_irqs); -- --void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev) --{ -- int pool_type; -- struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); -- -- for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) { -- struct fsl_mc_resource_pool *res_pool = -- &mc_bus->resource_pools[pool_type]; -- -- res_pool->type = pool_type; -- res_pool->max_count = 0; -- res_pool->free_count = 0; -- res_pool->mc_bus = mc_bus; -- INIT_LIST_HEAD(&res_pool->free_list); -- mutex_init(&res_pool->mutex); -- } --} -- --static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev, -- enum fsl_mc_pool_type pool_type) --{ -- struct fsl_mc_resource *resource; -- struct fsl_mc_resource *next; -- struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); -- struct fsl_mc_resource_pool *res_pool = -- &mc_bus->resource_pools[pool_type]; -- int free_count = 0; -- -- WARN_ON(res_pool->type != pool_type); -- WARN_ON(res_pool->free_count != res_pool->max_count); -- -- list_for_each_entry_safe(resource, next, &res_pool->free_list, node) { -- free_count++; -- WARN_ON(resource->type != res_pool->type); -- WARN_ON(resource->parent_pool != res_pool); -- devm_kfree(&mc_bus_dev->dev, resource); -- } -- -- WARN_ON(free_count != res_pool->free_count); --} -- --void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev) --{ -- int pool_type; -- -- for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) -- fsl_mc_cleanup_resource_pool(mc_bus_dev, pool_type); --} -- --/** -- * fsl_mc_allocator_probe - callback invoked when an allocatable device is -- * being added to the system -- */ --static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev) --{ -- enum fsl_mc_pool_type pool_type; -- struct fsl_mc_device *mc_bus_dev; -- struct fsl_mc_bus *mc_bus; -- int error; -- -- if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type))) -- return -EINVAL; -- -- mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); -- if (WARN_ON(!dev_is_fsl_mc(&mc_bus_dev->dev))) -- return -EINVAL; -- -- mc_bus = to_fsl_mc_bus(mc_bus_dev); -- error = object_type_to_pool_type(mc_dev->obj_desc.type, &pool_type); -- if (error < 0) -- return error; -- -- error = fsl_mc_resource_pool_add_device(mc_bus, pool_type, mc_dev); -- if (error < 0) -- return error; -- -- dev_dbg(&mc_dev->dev, -- "Allocatable MC object device bound to fsl_mc_allocator driver"); -- return 0; --} -- --/** -- * fsl_mc_allocator_remove - callback invoked when an allocatable device is -- * being removed from the system -- */ --static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev) --{ -- int error; -- -- if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type))) -- return -EINVAL; -- -- if (mc_dev->resource) { -- error = fsl_mc_resource_pool_remove_device(mc_dev); -- if (error < 0) -- return error; -- } -- -- dev_dbg(&mc_dev->dev, -- "Allocatable MC object device unbound from fsl_mc_allocator driver"); -- return 0; --} -- --static const struct fsl_mc_device_id match_id_table[] = { -- { -- .vendor = FSL_MC_VENDOR_FREESCALE, -- .obj_type = "dpbp", -- }, -- { -- .vendor = FSL_MC_VENDOR_FREESCALE, -- .obj_type = "dpmcp", -- }, -- { -- .vendor = FSL_MC_VENDOR_FREESCALE, -- .obj_type = "dpcon", -- }, -- {.vendor = 0x0}, --}; -- --static struct fsl_mc_driver fsl_mc_allocator_driver = { -- .driver = { -- .name = "fsl_mc_allocator", -- .pm = NULL, -- }, -- .match_id_table = match_id_table, -- .probe = fsl_mc_allocator_probe, -- .remove = fsl_mc_allocator_remove, --}; -- --int __init fsl_mc_allocator_driver_init(void) --{ -- return fsl_mc_driver_register(&fsl_mc_allocator_driver); --} -- --void fsl_mc_allocator_driver_exit(void) --{ -- fsl_mc_driver_unregister(&fsl_mc_allocator_driver); --} ---- /dev/null -+++ b/drivers/bus/fsl-mc/fsl-mc-allocator.c -@@ -0,0 +1,655 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * fsl-mc object allocator driver -+ * -+ * Copyright (C) 2013-2016 Freescale Semiconductor, Inc. -+ * -+ */ -+ -+#include <linux/module.h> -+#include <linux/msi.h> -+#include <linux/fsl/mc.h> -+ -+#include "fsl-mc-private.h" -+ -+static bool __must_check fsl_mc_is_allocatable(struct fsl_mc_device *mc_dev) -+{ -+ return is_fsl_mc_bus_dpbp(mc_dev) || -+ is_fsl_mc_bus_dpmcp(mc_dev) || -+ is_fsl_mc_bus_dpcon(mc_dev); -+} -+ -+/** -+ * fsl_mc_resource_pool_add_device - add allocatable object to a resource -+ * pool of a given fsl-mc bus -+ * -+ * @mc_bus: pointer to the fsl-mc bus -+ * @pool_type: pool type -+ * @mc_dev: pointer to allocatable fsl-mc device -+ */ -+static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus -+ *mc_bus, -+ enum fsl_mc_pool_type -+ pool_type, -+ struct fsl_mc_device -+ *mc_dev) -+{ -+ struct fsl_mc_resource_pool *res_pool; -+ struct fsl_mc_resource *resource; -+ struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; -+ int error = -EINVAL; -+ -+ if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES) -+ goto out; -+ if (!fsl_mc_is_allocatable(mc_dev)) -+ goto out; -+ if (mc_dev->resource) -+ goto out; -+ -+ res_pool = &mc_bus->resource_pools[pool_type]; -+ if (res_pool->type != pool_type) -+ goto out; -+ if (res_pool->mc_bus != mc_bus) -+ goto out; -+ -+ mutex_lock(&res_pool->mutex); -+ -+ if (res_pool->max_count < 0) -+ goto out_unlock; -+ if (res_pool->free_count < 0 || -+ res_pool->free_count > res_pool->max_count) -+ goto out_unlock; -+ -+ resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource), -+ GFP_KERNEL); -+ if (!resource) { -+ error = -ENOMEM; -+ dev_err(&mc_bus_dev->dev, -+ "Failed to allocate memory for fsl_mc_resource\n"); -+ goto out_unlock; -+ } -+ -+ resource->type = pool_type; -+ resource->id = mc_dev->obj_desc.id; -+ resource->data = mc_dev; -+ resource->parent_pool = res_pool; -+ INIT_LIST_HEAD(&resource->node); -+ list_add_tail(&resource->node, &res_pool->free_list); -+ mc_dev->resource = resource; -+ res_pool->free_count++; -+ res_pool->max_count++; -+ error = 0; -+out_unlock: -+ mutex_unlock(&res_pool->mutex); -+out: -+ return error; -+} -+ -+/** -+ * fsl_mc_resource_pool_remove_device - remove an allocatable device from a -+ * resource pool -+ * -+ * @mc_dev: pointer to allocatable fsl-mc device -+ * -+ * It permanently removes an allocatable fsl-mc device from the resource -+ * pool. It's an error if the device is in use. -+ */ -+static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device -+ *mc_dev) -+{ -+ struct fsl_mc_device *mc_bus_dev; -+ struct fsl_mc_bus *mc_bus; -+ struct fsl_mc_resource_pool *res_pool; -+ struct fsl_mc_resource *resource; -+ int error = -EINVAL; -+ -+ if (!fsl_mc_is_allocatable(mc_dev)) -+ goto out; -+ -+ resource = mc_dev->resource; -+ if (!resource || resource->data != mc_dev) -+ goto out; -+ -+ mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); -+ mc_bus = to_fsl_mc_bus(mc_bus_dev); -+ res_pool = resource->parent_pool; -+ if (res_pool != &mc_bus->resource_pools[resource->type]) -+ goto out; -+ -+ mutex_lock(&res_pool->mutex); -+ -+ if (res_pool->max_count <= 0) -+ goto out_unlock; -+ if (res_pool->free_count <= 0 || -+ res_pool->free_count > res_pool->max_count) -+ goto out_unlock; -+ -+ /* -+ * If the device is currently allocated, its resource is not -+ * in the free list and thus, the device cannot be removed. -+ */ -+ if (list_empty(&resource->node)) { -+ error = -EBUSY; -+ dev_err(&mc_bus_dev->dev, -+ "Device %s cannot be removed from resource pool\n", -+ dev_name(&mc_dev->dev)); -+ goto out_unlock; -+ } -+ -+ list_del_init(&resource->node); -+ res_pool->free_count--; -+ res_pool->max_count--; -+ -+ devm_kfree(&mc_bus_dev->dev, resource); -+ mc_dev->resource = NULL; -+ error = 0; -+out_unlock: -+ mutex_unlock(&res_pool->mutex); -+out: -+ return error; -+} -+ -+static const char *const fsl_mc_pool_type_strings[] = { -+ [FSL_MC_POOL_DPMCP] = "dpmcp", -+ [FSL_MC_POOL_DPBP] = "dpbp", -+ [FSL_MC_POOL_DPCON] = "dpcon", -+ [FSL_MC_POOL_IRQ] = "irq", -+}; -+ -+static int __must_check object_type_to_pool_type(const char *object_type, -+ enum fsl_mc_pool_type -+ *pool_type) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(fsl_mc_pool_type_strings); i++) { -+ if (strcmp(object_type, fsl_mc_pool_type_strings[i]) == 0) { -+ *pool_type = i; -+ return 0; -+ } -+ } -+ -+ return -EINVAL; -+} -+ -+int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, -+ enum fsl_mc_pool_type pool_type, -+ struct fsl_mc_resource **new_resource) -+{ -+ struct fsl_mc_resource_pool *res_pool; -+ struct fsl_mc_resource *resource; -+ struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; -+ int error = -EINVAL; -+ -+ BUILD_BUG_ON(ARRAY_SIZE(fsl_mc_pool_type_strings) != -+ FSL_MC_NUM_POOL_TYPES); -+ -+ *new_resource = NULL; -+ if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES) -+ goto out; -+ -+ res_pool = &mc_bus->resource_pools[pool_type]; -+ if (res_pool->mc_bus != mc_bus) -+ goto out; -+ -+ mutex_lock(&res_pool->mutex); -+ resource = list_first_entry_or_null(&res_pool->free_list, -+ struct fsl_mc_resource, node); -+ -+ if (!resource) { -+ error = -ENXIO; -+ dev_err(&mc_bus_dev->dev, -+ "No more resources of type %s left\n", -+ fsl_mc_pool_type_strings[pool_type]); -+ goto out_unlock; -+ } -+ -+ if (resource->type != pool_type) -+ goto out_unlock; -+ if (resource->parent_pool != res_pool) -+ goto out_unlock; -+ if (res_pool->free_count <= 0 || -+ res_pool->free_count > res_pool->max_count) -+ goto out_unlock; -+ -+ list_del_init(&resource->node); -+ -+ res_pool->free_count--; -+ error = 0; -+out_unlock: -+ mutex_unlock(&res_pool->mutex); -+ *new_resource = resource; -+out: -+ return error; -+} -+EXPORT_SYMBOL_GPL(fsl_mc_resource_allocate); -+ -+void fsl_mc_resource_free(struct fsl_mc_resource *resource) -+{ -+ struct fsl_mc_resource_pool *res_pool; -+ -+ res_pool = resource->parent_pool; -+ if (resource->type != res_pool->type) -+ return; -+ -+ mutex_lock(&res_pool->mutex); -+ if (res_pool->free_count < 0 || -+ res_pool->free_count >= res_pool->max_count) -+ goto out_unlock; -+ -+ if (!list_empty(&resource->node)) -+ goto out_unlock; -+ -+ list_add_tail(&resource->node, &res_pool->free_list); -+ res_pool->free_count++; -+out_unlock: -+ mutex_unlock(&res_pool->mutex); -+} -+EXPORT_SYMBOL_GPL(fsl_mc_resource_free); -+ -+/** -+ * fsl_mc_object_allocate - Allocates an fsl-mc object of the given -+ * pool type from a given fsl-mc bus instance -+ * -+ * @mc_dev: fsl-mc device which is used in conjunction with the -+ * allocated object -+ * @pool_type: pool type -+ * @new_mc_dev: pointer to area where the pointer to the allocated device -+ * is to be returned -+ * -+ * Allocatable objects are always used in conjunction with some functional -+ * device. This function allocates an object of the specified type from -+ * the DPRC containing the functional device. -+ * -+ * NOTE: pool_type must be different from FSL_MC_POOL_MCP, since MC -+ * portals are allocated using fsl_mc_portal_allocate(), instead of -+ * this function. -+ */ -+int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev, -+ enum fsl_mc_pool_type pool_type, -+ struct fsl_mc_device **new_mc_adev) -+{ -+ struct fsl_mc_device *mc_bus_dev; -+ struct fsl_mc_bus *mc_bus; -+ struct fsl_mc_device *mc_adev; -+ int error = -EINVAL; -+ struct fsl_mc_resource *resource = NULL; -+ -+ *new_mc_adev = NULL; -+ if (mc_dev->flags & FSL_MC_IS_DPRC) -+ goto error; -+ -+ if (!dev_is_fsl_mc(mc_dev->dev.parent)) -+ goto error; -+ -+ if (pool_type == FSL_MC_POOL_DPMCP) -+ goto error; -+ -+ mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); -+ mc_bus = to_fsl_mc_bus(mc_bus_dev); -+ error = fsl_mc_resource_allocate(mc_bus, pool_type, &resource); -+ if (error < 0) -+ goto error; -+ -+ mc_adev = resource->data; -+ if (!mc_adev) -+ goto error; -+ -+ *new_mc_adev = mc_adev; -+ return 0; -+error: -+ if (resource) -+ fsl_mc_resource_free(resource); -+ -+ return error; -+} -+EXPORT_SYMBOL_GPL(fsl_mc_object_allocate); -+ -+/** -+ * fsl_mc_object_free - Returns an fsl-mc object to the resource -+ * pool where it came from. -+ * @mc_adev: Pointer to the fsl-mc device -+ */ -+void fsl_mc_object_free(struct fsl_mc_device *mc_adev) -+{ -+ struct fsl_mc_resource *resource; -+ -+ resource = mc_adev->resource; -+ if (resource->type == FSL_MC_POOL_DPMCP) -+ return; -+ if (resource->data != mc_adev) -+ return; -+ -+ fsl_mc_resource_free(resource); -+} -+EXPORT_SYMBOL_GPL(fsl_mc_object_free); -+ -+/* -+ * A DPRC and the devices in the DPRC all share the same GIC-ITS device -+ * ID. A block of IRQs is pre-allocated and maintained in a pool -+ * from which devices can allocate them when needed. -+ */ -+ -+/* -+ * Initialize the interrupt pool associated with an fsl-mc bus. -+ * It allocates a block of IRQs from the GIC-ITS. -+ */ -+int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, -+ unsigned int irq_count) -+{ -+ unsigned int i; -+ struct msi_desc *msi_desc; -+ struct fsl_mc_device_irq *irq_resources; -+ struct fsl_mc_device_irq *mc_dev_irq; -+ int error; -+ struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; -+ struct fsl_mc_resource_pool *res_pool = -+ &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; -+ -+ if (irq_count == 0 || -+ irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) -+ return -EINVAL; -+ -+ error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count); -+ if (error < 0) -+ return error; -+ -+ irq_resources = devm_kzalloc(&mc_bus_dev->dev, -+ sizeof(*irq_resources) * irq_count, -+ GFP_KERNEL); -+ if (!irq_resources) { -+ error = -ENOMEM; -+ goto cleanup_msi_irqs; -+ } -+ -+ for (i = 0; i < irq_count; i++) { -+ mc_dev_irq = &irq_resources[i]; -+ -+ /* -+ * NOTE: This mc_dev_irq's MSI addr/value pair will be set -+ * by the fsl_mc_msi_write_msg() callback -+ */ -+ mc_dev_irq->resource.type = res_pool->type; -+ mc_dev_irq->resource.data = mc_dev_irq; -+ mc_dev_irq->resource.parent_pool = res_pool; -+ INIT_LIST_HEAD(&mc_dev_irq->resource.node); -+ list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list); -+ } -+ -+ for_each_msi_entry(msi_desc, &mc_bus_dev->dev) { -+ mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index]; -+ mc_dev_irq->msi_desc = msi_desc; -+ mc_dev_irq->resource.id = msi_desc->irq; -+ } -+ -+ res_pool->max_count = irq_count; -+ res_pool->free_count = irq_count; -+ mc_bus->irq_resources = irq_resources; -+ return 0; -+ -+cleanup_msi_irqs: -+ fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); -+ return error; -+} -+EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool); -+ -+/** -+ * Teardown the interrupt pool associated with an fsl-mc bus. -+ * It frees the IRQs that were allocated to the pool, back to the GIC-ITS. -+ */ -+void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus) -+{ -+ struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; -+ struct fsl_mc_resource_pool *res_pool = -+ &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; -+ -+ if (!mc_bus->irq_resources) -+ return; -+ -+ if (res_pool->max_count == 0) -+ return; -+ -+ if (res_pool->free_count != res_pool->max_count) -+ return; -+ -+ INIT_LIST_HEAD(&res_pool->free_list); -+ res_pool->max_count = 0; -+ res_pool->free_count = 0; -+ mc_bus->irq_resources = NULL; -+ fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); -+} -+EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool); -+ -+/** -+ * Allocate the IRQs required by a given fsl-mc device. -+ */ -+int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev) -+{ -+ int i; -+ int irq_count; -+ int res_allocated_count = 0; -+ int error = -EINVAL; -+ struct fsl_mc_device_irq **irqs = NULL; -+ struct fsl_mc_bus *mc_bus; -+ struct fsl_mc_resource_pool *res_pool; -+ -+ if (mc_dev->irqs) -+ return -EINVAL; -+ -+ irq_count = mc_dev->obj_desc.irq_count; -+ if (irq_count == 0) -+ return -EINVAL; -+ -+ if (is_fsl_mc_bus_dprc(mc_dev)) -+ mc_bus = to_fsl_mc_bus(mc_dev); -+ else -+ mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); -+ -+ if (!mc_bus->irq_resources) -+ return -EINVAL; -+ -+ res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; -+ if (res_pool->free_count < irq_count) { -+ dev_err(&mc_dev->dev, -+ "Not able to allocate %u irqs for device\n", irq_count); -+ return -ENOSPC; -+ } -+ -+ irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]), -+ GFP_KERNEL); -+ if (!irqs) -+ return -ENOMEM; -+ -+ for (i = 0; i < irq_count; i++) { -+ struct fsl_mc_resource *resource; -+ -+ error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ, -+ &resource); -+ if (error < 0) -+ goto error_resource_alloc; -+ -+ irqs[i] = to_fsl_mc_irq(resource); -+ res_allocated_count++; -+ -+ irqs[i]->mc_dev = mc_dev; -+ irqs[i]->dev_irq_index = i; -+ } -+ -+ mc_dev->irqs = irqs; -+ return 0; -+ -+error_resource_alloc: -+ for (i = 0; i < res_allocated_count; i++) { -+ irqs[i]->mc_dev = NULL; -+ fsl_mc_resource_free(&irqs[i]->resource); -+ } -+ -+ return error; -+} -+EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs); -+ -+/* -+ * Frees the IRQs that were allocated for an fsl-mc device. -+ */ -+void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev) -+{ -+ int i; -+ int irq_count; -+ struct fsl_mc_bus *mc_bus; -+ struct fsl_mc_device_irq **irqs = mc_dev->irqs; -+ -+ if (!irqs) -+ return; -+ -+ irq_count = mc_dev->obj_desc.irq_count; -+ -+ if (is_fsl_mc_bus_dprc(mc_dev)) -+ mc_bus = to_fsl_mc_bus(mc_dev); -+ else -+ mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); -+ -+ if (!mc_bus->irq_resources) -+ return; -+ -+ for (i = 0; i < irq_count; i++) { -+ irqs[i]->mc_dev = NULL; -+ fsl_mc_resource_free(&irqs[i]->resource); -+ } -+ -+ mc_dev->irqs = NULL; -+} -+EXPORT_SYMBOL_GPL(fsl_mc_free_irqs); -+ -+void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev) -+{ -+ int pool_type; -+ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); -+ -+ for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) { -+ struct fsl_mc_resource_pool *res_pool = -+ &mc_bus->resource_pools[pool_type]; -+ -+ res_pool->type = pool_type; -+ res_pool->max_count = 0; -+ res_pool->free_count = 0; -+ res_pool->mc_bus = mc_bus; -+ INIT_LIST_HEAD(&res_pool->free_list); -+ mutex_init(&res_pool->mutex); -+ } -+} -+EXPORT_SYMBOL_GPL(fsl_mc_init_all_resource_pools); -+ -+static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev, -+ enum fsl_mc_pool_type pool_type) -+{ -+ struct fsl_mc_resource *resource; -+ struct fsl_mc_resource *next; -+ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); -+ struct fsl_mc_resource_pool *res_pool = -+ &mc_bus->resource_pools[pool_type]; -+ int free_count = 0; -+ -+ list_for_each_entry_safe(resource, next, &res_pool->free_list, node) { -+ free_count++; -+ devm_kfree(&mc_bus_dev->dev, resource); -+ } -+} -+ -+void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev) -+{ -+ int pool_type; -+ -+ for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) -+ fsl_mc_cleanup_resource_pool(mc_bus_dev, pool_type); -+} -+EXPORT_SYMBOL_GPL(fsl_mc_cleanup_all_resource_pools); -+ -+/** -+ * fsl_mc_allocator_probe - callback invoked when an allocatable device is -+ * being added to the system -+ */ -+static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev) -+{ -+ enum fsl_mc_pool_type pool_type; -+ struct fsl_mc_device *mc_bus_dev; -+ struct fsl_mc_bus *mc_bus; -+ int error; -+ -+ if (!fsl_mc_is_allocatable(mc_dev)) -+ return -EINVAL; -+ -+ mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); -+ if (!dev_is_fsl_mc(&mc_bus_dev->dev)) -+ return -EINVAL; -+ -+ mc_bus = to_fsl_mc_bus(mc_bus_dev); -+ error = object_type_to_pool_type(mc_dev->obj_desc.type, &pool_type); -+ if (error < 0) -+ return error; -+ -+ error = fsl_mc_resource_pool_add_device(mc_bus, pool_type, mc_dev); -+ if (error < 0) -+ return error; -+ -+ dev_dbg(&mc_dev->dev, -+ "Allocatable fsl-mc device bound to fsl_mc_allocator driver"); -+ return 0; -+} -+ -+/** -+ * fsl_mc_allocator_remove - callback invoked when an allocatable device is -+ * being removed from the system -+ */ -+static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev) -+{ -+ int error; -+ -+ if (!fsl_mc_is_allocatable(mc_dev)) -+ return -EINVAL; -+ -+ if (mc_dev->resource) { -+ error = fsl_mc_resource_pool_remove_device(mc_dev); -+ if (error < 0) -+ return error; -+ } -+ -+ dev_dbg(&mc_dev->dev, -+ "Allocatable fsl-mc device unbound from fsl_mc_allocator driver"); -+ return 0; -+} -+ -+static const struct fsl_mc_device_id match_id_table[] = { -+ { -+ .vendor = FSL_MC_VENDOR_FREESCALE, -+ .obj_type = "dpbp", -+ }, -+ { -+ .vendor = FSL_MC_VENDOR_FREESCALE, -+ .obj_type = "dpmcp", -+ }, -+ { -+ .vendor = FSL_MC_VENDOR_FREESCALE, -+ .obj_type = "dpcon", -+ }, -+ {.vendor = 0x0}, -+}; -+ -+static struct fsl_mc_driver fsl_mc_allocator_driver = { -+ .driver = { -+ .name = "fsl_mc_allocator", -+ .pm = NULL, -+ }, -+ .match_id_table = match_id_table, -+ .probe = fsl_mc_allocator_probe, -+ .remove = fsl_mc_allocator_remove, -+}; -+ -+int __init fsl_mc_allocator_driver_init(void) -+{ -+ return fsl_mc_driver_register(&fsl_mc_allocator_driver); -+} -+ -+void fsl_mc_allocator_driver_exit(void) -+{ -+ fsl_mc_driver_unregister(&fsl_mc_allocator_driver); -+} ---- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c -+++ /dev/null -@@ -1,920 +0,0 @@ --/* -- * Freescale Management Complex (MC) bus driver -- * -- * Copyright (C) 2014 Freescale Semiconductor, Inc. -- * Author: German Rivera <German.Rivera@freescale.com> -- * -- * This file is licensed under the terms of the GNU General Public -- * License version 2. This program is licensed "as is" without any -- * warranty of any kind, whether express or implied. -- */ -- --#include <linux/module.h> --#include <linux/of_device.h> --#include <linux/of_address.h> --#include <linux/ioport.h> --#include <linux/slab.h> --#include <linux/limits.h> --#include <linux/bitops.h> --#include <linux/msi.h> --#include <linux/dma-mapping.h> --#include "../include/mc-bus.h" --#include "../include/dpmng.h" --#include "../include/mc-sys.h" -- --#include "fsl-mc-private.h" --#include "dprc-cmd.h" -- --static struct kmem_cache *mc_dev_cache; -- --/** -- * Default DMA mask for devices on a fsl-mc bus -- */ --#define FSL_MC_DEFAULT_DMA_MASK (~0ULL) -- --/** -- * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device -- * @root_mc_bus_dev: MC object device representing the root DPRC -- * @num_translation_ranges: number of entries in addr_translation_ranges -- * @translation_ranges: array of bus to system address translation ranges -- */ --struct fsl_mc { -- struct fsl_mc_device *root_mc_bus_dev; -- u8 num_translation_ranges; -- struct fsl_mc_addr_translation_range *translation_ranges; --}; -- --/** -- * struct fsl_mc_addr_translation_range - bus to system address translation -- * range -- * @mc_region_type: Type of MC region for the range being translated -- * @start_mc_offset: Start MC offset of the range being translated -- * @end_mc_offset: MC offset of the first byte after the range (last MC -- * offset of the range is end_mc_offset - 1) -- * @start_phys_addr: system physical address corresponding to start_mc_addr -- */ --struct fsl_mc_addr_translation_range { -- enum dprc_region_type mc_region_type; -- u64 start_mc_offset; -- u64 end_mc_offset; -- phys_addr_t start_phys_addr; --}; -- --/** -- * fsl_mc_bus_match - device to driver matching callback -- * @dev: the MC object device structure to match against -- * @drv: the device driver to search for matching MC object device id -- * structures -- * -- * Returns 1 on success, 0 otherwise. -- */ --static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv) --{ -- const struct fsl_mc_device_id *id; -- struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); -- struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv); -- bool found = false; -- -- if (WARN_ON(!fsl_mc_bus_exists())) -- goto out; -- -- if (!mc_drv->match_id_table) -- goto out; -- -- /* -- * If the object is not 'plugged' don't match. -- * Only exception is the root DPRC, which is a special case. -- */ -- if ((mc_dev->obj_desc.state & DPRC_OBJ_STATE_PLUGGED) == 0 && -- !fsl_mc_is_root_dprc(&mc_dev->dev)) -- goto out; -- -- /* -- * Traverse the match_id table of the given driver, trying to find -- * a matching for the given MC object device. -- */ -- for (id = mc_drv->match_id_table; id->vendor != 0x0; id++) { -- if (id->vendor == mc_dev->obj_desc.vendor && -- strcmp(id->obj_type, mc_dev->obj_desc.type) == 0) { -- found = true; -- -- break; -- } -- } -- --out: -- dev_dbg(dev, "%smatched\n", found ? "" : "not "); -- return found; --} -- --/** -- * fsl_mc_bus_uevent - callback invoked when a device is added -- */ --static int fsl_mc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) --{ -- struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); -- -- if (add_uevent_var(env, "MODALIAS=fsl-mc:v%08Xd%s", -- mc_dev->obj_desc.vendor, -- mc_dev->obj_desc.type)) -- return -ENOMEM; -- -- return 0; --} -- --static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, -- char *buf) --{ -- struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); -- -- return sprintf(buf, "fsl-mc:v%08Xd%s\n", mc_dev->obj_desc.vendor, -- mc_dev->obj_desc.type); --} --static DEVICE_ATTR_RO(modalias); -- --static struct attribute *fsl_mc_dev_attrs[] = { -- &dev_attr_modalias.attr, -- NULL, --}; -- --ATTRIBUTE_GROUPS(fsl_mc_dev); -- --struct bus_type fsl_mc_bus_type = { -- .name = "fsl-mc", -- .match = fsl_mc_bus_match, -- .uevent = fsl_mc_bus_uevent, -- .dev_groups = fsl_mc_dev_groups, --}; --EXPORT_SYMBOL_GPL(fsl_mc_bus_type); -- --static atomic_t root_dprc_count = ATOMIC_INIT(0); -- --static int fsl_mc_driver_probe(struct device *dev) --{ -- struct fsl_mc_driver *mc_drv; -- struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); -- int error; -- -- if (WARN_ON(!dev->driver)) -- return -EINVAL; -- -- mc_drv = to_fsl_mc_driver(dev->driver); -- if (WARN_ON(!mc_drv->probe)) -- return -EINVAL; -- -- error = mc_drv->probe(mc_dev); -- if (error < 0) { -- dev_err(dev, "MC object device probe callback failed: %d\n", -- error); -- return error; -- } -- -- return 0; --} -- --static int fsl_mc_driver_remove(struct device *dev) --{ -- struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); -- struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); -- int error; -- -- if (WARN_ON(!dev->driver)) -- return -EINVAL; -- -- error = mc_drv->remove(mc_dev); -- if (error < 0) { -- dev_err(dev, -- "MC object device remove callback failed: %d\n", -- error); -- return error; -- } -- -- return 0; --} -- --static void fsl_mc_driver_shutdown(struct device *dev) --{ -- struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); -- struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); -- -- mc_drv->shutdown(mc_dev); --} -- --/** -- * __fsl_mc_driver_register - registers a child device driver with the -- * MC bus -- * -- * This function is implicitly invoked from the registration function of -- * fsl_mc device drivers, which is generated by the -- * module_fsl_mc_driver() macro. -- */ --int __fsl_mc_driver_register(struct fsl_mc_driver *mc_driver, -- struct module *owner) --{ -- int error; -- -- mc_driver->driver.owner = owner; -- mc_driver->driver.bus = &fsl_mc_bus_type; -- -- if (mc_driver->probe) -- mc_driver->driver.probe = fsl_mc_driver_probe; -- -- if (mc_driver->remove) -- mc_driver->driver.remove = fsl_mc_driver_remove; -- -- if (mc_driver->shutdown) -- mc_driver->driver.shutdown = fsl_mc_driver_shutdown; -- -- error = driver_register(&mc_driver->driver); -- if (error < 0) { -- pr_err("driver_register() failed for %s: %d\n", -- mc_driver->driver.name, error); -- return error; -- } -- -- pr_info("MC object device driver %s registered\n", -- mc_driver->driver.name); -- return 0; --} --EXPORT_SYMBOL_GPL(__fsl_mc_driver_register); -- --/** -- * fsl_mc_driver_unregister - unregisters a device driver from the -- * MC bus -- */ --void fsl_mc_driver_unregister(struct fsl_mc_driver *mc_driver) --{ -- driver_unregister(&mc_driver->driver); --} --EXPORT_SYMBOL_GPL(fsl_mc_driver_unregister); -- --/** -- * fsl_mc_bus_exists - check if a root dprc exists -- */ --bool fsl_mc_bus_exists(void) --{ -- return atomic_read(&root_dprc_count) > 0; --} --EXPORT_SYMBOL_GPL(fsl_mc_bus_exists); -- --/** -- * fsl_mc_get_root_dprc - function to traverse to the root dprc -- */ --void fsl_mc_get_root_dprc(struct device *dev, -- struct device **root_dprc_dev) --{ -- if (WARN_ON(!dev)) { -- *root_dprc_dev = NULL; -- } else if (WARN_ON(!dev_is_fsl_mc(dev))) { -- *root_dprc_dev = NULL; -- } else { -- *root_dprc_dev = dev; -- while (dev_is_fsl_mc((*root_dprc_dev)->parent)) -- *root_dprc_dev = (*root_dprc_dev)->parent; -- } --} --EXPORT_SYMBOL_GPL(fsl_mc_get_root_dprc); -- --static int get_dprc_attr(struct fsl_mc_io *mc_io, -- int container_id, struct dprc_attributes *attr) --{ -- u16 dprc_handle; -- int error; -- -- error = dprc_open(mc_io, 0, container_id, &dprc_handle); -- if (error < 0) { -- dev_err(mc_io->dev, "dprc_open() failed: %d\n", error); -- return error; -- } -- -- memset(attr, 0, sizeof(struct dprc_attributes)); -- error = dprc_get_attributes(mc_io, 0, dprc_handle, attr); -- if (error < 0) { -- dev_err(mc_io->dev, "dprc_get_attributes() failed: %d\n", -- error); -- goto common_cleanup; -- } -- -- error = 0; -- --common_cleanup: -- (void)dprc_close(mc_io, 0, dprc_handle); -- return error; --} -- --static int get_dprc_icid(struct fsl_mc_io *mc_io, -- int container_id, u16 *icid) --{ -- struct dprc_attributes attr; -- int error; -- -- error = get_dprc_attr(mc_io, container_id, &attr); -- if (error == 0) -- *icid = attr.icid; -- -- return error; --} -- --static int get_dprc_version(struct fsl_mc_io *mc_io, -- int container_id, u16 *major, u16 *minor) --{ -- struct dprc_attributes attr; -- int error; -- -- error = get_dprc_attr(mc_io, container_id, &attr); -- if (error == 0) { -- *major = attr.version.major; -- *minor = attr.version.minor; -- } -- -- return error; --} -- --static int translate_mc_addr(struct fsl_mc_device *mc_dev, -- enum dprc_region_type mc_region_type, -- u64 mc_offset, phys_addr_t *phys_addr) --{ -- int i; -- struct device *root_dprc_dev; -- struct fsl_mc *mc; -- -- fsl_mc_get_root_dprc(&mc_dev->dev, &root_dprc_dev); -- if (WARN_ON(!root_dprc_dev)) -- return -EINVAL; -- mc = dev_get_drvdata(root_dprc_dev->parent); -- -- if (mc->num_translation_ranges == 0) { -- /* -- * Do identity mapping: -- */ -- *phys_addr = mc_offset; -- return 0; -- } -- -- for (i = 0; i < mc->num_translation_ranges; i++) { -- struct fsl_mc_addr_translation_range *range = -- &mc->translation_ranges[i]; -- -- if (mc_region_type == range->mc_region_type && -- mc_offset >= range->start_mc_offset && -- mc_offset < range->end_mc_offset) { -- *phys_addr = range->start_phys_addr + -- (mc_offset - range->start_mc_offset); -- return 0; -- } -- } -- -- return -EFAULT; --} -- --static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev, -- struct fsl_mc_device *mc_bus_dev) --{ -- int i; -- int error; -- struct resource *regions; -- struct dprc_obj_desc *obj_desc = &mc_dev->obj_desc; -- struct device *parent_dev = mc_dev->dev.parent; -- enum dprc_region_type mc_region_type; -- -- if (strcmp(obj_desc->type, "dprc") == 0 || -- strcmp(obj_desc->type, "dpmcp") == 0) { -- mc_region_type = DPRC_REGION_TYPE_MC_PORTAL; -- } else if (strcmp(obj_desc->type, "dpio") == 0) { -- mc_region_type = DPRC_REGION_TYPE_QBMAN_PORTAL; -- } else { -- /* -- * This function should not have been called for this MC object -- * type, as this object type is not supposed to have MMIO -- * regions -- */ -- WARN_ON(true); -- return -EINVAL; -- } -- -- regions = kmalloc_array(obj_desc->region_count, -- sizeof(regions[0]), GFP_KERNEL); -- if (!regions) -- return -ENOMEM; -- -- for (i = 0; i < obj_desc->region_count; i++) { -- struct dprc_region_desc region_desc; -- -- error = dprc_get_obj_region(mc_bus_dev->mc_io, -- 0, -- mc_bus_dev->mc_handle, -- obj_desc->type, -- obj_desc->id, i, ®ion_desc); -- if (error < 0) { -- dev_err(parent_dev, -- "dprc_get_obj_region() failed: %d\n", error); -- goto error_cleanup_regions; -- } -- -- WARN_ON(region_desc.size == 0); -- error = translate_mc_addr(mc_dev, mc_region_type, -- region_desc.base_offset, -- ®ions[i].start); -- if (error < 0) { -- dev_err(parent_dev, -- "Invalid MC offset: %#x (for %s.%d\'s region %d)\n", -- region_desc.base_offset, -- obj_desc->type, obj_desc->id, i); -- goto error_cleanup_regions; -- } -- -- regions[i].end = regions[i].start + region_desc.size - 1; -- regions[i].name = "fsl-mc object MMIO region"; -- regions[i].flags = IORESOURCE_IO; -- if (region_desc.flags & DPRC_REGION_CACHEABLE) -- regions[i].flags |= IORESOURCE_CACHEABLE; -- } -- -- mc_dev->regions = regions; -- return 0; -- --error_cleanup_regions: -- kfree(regions); -- return error; --} -- --/** -- * fsl_mc_is_root_dprc - function to check if a given device is a root dprc -- */ --bool fsl_mc_is_root_dprc(struct device *dev) --{ -- struct device *root_dprc_dev; -- -- fsl_mc_get_root_dprc(dev, &root_dprc_dev); -- if (!root_dprc_dev) -- return false; -- return dev == root_dprc_dev; --} -- --/** -- * Add a newly discovered MC object device to be visible in Linux -- */ --int fsl_mc_device_add(struct dprc_obj_desc *obj_desc, -- struct fsl_mc_io *mc_io, -- struct device *parent_dev, -- struct fsl_mc_device **new_mc_dev) --{ -- int error; -- struct fsl_mc_device *mc_dev = NULL; -- struct fsl_mc_bus *mc_bus = NULL; -- struct fsl_mc_device *parent_mc_dev; -- -- if (dev_is_fsl_mc(parent_dev)) -- parent_mc_dev = to_fsl_mc_device(parent_dev); -- else -- parent_mc_dev = NULL; -- -- if (strcmp(obj_desc->type, "dprc") == 0) { -- /* -- * Allocate an MC bus device object: -- */ -- mc_bus = devm_kzalloc(parent_dev, sizeof(*mc_bus), GFP_KERNEL); -- if (!mc_bus) -- return -ENOMEM; -- -- mc_dev = &mc_bus->mc_dev; -- } else { -- /* -- * Allocate a regular fsl_mc_device object: -- */ -- mc_dev = kmem_cache_zalloc(mc_dev_cache, GFP_KERNEL); -- if (!mc_dev) -- return -ENOMEM; -- } -- -- mc_dev->obj_desc = *obj_desc; -- mc_dev->mc_io = mc_io; -- device_initialize(&mc_dev->dev); -- mc_dev->dev.parent = parent_dev; -- mc_dev->dev.bus = &fsl_mc_bus_type; -- dev_set_name(&mc_dev->dev, "%s.%d", obj_desc->type, obj_desc->id); -- -- if (strcmp(obj_desc->type, "dprc") == 0) { -- struct fsl_mc_io *mc_io2; -- -- mc_dev->flags |= FSL_MC_IS_DPRC; -- -- /* -- * To get the DPRC's ICID, we need to open the DPRC -- * in get_dprc_icid(). For child DPRCs, we do so using the -- * parent DPRC's MC portal instead of the child DPRC's MC -- * portal, in case the child DPRC is already opened with -- * its own portal (e.g., the DPRC used by AIOP). -- * -- * NOTE: There cannot be more than one active open for a -- * given MC object, using the same MC portal. -- */ -- if (parent_mc_dev) { -- /* -- * device being added is a child DPRC device -- */ -- mc_io2 = parent_mc_dev->mc_io; -- } else { -- /* -- * device being added is the root DPRC device -- */ -- if (WARN_ON(!mc_io)) { -- error = -EINVAL; -- goto error_cleanup_dev; -- } -- -- mc_io2 = mc_io; -- -- atomic_inc(&root_dprc_count); -- } -- -- error = get_dprc_icid(mc_io2, obj_desc->id, &mc_dev->icid); -- if (error < 0) -- goto error_cleanup_dev; -- } else { -- /* -- * A non-DPRC MC object device has to be a child of another -- * MC object (specifically a DPRC object) -- */ -- mc_dev->icid = parent_mc_dev->icid; -- mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK; -- mc_dev->dev.dma_mask = &mc_dev->dma_mask; -- dev_set_msi_domain(&mc_dev->dev, -- dev_get_msi_domain(&parent_mc_dev->dev)); -- } -- -- /* -- * Get MMIO regions for the device from the MC: -- * -- * NOTE: the root DPRC is a special case as its MMIO region is -- * obtained from the device tree -- */ -- if (parent_mc_dev && obj_desc->region_count != 0) { -- error = fsl_mc_device_get_mmio_regions(mc_dev, -- parent_mc_dev); -- if (error < 0) -- goto error_cleanup_dev; -- } -- -- /* Objects are coherent, unless 'no shareability' flag set. */ -- if (!(obj_desc->flags & DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY)) -- arch_setup_dma_ops(&mc_dev->dev, 0, 0, NULL, true); -- -- /* -- * The device-specific probe callback will get invoked by device_add() -- */ -- error = device_add(&mc_dev->dev); -- if (error < 0) { -- dev_err(parent_dev, -- "device_add() failed for device %s: %d\n", -- dev_name(&mc_dev->dev), error); -- goto error_cleanup_dev; -- } -- -- (void)get_device(&mc_dev->dev); -- dev_dbg(parent_dev, "Added MC object device %s\n", -- dev_name(&mc_dev->dev)); -- -- *new_mc_dev = mc_dev; -- return 0; -- --error_cleanup_dev: -- kfree(mc_dev->regions); -- if (mc_bus) -- devm_kfree(parent_dev, mc_bus); -- else -- kmem_cache_free(mc_dev_cache, mc_dev); -- -- return error; --} --EXPORT_SYMBOL_GPL(fsl_mc_device_add); -- --/** -- * fsl_mc_device_remove - Remove a MC object device from being visible to -- * Linux -- * -- * @mc_dev: Pointer to a MC object device object -- */ --void fsl_mc_device_remove(struct fsl_mc_device *mc_dev) --{ -- struct fsl_mc_bus *mc_bus = NULL; -- -- kfree(mc_dev->regions); -- -- /* -- * The device-specific remove callback will get invoked by device_del() -- */ -- device_del(&mc_dev->dev); -- put_device(&mc_dev->dev); -- -- if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) { -- mc_bus = to_fsl_mc_bus(mc_dev); -- -- if (fsl_mc_is_root_dprc(&mc_dev->dev)) { -- if (atomic_read(&root_dprc_count) > 0) -- atomic_dec(&root_dprc_count); -- else -- WARN_ON(1); -- } -- } -- -- if (mc_bus) -- devm_kfree(mc_dev->dev.parent, mc_bus); -- else -- kmem_cache_free(mc_dev_cache, mc_dev); --} --EXPORT_SYMBOL_GPL(fsl_mc_device_remove); -- --static int parse_mc_ranges(struct device *dev, -- int *paddr_cells, -- int *mc_addr_cells, -- int *mc_size_cells, -- const __be32 **ranges_start, -- u8 *num_ranges) --{ -- const __be32 *prop; -- int range_tuple_cell_count; -- int ranges_len; -- int tuple_len; -- struct device_node *mc_node = dev->of_node; -- -- *ranges_start = of_get_property(mc_node, "ranges", &ranges_len); -- if (!(*ranges_start) || !ranges_len) { -- dev_warn(dev, -- "missing or empty ranges property for device tree node '%s'\n", -- mc_node->name); -- -- *num_ranges = 0; -- return 0; -- } -- -- *paddr_cells = of_n_addr_cells(mc_node); -- -- prop = of_get_property(mc_node, "#address-cells", NULL); -- if (prop) -- *mc_addr_cells = be32_to_cpup(prop); -- else -- *mc_addr_cells = *paddr_cells; -- -- prop = of_get_property(mc_node, "#size-cells", NULL); -- if (prop) -- *mc_size_cells = be32_to_cpup(prop); -- else -- *mc_size_cells = of_n_size_cells(mc_node); -- -- range_tuple_cell_count = *paddr_cells + *mc_addr_cells + -- *mc_size_cells; -- -- tuple_len = range_tuple_cell_count * sizeof(__be32); -- if (ranges_len % tuple_len != 0) { -- dev_err(dev, "malformed ranges property '%s'\n", mc_node->name); -- return -EINVAL; -- } -- -- *num_ranges = ranges_len / tuple_len; -- return 0; --} -- --static int get_mc_addr_translation_ranges(struct device *dev, -- struct fsl_mc_addr_translation_range -- **ranges, -- u8 *num_ranges) --{ -- int error; -- int paddr_cells; -- int mc_addr_cells; -- int mc_size_cells; -- int i; -- const __be32 *ranges_start; -- const __be32 *cell; -- -- error = parse_mc_ranges(dev, -- &paddr_cells, -- &mc_addr_cells, -- &mc_size_cells, -- &ranges_start, -- num_ranges); -- if (error < 0) -- return error; -- -- if (!(*num_ranges)) { -- /* -- * Missing or empty ranges property ("ranges;") for the -- * 'fsl,qoriq-mc' node. In this case, identity mapping -- * will be used. -- */ -- *ranges = NULL; -- return 0; -- } -- -- *ranges = devm_kcalloc(dev, *num_ranges, -- sizeof(struct fsl_mc_addr_translation_range), -- GFP_KERNEL); -- if (!(*ranges)) -- return -ENOMEM; -- -- cell = ranges_start; -- for (i = 0; i < *num_ranges; ++i) { -- struct fsl_mc_addr_translation_range *range = &(*ranges)[i]; -- -- range->mc_region_type = of_read_number(cell, 1); -- range->start_mc_offset = of_read_number(cell + 1, -- mc_addr_cells - 1); -- cell += mc_addr_cells; -- range->start_phys_addr = of_read_number(cell, paddr_cells); -- cell += paddr_cells; -- range->end_mc_offset = range->start_mc_offset + -- of_read_number(cell, mc_size_cells); -- -- cell += mc_size_cells; -- } -- -- return 0; --} -- --/** -- * fsl_mc_bus_probe - callback invoked when the root MC bus is being -- * added -- */ --static int fsl_mc_bus_probe(struct platform_device *pdev) --{ -- struct dprc_obj_desc obj_desc; -- int error; -- struct fsl_mc *mc; -- struct fsl_mc_device *mc_bus_dev = NULL; -- struct fsl_mc_io *mc_io = NULL; -- int container_id; -- phys_addr_t mc_portal_phys_addr; -- u32 mc_portal_size; -- struct mc_version mc_version; -- struct resource res; -- -- dev_info(&pdev->dev, "Root MC bus device probed"); -- -- mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL); -- if (!mc) -- return -ENOMEM; -- -- platform_set_drvdata(pdev, mc); -- -- /* -- * Get physical address of MC portal for the root DPRC: -- */ -- error = of_address_to_resource(pdev->dev.of_node, 0, &res); -- if (error < 0) { -- dev_err(&pdev->dev, -- "of_address_to_resource() failed for %s\n", -- pdev->dev.of_node->full_name); -- return error; -- } -- -- mc_portal_phys_addr = res.start; -- mc_portal_size = resource_size(&res); -- error = fsl_create_mc_io(&pdev->dev, mc_portal_phys_addr, -- mc_portal_size, NULL, -- FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, &mc_io); -- if (error < 0) -- return error; -- -- error = mc_get_version(mc_io, 0, &mc_version); -- if (error != 0) { -- dev_err(&pdev->dev, -- "mc_get_version() failed with error %d\n", error); -- goto error_cleanup_mc_io; -- } -- -- dev_info(&pdev->dev, -- "Freescale Management Complex Firmware version: %u.%u.%u\n", -- mc_version.major, mc_version.minor, mc_version.revision); -- -- error = get_mc_addr_translation_ranges(&pdev->dev, -- &mc->translation_ranges, -- &mc->num_translation_ranges); -- if (error < 0) -- goto error_cleanup_mc_io; -- -- error = dpmng_get_container_id(mc_io, 0, &container_id); -- if (error < 0) { -- dev_err(&pdev->dev, -- "dpmng_get_container_id() failed: %d\n", error); -- goto error_cleanup_mc_io; -- } -- -- memset(&obj_desc, 0, sizeof(struct dprc_obj_desc)); -- error = get_dprc_version(mc_io, container_id, -- &obj_desc.ver_major, &obj_desc.ver_minor); -- if (error < 0) -- goto error_cleanup_mc_io; -- -- obj_desc.vendor = FSL_MC_VENDOR_FREESCALE; -- strcpy(obj_desc.type, "dprc"); -- obj_desc.id = container_id; -- obj_desc.irq_count = 1; -- obj_desc.region_count = 0; -- -- error = fsl_mc_device_add(&obj_desc, mc_io, &pdev->dev, &mc_bus_dev); -- if (error < 0) -- goto error_cleanup_mc_io; -- -- mc->root_mc_bus_dev = mc_bus_dev; -- return 0; -- --error_cleanup_mc_io: -- fsl_destroy_mc_io(mc_io); -- return error; --} -- --/** -- * fsl_mc_bus_remove - callback invoked when the root MC bus is being -- * removed -- */ --static int fsl_mc_bus_remove(struct platform_device *pdev) --{ -- struct fsl_mc *mc = platform_get_drvdata(pdev); -- -- if (WARN_ON(!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev))) -- return -EINVAL; -- -- fsl_mc_device_remove(mc->root_mc_bus_dev); -- -- fsl_destroy_mc_io(mc->root_mc_bus_dev->mc_io); -- mc->root_mc_bus_dev->mc_io = NULL; -- -- dev_info(&pdev->dev, "Root MC bus device removed"); -- return 0; --} -- --static const struct of_device_id fsl_mc_bus_match_table[] = { -- {.compatible = "fsl,qoriq-mc",}, -- {}, --}; -- --MODULE_DEVICE_TABLE(of, fsl_mc_bus_match_table); -- --static struct platform_driver fsl_mc_bus_driver = { -- .driver = { -- .name = "fsl_mc_bus", -- .pm = NULL, -- .of_match_table = fsl_mc_bus_match_table, -- }, -- .probe = fsl_mc_bus_probe, -- .remove = fsl_mc_bus_remove, --}; -- --static int __init fsl_mc_bus_driver_init(void) --{ -- int error; -- -- mc_dev_cache = kmem_cache_create("fsl_mc_device", -- sizeof(struct fsl_mc_device), 0, 0, -- NULL); -- if (!mc_dev_cache) { -- pr_err("Could not create fsl_mc_device cache\n"); -- return -ENOMEM; -- } -- -- error = bus_register(&fsl_mc_bus_type); -- if (error < 0) { -- pr_err("fsl-mc bus type registration failed: %d\n", error); -- goto error_cleanup_cache; -- } -- -- pr_info("fsl-mc bus type registered\n"); -- -- error = platform_driver_register(&fsl_mc_bus_driver); -- if (error < 0) { -- pr_err("platform_driver_register() failed: %d\n", error); -- goto error_cleanup_bus; -- } -- -- error = dprc_driver_init(); -- if (error < 0) -- goto error_cleanup_driver; -- -- error = fsl_mc_allocator_driver_init(); -- if (error < 0) -- goto error_cleanup_dprc_driver; -- -- error = its_fsl_mc_msi_init(); -- if (error < 0) -- goto error_cleanup_mc_allocator; -- -- return 0; -- --error_cleanup_mc_allocator: -- fsl_mc_allocator_driver_exit(); -- --error_cleanup_dprc_driver: -- dprc_driver_exit(); -- --error_cleanup_driver: -- platform_driver_unregister(&fsl_mc_bus_driver); -- --error_cleanup_bus: -- bus_unregister(&fsl_mc_bus_type); -- --error_cleanup_cache: -- kmem_cache_destroy(mc_dev_cache); -- return error; --} --postcore_initcall(fsl_mc_bus_driver_init); ---- /dev/null -+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c -@@ -0,0 +1,1151 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Freescale Management Complex (MC) bus driver -+ * -+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. -+ * Author: German Rivera <German.Rivera@freescale.com> -+ * -+ */ -+ -+#define pr_fmt(fmt) "fsl-mc: " fmt -+ -+#include <linux/module.h> -+#include <linux/of_device.h> -+#include <linux/of_address.h> -+#include <linux/ioport.h> -+#include <linux/slab.h> -+#include <linux/limits.h> -+#include <linux/bitops.h> -+#include <linux/msi.h> -+#include <linux/dma-mapping.h> -+#include <linux/fsl/mc.h> -+ -+#include "fsl-mc-private.h" -+ -+/** -+ * Default DMA mask for devices on a fsl-mc bus -+ */ -+#define FSL_MC_DEFAULT_DMA_MASK (~0ULL) -+ -+/** -+ * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device -+ * @root_mc_bus_dev: fsl-mc device representing the root DPRC -+ * @num_translation_ranges: number of entries in addr_translation_ranges -+ * @translation_ranges: array of bus to system address translation ranges -+ */ -+struct fsl_mc { -+ struct fsl_mc_device *root_mc_bus_dev; -+ u8 num_translation_ranges; -+ struct fsl_mc_addr_translation_range *translation_ranges; -+}; -+ -+/** -+ * struct fsl_mc_addr_translation_range - bus to system address translation -+ * range -+ * @mc_region_type: Type of MC region for the range being translated -+ * @start_mc_offset: Start MC offset of the range being translated -+ * @end_mc_offset: MC offset of the first byte after the range (last MC -+ * offset of the range is end_mc_offset - 1) -+ * @start_phys_addr: system physical address corresponding to start_mc_addr -+ */ -+struct fsl_mc_addr_translation_range { -+ enum dprc_region_type mc_region_type; -+ u64 start_mc_offset; -+ u64 end_mc_offset; -+ phys_addr_t start_phys_addr; -+}; -+ -+/** -+ * struct mc_version -+ * @major: Major version number: incremented on API compatibility changes -+ * @minor: Minor version number: incremented on API additions (that are -+ * backward compatible); reset when major version is incremented -+ * @revision: Internal revision number: incremented on implementation changes -+ * and/or bug fixes that have no impact on API -+ */ -+struct mc_version { -+ u32 major; -+ u32 minor; -+ u32 revision; -+}; -+ -+/** -+ * fsl_mc_bus_match - device to driver matching callback -+ * @dev: the fsl-mc device to match against -+ * @drv: the device driver to search for matching fsl-mc object type -+ * structures -+ * -+ * Returns 1 on success, 0 otherwise. -+ */ -+static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv) -+{ -+ const struct fsl_mc_device_id *id; -+ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); -+ struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv); -+ bool found = false; -+ -+ /* When driver_override is set, only bind to the matching driver */ -+ if (mc_dev->driver_override) { -+ found = !strcmp(mc_dev->driver_override, mc_drv->driver.name); -+ goto out; -+ } -+ -+ if (!mc_drv->match_id_table) -+ goto out; -+ -+ /* -+ * If the object is not 'plugged' don't match. -+ * Only exception is the root DPRC, which is a special case. -+ */ -+ if ((mc_dev->obj_desc.state & FSL_MC_OBJ_STATE_PLUGGED) == 0 && -+ !fsl_mc_is_root_dprc(&mc_dev->dev)) -+ goto out; -+ -+ /* -+ * Traverse the match_id table of the given driver, trying to find -+ * a matching for the given device. -+ */ -+ for (id = mc_drv->match_id_table; id->vendor != 0x0; id++) { -+ if (id->vendor == mc_dev->obj_desc.vendor && -+ strcmp(id->obj_type, mc_dev->obj_desc.type) == 0) { -+ found = true; -+ -+ break; -+ } -+ } -+ -+out: -+ dev_dbg(dev, "%smatched\n", found ? "" : "not "); -+ return found; -+} -+ -+/** -+ * fsl_mc_bus_uevent - callback invoked when a device is added -+ */ -+static int fsl_mc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) -+{ -+ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); -+ -+ if (add_uevent_var(env, "MODALIAS=fsl-mc:v%08Xd%s", -+ mc_dev->obj_desc.vendor, -+ mc_dev->obj_desc.type)) -+ return -ENOMEM; -+ -+ return 0; -+} -+ -+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); -+ -+ return sprintf(buf, "fsl-mc:v%08Xd%s\n", mc_dev->obj_desc.vendor, -+ mc_dev->obj_desc.type); -+} -+static DEVICE_ATTR_RO(modalias); -+ -+static ssize_t rescan_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct fsl_mc_device *root_mc_dev; -+ struct fsl_mc_bus *root_mc_bus; -+ unsigned long val; -+ -+ if (!fsl_mc_is_root_dprc(dev)) -+ return -EINVAL; -+ -+ root_mc_dev = to_fsl_mc_device(dev); -+ root_mc_bus = to_fsl_mc_bus(root_mc_dev); -+ -+ if (kstrtoul(buf, 0, &val) < 0) -+ return -EINVAL; -+ -+ if (val) { -+ mutex_lock(&root_mc_bus->scan_mutex); -+ dprc_scan_objects(root_mc_dev, NULL, NULL); -+ mutex_unlock(&root_mc_bus->scan_mutex); -+ } -+ -+ return count; -+} -+static DEVICE_ATTR_WO(rescan); -+ -+static ssize_t driver_override_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); -+ const char *driver_override, *old = mc_dev->driver_override; -+ char *cp; -+ -+ if (WARN_ON(dev->bus != &fsl_mc_bus_type)) -+ return -EINVAL; -+ -+ if (count >= (PAGE_SIZE - 1)) -+ return -EINVAL; -+ -+ driver_override = kstrndup(buf, count, GFP_KERNEL); -+ if (!driver_override) -+ return -ENOMEM; -+ -+ cp = strchr(driver_override, '\n'); -+ if (cp) -+ *cp = '\0'; -+ -+ if (strlen(driver_override)) { -+ mc_dev->driver_override = driver_override; -+ } else { -+ kfree(driver_override); -+ mc_dev->driver_override = NULL; -+ } -+ -+ kfree(old); -+ -+ return count; -+} -+ -+static ssize_t driver_override_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); -+ -+ return snprintf(buf, PAGE_SIZE, "%s\n", mc_dev->driver_override); -+} -+static DEVICE_ATTR_RW(driver_override); -+ -+static struct attribute *fsl_mc_dev_attrs[] = { -+ &dev_attr_modalias.attr, -+ &dev_attr_rescan.attr, -+ &dev_attr_driver_override.attr, -+ NULL, -+}; -+ -+ATTRIBUTE_GROUPS(fsl_mc_dev); -+ -+static int scan_fsl_mc_bus(struct device *dev, void *data) -+{ -+ struct fsl_mc_device *root_mc_dev; -+ struct fsl_mc_bus *root_mc_bus; -+ -+ if (!fsl_mc_is_root_dprc(dev)) -+ goto exit; -+ -+ root_mc_dev = to_fsl_mc_device(dev); -+ root_mc_bus = to_fsl_mc_bus(root_mc_dev); -+ mutex_lock(&root_mc_bus->scan_mutex); -+ dprc_scan_objects(root_mc_dev, NULL, NULL); -+ mutex_unlock(&root_mc_bus->scan_mutex); -+ -+exit: -+ return 0; -+} -+ -+static ssize_t bus_rescan_store(struct bus_type *bus, -+ const char *buf, size_t count) -+{ -+ unsigned long val; -+ -+ if (kstrtoul(buf, 0, &val) < 0) -+ return -EINVAL; -+ -+ if (val) -+ bus_for_each_dev(bus, NULL, NULL, scan_fsl_mc_bus); -+ -+ return count; -+} -+static BUS_ATTR(rescan, 0220, NULL, bus_rescan_store); -+ -+static struct attribute *fsl_mc_bus_attrs[] = { -+ &bus_attr_rescan.attr, -+ NULL, -+}; -+ -+static const struct attribute_group fsl_mc_bus_group = { -+ .attrs = fsl_mc_bus_attrs, -+}; -+ -+static const struct attribute_group *fsl_mc_bus_groups[] = { -+ &fsl_mc_bus_group, -+ NULL, -+}; -+ -+struct bus_type fsl_mc_bus_type = { -+ .name = "fsl-mc", -+ .match = fsl_mc_bus_match, -+ .uevent = fsl_mc_bus_uevent, -+ .dev_groups = fsl_mc_dev_groups, -+ .bus_groups = fsl_mc_bus_groups, -+}; -+EXPORT_SYMBOL_GPL(fsl_mc_bus_type); -+ -+struct device_type fsl_mc_bus_dprc_type = { -+ .name = "fsl_mc_bus_dprc" -+}; -+ -+struct device_type fsl_mc_bus_dpni_type = { -+ .name = "fsl_mc_bus_dpni" -+}; -+ -+struct device_type fsl_mc_bus_dpio_type = { -+ .name = "fsl_mc_bus_dpio" -+}; -+ -+struct device_type fsl_mc_bus_dpsw_type = { -+ .name = "fsl_mc_bus_dpsw" -+}; -+ -+struct device_type fsl_mc_bus_dpdmux_type = { -+ .name = "fsl_mc_bus_dpdmux" -+}; -+ -+struct device_type fsl_mc_bus_dpbp_type = { -+ .name = "fsl_mc_bus_dpbp" -+}; -+ -+struct device_type fsl_mc_bus_dpcon_type = { -+ .name = "fsl_mc_bus_dpcon" -+}; -+ -+struct device_type fsl_mc_bus_dpmcp_type = { -+ .name = "fsl_mc_bus_dpmcp" -+}; -+ -+struct device_type fsl_mc_bus_dpmac_type = { -+ .name = "fsl_mc_bus_dpmac" -+}; -+ -+struct device_type fsl_mc_bus_dprtc_type = { -+ .name = "fsl_mc_bus_dprtc" -+}; -+ -+struct device_type fsl_mc_bus_dpseci_type = { -+ .name = "fsl_mc_bus_dpseci" -+}; -+ -+struct device_type fsl_mc_bus_dpdcei_type = { -+ .name = "fsl_mc_bus_dpdcei" -+}; -+ -+struct device_type fsl_mc_bus_dpaiop_type = { -+ .name = "fsl_mc_bus_dpaiop" -+}; -+ -+struct device_type fsl_mc_bus_dpci_type = { -+ .name = "fsl_mc_bus_dpci" -+}; -+ -+struct device_type fsl_mc_bus_dpdmai_type = { -+ .name = "fsl_mc_bus_dpdmai" -+}; -+ -+static struct device_type *fsl_mc_get_device_type(const char *type) -+{ -+ static const struct { -+ struct device_type *dev_type; -+ const char *type; -+ } dev_types[] = { -+ { &fsl_mc_bus_dprc_type, "dprc" }, -+ { &fsl_mc_bus_dpni_type, "dpni" }, -+ { &fsl_mc_bus_dpio_type, "dpio" }, -+ { &fsl_mc_bus_dpsw_type, "dpsw" }, -+ { &fsl_mc_bus_dpdmux_type, "dpdmux" }, -+ { &fsl_mc_bus_dpbp_type, "dpbp" }, -+ { &fsl_mc_bus_dpcon_type, "dpcon" }, -+ { &fsl_mc_bus_dpmcp_type, "dpmcp" }, -+ { &fsl_mc_bus_dpmac_type, "dpmac" }, -+ { &fsl_mc_bus_dprtc_type, "dprtc" }, -+ { &fsl_mc_bus_dpseci_type, "dpseci" }, -+ { &fsl_mc_bus_dpdcei_type, "dpdcei" }, -+ { &fsl_mc_bus_dpaiop_type, "dpaiop" }, -+ { &fsl_mc_bus_dpci_type, "dpci" }, -+ { &fsl_mc_bus_dpdmai_type, "dpdmai" }, -+ { NULL, NULL } -+ }; -+ int i; -+ -+ for (i = 0; dev_types[i].dev_type; i++) -+ if (!strcmp(dev_types[i].type, type)) -+ return dev_types[i].dev_type; -+ -+ return NULL; -+} -+ -+static int fsl_mc_driver_probe(struct device *dev) -+{ -+ struct fsl_mc_driver *mc_drv; -+ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); -+ int error; -+ -+ mc_drv = to_fsl_mc_driver(dev->driver); -+ -+ error = mc_drv->probe(mc_dev); -+ if (error < 0) { -+ if (error != -EPROBE_DEFER) -+ dev_err(dev, "%s failed: %d\n", __func__, error); -+ return error; -+ } -+ -+ return 0; -+} -+ -+static int fsl_mc_driver_remove(struct device *dev) -+{ -+ struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); -+ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); -+ int error; -+ -+ error = mc_drv->remove(mc_dev); -+ if (error < 0) { -+ dev_err(dev, "%s failed: %d\n", __func__, error); -+ return error; -+ } -+ -+ return 0; -+} -+ -+static void fsl_mc_driver_shutdown(struct device *dev) -+{ -+ struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); -+ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); -+ -+ mc_drv->shutdown(mc_dev); -+} -+ -+/** -+ * __fsl_mc_driver_register - registers a child device driver with the -+ * MC bus -+ * -+ * This function is implicitly invoked from the registration function of -+ * fsl_mc device drivers, which is generated by the -+ * module_fsl_mc_driver() macro. -+ */ -+int __fsl_mc_driver_register(struct fsl_mc_driver *mc_driver, -+ struct module *owner) -+{ -+ int error; -+ -+ mc_driver->driver.owner = owner; -+ mc_driver->driver.bus = &fsl_mc_bus_type; -+ -+ if (mc_driver->probe) -+ mc_driver->driver.probe = fsl_mc_driver_probe; -+ -+ if (mc_driver->remove) -+ mc_driver->driver.remove = fsl_mc_driver_remove; -+ -+ if (mc_driver->shutdown) -+ mc_driver->driver.shutdown = fsl_mc_driver_shutdown; -+ -+ error = driver_register(&mc_driver->driver); -+ if (error < 0) { -+ pr_err("driver_register() failed for %s: %d\n", -+ mc_driver->driver.name, error); -+ return error; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(__fsl_mc_driver_register); -+ -+/** -+ * fsl_mc_driver_unregister - unregisters a device driver from the -+ * MC bus -+ */ -+void fsl_mc_driver_unregister(struct fsl_mc_driver *mc_driver) -+{ -+ driver_unregister(&mc_driver->driver); -+} -+EXPORT_SYMBOL_GPL(fsl_mc_driver_unregister); -+ -+/** -+ * mc_get_version() - Retrieves the Management Complex firmware -+ * version information -+ * @mc_io: Pointer to opaque I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @mc_ver_info: Returned version information structure -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+static int mc_get_version(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ struct mc_version *mc_ver_info) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpmng_rsp_get_version *rsp_params; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_VERSION, -+ cmd_flags, -+ 0); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ rsp_params = (struct dpmng_rsp_get_version *)cmd.params; -+ mc_ver_info->revision = le32_to_cpu(rsp_params->revision); -+ mc_ver_info->major = le32_to_cpu(rsp_params->version_major); -+ mc_ver_info->minor = le32_to_cpu(rsp_params->version_minor); -+ -+ return 0; -+} -+ -+/** -+ * fsl_mc_get_root_dprc - function to traverse to the root dprc -+ */ -+void fsl_mc_get_root_dprc(struct device *dev, -+ struct device **root_dprc_dev) -+{ -+ if (!dev) { -+ *root_dprc_dev = NULL; -+ } else if (!dev_is_fsl_mc(dev)) { -+ *root_dprc_dev = NULL; -+ } else { -+ *root_dprc_dev = dev; -+ while (dev_is_fsl_mc((*root_dprc_dev)->parent)) -+ *root_dprc_dev = (*root_dprc_dev)->parent; -+ } -+} -+EXPORT_SYMBOL_GPL(fsl_mc_get_root_dprc); -+ -+static int get_dprc_attr(struct fsl_mc_io *mc_io, -+ int container_id, struct dprc_attributes *attr) -+{ -+ u16 dprc_handle; -+ int error; -+ -+ error = dprc_open(mc_io, 0, container_id, &dprc_handle); -+ if (error < 0) { -+ dev_err(mc_io->dev, "dprc_open() failed: %d\n", error); -+ return error; -+ } -+ -+ memset(attr, 0, sizeof(struct dprc_attributes)); -+ error = dprc_get_attributes(mc_io, 0, dprc_handle, attr); -+ if (error < 0) { -+ dev_err(mc_io->dev, "dprc_get_attributes() failed: %d\n", -+ error); -+ goto common_cleanup; -+ } -+ -+ error = 0; -+ -+common_cleanup: -+ (void)dprc_close(mc_io, 0, dprc_handle); -+ return error; -+} -+ -+static int get_dprc_icid(struct fsl_mc_io *mc_io, -+ int container_id, u32 *icid) -+{ -+ struct dprc_attributes attr; -+ int error; -+ -+ error = get_dprc_attr(mc_io, container_id, &attr); -+ if (error == 0) -+ *icid = attr.icid; -+ -+ return error; -+} -+ -+static int translate_mc_addr(struct fsl_mc_device *mc_dev, -+ enum dprc_region_type mc_region_type, -+ u64 mc_offset, phys_addr_t *phys_addr) -+{ -+ int i; -+ struct device *root_dprc_dev; -+ struct fsl_mc *mc; -+ -+ fsl_mc_get_root_dprc(&mc_dev->dev, &root_dprc_dev); -+ mc = dev_get_drvdata(root_dprc_dev->parent); -+ -+ if (mc->num_translation_ranges == 0) { -+ /* -+ * Do identity mapping: -+ */ -+ *phys_addr = mc_offset; -+ return 0; -+ } -+ -+ for (i = 0; i < mc->num_translation_ranges; i++) { -+ struct fsl_mc_addr_translation_range *range = -+ &mc->translation_ranges[i]; -+ -+ if (mc_region_type == range->mc_region_type && -+ mc_offset >= range->start_mc_offset && -+ mc_offset < range->end_mc_offset) { -+ *phys_addr = range->start_phys_addr + -+ (mc_offset - range->start_mc_offset); -+ return 0; -+ } -+ } -+ -+ return -EFAULT; -+} -+ -+static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev, -+ struct fsl_mc_device *mc_bus_dev) -+{ -+ int i; -+ int error; -+ struct resource *regions; -+ struct fsl_mc_obj_desc *obj_desc = &mc_dev->obj_desc; -+ struct device *parent_dev = mc_dev->dev.parent; -+ enum dprc_region_type mc_region_type; -+ -+ if (is_fsl_mc_bus_dprc(mc_dev) || -+ is_fsl_mc_bus_dpmcp(mc_dev)) { -+ mc_region_type = DPRC_REGION_TYPE_MC_PORTAL; -+ } else if (is_fsl_mc_bus_dpio(mc_dev)) { -+ mc_region_type = DPRC_REGION_TYPE_QBMAN_PORTAL; -+ } else { -+ /* -+ * This function should not have been called for this MC object -+ * type, as this object type is not supposed to have MMIO -+ * regions -+ */ -+ return -EINVAL; -+ } -+ -+ regions = kmalloc_array(obj_desc->region_count, -+ sizeof(regions[0]), GFP_KERNEL); -+ if (!regions) -+ return -ENOMEM; -+ -+ for (i = 0; i < obj_desc->region_count; i++) { -+ struct dprc_region_desc region_desc; -+ -+ error = dprc_get_obj_region(mc_bus_dev->mc_io, -+ 0, -+ mc_bus_dev->mc_handle, -+ obj_desc->type, -+ obj_desc->id, i, ®ion_desc); -+ if (error < 0) { -+ dev_err(parent_dev, -+ "dprc_get_obj_region() failed: %d\n", error); -+ goto error_cleanup_regions; -+ } -+ -+ error = translate_mc_addr(mc_dev, mc_region_type, -+ region_desc.base_offset, -+ ®ions[i].start); -+ if (error < 0) { -+ dev_err(parent_dev, -+ "Invalid MC offset: %#x (for %s.%d\'s region %d)\n", -+ region_desc.base_offset, -+ obj_desc->type, obj_desc->id, i); -+ goto error_cleanup_regions; -+ } -+ -+ regions[i].end = regions[i].start + region_desc.size - 1; -+ regions[i].name = "fsl-mc object MMIO region"; -+ regions[i].flags = IORESOURCE_IO; -+ if (region_desc.flags & DPRC_REGION_CACHEABLE) -+ regions[i].flags |= IORESOURCE_CACHEABLE; -+ } -+ -+ mc_dev->regions = regions; -+ return 0; -+ -+error_cleanup_regions: -+ kfree(regions); -+ return error; -+} -+ -+/** -+ * fsl_mc_is_root_dprc - function to check if a given device is a root dprc -+ */ -+bool fsl_mc_is_root_dprc(struct device *dev) -+{ -+ struct device *root_dprc_dev; -+ -+ fsl_mc_get_root_dprc(dev, &root_dprc_dev); -+ if (!root_dprc_dev) -+ return false; -+ return dev == root_dprc_dev; -+} -+ -+static void fsl_mc_device_release(struct device *dev) -+{ -+ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); -+ -+ kfree(mc_dev->regions); -+ -+ if (is_fsl_mc_bus_dprc(mc_dev)) -+ kfree(to_fsl_mc_bus(mc_dev)); -+ else -+ kfree(mc_dev); -+} -+ -+/** -+ * Add a newly discovered fsl-mc device to be visible in Linux -+ */ -+int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc, -+ struct fsl_mc_io *mc_io, -+ struct device *parent_dev, -+ const char *driver_override, -+ struct fsl_mc_device **new_mc_dev) -+{ -+ int error; -+ struct fsl_mc_device *mc_dev = NULL; -+ struct fsl_mc_bus *mc_bus = NULL; -+ struct fsl_mc_device *parent_mc_dev; -+ struct device *fsl_mc_platform_dev; -+ struct device_node *fsl_mc_platform_node; -+ -+ if (dev_is_fsl_mc(parent_dev)) -+ parent_mc_dev = to_fsl_mc_device(parent_dev); -+ else -+ parent_mc_dev = NULL; -+ -+ if (strcmp(obj_desc->type, "dprc") == 0) { -+ /* -+ * Allocate an MC bus device object: -+ */ -+ mc_bus = kzalloc(sizeof(*mc_bus), GFP_KERNEL); -+ if (!mc_bus) -+ return -ENOMEM; -+ -+ mc_dev = &mc_bus->mc_dev; -+ } else { -+ /* -+ * Allocate a regular fsl_mc_device object: -+ */ -+ mc_dev = kzalloc(sizeof(*mc_dev), GFP_KERNEL); -+ if (!mc_dev) -+ return -ENOMEM; -+ } -+ -+ mc_dev->obj_desc = *obj_desc; -+ mc_dev->mc_io = mc_io; -+ -+ if (driver_override) { -+ /* -+ * We trust driver_override, so we don't need to use -+ * kstrndup() here -+ */ -+ mc_dev->driver_override = kstrdup(driver_override, GFP_KERNEL); -+ if (!mc_dev->driver_override) { -+ error = -ENOMEM; -+ goto error_cleanup_dev; -+ } -+ } -+ -+ device_initialize(&mc_dev->dev); -+ mc_dev->dev.parent = parent_dev; -+ mc_dev->dev.bus = &fsl_mc_bus_type; -+ mc_dev->dev.release = fsl_mc_device_release; -+ mc_dev->dev.type = fsl_mc_get_device_type(obj_desc->type); -+ if (!mc_dev->dev.type) { -+ error = -ENODEV; -+ dev_err(parent_dev, "unknown device type %s\n", obj_desc->type); -+ goto error_cleanup_dev; -+ } -+ dev_set_name(&mc_dev->dev, "%s.%d", obj_desc->type, obj_desc->id); -+ -+ if (strcmp(obj_desc->type, "dprc") == 0) { -+ struct fsl_mc_io *mc_io2; -+ -+ mc_dev->flags |= FSL_MC_IS_DPRC; -+ -+ /* -+ * To get the DPRC's ICID, we need to open the DPRC -+ * in get_dprc_icid(). For child DPRCs, we do so using the -+ * parent DPRC's MC portal instead of the child DPRC's MC -+ * portal, in case the child DPRC is already opened with -+ * its own portal (e.g., the DPRC used by AIOP). -+ * -+ * NOTE: There cannot be more than one active open for a -+ * given MC object, using the same MC portal. -+ */ -+ if (parent_mc_dev) { -+ /* -+ * device being added is a child DPRC device -+ */ -+ mc_io2 = parent_mc_dev->mc_io; -+ } else { -+ /* -+ * device being added is the root DPRC device -+ */ -+ if (!mc_io) { -+ error = -EINVAL; -+ goto error_cleanup_dev; -+ } -+ -+ mc_io2 = mc_io; -+ } -+ -+ error = get_dprc_icid(mc_io2, obj_desc->id, &mc_dev->icid); -+ if (error < 0) -+ goto error_cleanup_dev; -+ } else { -+ /* -+ * A non-DPRC object has to be a child of a DPRC, use the -+ * parent's ICID and interrupt domain. -+ */ -+ mc_dev->icid = parent_mc_dev->icid; -+ mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK; -+ mc_dev->dev.dma_mask = &mc_dev->dma_mask; -+ mc_dev->dev.coherent_dma_mask = mc_dev->dma_mask; -+ dev_set_msi_domain(&mc_dev->dev, -+ dev_get_msi_domain(&parent_mc_dev->dev)); -+ } -+ -+ /* -+ * Get MMIO regions for the device from the MC: -+ * -+ * NOTE: the root DPRC is a special case as its MMIO region is -+ * obtained from the device tree -+ */ -+ if (parent_mc_dev && obj_desc->region_count != 0) { -+ error = fsl_mc_device_get_mmio_regions(mc_dev, -+ parent_mc_dev); -+ if (error < 0) -+ goto error_cleanup_dev; -+ } -+ -+ fsl_mc_platform_dev = &mc_dev->dev; -+ while (dev_is_fsl_mc(fsl_mc_platform_dev)) -+ fsl_mc_platform_dev = fsl_mc_platform_dev->parent; -+ fsl_mc_platform_node = fsl_mc_platform_dev->of_node; -+ -+ /* Set up the iommu configuration for the devices. */ -+ fsl_mc_dma_configure(mc_dev, fsl_mc_platform_node, -+ !(obj_desc->flags & DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY)); -+ -+ /* -+ * The device-specific probe callback will get invoked by device_add() -+ */ -+ error = device_add(&mc_dev->dev); -+ if (error < 0) { -+ dev_err(parent_dev, -+ "device_add() failed for device %s: %d\n", -+ dev_name(&mc_dev->dev), error); -+ goto error_cleanup_dev; -+ } -+ -+ dev_dbg(parent_dev, "added %s\n", dev_name(&mc_dev->dev)); -+ -+ *new_mc_dev = mc_dev; -+ return 0; -+ -+error_cleanup_dev: -+ kfree(mc_dev->regions); -+ kfree(mc_bus); -+ kfree(mc_dev); -+ -+ return error; -+} -+EXPORT_SYMBOL_GPL(fsl_mc_device_add); -+ -+/** -+ * fsl_mc_device_remove - Remove an fsl-mc device from being visible to -+ * Linux -+ * -+ * @mc_dev: Pointer to an fsl-mc device -+ */ -+void fsl_mc_device_remove(struct fsl_mc_device *mc_dev) -+{ -+ kfree(mc_dev->driver_override); -+ mc_dev->driver_override = NULL; -+ -+ /* -+ * The device-specific remove callback will get invoked by device_del() -+ */ -+ device_del(&mc_dev->dev); -+ put_device(&mc_dev->dev); -+} -+EXPORT_SYMBOL_GPL(fsl_mc_device_remove); -+ -+static int parse_mc_ranges(struct device *dev, -+ int *paddr_cells, -+ int *mc_addr_cells, -+ int *mc_size_cells, -+ const __be32 **ranges_start) -+{ -+ const __be32 *prop; -+ int range_tuple_cell_count; -+ int ranges_len; -+ int tuple_len; -+ struct device_node *mc_node = dev->of_node; -+ -+ *ranges_start = of_get_property(mc_node, "ranges", &ranges_len); -+ if (!(*ranges_start) || !ranges_len) { -+ dev_warn(dev, -+ "missing or empty ranges property for device tree node '%s'\n", -+ mc_node->name); -+ return 0; -+ } -+ -+ *paddr_cells = of_n_addr_cells(mc_node); -+ -+ prop = of_get_property(mc_node, "#address-cells", NULL); -+ if (prop) -+ *mc_addr_cells = be32_to_cpup(prop); -+ else -+ *mc_addr_cells = *paddr_cells; -+ -+ prop = of_get_property(mc_node, "#size-cells", NULL); -+ if (prop) -+ *mc_size_cells = be32_to_cpup(prop); -+ else -+ *mc_size_cells = of_n_size_cells(mc_node); -+ -+ range_tuple_cell_count = *paddr_cells + *mc_addr_cells + -+ *mc_size_cells; -+ -+ tuple_len = range_tuple_cell_count * sizeof(__be32); -+ if (ranges_len % tuple_len != 0) { -+ dev_err(dev, "malformed ranges property '%s'\n", mc_node->name); -+ return -EINVAL; -+ } -+ -+ return ranges_len / tuple_len; -+} -+ -+static int get_mc_addr_translation_ranges(struct device *dev, -+ struct fsl_mc_addr_translation_range -+ **ranges, -+ u8 *num_ranges) -+{ -+ int ret; -+ int paddr_cells; -+ int mc_addr_cells; -+ int mc_size_cells; -+ int i; -+ const __be32 *ranges_start; -+ const __be32 *cell; -+ -+ ret = parse_mc_ranges(dev, -+ &paddr_cells, -+ &mc_addr_cells, -+ &mc_size_cells, -+ &ranges_start); -+ if (ret < 0) -+ return ret; -+ -+ *num_ranges = ret; -+ if (!ret) { -+ /* -+ * Missing or empty ranges property ("ranges;") for the -+ * 'fsl,qoriq-mc' node. In this case, identity mapping -+ * will be used. -+ */ -+ *ranges = NULL; -+ return 0; -+ } -+ -+ *ranges = devm_kcalloc(dev, *num_ranges, -+ sizeof(struct fsl_mc_addr_translation_range), -+ GFP_KERNEL); -+ if (!(*ranges)) -+ return -ENOMEM; -+ -+ cell = ranges_start; -+ for (i = 0; i < *num_ranges; ++i) { -+ struct fsl_mc_addr_translation_range *range = &(*ranges)[i]; -+ -+ range->mc_region_type = of_read_number(cell, 1); -+ range->start_mc_offset = of_read_number(cell + 1, -+ mc_addr_cells - 1); -+ cell += mc_addr_cells; -+ range->start_phys_addr = of_read_number(cell, paddr_cells); -+ cell += paddr_cells; -+ range->end_mc_offset = range->start_mc_offset + -+ of_read_number(cell, mc_size_cells); -+ -+ cell += mc_size_cells; -+ } -+ -+ return 0; -+} -+ -+/** -+ * fsl_mc_bus_probe - callback invoked when the root MC bus is being -+ * added -+ */ -+static int fsl_mc_bus_probe(struct platform_device *pdev) -+{ -+ struct fsl_mc_obj_desc obj_desc; -+ int error; -+ struct fsl_mc *mc; -+ struct fsl_mc_device *mc_bus_dev = NULL; -+ struct fsl_mc_io *mc_io = NULL; -+ struct fsl_mc_bus *mc_bus = NULL; -+ int container_id; -+ phys_addr_t mc_portal_phys_addr; -+ u32 mc_portal_size; -+ struct mc_version mc_version; -+ struct resource res; -+ -+ mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL); -+ if (!mc) -+ return -ENOMEM; -+ -+ platform_set_drvdata(pdev, mc); -+ -+ /* -+ * Get physical address of MC portal for the root DPRC: -+ */ -+ error = of_address_to_resource(pdev->dev.of_node, 0, &res); -+ if (error < 0) { -+ dev_err(&pdev->dev, -+ "of_address_to_resource() failed for %pOF\n", -+ pdev->dev.of_node); -+ return error; -+ } -+ -+ mc_portal_phys_addr = res.start; -+ mc_portal_size = resource_size(&res); -+ error = fsl_create_mc_io(&pdev->dev, mc_portal_phys_addr, -+ mc_portal_size, NULL, -+ FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, &mc_io); -+ if (error < 0) -+ return error; -+ -+ error = mc_get_version(mc_io, 0, &mc_version); -+ if (error != 0) { -+ dev_err(&pdev->dev, -+ "mc_get_version() failed with error %d\n", error); -+ goto error_cleanup_mc_io; -+ } -+ -+ dev_info(&pdev->dev, "MC firmware version: %u.%u.%u\n", -+ mc_version.major, mc_version.minor, mc_version.revision); -+ -+ error = get_mc_addr_translation_ranges(&pdev->dev, -+ &mc->translation_ranges, -+ &mc->num_translation_ranges); -+ if (error < 0) -+ goto error_cleanup_mc_io; -+ -+ error = dprc_get_container_id(mc_io, 0, &container_id); -+ if (error < 0) { -+ dev_err(&pdev->dev, -+ "dprc_get_container_id() failed: %d\n", error); -+ goto error_cleanup_mc_io; -+ } -+ -+ memset(&obj_desc, 0, sizeof(struct fsl_mc_obj_desc)); -+ error = dprc_get_api_version(mc_io, 0, -+ &obj_desc.ver_major, -+ &obj_desc.ver_minor); -+ if (error < 0) -+ goto error_cleanup_mc_io; -+ -+ obj_desc.vendor = FSL_MC_VENDOR_FREESCALE; -+ strcpy(obj_desc.type, "dprc"); -+ obj_desc.id = container_id; -+ obj_desc.irq_count = 1; -+ obj_desc.region_count = 0; -+ -+ error = fsl_mc_device_add(&obj_desc, mc_io, &pdev->dev, NULL, -+ &mc_bus_dev); -+ if (error < 0) -+ goto error_cleanup_mc_io; -+ -+ mc_bus = to_fsl_mc_bus(mc_bus_dev); -+ error = fsl_mc_restool_create_device_file(mc_bus); -+ if (error < 0) -+ goto error_cleanup_device; -+ -+ mc->root_mc_bus_dev = mc_bus_dev; -+ -+ return 0; -+ -+error_cleanup_device: -+ fsl_mc_device_remove(mc_bus_dev); -+ -+error_cleanup_mc_io: -+ fsl_destroy_mc_io(mc_io); -+ return error; -+} -+ -+/** -+ * fsl_mc_bus_remove - callback invoked when the root MC bus is being -+ * removed -+ */ -+static int fsl_mc_bus_remove(struct platform_device *pdev) -+{ -+ struct fsl_mc *mc = platform_get_drvdata(pdev); -+ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc->root_mc_bus_dev); -+ -+ if (!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev)) -+ return -EINVAL; -+ -+ fsl_mc_restool_remove_device_file(mc_bus); -+ fsl_mc_device_remove(mc->root_mc_bus_dev); -+ -+ fsl_destroy_mc_io(mc->root_mc_bus_dev->mc_io); -+ mc->root_mc_bus_dev->mc_io = NULL; -+ -+ return 0; -+} -+ -+static const struct of_device_id fsl_mc_bus_match_table[] = { -+ {.compatible = "fsl,qoriq-mc",}, -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(of, fsl_mc_bus_match_table); -+ -+static struct platform_driver fsl_mc_bus_driver = { -+ .driver = { -+ .name = "fsl_mc_bus", -+ .pm = NULL, -+ .of_match_table = fsl_mc_bus_match_table, -+ }, -+ .probe = fsl_mc_bus_probe, -+ .remove = fsl_mc_bus_remove, -+}; -+ -+static int __init fsl_mc_bus_driver_init(void) -+{ -+ int error; -+ -+ error = bus_register(&fsl_mc_bus_type); -+ if (error < 0) { -+ pr_err("bus type registration failed: %d\n", error); -+ goto error_cleanup_cache; -+ } -+ -+ error = platform_driver_register(&fsl_mc_bus_driver); -+ if (error < 0) { -+ pr_err("platform_driver_register() failed: %d\n", error); -+ goto error_cleanup_bus; -+ } -+ -+ error = dprc_driver_init(); -+ if (error < 0) -+ goto error_cleanup_driver; -+ -+ error = fsl_mc_allocator_driver_init(); -+ if (error < 0) -+ goto error_cleanup_dprc_driver; -+ -+ error = fsl_mc_restool_init(); -+ if (error < 0) -+ goto error_cleanup_mc_allocator; -+ -+ return 0; -+ -+error_cleanup_mc_allocator: -+ fsl_mc_allocator_driver_exit(); -+ -+error_cleanup_dprc_driver: -+ dprc_driver_exit(); -+ -+error_cleanup_driver: -+ platform_driver_unregister(&fsl_mc_bus_driver); -+ -+error_cleanup_bus: -+ bus_unregister(&fsl_mc_bus_type); -+ -+error_cleanup_cache: -+ return error; -+} -+postcore_initcall(fsl_mc_bus_driver_init); ---- /dev/null -+++ b/drivers/bus/fsl-mc/fsl-mc-iommu.c -@@ -0,0 +1,78 @@ -+/* -+ * Copyright 2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ * Author: Nipun Gupta <nipun.gupta@nxp.com> -+ * -+ * This file is licensed under the terms of the GNU General Public -+ * License version 2. This program is licensed "as is" without any -+ * warranty of any kind, whether express or implied. -+ */ -+ -+#include <linux/iommu.h> -+#include <linux/of.h> -+#include <linux/of_iommu.h> -+#include <linux/fsl/mc.h> -+ -+/* Setup the IOMMU for the DPRC container */ -+static const struct iommu_ops -+*fsl_mc_iommu_configure(struct fsl_mc_device *mc_dev, -+ struct device_node *fsl_mc_platform_node) -+{ -+ struct of_phandle_args iommu_spec; -+ const struct iommu_ops *ops; -+ u32 iommu_phandle; -+ struct device_node *iommu_node; -+ const __be32 *map = NULL; -+ int iommu_cells, map_len, ret; -+ -+ map = of_get_property(fsl_mc_platform_node, "iommu-map", &map_len); -+ if (!map) -+ return NULL; -+ -+ ops = mc_dev->dev.bus->iommu_ops; -+ if (!ops || !ops->of_xlate) -+ return NULL; -+ -+ iommu_phandle = be32_to_cpup(map + 1); -+ iommu_node = of_find_node_by_phandle(iommu_phandle); -+ -+ if (of_property_read_u32(iommu_node, "#iommu-cells", &iommu_cells)) { -+ pr_err("%s: missing #iommu-cells property\n", iommu_node->name); -+ return NULL; -+ } -+ -+ /* Initialize the fwspec */ -+ ret = iommu_fwspec_init(&mc_dev->dev, &iommu_node->fwnode, ops); -+ if (ret) -+ return NULL; -+ -+ /* -+ * Fill in the required stream-id before calling the iommu's -+ * ops->xlate callback. -+ */ -+ iommu_spec.np = iommu_node; -+ iommu_spec.args[0] = mc_dev->icid; -+ iommu_spec.args_count = 1; -+ -+ ret = ops->of_xlate(&mc_dev->dev, &iommu_spec); -+ if (ret) -+ return NULL; -+ -+ of_node_put(iommu_spec.np); -+ -+ return ops; -+} -+ -+/* Set up DMA configuration for fsl-mc devices */ -+void fsl_mc_dma_configure(struct fsl_mc_device *mc_dev, -+ struct device_node *fsl_mc_platform_node, int coherent) -+{ -+ const struct iommu_ops *ops; -+ -+ ops = fsl_mc_iommu_configure(mc_dev, fsl_mc_platform_node); -+ -+ mc_dev->dev.coherent_dma_mask = DMA_BIT_MASK(48); -+ mc_dev->dev.dma_mask = &mc_dev->dev.coherent_dma_mask; -+ arch_setup_dma_ops(&mc_dev->dev, 0, -+ mc_dev->dev.coherent_dma_mask + 1, ops, coherent); -+} ---- a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c -+++ /dev/null -@@ -1,285 +0,0 @@ --/* -- * Freescale Management Complex (MC) bus driver MSI support -- * -- * Copyright (C) 2015 Freescale Semiconductor, Inc. -- * Author: German Rivera <German.Rivera@freescale.com> -- * -- * This file is licensed under the terms of the GNU General Public -- * License version 2. This program is licensed "as is" without any -- * warranty of any kind, whether express or implied. -- */ -- --#include <linux/of_device.h> --#include <linux/of_address.h> --#include <linux/irqchip/arm-gic-v3.h> --#include <linux/of_irq.h> --#include <linux/irq.h> --#include <linux/irqdomain.h> --#include <linux/msi.h> --#include "../include/mc-bus.h" --#include "fsl-mc-private.h" -- --/* -- * Generate a unique ID identifying the interrupt (only used within the MSI -- * irqdomain. Combine the icid with the interrupt index. -- */ --static irq_hw_number_t fsl_mc_domain_calc_hwirq(struct fsl_mc_device *dev, -- struct msi_desc *desc) --{ -- /* -- * Make the base hwirq value for ICID*10000 so it is readable -- * as a decimal value in /proc/interrupts. -- */ -- return (irq_hw_number_t)(desc->fsl_mc.msi_index + (dev->icid * 10000)); --} -- --static void fsl_mc_msi_set_desc(msi_alloc_info_t *arg, -- struct msi_desc *desc) --{ -- arg->desc = desc; -- arg->hwirq = fsl_mc_domain_calc_hwirq(to_fsl_mc_device(desc->dev), -- desc); --} -- --static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info) --{ -- struct msi_domain_ops *ops = info->ops; -- -- if (WARN_ON(!ops)) -- return; -- -- /* -- * set_desc should not be set by the caller -- */ -- if (!ops->set_desc) -- ops->set_desc = fsl_mc_msi_set_desc; --} -- --static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev, -- struct fsl_mc_device_irq *mc_dev_irq) --{ -- int error; -- struct fsl_mc_device *owner_mc_dev = mc_dev_irq->mc_dev; -- struct msi_desc *msi_desc = mc_dev_irq->msi_desc; -- struct dprc_irq_cfg irq_cfg; -- -- /* -- * msi_desc->msg.address is 0x0 when this function is invoked in -- * the free_irq() code path. In this case, for the MC, we don't -- * really need to "unprogram" the MSI, so we just return. -- */ -- if (msi_desc->msg.address_lo == 0x0 && msi_desc->msg.address_hi == 0x0) -- return; -- -- if (WARN_ON(!owner_mc_dev)) -- return; -- -- irq_cfg.paddr = ((u64)msi_desc->msg.address_hi << 32) | -- msi_desc->msg.address_lo; -- irq_cfg.val = msi_desc->msg.data; -- irq_cfg.irq_num = msi_desc->irq; -- -- if (owner_mc_dev == mc_bus_dev) { -- /* -- * IRQ is for the mc_bus_dev's DPRC itself -- */ -- error = dprc_set_irq(mc_bus_dev->mc_io, -- MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI, -- mc_bus_dev->mc_handle, -- mc_dev_irq->dev_irq_index, -- &irq_cfg); -- if (error < 0) { -- dev_err(&owner_mc_dev->dev, -- "dprc_set_irq() failed: %d\n", error); -- } -- } else { -- /* -- * IRQ is for for a child device of mc_bus_dev -- */ -- error = dprc_set_obj_irq(mc_bus_dev->mc_io, -- MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI, -- mc_bus_dev->mc_handle, -- owner_mc_dev->obj_desc.type, -- owner_mc_dev->obj_desc.id, -- mc_dev_irq->dev_irq_index, -- &irq_cfg); -- if (error < 0) { -- dev_err(&owner_mc_dev->dev, -- "dprc_obj_set_irq() failed: %d\n", error); -- } -- } --} -- --/* -- * NOTE: This function is invoked with interrupts disabled -- */ --static void fsl_mc_msi_write_msg(struct irq_data *irq_data, -- struct msi_msg *msg) --{ -- struct msi_desc *msi_desc = irq_data_get_msi_desc(irq_data); -- struct fsl_mc_device *mc_bus_dev = to_fsl_mc_device(msi_desc->dev); -- struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); -- struct fsl_mc_device_irq *mc_dev_irq = -- &mc_bus->irq_resources[msi_desc->fsl_mc.msi_index]; -- -- WARN_ON(mc_dev_irq->msi_desc != msi_desc); -- msi_desc->msg = *msg; -- -- /* -- * Program the MSI (paddr, value) pair in the device: -- */ -- __fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq); --} -- --static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info) --{ -- struct irq_chip *chip = info->chip; -- -- if (WARN_ON((!chip))) -- return; -- -- /* -- * irq_write_msi_msg should not be set by the caller -- */ -- if (!chip->irq_write_msi_msg) -- chip->irq_write_msi_msg = fsl_mc_msi_write_msg; --} -- --/** -- * fsl_mc_msi_create_irq_domain - Create a fsl-mc MSI interrupt domain -- * @np: Optional device-tree node of the interrupt controller -- * @info: MSI domain info -- * @parent: Parent irq domain -- * -- * Updates the domain and chip ops and creates a fsl-mc MSI -- * interrupt domain. -- * -- * Returns: -- * A domain pointer or NULL in case of failure. -- */ --struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode, -- struct msi_domain_info *info, -- struct irq_domain *parent) --{ -- struct irq_domain *domain; -- -- if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS) -- fsl_mc_msi_update_dom_ops(info); -- if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) -- fsl_mc_msi_update_chip_ops(info); -- -- domain = msi_create_irq_domain(fwnode, info, parent); -- if (domain) -- domain->bus_token = DOMAIN_BUS_FSL_MC_MSI; -- -- return domain; --} -- --int fsl_mc_find_msi_domain(struct device *mc_platform_dev, -- struct irq_domain **mc_msi_domain) --{ -- struct irq_domain *msi_domain; -- struct device_node *mc_of_node = mc_platform_dev->of_node; -- -- msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node, -- DOMAIN_BUS_FSL_MC_MSI); -- if (!msi_domain) { -- pr_err("Unable to find fsl-mc MSI domain for %s\n", -- mc_of_node->full_name); -- -- return -ENOENT; -- } -- -- *mc_msi_domain = msi_domain; -- return 0; --} -- --static void fsl_mc_msi_free_descs(struct device *dev) --{ -- struct msi_desc *desc, *tmp; -- -- list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) { -- list_del(&desc->list); -- free_msi_entry(desc); -- } --} -- --static int fsl_mc_msi_alloc_descs(struct device *dev, unsigned int irq_count) -- --{ -- unsigned int i; -- int error; -- struct msi_desc *msi_desc; -- -- for (i = 0; i < irq_count; i++) { -- msi_desc = alloc_msi_entry(dev, 1, NULL); -- if (!msi_desc) { -- dev_err(dev, "Failed to allocate msi entry\n"); -- error = -ENOMEM; -- goto cleanup_msi_descs; -- } -- -- msi_desc->fsl_mc.msi_index = i; -- INIT_LIST_HEAD(&msi_desc->list); -- list_add_tail(&msi_desc->list, dev_to_msi_list(dev)); -- } -- -- return 0; -- --cleanup_msi_descs: -- fsl_mc_msi_free_descs(dev); -- return error; --} -- --int fsl_mc_msi_domain_alloc_irqs(struct device *dev, -- unsigned int irq_count) --{ -- struct irq_domain *msi_domain; -- int error; -- -- if (WARN_ON(!list_empty(dev_to_msi_list(dev)))) -- return -EINVAL; -- -- error = fsl_mc_msi_alloc_descs(dev, irq_count); -- if (error < 0) -- return error; -- -- msi_domain = dev_get_msi_domain(dev); -- if (WARN_ON(!msi_domain)) { -- error = -EINVAL; -- goto cleanup_msi_descs; -- } -- -- /* -- * NOTE: Calling this function will trigger the invocation of the -- * its_fsl_mc_msi_prepare() callback -- */ -- error = msi_domain_alloc_irqs(msi_domain, dev, irq_count); -- -- if (error) { -- dev_err(dev, "Failed to allocate IRQs\n"); -- goto cleanup_msi_descs; -- } -- -- return 0; -- --cleanup_msi_descs: -- fsl_mc_msi_free_descs(dev); -- return error; --} -- --void fsl_mc_msi_domain_free_irqs(struct device *dev) --{ -- struct irq_domain *msi_domain; -- -- msi_domain = dev_get_msi_domain(dev); -- if (WARN_ON(!msi_domain)) -- return; -- -- msi_domain_free_irqs(msi_domain, dev); -- -- if (WARN_ON(list_empty(dev_to_msi_list(dev)))) -- return; -- -- fsl_mc_msi_free_descs(dev); --} ---- /dev/null -+++ b/drivers/bus/fsl-mc/fsl-mc-msi.c -@@ -0,0 +1,285 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Freescale Management Complex (MC) bus driver MSI support -+ * -+ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. -+ * Author: German Rivera <German.Rivera@freescale.com> -+ * -+ */ -+ -+#include <linux/of_device.h> -+#include <linux/of_address.h> -+#include <linux/of_irq.h> -+#include <linux/irq.h> -+#include <linux/irqdomain.h> -+#include <linux/msi.h> -+ -+#include "fsl-mc-private.h" -+ -+#ifdef GENERIC_MSI_DOMAIN_OPS -+/* -+ * Generate a unique ID identifying the interrupt (only used within the MSI -+ * irqdomain. Combine the icid with the interrupt index. -+ */ -+static irq_hw_number_t fsl_mc_domain_calc_hwirq(struct fsl_mc_device *dev, -+ struct msi_desc *desc) -+{ -+ /* -+ * Make the base hwirq value for ICID*10000 so it is readable -+ * as a decimal value in /proc/interrupts. -+ */ -+ return (irq_hw_number_t)(desc->fsl_mc.msi_index + (dev->icid * 10000)); -+} -+ -+static void fsl_mc_msi_set_desc(msi_alloc_info_t *arg, -+ struct msi_desc *desc) -+{ -+ arg->desc = desc; -+ arg->hwirq = fsl_mc_domain_calc_hwirq(to_fsl_mc_device(desc->dev), -+ desc); -+} -+#else -+#define fsl_mc_msi_set_desc NULL -+#endif -+ -+static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info) -+{ -+ struct msi_domain_ops *ops = info->ops; -+ -+ if (!ops) -+ return; -+ -+ /* -+ * set_desc should not be set by the caller -+ */ -+ if (!ops->set_desc) -+ ops->set_desc = fsl_mc_msi_set_desc; -+} -+ -+static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev, -+ struct fsl_mc_device_irq *mc_dev_irq) -+{ -+ int error; -+ struct fsl_mc_device *owner_mc_dev = mc_dev_irq->mc_dev; -+ struct msi_desc *msi_desc = mc_dev_irq->msi_desc; -+ struct dprc_irq_cfg irq_cfg; -+ -+ /* -+ * msi_desc->msg.address is 0x0 when this function is invoked in -+ * the free_irq() code path. In this case, for the MC, we don't -+ * really need to "unprogram" the MSI, so we just return. -+ */ -+ if (msi_desc->msg.address_lo == 0x0 && msi_desc->msg.address_hi == 0x0) -+ return; -+ -+ if (!owner_mc_dev) -+ return; -+ -+ irq_cfg.paddr = ((u64)msi_desc->msg.address_hi << 32) | -+ msi_desc->msg.address_lo; -+ irq_cfg.val = msi_desc->msg.data; -+ irq_cfg.irq_num = msi_desc->irq; -+ -+ if (owner_mc_dev == mc_bus_dev) { -+ /* -+ * IRQ is for the mc_bus_dev's DPRC itself -+ */ -+ error = dprc_set_irq(mc_bus_dev->mc_io, -+ MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI, -+ mc_bus_dev->mc_handle, -+ mc_dev_irq->dev_irq_index, -+ &irq_cfg); -+ if (error < 0) { -+ dev_err(&owner_mc_dev->dev, -+ "dprc_set_irq() failed: %d\n", error); -+ } -+ } else { -+ /* -+ * IRQ is for for a child device of mc_bus_dev -+ */ -+ error = dprc_set_obj_irq(mc_bus_dev->mc_io, -+ MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI, -+ mc_bus_dev->mc_handle, -+ owner_mc_dev->obj_desc.type, -+ owner_mc_dev->obj_desc.id, -+ mc_dev_irq->dev_irq_index, -+ &irq_cfg); -+ if (error < 0) { -+ dev_err(&owner_mc_dev->dev, -+ "dprc_obj_set_irq() failed: %d\n", error); -+ } -+ } -+} -+ -+/* -+ * NOTE: This function is invoked with interrupts disabled -+ */ -+static void fsl_mc_msi_write_msg(struct irq_data *irq_data, -+ struct msi_msg *msg) -+{ -+ struct msi_desc *msi_desc = irq_data_get_msi_desc(irq_data); -+ struct fsl_mc_device *mc_bus_dev = to_fsl_mc_device(msi_desc->dev); -+ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); -+ struct fsl_mc_device_irq *mc_dev_irq = -+ &mc_bus->irq_resources[msi_desc->fsl_mc.msi_index]; -+ -+ msi_desc->msg = *msg; -+ -+ /* -+ * Program the MSI (paddr, value) pair in the device: -+ */ -+ __fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq); -+} -+ -+static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info) -+{ -+ struct irq_chip *chip = info->chip; -+ -+ if (!chip) -+ return; -+ -+ /* -+ * irq_write_msi_msg should not be set by the caller -+ */ -+ if (!chip->irq_write_msi_msg) -+ chip->irq_write_msi_msg = fsl_mc_msi_write_msg; -+} -+ -+/** -+ * fsl_mc_msi_create_irq_domain - Create a fsl-mc MSI interrupt domain -+ * @np: Optional device-tree node of the interrupt controller -+ * @info: MSI domain info -+ * @parent: Parent irq domain -+ * -+ * Updates the domain and chip ops and creates a fsl-mc MSI -+ * interrupt domain. -+ * -+ * Returns: -+ * A domain pointer or NULL in case of failure. -+ */ -+struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode, -+ struct msi_domain_info *info, -+ struct irq_domain *parent) -+{ -+ struct irq_domain *domain; -+ -+ if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS) -+ fsl_mc_msi_update_dom_ops(info); -+ if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) -+ fsl_mc_msi_update_chip_ops(info); -+ -+ domain = msi_create_irq_domain(fwnode, info, parent); -+ if (domain) -+ irq_domain_update_bus_token(domain, DOMAIN_BUS_FSL_MC_MSI); -+ -+ return domain; -+} -+ -+int fsl_mc_find_msi_domain(struct device *mc_platform_dev, -+ struct irq_domain **mc_msi_domain) -+{ -+ struct irq_domain *msi_domain; -+ struct device_node *mc_of_node = mc_platform_dev->of_node; -+ -+ msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node, -+ DOMAIN_BUS_FSL_MC_MSI); -+ if (!msi_domain) { -+ pr_err("Unable to find fsl-mc MSI domain for %pOF\n", -+ mc_of_node); -+ -+ return -ENOENT; -+ } -+ -+ *mc_msi_domain = msi_domain; -+ return 0; -+} -+ -+static void fsl_mc_msi_free_descs(struct device *dev) -+{ -+ struct msi_desc *desc, *tmp; -+ -+ list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) { -+ list_del(&desc->list); -+ free_msi_entry(desc); -+ } -+} -+ -+static int fsl_mc_msi_alloc_descs(struct device *dev, unsigned int irq_count) -+ -+{ -+ unsigned int i; -+ int error; -+ struct msi_desc *msi_desc; -+ -+ for (i = 0; i < irq_count; i++) { -+ msi_desc = alloc_msi_entry(dev, 1, NULL); -+ if (!msi_desc) { -+ dev_err(dev, "Failed to allocate msi entry\n"); -+ error = -ENOMEM; -+ goto cleanup_msi_descs; -+ } -+ -+ msi_desc->fsl_mc.msi_index = i; -+ INIT_LIST_HEAD(&msi_desc->list); -+ list_add_tail(&msi_desc->list, dev_to_msi_list(dev)); -+ } -+ -+ return 0; -+ -+cleanup_msi_descs: -+ fsl_mc_msi_free_descs(dev); -+ return error; -+} -+ -+int fsl_mc_msi_domain_alloc_irqs(struct device *dev, -+ unsigned int irq_count) -+{ -+ struct irq_domain *msi_domain; -+ int error; -+ -+ if (!list_empty(dev_to_msi_list(dev))) -+ return -EINVAL; -+ -+ error = fsl_mc_msi_alloc_descs(dev, irq_count); -+ if (error < 0) -+ return error; -+ -+ msi_domain = dev_get_msi_domain(dev); -+ if (!msi_domain) { -+ error = -EINVAL; -+ goto cleanup_msi_descs; -+ } -+ -+ /* -+ * NOTE: Calling this function will trigger the invocation of the -+ * its_fsl_mc_msi_prepare() callback -+ */ -+ error = msi_domain_alloc_irqs(msi_domain, dev, irq_count); -+ -+ if (error) { -+ dev_err(dev, "Failed to allocate IRQs\n"); -+ goto cleanup_msi_descs; -+ } -+ -+ return 0; -+ -+cleanup_msi_descs: -+ fsl_mc_msi_free_descs(dev); -+ return error; -+} -+ -+void fsl_mc_msi_domain_free_irqs(struct device *dev) -+{ -+ struct irq_domain *msi_domain; -+ -+ msi_domain = dev_get_msi_domain(dev); -+ if (!msi_domain) -+ return; -+ -+ msi_domain_free_irqs(msi_domain, dev); -+ -+ if (list_empty(dev_to_msi_list(dev))) -+ return; -+ -+ fsl_mc_msi_free_descs(dev); -+} ---- /dev/null -+++ b/drivers/bus/fsl-mc/fsl-mc-private.h -@@ -0,0 +1,223 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Freescale Management Complex (MC) bus private declarations -+ * -+ * Copyright (C) 2016 Freescale Semiconductor, Inc. -+ * -+ */ -+#ifndef _FSL_MC_PRIVATE_H_ -+#define _FSL_MC_PRIVATE_H_ -+ -+#include <linux/fsl/mc.h> -+#include <linux/mutex.h> -+#include <linux/cdev.h> -+#include <linux/ioctl.h> -+ -+/* -+ * Data Path Management Complex (DPMNG) General API -+ */ -+ -+/* DPMNG command versioning */ -+#define DPMNG_CMD_BASE_VERSION 1 -+#define DPMNG_CMD_ID_OFFSET 4 -+ -+#define DPMNG_CMD(id) (((id) << DPMNG_CMD_ID_OFFSET) | DPMNG_CMD_BASE_VERSION) -+ -+/* DPMNG command IDs */ -+#define DPMNG_CMDID_GET_VERSION DPMNG_CMD(0x831) -+ -+struct dpmng_rsp_get_version { -+ __le32 revision; -+ __le32 version_major; -+ __le32 version_minor; -+}; -+ -+/* -+ * Data Path Management Command Portal (DPMCP) API -+ */ -+ -+/* Minimal supported DPMCP Version */ -+#define DPMCP_MIN_VER_MAJOR 3 -+#define DPMCP_MIN_VER_MINOR 0 -+ -+/* DPMCP command versioning */ -+#define DPMCP_CMD_BASE_VERSION 1 -+#define DPMCP_CMD_ID_OFFSET 4 -+ -+#define DPMCP_CMD(id) (((id) << DPMCP_CMD_ID_OFFSET) | DPMCP_CMD_BASE_VERSION) -+ -+/* DPMCP command IDs */ -+#define DPMCP_CMDID_CLOSE DPMCP_CMD(0x800) -+#define DPMCP_CMDID_OPEN DPMCP_CMD(0x80b) -+#define DPMCP_CMDID_RESET DPMCP_CMD(0x005) -+ -+struct dpmcp_cmd_open { -+ __le32 dpmcp_id; -+}; -+ -+/* -+ * Initialization and runtime control APIs for DPMCP -+ */ -+int dpmcp_open(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ int dpmcp_id, -+ u16 *token); -+ -+int dpmcp_close(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token); -+ -+int dpmcp_reset(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token); -+ -+/* -+ * Data Path Buffer Pool (DPBP) API -+ */ -+ -+/* DPBP Version */ -+#define DPBP_VER_MAJOR 3 -+#define DPBP_VER_MINOR 2 -+ -+/* Command versioning */ -+#define DPBP_CMD_BASE_VERSION 1 -+#define DPBP_CMD_ID_OFFSET 4 -+ -+#define DPBP_CMD(id) (((id) << DPBP_CMD_ID_OFFSET) | DPBP_CMD_BASE_VERSION) -+ -+/* Command IDs */ -+#define DPBP_CMDID_CLOSE DPBP_CMD(0x800) -+#define DPBP_CMDID_OPEN DPBP_CMD(0x804) -+ -+#define DPBP_CMDID_ENABLE DPBP_CMD(0x002) -+#define DPBP_CMDID_DISABLE DPBP_CMD(0x003) -+#define DPBP_CMDID_GET_ATTR DPBP_CMD(0x004) -+#define DPBP_CMDID_RESET DPBP_CMD(0x005) -+ -+struct dpbp_cmd_open { -+ __le32 dpbp_id; -+}; -+ -+#define DPBP_ENABLE 0x1 -+ -+struct dpbp_rsp_get_attributes { -+ /* response word 0 */ -+ __le16 pad; -+ __le16 bpid; -+ __le32 id; -+ /* response word 1 */ -+ __le16 version_major; -+ __le16 version_minor; -+}; -+ -+/* -+ * Data Path Concentrator (DPCON) API -+ */ -+ -+/* DPCON Version */ -+#define DPCON_VER_MAJOR 3 -+#define DPCON_VER_MINOR 2 -+ -+/* Command versioning */ -+#define DPCON_CMD_BASE_VERSION 1 -+#define DPCON_CMD_ID_OFFSET 4 -+ -+#define DPCON_CMD(id) (((id) << DPCON_CMD_ID_OFFSET) | DPCON_CMD_BASE_VERSION) -+ -+/* Command IDs */ -+#define DPCON_CMDID_CLOSE DPCON_CMD(0x800) -+#define DPCON_CMDID_OPEN DPCON_CMD(0x808) -+ -+#define DPCON_CMDID_ENABLE DPCON_CMD(0x002) -+#define DPCON_CMDID_DISABLE DPCON_CMD(0x003) -+#define DPCON_CMDID_GET_ATTR DPCON_CMD(0x004) -+#define DPCON_CMDID_RESET DPCON_CMD(0x005) -+ -+#define DPCON_CMDID_SET_NOTIFICATION DPCON_CMD(0x100) -+ -+struct dpcon_cmd_open { -+ __le32 dpcon_id; -+}; -+ -+#define DPCON_ENABLE 1 -+ -+struct dpcon_rsp_get_attr { -+ /* response word 0 */ -+ __le32 id; -+ __le16 qbman_ch_id; -+ u8 num_priorities; -+ u8 pad; -+}; -+ -+struct dpcon_cmd_set_notification { -+ /* cmd word 0 */ -+ __le32 dpio_id; -+ u8 priority; -+ u8 pad[3]; -+ /* cmd word 1 */ -+ __le64 user_ctx; -+}; -+ -+int __must_check fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc, -+ struct fsl_mc_io *mc_io, -+ struct device *parent_dev, -+ const char *driver_override, -+ struct fsl_mc_device **new_mc_dev); -+ -+int __init dprc_driver_init(void); -+ -+void dprc_driver_exit(void); -+ -+int __init fsl_mc_allocator_driver_init(void); -+ -+void fsl_mc_allocator_driver_exit(void); -+ -+int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, -+ enum fsl_mc_pool_type pool_type, -+ struct fsl_mc_resource -+ **new_resource); -+ -+void fsl_mc_resource_free(struct fsl_mc_resource *resource); -+ -+int fsl_mc_msi_domain_alloc_irqs(struct device *dev, -+ unsigned int irq_count); -+ -+void fsl_mc_msi_domain_free_irqs(struct device *dev); -+ -+int __must_check fsl_create_mc_io(struct device *dev, -+ phys_addr_t mc_portal_phys_addr, -+ u32 mc_portal_size, -+ struct fsl_mc_device *dpmcp_dev, -+ u32 flags, struct fsl_mc_io **new_mc_io); -+ -+void fsl_destroy_mc_io(struct fsl_mc_io *mc_io); -+ -+bool fsl_mc_is_root_dprc(struct device *dev); -+ -+#ifdef CONFIG_FSL_MC_RESTOOL -+ -+int fsl_mc_restool_create_device_file(struct fsl_mc_bus *mc_bus); -+ -+void fsl_mc_restool_remove_device_file(struct fsl_mc_bus *mc_bus); -+ -+int fsl_mc_restool_init(void); -+ -+#else -+ -+static inline int fsl_mc_restool_create_device_file(struct fsl_mc_bus *mc_bus) -+{ -+ return 0; -+} -+ -+static inline void fsl_mc_restool_remove_device_file(struct fsl_mc_bus *mc_bus) -+{ -+} -+ -+static inline int fsl_mc_restool_init(void) -+{ -+ return 0; -+} -+ -+#endif -+ -+#endif /* _FSL_MC_PRIVATE_H_ */ ---- /dev/null -+++ b/drivers/bus/fsl-mc/fsl-mc-restool.c -@@ -0,0 +1,219 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Management Complex (MC) restool support -+ * -+ * Copyright 2018 NXP -+ * -+ */ -+ -+#include <linux/slab.h> -+#include <linux/cdev.h> -+#include <linux/fs.h> -+#include <linux/uaccess.h> -+ -+#include "fsl-mc-private.h" -+ -+#define FSL_MC_BUS_MAX_MINORS 1 -+ -+static struct class *fsl_mc_bus_class; -+static int fsl_mc_bus_major; -+ -+static int fsl_mc_restool_send_command(unsigned long arg, -+ struct fsl_mc_io *mc_io) -+{ -+ struct fsl_mc_command mc_cmd; -+ int error; -+ -+ error = copy_from_user(&mc_cmd, (void __user *)arg, sizeof(mc_cmd)); -+ if (error) -+ return -EFAULT; -+ -+ error = mc_send_command(mc_io, &mc_cmd); -+ if (error) -+ return error; -+ -+ error = copy_to_user((void __user *)arg, &mc_cmd, sizeof(mc_cmd)); -+ if (error) -+ return -EFAULT; -+ -+ return 0; -+} -+ -+int fsl_mc_restool_init(void) -+{ -+ dev_t dev; -+ int error; -+ -+ fsl_mc_bus_class = class_create(THIS_MODULE, "fsl_mc_bus"); -+ if (IS_ERR(fsl_mc_bus_class)) { -+ error = PTR_ERR(fsl_mc_bus_class); -+ return error; -+ } -+ -+ error = alloc_chrdev_region(&dev, 0, -+ FSL_MC_BUS_MAX_MINORS, -+ "fsl_mc_bus"); -+ if (error < 0) -+ return error; -+ -+ fsl_mc_bus_major = MAJOR(dev); -+ -+ return 0; -+} -+ -+static int fsl_mc_restool_dev_open(struct inode *inode, struct file *filep) -+{ -+ struct fsl_mc_device *root_mc_device; -+ struct fsl_mc_restool *mc_restool; -+ struct fsl_mc_bus *mc_bus; -+ struct fsl_mc_io *dynamic_mc_io; -+ int error; -+ -+ mc_restool = container_of(inode->i_cdev, struct fsl_mc_restool, cdev); -+ mc_bus = container_of(mc_restool, struct fsl_mc_bus, restool_misc); -+ root_mc_device = &mc_bus->mc_dev; -+ -+ mutex_lock(&mc_restool->mutex); -+ -+ if (!mc_restool->local_instance_in_use) { -+ filep->private_data = root_mc_device->mc_io; -+ mc_restool->local_instance_in_use = true; -+ } else { -+ dynamic_mc_io = kzalloc(sizeof(*dynamic_mc_io), GFP_KERNEL); -+ if (!dynamic_mc_io) { -+ error = -ENOMEM; -+ goto error_alloc_mc_io; -+ } -+ -+ error = fsl_mc_portal_allocate(root_mc_device, 0, -+ &dynamic_mc_io); -+ if (error) { -+ pr_err("Could not allocate MC portal\n"); -+ goto error_portal_allocate; -+ } -+ -+ mc_restool->dynamic_instance_count++; -+ filep->private_data = dynamic_mc_io; -+ } -+ -+ mutex_unlock(&mc_restool->mutex); -+ -+ return 0; -+ -+error_portal_allocate: -+ kfree(dynamic_mc_io); -+ -+error_alloc_mc_io: -+ mutex_unlock(&mc_restool->mutex); -+ -+ return error; -+} -+ -+static int fsl_mc_restool_dev_release(struct inode *inode, struct file *filep) -+{ -+ struct fsl_mc_device *root_mc_device; -+ struct fsl_mc_restool *mc_restool; -+ struct fsl_mc_bus *mc_bus; -+ struct fsl_mc_io *mc_io; -+ -+ mc_restool = container_of(inode->i_cdev, struct fsl_mc_restool, cdev); -+ mc_bus = container_of(mc_restool, struct fsl_mc_bus, restool_misc); -+ root_mc_device = &mc_bus->mc_dev; -+ mc_io = filep->private_data; -+ -+ mutex_lock(&mc_restool->mutex); -+ -+ if (WARN_ON(!mc_restool->local_instance_in_use && -+ mc_restool->dynamic_instance_count == 0)) { -+ mutex_unlock(&mc_restool->mutex); -+ return -EINVAL; -+ } -+ -+ if (filep->private_data == root_mc_device->mc_io) { -+ mc_restool->local_instance_in_use = false; -+ } else { -+ fsl_mc_portal_free(mc_io); -+ kfree(mc_io); -+ mc_restool->dynamic_instance_count--; -+ } -+ -+ filep->private_data = NULL; -+ mutex_unlock(&mc_restool->mutex); -+ -+ return 0; -+} -+ -+static long fsl_mc_restool_dev_ioctl(struct file *file, -+ unsigned int cmd, -+ unsigned long arg) -+{ -+ int error; -+ -+ switch (cmd) { -+ case RESTOOL_SEND_MC_COMMAND: -+ error = fsl_mc_restool_send_command(arg, file->private_data); -+ break; -+ default: -+ pr_err("%s: unexpected ioctl call number\n", __func__); -+ error = -EINVAL; -+ } -+ -+ return error; -+} -+ -+static const struct file_operations fsl_mc_restool_dev_fops = { -+ .owner = THIS_MODULE, -+ .open = fsl_mc_restool_dev_open, -+ .release = fsl_mc_restool_dev_release, -+ .unlocked_ioctl = fsl_mc_restool_dev_ioctl, -+}; -+ -+int fsl_mc_restool_create_device_file(struct fsl_mc_bus *mc_bus) -+{ -+ struct fsl_mc_device *mc_dev = &mc_bus->mc_dev; -+ struct fsl_mc_restool *mc_restool = &mc_bus->restool_misc; -+ int error; -+ -+ mc_restool = &mc_bus->restool_misc; -+ mc_restool->dev = MKDEV(fsl_mc_bus_major, 0); -+ cdev_init(&mc_restool->cdev, &fsl_mc_restool_dev_fops); -+ -+ error = cdev_add(&mc_restool->cdev, -+ mc_restool->dev, -+ FSL_MC_BUS_MAX_MINORS); -+ if (error) -+ return error; -+ -+ mc_restool->device = device_create(fsl_mc_bus_class, -+ NULL, -+ mc_restool->dev, -+ NULL, -+ "%s", -+ dev_name(&mc_dev->dev)); -+ if (IS_ERR(mc_restool->device)) { -+ error = PTR_ERR(mc_restool->device); -+ goto error_device_create; -+ } -+ -+ mutex_init(&mc_restool->mutex); -+ -+ return 0; -+ -+error_device_create: -+ cdev_del(&mc_restool->cdev); -+ -+ return error; -+} -+ -+void fsl_mc_restool_remove_device_file(struct fsl_mc_bus *mc_bus) -+{ -+ struct fsl_mc_restool *mc_restool = &mc_bus->restool_misc; -+ -+ if (WARN_ON(mc_restool->local_instance_in_use)) -+ return; -+ -+ if (WARN_ON(mc_restool->dynamic_instance_count != 0)) -+ return; -+ -+ cdev_del(&mc_restool->cdev); -+} ---- a/drivers/staging/fsl-mc/bus/mc-io.c -+++ /dev/null -@@ -1,320 +0,0 @@ --/* Copyright 2013-2016 Freescale Semiconductor Inc. -- * -- * Redistribution and use in source and binary forms, with or without -- * modification, are permitted provided that the following conditions are met: -- * * Redistributions of source code must retain the above copyright -- * notice, this list of conditions and the following disclaimer. -- * * Redistributions in binary form must reproduce the above copyright -- * notice, this list of conditions and the following disclaimer in the -- * documentation and/or other materials provided with the distribution. -- * * Neither the name of the above-listed copyright holders nor the -- * names of any contributors may be used to endorse or promote products -- * derived from this software without specific prior written permission. -- * -- * -- * ALTERNATIVELY, this software may be distributed under the terms of the -- * GNU General Public License ("GPL") as published by the Free Software -- * Foundation, either version 2 of that License or (at your option) any -- * later version. -- * -- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -- * POSSIBILITY OF SUCH DAMAGE. -- */ -- --#include <linux/io.h> --#include "../include/mc-bus.h" --#include "../include/mc-sys.h" -- --#include "fsl-mc-private.h" --#include "dpmcp.h" --#include "dpmcp-cmd.h" -- --static int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io, -- struct fsl_mc_device *dpmcp_dev) --{ -- int error; -- -- if (WARN_ON(!dpmcp_dev)) -- return -EINVAL; -- -- if (WARN_ON(mc_io->dpmcp_dev)) -- return -EINVAL; -- -- if (WARN_ON(dpmcp_dev->mc_io)) -- return -EINVAL; -- -- error = dpmcp_open(mc_io, -- 0, -- dpmcp_dev->obj_desc.id, -- &dpmcp_dev->mc_handle); -- if (error < 0) -- return error; -- -- mc_io->dpmcp_dev = dpmcp_dev; -- dpmcp_dev->mc_io = mc_io; -- return 0; --} -- --static void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io) --{ -- int error; -- struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; -- -- if (WARN_ON(!dpmcp_dev)) -- return; -- -- if (WARN_ON(dpmcp_dev->mc_io != mc_io)) -- return; -- -- error = dpmcp_close(mc_io, -- 0, -- dpmcp_dev->mc_handle); -- if (error < 0) { -- dev_err(&dpmcp_dev->dev, "dpmcp_close() failed: %d\n", -- error); -- } -- -- mc_io->dpmcp_dev = NULL; -- dpmcp_dev->mc_io = NULL; --} -- --/** -- * Creates an MC I/O object -- * -- * @dev: device to be associated with the MC I/O object -- * @mc_portal_phys_addr: physical address of the MC portal to use -- * @mc_portal_size: size in bytes of the MC portal -- * @dpmcp-dev: Pointer to the DPMCP object associated with this MC I/O -- * object or NULL if none. -- * @flags: flags for the new MC I/O object -- * @new_mc_io: Area to return pointer to newly created MC I/O object -- * -- * Returns '0' on Success; Error code otherwise. -- */ --int __must_check fsl_create_mc_io(struct device *dev, -- phys_addr_t mc_portal_phys_addr, -- u32 mc_portal_size, -- struct fsl_mc_device *dpmcp_dev, -- u32 flags, struct fsl_mc_io **new_mc_io) --{ -- int error; -- struct fsl_mc_io *mc_io; -- void __iomem *mc_portal_virt_addr; -- struct resource *res; -- -- mc_io = devm_kzalloc(dev, sizeof(*mc_io), GFP_KERNEL); -- if (!mc_io) -- return -ENOMEM; -- -- mc_io->dev = dev; -- mc_io->flags = flags; -- mc_io->portal_phys_addr = mc_portal_phys_addr; -- mc_io->portal_size = mc_portal_size; -- if (flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) -- spin_lock_init(&mc_io->spinlock); -- else -- mutex_init(&mc_io->mutex); -- -- res = devm_request_mem_region(dev, -- mc_portal_phys_addr, -- mc_portal_size, -- "mc_portal"); -- if (!res) { -- dev_err(dev, -- "devm_request_mem_region failed for MC portal %#llx\n", -- mc_portal_phys_addr); -- return -EBUSY; -- } -- -- mc_portal_virt_addr = devm_ioremap_nocache(dev, -- mc_portal_phys_addr, -- mc_portal_size); -- if (!mc_portal_virt_addr) { -- dev_err(dev, -- "devm_ioremap_nocache failed for MC portal %#llx\n", -- mc_portal_phys_addr); -- return -ENXIO; -- } -- -- mc_io->portal_virt_addr = mc_portal_virt_addr; -- if (dpmcp_dev) { -- error = fsl_mc_io_set_dpmcp(mc_io, dpmcp_dev); -- if (error < 0) -- goto error_destroy_mc_io; -- } -- -- *new_mc_io = mc_io; -- return 0; -- --error_destroy_mc_io: -- fsl_destroy_mc_io(mc_io); -- return error; --} -- --/** -- * Destroys an MC I/O object -- * -- * @mc_io: MC I/O object to destroy -- */ --void fsl_destroy_mc_io(struct fsl_mc_io *mc_io) --{ -- struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; -- -- if (dpmcp_dev) -- fsl_mc_io_unset_dpmcp(mc_io); -- -- devm_iounmap(mc_io->dev, mc_io->portal_virt_addr); -- devm_release_mem_region(mc_io->dev, -- mc_io->portal_phys_addr, -- mc_io->portal_size); -- -- mc_io->portal_virt_addr = NULL; -- devm_kfree(mc_io->dev, mc_io); --} -- --/** -- * fsl_mc_portal_allocate - Allocates an MC portal -- * -- * @mc_dev: MC device for which the MC portal is to be allocated -- * @mc_io_flags: Flags for the fsl_mc_io object that wraps the allocated -- * MC portal. -- * @new_mc_io: Pointer to area where the pointer to the fsl_mc_io object -- * that wraps the allocated MC portal is to be returned -- * -- * This function allocates an MC portal from the device's parent DPRC, -- * from the corresponding MC bus' pool of MC portals and wraps -- * it in a new fsl_mc_io object. If 'mc_dev' is a DPRC itself, the -- * portal is allocated from its own MC bus. -- */ --int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, -- u16 mc_io_flags, -- struct fsl_mc_io **new_mc_io) --{ -- struct fsl_mc_device *mc_bus_dev; -- struct fsl_mc_bus *mc_bus; -- phys_addr_t mc_portal_phys_addr; -- size_t mc_portal_size; -- struct fsl_mc_device *dpmcp_dev; -- int error = -EINVAL; -- struct fsl_mc_resource *resource = NULL; -- struct fsl_mc_io *mc_io = NULL; -- -- if (mc_dev->flags & FSL_MC_IS_DPRC) { -- mc_bus_dev = mc_dev; -- } else { -- if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent))) -- return error; -- -- mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); -- } -- -- mc_bus = to_fsl_mc_bus(mc_bus_dev); -- *new_mc_io = NULL; -- error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_DPMCP, &resource); -- if (error < 0) -- return error; -- -- error = -EINVAL; -- dpmcp_dev = resource->data; -- if (WARN_ON(!dpmcp_dev)) -- goto error_cleanup_resource; -- -- if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR || -- (dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR && -- dpmcp_dev->obj_desc.ver_minor < DPMCP_MIN_VER_MINOR)) { -- dev_err(&dpmcp_dev->dev, -- "ERROR: Version %d.%d of DPMCP not supported.\n", -- dpmcp_dev->obj_desc.ver_major, -- dpmcp_dev->obj_desc.ver_minor); -- error = -ENOTSUPP; -- goto error_cleanup_resource; -- } -- -- if (WARN_ON(dpmcp_dev->obj_desc.region_count == 0)) -- goto error_cleanup_resource; -- -- mc_portal_phys_addr = dpmcp_dev->regions[0].start; -- mc_portal_size = dpmcp_dev->regions[0].end - -- dpmcp_dev->regions[0].start + 1; -- -- if (WARN_ON(mc_portal_size != mc_bus_dev->mc_io->portal_size)) -- goto error_cleanup_resource; -- -- error = fsl_create_mc_io(&mc_bus_dev->dev, -- mc_portal_phys_addr, -- mc_portal_size, dpmcp_dev, -- mc_io_flags, &mc_io); -- if (error < 0) -- goto error_cleanup_resource; -- -- *new_mc_io = mc_io; -- return 0; -- --error_cleanup_resource: -- fsl_mc_resource_free(resource); -- return error; --} --EXPORT_SYMBOL_GPL(fsl_mc_portal_allocate); -- --/** -- * fsl_mc_portal_free - Returns an MC portal to the pool of free MC portals -- * of a given MC bus -- * -- * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free -- */ --void fsl_mc_portal_free(struct fsl_mc_io *mc_io) --{ -- struct fsl_mc_device *dpmcp_dev; -- struct fsl_mc_resource *resource; -- -- /* -- * Every mc_io obtained by calling fsl_mc_portal_allocate() is supposed -- * to have a DPMCP object associated with. -- */ -- dpmcp_dev = mc_io->dpmcp_dev; -- if (WARN_ON(!dpmcp_dev)) -- return; -- -- resource = dpmcp_dev->resource; -- if (WARN_ON(!resource || resource->type != FSL_MC_POOL_DPMCP)) -- return; -- -- if (WARN_ON(resource->data != dpmcp_dev)) -- return; -- -- fsl_destroy_mc_io(mc_io); -- fsl_mc_resource_free(resource); --} --EXPORT_SYMBOL_GPL(fsl_mc_portal_free); -- --/** -- * fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object -- * -- * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free -- */ --int fsl_mc_portal_reset(struct fsl_mc_io *mc_io) --{ -- int error; -- struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; -- -- if (WARN_ON(!dpmcp_dev)) -- return -EINVAL; -- -- error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle); -- if (error < 0) { -- dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error); -- return error; -- } -- -- return 0; --} --EXPORT_SYMBOL_GPL(fsl_mc_portal_reset); ---- /dev/null -+++ b/drivers/bus/fsl-mc/mc-io.c -@@ -0,0 +1,268 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright 2013-2016 Freescale Semiconductor Inc. -+ * -+ */ -+ -+#include <linux/io.h> -+#include <linux/fsl/mc.h> -+ -+#include "fsl-mc-private.h" -+ -+static int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io, -+ struct fsl_mc_device *dpmcp_dev) -+{ -+ int error; -+ -+ if (mc_io->dpmcp_dev) -+ return -EINVAL; -+ -+ if (dpmcp_dev->mc_io) -+ return -EINVAL; -+ -+ error = dpmcp_open(mc_io, -+ 0, -+ dpmcp_dev->obj_desc.id, -+ &dpmcp_dev->mc_handle); -+ if (error < 0) -+ return error; -+ -+ mc_io->dpmcp_dev = dpmcp_dev; -+ dpmcp_dev->mc_io = mc_io; -+ return 0; -+} -+ -+static void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io) -+{ -+ int error; -+ struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; -+ -+ error = dpmcp_close(mc_io, -+ 0, -+ dpmcp_dev->mc_handle); -+ if (error < 0) { -+ dev_err(&dpmcp_dev->dev, "dpmcp_close() failed: %d\n", -+ error); -+ } -+ -+ mc_io->dpmcp_dev = NULL; -+ dpmcp_dev->mc_io = NULL; -+} -+ -+/** -+ * Creates an MC I/O object -+ * -+ * @dev: device to be associated with the MC I/O object -+ * @mc_portal_phys_addr: physical address of the MC portal to use -+ * @mc_portal_size: size in bytes of the MC portal -+ * @dpmcp-dev: Pointer to the DPMCP object associated with this MC I/O -+ * object or NULL if none. -+ * @flags: flags for the new MC I/O object -+ * @new_mc_io: Area to return pointer to newly created MC I/O object -+ * -+ * Returns '0' on Success; Error code otherwise. -+ */ -+int __must_check fsl_create_mc_io(struct device *dev, -+ phys_addr_t mc_portal_phys_addr, -+ u32 mc_portal_size, -+ struct fsl_mc_device *dpmcp_dev, -+ u32 flags, struct fsl_mc_io **new_mc_io) -+{ -+ int error; -+ struct fsl_mc_io *mc_io; -+ void __iomem *mc_portal_virt_addr; -+ struct resource *res; -+ -+ mc_io = devm_kzalloc(dev, sizeof(*mc_io), GFP_KERNEL); -+ if (!mc_io) -+ return -ENOMEM; -+ -+ mc_io->dev = dev; -+ mc_io->flags = flags; -+ mc_io->portal_phys_addr = mc_portal_phys_addr; -+ mc_io->portal_size = mc_portal_size; -+ if (flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) -+ spin_lock_init(&mc_io->spinlock); -+ else -+ mutex_init(&mc_io->mutex); -+ -+ res = devm_request_mem_region(dev, -+ mc_portal_phys_addr, -+ mc_portal_size, -+ "mc_portal"); -+ if (!res) { -+ dev_err(dev, -+ "devm_request_mem_region failed for MC portal %pa\n", -+ &mc_portal_phys_addr); -+ return -EBUSY; -+ } -+ -+ mc_portal_virt_addr = devm_ioremap_nocache(dev, -+ mc_portal_phys_addr, -+ mc_portal_size); -+ if (!mc_portal_virt_addr) { -+ dev_err(dev, -+ "devm_ioremap_nocache failed for MC portal %pa\n", -+ &mc_portal_phys_addr); -+ return -ENXIO; -+ } -+ -+ mc_io->portal_virt_addr = mc_portal_virt_addr; -+ if (dpmcp_dev) { -+ error = fsl_mc_io_set_dpmcp(mc_io, dpmcp_dev); -+ if (error < 0) -+ goto error_destroy_mc_io; -+ } -+ -+ *new_mc_io = mc_io; -+ return 0; -+ -+error_destroy_mc_io: -+ fsl_destroy_mc_io(mc_io); -+ return error; -+} -+ -+/** -+ * Destroys an MC I/O object -+ * -+ * @mc_io: MC I/O object to destroy -+ */ -+void fsl_destroy_mc_io(struct fsl_mc_io *mc_io) -+{ -+ struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; -+ -+ if (dpmcp_dev) -+ fsl_mc_io_unset_dpmcp(mc_io); -+ -+ devm_iounmap(mc_io->dev, mc_io->portal_virt_addr); -+ devm_release_mem_region(mc_io->dev, -+ mc_io->portal_phys_addr, -+ mc_io->portal_size); -+ -+ mc_io->portal_virt_addr = NULL; -+ devm_kfree(mc_io->dev, mc_io); -+} -+ -+/** -+ * fsl_mc_portal_allocate - Allocates an MC portal -+ * -+ * @mc_dev: MC device for which the MC portal is to be allocated -+ * @mc_io_flags: Flags for the fsl_mc_io object that wraps the allocated -+ * MC portal. -+ * @new_mc_io: Pointer to area where the pointer to the fsl_mc_io object -+ * that wraps the allocated MC portal is to be returned -+ * -+ * This function allocates an MC portal from the device's parent DPRC, -+ * from the corresponding MC bus' pool of MC portals and wraps -+ * it in a new fsl_mc_io object. If 'mc_dev' is a DPRC itself, the -+ * portal is allocated from its own MC bus. -+ */ -+int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, -+ u16 mc_io_flags, -+ struct fsl_mc_io **new_mc_io) -+{ -+ struct fsl_mc_device *mc_bus_dev; -+ struct fsl_mc_bus *mc_bus; -+ phys_addr_t mc_portal_phys_addr; -+ size_t mc_portal_size; -+ struct fsl_mc_device *dpmcp_dev; -+ int error = -EINVAL; -+ struct fsl_mc_resource *resource = NULL; -+ struct fsl_mc_io *mc_io = NULL; -+ -+ if (mc_dev->flags & FSL_MC_IS_DPRC) { -+ mc_bus_dev = mc_dev; -+ } else { -+ if (!dev_is_fsl_mc(mc_dev->dev.parent)) -+ return error; -+ -+ mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); -+ } -+ -+ mc_bus = to_fsl_mc_bus(mc_bus_dev); -+ *new_mc_io = NULL; -+ error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_DPMCP, &resource); -+ if (error < 0) -+ return error; -+ -+ error = -EINVAL; -+ dpmcp_dev = resource->data; -+ -+ if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR || -+ (dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR && -+ dpmcp_dev->obj_desc.ver_minor < DPMCP_MIN_VER_MINOR)) { -+ dev_err(&dpmcp_dev->dev, -+ "ERROR: Version %d.%d of DPMCP not supported.\n", -+ dpmcp_dev->obj_desc.ver_major, -+ dpmcp_dev->obj_desc.ver_minor); -+ error = -ENOTSUPP; -+ goto error_cleanup_resource; -+ } -+ -+ mc_portal_phys_addr = dpmcp_dev->regions[0].start; -+ mc_portal_size = resource_size(dpmcp_dev->regions); -+ -+ error = fsl_create_mc_io(&mc_bus_dev->dev, -+ mc_portal_phys_addr, -+ mc_portal_size, dpmcp_dev, -+ mc_io_flags, &mc_io); -+ if (error < 0) -+ goto error_cleanup_resource; -+ -+ *new_mc_io = mc_io; -+ return 0; -+ -+error_cleanup_resource: -+ fsl_mc_resource_free(resource); -+ return error; -+} -+EXPORT_SYMBOL_GPL(fsl_mc_portal_allocate); -+ -+/** -+ * fsl_mc_portal_free - Returns an MC portal to the pool of free MC portals -+ * of a given MC bus -+ * -+ * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free -+ */ -+void fsl_mc_portal_free(struct fsl_mc_io *mc_io) -+{ -+ struct fsl_mc_device *dpmcp_dev; -+ struct fsl_mc_resource *resource; -+ -+ /* -+ * Every mc_io obtained by calling fsl_mc_portal_allocate() is supposed -+ * to have a DPMCP object associated with. -+ */ -+ dpmcp_dev = mc_io->dpmcp_dev; -+ -+ resource = dpmcp_dev->resource; -+ if (!resource || resource->type != FSL_MC_POOL_DPMCP) -+ return; -+ -+ if (resource->data != dpmcp_dev) -+ return; -+ -+ fsl_destroy_mc_io(mc_io); -+ fsl_mc_resource_free(resource); -+} -+EXPORT_SYMBOL_GPL(fsl_mc_portal_free); -+ -+/** -+ * fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object -+ * -+ * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free -+ */ -+int fsl_mc_portal_reset(struct fsl_mc_io *mc_io) -+{ -+ int error; -+ struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; -+ -+ error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle); -+ if (error < 0) { -+ dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error); -+ return error; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(fsl_mc_portal_reset); ---- a/drivers/staging/fsl-mc/bus/mc-sys.c -+++ /dev/null -@@ -1,317 +0,0 @@ --/* Copyright 2013-2014 Freescale Semiconductor Inc. -- * -- * I/O services to send MC commands to the MC hardware -- * -- * Redistribution and use in source and binary forms, with or without -- * modification, are permitted provided that the following conditions are met: -- * * Redistributions of source code must retain the above copyright -- * notice, this list of conditions and the following disclaimer. -- * * Redistributions in binary form must reproduce the above copyright -- * notice, this list of conditions and the following disclaimer in the -- * documentation and/or other materials provided with the distribution. -- * * Neither the name of the above-listed copyright holders nor the -- * names of any contributors may be used to endorse or promote products -- * derived from this software without specific prior written permission. -- * -- * -- * ALTERNATIVELY, this software may be distributed under the terms of the -- * GNU General Public License ("GPL") as published by the Free Software -- * Foundation, either version 2 of that License or (at your option) any -- * later version. -- * -- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -- * POSSIBILITY OF SUCH DAMAGE. -- */ -- --#include <linux/delay.h> --#include <linux/slab.h> --#include <linux/ioport.h> --#include <linux/device.h> --#include <linux/io.h> --#include "../include/mc-sys.h" --#include "../include/mc-cmd.h" --#include "../include/mc.h" -- --#include "dpmcp.h" -- --/** -- * Timeout in milliseconds to wait for the completion of an MC command -- */ --#define MC_CMD_COMPLETION_TIMEOUT_MS 500 -- --/* -- * usleep_range() min and max values used to throttle down polling -- * iterations while waiting for MC command completion -- */ --#define MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS 10 --#define MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS 500 -- --static enum mc_cmd_status mc_cmd_hdr_read_status(struct mc_command *cmd) --{ -- struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header; -- -- return (enum mc_cmd_status)hdr->status; --} -- --static u16 mc_cmd_hdr_read_cmdid(struct mc_command *cmd) --{ -- struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header; -- u16 cmd_id = le16_to_cpu(hdr->cmd_id); -- -- return (cmd_id & MC_CMD_HDR_CMDID_MASK) >> MC_CMD_HDR_CMDID_SHIFT; --} -- --static int mc_status_to_error(enum mc_cmd_status status) --{ -- static const int mc_status_to_error_map[] = { -- [MC_CMD_STATUS_OK] = 0, -- [MC_CMD_STATUS_AUTH_ERR] = -EACCES, -- [MC_CMD_STATUS_NO_PRIVILEGE] = -EPERM, -- [MC_CMD_STATUS_DMA_ERR] = -EIO, -- [MC_CMD_STATUS_CONFIG_ERR] = -ENXIO, -- [MC_CMD_STATUS_TIMEOUT] = -ETIMEDOUT, -- [MC_CMD_STATUS_NO_RESOURCE] = -ENAVAIL, -- [MC_CMD_STATUS_NO_MEMORY] = -ENOMEM, -- [MC_CMD_STATUS_BUSY] = -EBUSY, -- [MC_CMD_STATUS_UNSUPPORTED_OP] = -ENOTSUPP, -- [MC_CMD_STATUS_INVALID_STATE] = -ENODEV, -- }; -- -- if (WARN_ON((u32)status >= ARRAY_SIZE(mc_status_to_error_map))) -- return -EINVAL; -- -- return mc_status_to_error_map[status]; --} -- --static const char *mc_status_to_string(enum mc_cmd_status status) --{ -- static const char *const status_strings[] = { -- [MC_CMD_STATUS_OK] = "Command completed successfully", -- [MC_CMD_STATUS_READY] = "Command ready to be processed", -- [MC_CMD_STATUS_AUTH_ERR] = "Authentication error", -- [MC_CMD_STATUS_NO_PRIVILEGE] = "No privilege", -- [MC_CMD_STATUS_DMA_ERR] = "DMA or I/O error", -- [MC_CMD_STATUS_CONFIG_ERR] = "Configuration error", -- [MC_CMD_STATUS_TIMEOUT] = "Operation timed out", -- [MC_CMD_STATUS_NO_RESOURCE] = "No resources", -- [MC_CMD_STATUS_NO_MEMORY] = "No memory available", -- [MC_CMD_STATUS_BUSY] = "Device is busy", -- [MC_CMD_STATUS_UNSUPPORTED_OP] = "Unsupported operation", -- [MC_CMD_STATUS_INVALID_STATE] = "Invalid state" -- }; -- -- if ((unsigned int)status >= ARRAY_SIZE(status_strings)) -- return "Unknown MC error"; -- -- return status_strings[status]; --} -- --/** -- * mc_write_command - writes a command to a Management Complex (MC) portal -- * -- * @portal: pointer to an MC portal -- * @cmd: pointer to a filled command -- */ --static inline void mc_write_command(struct mc_command __iomem *portal, -- struct mc_command *cmd) --{ -- int i; -- -- /* copy command parameters into the portal */ -- for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++) -- __raw_writeq(cmd->params[i], &portal->params[i]); -- __iowmb(); -- -- /* submit the command by writing the header */ -- __raw_writeq(cmd->header, &portal->header); --} -- --/** -- * mc_read_response - reads the response for the last MC command from a -- * Management Complex (MC) portal -- * -- * @portal: pointer to an MC portal -- * @resp: pointer to command response buffer -- * -- * Returns MC_CMD_STATUS_OK on Success; Error code otherwise. -- */ --static inline enum mc_cmd_status mc_read_response(struct mc_command __iomem * -- portal, -- struct mc_command *resp) --{ -- int i; -- enum mc_cmd_status status; -- -- /* Copy command response header from MC portal: */ -- __iormb(); -- resp->header = __raw_readq(&portal->header); -- __iormb(); -- status = mc_cmd_hdr_read_status(resp); -- if (status != MC_CMD_STATUS_OK) -- return status; -- -- /* Copy command response data from MC portal: */ -- for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++) -- resp->params[i] = __raw_readq(&portal->params[i]); -- __iormb(); -- -- return status; --} -- --/** -- * Waits for the completion of an MC command doing preemptible polling. -- * uslepp_range() is called between polling iterations. -- * -- * @mc_io: MC I/O object to be used -- * @cmd: command buffer to receive MC response -- * @mc_status: MC command completion status -- */ --static int mc_polling_wait_preemptible(struct fsl_mc_io *mc_io, -- struct mc_command *cmd, -- enum mc_cmd_status *mc_status) --{ -- enum mc_cmd_status status; -- unsigned long jiffies_until_timeout = -- jiffies + msecs_to_jiffies(MC_CMD_COMPLETION_TIMEOUT_MS); -- -- /* -- * Wait for response from the MC hardware: -- */ -- for (;;) { -- status = mc_read_response(mc_io->portal_virt_addr, cmd); -- if (status != MC_CMD_STATUS_READY) -- break; -- -- /* -- * TODO: When MC command completion interrupts are supported -- * call wait function here instead of usleep_range() -- */ -- usleep_range(MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS, -- MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS); -- -- if (time_after_eq(jiffies, jiffies_until_timeout)) { -- dev_dbg(mc_io->dev, -- "MC command timed out (portal: %#llx, obj handle: %#x, command: %#x)\n", -- mc_io->portal_phys_addr, -- (unsigned int)mc_cmd_hdr_read_token(cmd), -- (unsigned int)mc_cmd_hdr_read_cmdid(cmd)); -- -- return -ETIMEDOUT; -- } -- } -- -- *mc_status = status; -- return 0; --} -- --/** -- * Waits for the completion of an MC command doing atomic polling. -- * udelay() is called between polling iterations. -- * -- * @mc_io: MC I/O object to be used -- * @cmd: command buffer to receive MC response -- * @mc_status: MC command completion status -- */ --static int mc_polling_wait_atomic(struct fsl_mc_io *mc_io, -- struct mc_command *cmd, -- enum mc_cmd_status *mc_status) --{ -- enum mc_cmd_status status; -- unsigned long timeout_usecs = MC_CMD_COMPLETION_TIMEOUT_MS * 1000; -- -- BUILD_BUG_ON((MC_CMD_COMPLETION_TIMEOUT_MS * 1000) % -- MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS != 0); -- -- for (;;) { -- status = mc_read_response(mc_io->portal_virt_addr, cmd); -- if (status != MC_CMD_STATUS_READY) -- break; -- -- udelay(MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS); -- timeout_usecs -= MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS; -- if (timeout_usecs == 0) { -- dev_dbg(mc_io->dev, -- "MC command timed out (portal: %#llx, obj handle: %#x, command: %#x)\n", -- mc_io->portal_phys_addr, -- (unsigned int)mc_cmd_hdr_read_token(cmd), -- (unsigned int)mc_cmd_hdr_read_cmdid(cmd)); -- -- return -ETIMEDOUT; -- } -- } -- -- *mc_status = status; -- return 0; --} -- --/** -- * Sends a command to the MC device using the given MC I/O object -- * -- * @mc_io: MC I/O object to be used -- * @cmd: command to be sent -- * -- * Returns '0' on Success; Error code otherwise. -- */ --int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd) --{ -- int error; -- enum mc_cmd_status status; -- unsigned long irq_flags = 0; -- -- if (WARN_ON(in_irq() && -- !(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL))) -- return -EINVAL; -- -- if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) -- spin_lock_irqsave(&mc_io->spinlock, irq_flags); -- else -- mutex_lock(&mc_io->mutex); -- -- /* -- * Send command to the MC hardware: -- */ -- mc_write_command(mc_io->portal_virt_addr, cmd); -- -- /* -- * Wait for response from the MC hardware: -- */ -- if (!(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)) -- error = mc_polling_wait_preemptible(mc_io, cmd, &status); -- else -- error = mc_polling_wait_atomic(mc_io, cmd, &status); -- -- if (error < 0) -- goto common_exit; -- -- if (status != MC_CMD_STATUS_OK) { -- dev_dbg(mc_io->dev, -- "MC command failed: portal: %#llx, obj handle: %#x, command: %#x, status: %s (%#x)\n", -- mc_io->portal_phys_addr, -- (unsigned int)mc_cmd_hdr_read_token(cmd), -- (unsigned int)mc_cmd_hdr_read_cmdid(cmd), -- mc_status_to_string(status), -- (unsigned int)status); -- -- error = mc_status_to_error(status); -- goto common_exit; -- } -- -- error = 0; --common_exit: -- if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) -- spin_unlock_irqrestore(&mc_io->spinlock, irq_flags); -- else -- mutex_unlock(&mc_io->mutex); -- -- return error; --} --EXPORT_SYMBOL(mc_send_command); ---- /dev/null -+++ b/drivers/bus/fsl-mc/mc-sys.c -@@ -0,0 +1,296 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright 2013-2016 Freescale Semiconductor Inc. -+ * -+ * I/O services to send MC commands to the MC hardware -+ * -+ */ -+ -+#include <linux/delay.h> -+#include <linux/slab.h> -+#include <linux/ioport.h> -+#include <linux/device.h> -+#include <linux/io.h> -+#include <linux/io-64-nonatomic-hi-lo.h> -+#include <linux/fsl/mc.h> -+ -+#include "fsl-mc-private.h" -+ -+/** -+ * Timeout in milliseconds to wait for the completion of an MC command -+ */ -+#define MC_CMD_COMPLETION_TIMEOUT_MS 15000 -+ -+/* -+ * usleep_range() min and max values used to throttle down polling -+ * iterations while waiting for MC command completion -+ */ -+#define MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS 10 -+#define MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS 500 -+ -+static enum mc_cmd_status mc_cmd_hdr_read_status(struct fsl_mc_command *cmd) -+{ -+ struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header; -+ -+ return (enum mc_cmd_status)hdr->status; -+} -+ -+static u16 mc_cmd_hdr_read_cmdid(struct fsl_mc_command *cmd) -+{ -+ struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header; -+ u16 cmd_id = le16_to_cpu(hdr->cmd_id); -+ -+ return cmd_id; -+} -+ -+static int mc_status_to_error(enum mc_cmd_status status) -+{ -+ static const int mc_status_to_error_map[] = { -+ [MC_CMD_STATUS_OK] = 0, -+ [MC_CMD_STATUS_AUTH_ERR] = -EACCES, -+ [MC_CMD_STATUS_NO_PRIVILEGE] = -EPERM, -+ [MC_CMD_STATUS_DMA_ERR] = -EIO, -+ [MC_CMD_STATUS_CONFIG_ERR] = -ENXIO, -+ [MC_CMD_STATUS_TIMEOUT] = -ETIMEDOUT, -+ [MC_CMD_STATUS_NO_RESOURCE] = -ENAVAIL, -+ [MC_CMD_STATUS_NO_MEMORY] = -ENOMEM, -+ [MC_CMD_STATUS_BUSY] = -EBUSY, -+ [MC_CMD_STATUS_UNSUPPORTED_OP] = -ENOTSUPP, -+ [MC_CMD_STATUS_INVALID_STATE] = -ENODEV, -+ }; -+ -+ if ((u32)status >= ARRAY_SIZE(mc_status_to_error_map)) -+ return -EINVAL; -+ -+ return mc_status_to_error_map[status]; -+} -+ -+static const char *mc_status_to_string(enum mc_cmd_status status) -+{ -+ static const char *const status_strings[] = { -+ [MC_CMD_STATUS_OK] = "Command completed successfully", -+ [MC_CMD_STATUS_READY] = "Command ready to be processed", -+ [MC_CMD_STATUS_AUTH_ERR] = "Authentication error", -+ [MC_CMD_STATUS_NO_PRIVILEGE] = "No privilege", -+ [MC_CMD_STATUS_DMA_ERR] = "DMA or I/O error", -+ [MC_CMD_STATUS_CONFIG_ERR] = "Configuration error", -+ [MC_CMD_STATUS_TIMEOUT] = "Operation timed out", -+ [MC_CMD_STATUS_NO_RESOURCE] = "No resources", -+ [MC_CMD_STATUS_NO_MEMORY] = "No memory available", -+ [MC_CMD_STATUS_BUSY] = "Device is busy", -+ [MC_CMD_STATUS_UNSUPPORTED_OP] = "Unsupported operation", -+ [MC_CMD_STATUS_INVALID_STATE] = "Invalid state" -+ }; -+ -+ if ((unsigned int)status >= ARRAY_SIZE(status_strings)) -+ return "Unknown MC error"; -+ -+ return status_strings[status]; -+} -+ -+/** -+ * mc_write_command - writes a command to a Management Complex (MC) portal -+ * -+ * @portal: pointer to an MC portal -+ * @cmd: pointer to a filled command -+ */ -+static inline void mc_write_command(struct fsl_mc_command __iomem *portal, -+ struct fsl_mc_command *cmd) -+{ -+ int i; -+ -+ /* copy command parameters into the portal */ -+ for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++) -+ /* -+ * Data is already in the expected LE byte-order. Do an -+ * extra LE -> CPU conversion so that the CPU -> LE done in -+ * the device io write api puts it back in the right order. -+ */ -+ writeq_relaxed(le64_to_cpu(cmd->params[i]), &portal->params[i]); -+ -+ /* submit the command by writing the header */ -+ writeq(le64_to_cpu(cmd->header), &portal->header); -+} -+ -+/** -+ * mc_read_response - reads the response for the last MC command from a -+ * Management Complex (MC) portal -+ * -+ * @portal: pointer to an MC portal -+ * @resp: pointer to command response buffer -+ * -+ * Returns MC_CMD_STATUS_OK on Success; Error code otherwise. -+ */ -+static inline enum mc_cmd_status mc_read_response(struct fsl_mc_command __iomem -+ *portal, -+ struct fsl_mc_command *resp) -+{ -+ int i; -+ enum mc_cmd_status status; -+ -+ /* Copy command response header from MC portal: */ -+ resp->header = cpu_to_le64(readq_relaxed(&portal->header)); -+ status = mc_cmd_hdr_read_status(resp); -+ if (status != MC_CMD_STATUS_OK) -+ return status; -+ -+ /* Copy command response data from MC portal: */ -+ for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++) -+ /* -+ * Data is expected to be in LE byte-order. Do an -+ * extra CPU -> LE to revert the LE -> CPU done in -+ * the device io read api. -+ */ -+ resp->params[i] = -+ cpu_to_le64(readq_relaxed(&portal->params[i])); -+ -+ return status; -+} -+ -+/** -+ * Waits for the completion of an MC command doing preemptible polling. -+ * uslepp_range() is called between polling iterations. -+ * -+ * @mc_io: MC I/O object to be used -+ * @cmd: command buffer to receive MC response -+ * @mc_status: MC command completion status -+ */ -+static int mc_polling_wait_preemptible(struct fsl_mc_io *mc_io, -+ struct fsl_mc_command *cmd, -+ enum mc_cmd_status *mc_status) -+{ -+ enum mc_cmd_status status; -+ unsigned long jiffies_until_timeout = -+ jiffies + msecs_to_jiffies(MC_CMD_COMPLETION_TIMEOUT_MS); -+ -+ /* -+ * Wait for response from the MC hardware: -+ */ -+ for (;;) { -+ status = mc_read_response(mc_io->portal_virt_addr, cmd); -+ if (status != MC_CMD_STATUS_READY) -+ break; -+ -+ /* -+ * TODO: When MC command completion interrupts are supported -+ * call wait function here instead of usleep_range() -+ */ -+ usleep_range(MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS, -+ MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS); -+ -+ if (time_after_eq(jiffies, jiffies_until_timeout)) { -+ dev_dbg(mc_io->dev, -+ "MC command timed out (portal: %pa, dprc handle: %#x, command: %#x)\n", -+ &mc_io->portal_phys_addr, -+ (unsigned int)mc_cmd_hdr_read_token(cmd), -+ (unsigned int)mc_cmd_hdr_read_cmdid(cmd)); -+ -+ return -ETIMEDOUT; -+ } -+ } -+ -+ *mc_status = status; -+ return 0; -+} -+ -+/** -+ * Waits for the completion of an MC command doing atomic polling. -+ * udelay() is called between polling iterations. -+ * -+ * @mc_io: MC I/O object to be used -+ * @cmd: command buffer to receive MC response -+ * @mc_status: MC command completion status -+ */ -+static int mc_polling_wait_atomic(struct fsl_mc_io *mc_io, -+ struct fsl_mc_command *cmd, -+ enum mc_cmd_status *mc_status) -+{ -+ enum mc_cmd_status status; -+ unsigned long timeout_usecs = MC_CMD_COMPLETION_TIMEOUT_MS * 1000; -+ -+ BUILD_BUG_ON((MC_CMD_COMPLETION_TIMEOUT_MS * 1000) % -+ MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS != 0); -+ -+ for (;;) { -+ status = mc_read_response(mc_io->portal_virt_addr, cmd); -+ if (status != MC_CMD_STATUS_READY) -+ break; -+ -+ udelay(MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS); -+ timeout_usecs -= MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS; -+ if (timeout_usecs == 0) { -+ dev_dbg(mc_io->dev, -+ "MC command timed out (portal: %pa, dprc handle: %#x, command: %#x)\n", -+ &mc_io->portal_phys_addr, -+ (unsigned int)mc_cmd_hdr_read_token(cmd), -+ (unsigned int)mc_cmd_hdr_read_cmdid(cmd)); -+ -+ return -ETIMEDOUT; -+ } -+ } -+ -+ *mc_status = status; -+ return 0; -+} -+ -+/** -+ * Sends a command to the MC device using the given MC I/O object -+ * -+ * @mc_io: MC I/O object to be used -+ * @cmd: command to be sent -+ * -+ * Returns '0' on Success; Error code otherwise. -+ */ -+int mc_send_command(struct fsl_mc_io *mc_io, struct fsl_mc_command *cmd) -+{ -+ int error; -+ enum mc_cmd_status status; -+ unsigned long irq_flags = 0; -+ -+ if (in_irq() && !(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)) -+ return -EINVAL; -+ -+ if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) -+ spin_lock_irqsave(&mc_io->spinlock, irq_flags); -+ else -+ mutex_lock(&mc_io->mutex); -+ -+ /* -+ * Send command to the MC hardware: -+ */ -+ mc_write_command(mc_io->portal_virt_addr, cmd); -+ -+ /* -+ * Wait for response from the MC hardware: -+ */ -+ if (!(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)) -+ error = mc_polling_wait_preemptible(mc_io, cmd, &status); -+ else -+ error = mc_polling_wait_atomic(mc_io, cmd, &status); -+ -+ if (error < 0) -+ goto common_exit; -+ -+ if (status != MC_CMD_STATUS_OK) { -+ dev_dbg(mc_io->dev, -+ "MC command failed: portal: %pa, dprc handle: %#x, command: %#x, status: %s (%#x)\n", -+ &mc_io->portal_phys_addr, -+ (unsigned int)mc_cmd_hdr_read_token(cmd), -+ (unsigned int)mc_cmd_hdr_read_cmdid(cmd), -+ mc_status_to_string(status), -+ (unsigned int)status); -+ -+ error = mc_status_to_error(status); -+ goto common_exit; -+ } -+ -+ error = 0; -+common_exit: -+ if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) -+ spin_unlock_irqrestore(&mc_io->spinlock, irq_flags); -+ else -+ mutex_unlock(&mc_io->mutex); -+ -+ return error; -+} -+EXPORT_SYMBOL_GPL(mc_send_command); ---- a/drivers/irqchip/Kconfig -+++ b/drivers/irqchip/Kconfig -@@ -41,6 +41,12 @@ config ARM_GIC_V3_ITS - depends on PCI_MSI - select ACPI_IORT if ACPI - -+config ARM_GIC_V3_ITS_FSL_MC -+ bool -+ depends on ARM_GIC_V3_ITS -+ depends on FSL_MC_BUS -+ default ARM_GIC_V3_ITS -+ - config ARM_NVIC - bool - select IRQ_DOMAIN ---- a/drivers/irqchip/Makefile -+++ b/drivers/irqchip/Makefile -@@ -29,6 +29,7 @@ obj-$(CONFIG_ARCH_REALVIEW) += irq-gic- - obj-$(CONFIG_ARM_GIC_V2M) += irq-gic-v2m.o - obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-common.o - 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 -+obj-$(CONFIG_ARM_GIC_V3_ITS_FSL_MC) += irq-gic-v3-its-fsl-mc-msi.o - obj-$(CONFIG_PARTITION_PERCPU) += irq-partition-percpu.o - obj-$(CONFIG_HISILICON_IRQ_MBIGEN) += irq-mbigen.o - obj-$(CONFIG_ARM_NVIC) += irq-nvic.o ---- a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c -+++ /dev/null -@@ -1,126 +0,0 @@ --/* -- * Freescale Management Complex (MC) bus driver MSI support -- * -- * Copyright (C) 2015 Freescale Semiconductor, Inc. -- * Author: German Rivera <German.Rivera@freescale.com> -- * -- * This file is licensed under the terms of the GNU General Public -- * License version 2. This program is licensed "as is" without any -- * warranty of any kind, whether express or implied. -- */ -- --#include <linux/of_device.h> --#include <linux/of_address.h> --#include <linux/irqchip/arm-gic-v3.h> --#include <linux/irq.h> --#include <linux/msi.h> --#include <linux/of.h> --#include <linux/of_irq.h> --#include "../include/mc-bus.h" --#include "fsl-mc-private.h" -- --static struct irq_chip its_msi_irq_chip = { -- .name = "fsl-mc-bus-msi", -- .irq_mask = irq_chip_mask_parent, -- .irq_unmask = irq_chip_unmask_parent, -- .irq_eoi = irq_chip_eoi_parent, -- .irq_set_affinity = msi_domain_set_affinity --}; -- --static int its_fsl_mc_msi_prepare(struct irq_domain *msi_domain, -- struct device *dev, -- int nvec, msi_alloc_info_t *info) --{ -- struct fsl_mc_device *mc_bus_dev; -- struct msi_domain_info *msi_info; -- -- if (WARN_ON(!dev_is_fsl_mc(dev))) -- return -EINVAL; -- -- mc_bus_dev = to_fsl_mc_device(dev); -- if (WARN_ON(!(mc_bus_dev->flags & FSL_MC_IS_DPRC))) -- return -EINVAL; -- -- /* -- * Set the device Id to be passed to the GIC-ITS: -- * -- * NOTE: This device id corresponds to the IOMMU stream ID -- * associated with the DPRC object (ICID). -- */ -- info->scratchpad[0].ul = mc_bus_dev->icid; -- msi_info = msi_get_domain_info(msi_domain->parent); -- return msi_info->ops->msi_prepare(msi_domain->parent, dev, nvec, info); --} -- --static struct msi_domain_ops its_fsl_mc_msi_ops = { -- .msi_prepare = its_fsl_mc_msi_prepare, --}; -- --static struct msi_domain_info its_fsl_mc_msi_domain_info = { -- .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS), -- .ops = &its_fsl_mc_msi_ops, -- .chip = &its_msi_irq_chip, --}; -- --static const struct of_device_id its_device_id[] = { -- { .compatible = "arm,gic-v3-its", }, -- {}, --}; -- --int __init its_fsl_mc_msi_init(void) --{ -- struct device_node *np; -- struct irq_domain *parent; -- struct irq_domain *mc_msi_domain; -- -- for (np = of_find_matching_node(NULL, its_device_id); np; -- np = of_find_matching_node(np, its_device_id)) { -- if (!of_device_is_available(np)) -- continue; -- if (!of_property_read_bool(np, "msi-controller")) -- continue; -- -- parent = irq_find_matching_host(np, DOMAIN_BUS_NEXUS); -- if (!parent || !msi_get_domain_info(parent)) { -- pr_err("%s: unable to locate ITS domain\n", -- np->full_name); -- continue; -- } -- -- mc_msi_domain = fsl_mc_msi_create_irq_domain( -- of_node_to_fwnode(np), -- &its_fsl_mc_msi_domain_info, -- parent); -- if (!mc_msi_domain) { -- pr_err("%s: unable to create fsl-mc domain\n", -- np->full_name); -- continue; -- } -- -- WARN_ON(mc_msi_domain-> -- host_data != &its_fsl_mc_msi_domain_info); -- -- pr_info("fsl-mc MSI: %s domain created\n", np->full_name); -- } -- -- return 0; --} -- --void its_fsl_mc_msi_cleanup(void) --{ -- struct device_node *np; -- -- for (np = of_find_matching_node(NULL, its_device_id); np; -- np = of_find_matching_node(np, its_device_id)) { -- struct irq_domain *mc_msi_domain = irq_find_matching_host( -- np, -- DOMAIN_BUS_FSL_MC_MSI); -- -- if (!of_property_read_bool(np, "msi-controller")) -- continue; -- -- if (mc_msi_domain && -- mc_msi_domain->host_data == &its_fsl_mc_msi_domain_info) -- irq_domain_remove(mc_msi_domain); -- } --} ---- /dev/null -+++ b/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c -@@ -0,0 +1,98 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Freescale Management Complex (MC) bus driver MSI support -+ * -+ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. -+ * Author: German Rivera <German.Rivera@freescale.com> -+ * -+ */ -+ -+#include <linux/of_device.h> -+#include <linux/of_address.h> -+#include <linux/irq.h> -+#include <linux/msi.h> -+#include <linux/of.h> -+#include <linux/of_irq.h> -+#include <linux/fsl/mc.h> -+ -+static struct irq_chip its_msi_irq_chip = { -+ .name = "ITS-fMSI", -+ .irq_mask = irq_chip_mask_parent, -+ .irq_unmask = irq_chip_unmask_parent, -+ .irq_eoi = irq_chip_eoi_parent, -+ .irq_set_affinity = msi_domain_set_affinity -+}; -+ -+static int its_fsl_mc_msi_prepare(struct irq_domain *msi_domain, -+ struct device *dev, -+ int nvec, msi_alloc_info_t *info) -+{ -+ struct fsl_mc_device *mc_bus_dev; -+ struct msi_domain_info *msi_info; -+ -+ if (!dev_is_fsl_mc(dev)) -+ return -EINVAL; -+ -+ mc_bus_dev = to_fsl_mc_device(dev); -+ if (!(mc_bus_dev->flags & FSL_MC_IS_DPRC)) -+ return -EINVAL; -+ -+ /* -+ * Set the device Id to be passed to the GIC-ITS: -+ * -+ * NOTE: This device id corresponds to the IOMMU stream ID -+ * associated with the DPRC object (ICID). -+ */ -+ info->scratchpad[0].ul = mc_bus_dev->icid; -+ msi_info = msi_get_domain_info(msi_domain->parent); -+ return msi_info->ops->msi_prepare(msi_domain->parent, dev, nvec, info); -+} -+ -+static struct msi_domain_ops its_fsl_mc_msi_ops __ro_after_init = { -+ .msi_prepare = its_fsl_mc_msi_prepare, -+}; -+ -+static struct msi_domain_info its_fsl_mc_msi_domain_info = { -+ .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS), -+ .ops = &its_fsl_mc_msi_ops, -+ .chip = &its_msi_irq_chip, -+}; -+ -+static const struct of_device_id its_device_id[] = { -+ { .compatible = "arm,gic-v3-its", }, -+ {}, -+}; -+ -+static int __init its_fsl_mc_msi_init(void) -+{ -+ struct device_node *np; -+ struct irq_domain *parent; -+ struct irq_domain *mc_msi_domain; -+ -+ for (np = of_find_matching_node(NULL, its_device_id); np; -+ np = of_find_matching_node(np, its_device_id)) { -+ if (!of_property_read_bool(np, "msi-controller")) -+ continue; -+ -+ parent = irq_find_matching_host(np, DOMAIN_BUS_NEXUS); -+ if (!parent || !msi_get_domain_info(parent)) { -+ pr_err("%pOF: unable to locate ITS domain\n", np); -+ continue; -+ } -+ -+ mc_msi_domain = fsl_mc_msi_create_irq_domain( -+ of_node_to_fwnode(np), -+ &its_fsl_mc_msi_domain_info, -+ parent); -+ if (!mc_msi_domain) { -+ pr_err("%pOF: unable to create fsl-mc domain\n", np); -+ continue; -+ } -+ -+ pr_info("fsl-mc MSI: %pOF domain created\n", np); -+ } -+ -+ return 0; -+} -+ -+early_initcall(its_fsl_mc_msi_init); ---- a/drivers/staging/fsl-mc/Kconfig -+++ b/drivers/staging/fsl-mc/Kconfig -@@ -1 +1,2 @@ -+# SPDX-License-Identifier: GPL-2.0 - source "drivers/staging/fsl-mc/bus/Kconfig" ---- a/drivers/staging/fsl-mc/Makefile -+++ b/drivers/staging/fsl-mc/Makefile -@@ -1,2 +1,3 @@ -+# SPDX-License-Identifier: GPL-2.0 - # Freescale Management Complex (MC) bus drivers - obj-$(CONFIG_FSL_MC_BUS) += bus/ ---- a/drivers/staging/fsl-mc/TODO -+++ /dev/null -@@ -1,18 +0,0 @@ --* Add at least one device driver for a DPAA2 object (child device of the -- fsl-mc bus). Most likely candidate for this is adding DPAA2 Ethernet -- driver support, which depends on drivers for several objects: DPNI, -- DPIO, DPMAC. Other pre-requisites include: -- -- * MC firmware uprev. The MC firmware upon which the fsl-mc -- bus driver and DPAA2 object drivers are based is continuing -- to evolve, so minor updates are needed to keep in sync with binary -- interface changes to the MC. -- --* Cleanup -- --Please send any patches to Greg Kroah-Hartman <gregkh@linuxfoundation.org>, --german.rivera@freescale.com, devel@driverdev.osuosl.org, --linux-kernel@vger.kernel.org -- --[1] https://lkml.org/lkml/2015/7/9/93 --[2] https://lkml.org/lkml/2015/7/7/712 ---- a/drivers/staging/fsl-mc/bus/Kconfig -+++ b/drivers/staging/fsl-mc/bus/Kconfig -@@ -1,25 +1,22 @@ -+# SPDX-License-Identifier: GPL-2.0 - # --# Freescale Management Complex (MC) bus drivers -+# DPAA2 fsl-mc bus - # --# Copyright (C) 2014 Freescale Semiconductor, Inc. -+# Copyright (C) 2014-2016 Freescale Semiconductor, Inc. - # --# This file is released under the GPLv2 --# -- --config FSL_MC_BUS -- bool "Freescale Management Complex (MC) bus driver" -- depends on OF && ARM64 -- select GENERIC_MSI_IRQ_DOMAIN -- help -- Driver to enable the bus infrastructure for the Freescale -- QorIQ Management Complex (fsl-mc). The fsl-mc is a hardware -- module of the QorIQ LS2 SoCs, that does resource management -- for hardware building-blocks in the SoC that can be used -- to dynamically create networking hardware objects such as -- network interfaces (NICs), crypto accelerator instances, -- or L2 switches. -- -- Only enable this option when building the kernel for -- Freescale QorQIQ LS2xxxx SoCs. - -+config FSL_MC_DPIO -+ tristate "QorIQ DPAA2 DPIO driver" -+ depends on FSL_MC_BUS -+ help -+ Driver for the DPAA2 DPIO object. A DPIO provides queue and -+ buffer management facilities for software to interact with -+ other DPAA2 objects. This driver does not expose the DPIO -+ objects individually, but groups them under a service layer -+ API. - -+config FSL_QBMAN_DEBUG -+ tristate "Freescale QBMAN Debug APIs" -+ depends on FSL_MC_DPIO -+ help -+ QBMan debug assistant APIs. ---- a/drivers/staging/fsl-mc/bus/Makefile -+++ b/drivers/staging/fsl-mc/bus/Makefile -@@ -1,20 +1,9 @@ -+# SPDX-License-Identifier: GPL-2.0 - # - # Freescale Management Complex (MC) bus drivers - # - # Copyright (C) 2014 Freescale Semiconductor, Inc. - # --# This file is released under the GPLv2 --# --obj-$(CONFIG_FSL_MC_BUS) += mc-bus-driver.o - --mc-bus-driver-objs := fsl-mc-bus.o \ -- mc-sys.o \ -- mc-io.o \ -- dprc.o \ -- dpmng.o \ -- dprc-driver.o \ -- fsl-mc-allocator.o \ -- fsl-mc-msi.o \ -- irq-gic-v3-its-fsl-mc-msi.o \ -- dpmcp.o \ -- dpbp.o -+# MC DPIO driver -+obj-$(CONFIG_FSL_MC_DPIO) += dpio/ ---- a/drivers/staging/fsl-mc/bus/dpbp.c -+++ /dev/null -@@ -1,691 +0,0 @@ --/* Copyright 2013-2016 Freescale Semiconductor Inc. -- * -- * Redistribution and use in source and binary forms, with or without -- * modification, are permitted provided that the following conditions are met: -- * * Redistributions of source code must retain the above copyright -- * notice, this list of conditions and the following disclaimer. -- * * Redistributions in binary form must reproduce the above copyright -- * notice, this list of conditions and the following disclaimer in the -- * documentation and/or other materials provided with the distribution. -- * * Neither the name of the above-listed copyright holders nor the -- * names of any contributors may be used to endorse or promote products -- * derived from this software without specific prior written permission. -- * -- * -- * ALTERNATIVELY, this software may be distributed under the terms of the -- * GNU General Public License ("GPL") as published by the Free Software -- * Foundation, either version 2 of that License or (at your option) any -- * later version. -- * -- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -- * POSSIBILITY OF SUCH DAMAGE. -- */ --#include "../include/mc-sys.h" --#include "../include/mc-cmd.h" --#include "../include/dpbp.h" --#include "../include/dpbp-cmd.h" -- --/** -- * dpbp_open() - Open a control session for the specified object. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @dpbp_id: DPBP unique ID -- * @token: Returned token; use in subsequent API calls -- * -- * This function can be used to open a control session for an -- * already created object; an object may have been declared in -- * the DPL or by calling the dpbp_create function. -- * This function returns a unique authentication token, -- * associated with the specific object ID and the specific MC -- * portal; this token must be used in all subsequent commands for -- * this specific object -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpbp_open(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- int dpbp_id, -- u16 *token) --{ -- struct mc_command cmd = { 0 }; -- struct dpbp_cmd_open *cmd_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPBP_CMDID_OPEN, -- cmd_flags, 0); -- cmd_params = (struct dpbp_cmd_open *)cmd.params; -- cmd_params->dpbp_id = cpu_to_le32(dpbp_id); -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- *token = mc_cmd_hdr_read_token(&cmd); -- -- return err; --} --EXPORT_SYMBOL(dpbp_open); -- --/** -- * dpbp_close() - Close the control session of the object -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPBP object -- * -- * After this function is called, no further operations are -- * allowed on the object without opening a new control session. -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpbp_close(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token) --{ -- struct mc_command cmd = { 0 }; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLOSE, cmd_flags, -- token); -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} --EXPORT_SYMBOL(dpbp_close); -- --/** -- * dpbp_create() - Create the DPBP object. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @cfg: Configuration structure -- * @token: Returned token; use in subsequent API calls -- * -- * Create the DPBP object, allocate required resources and -- * perform required initialization. -- * -- * The object can be created either by declaring it in the -- * DPL file, or by calling this function. -- * This function returns a unique authentication token, -- * associated with the specific object ID and the specific MC -- * portal; this token must be used in all subsequent calls to -- * this specific object. For objects that are created using the -- * DPL file, call dpbp_open function to get an authentication -- * token first. -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpbp_create(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- const struct dpbp_cfg *cfg, -- u16 *token) --{ -- struct mc_command cmd = { 0 }; -- int err; -- -- (void)(cfg); /* unused */ -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPBP_CMDID_CREATE, -- cmd_flags, 0); -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- *token = mc_cmd_hdr_read_token(&cmd); -- -- return 0; --} -- --/** -- * dpbp_destroy() - Destroy the DPBP object and release all its resources. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPBP object -- * -- * Return: '0' on Success; error code otherwise. -- */ --int dpbp_destroy(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token) --{ -- struct mc_command cmd = { 0 }; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPBP_CMDID_DESTROY, -- cmd_flags, token); -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} -- --/** -- * dpbp_enable() - Enable the DPBP. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPBP object -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpbp_enable(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token) --{ -- struct mc_command cmd = { 0 }; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPBP_CMDID_ENABLE, cmd_flags, -- token); -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} --EXPORT_SYMBOL(dpbp_enable); -- --/** -- * dpbp_disable() - Disable the DPBP. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPBP object -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpbp_disable(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token) --{ -- struct mc_command cmd = { 0 }; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPBP_CMDID_DISABLE, -- cmd_flags, token); -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} --EXPORT_SYMBOL(dpbp_disable); -- --/** -- * dpbp_is_enabled() - Check if the DPBP is enabled. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPBP object -- * @en: Returns '1' if object is enabled; '0' otherwise -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpbp_is_enabled(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- int *en) --{ -- struct mc_command cmd = { 0 }; -- struct dpbp_rsp_is_enabled *rsp_params; -- int err; -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPBP_CMDID_IS_ENABLED, cmd_flags, -- token); -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dpbp_rsp_is_enabled *)cmd.params; -- *en = rsp_params->enabled & DPBP_ENABLE; -- -- return 0; --} -- --/** -- * dpbp_reset() - Reset the DPBP, returns the object to initial state. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPBP object -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpbp_reset(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token) --{ -- struct mc_command cmd = { 0 }; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPBP_CMDID_RESET, -- cmd_flags, token); -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} -- --/** -- * dpbp_set_irq() - Set IRQ information for the DPBP to trigger an interrupt. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPBP object -- * @irq_index: Identifies the interrupt index to configure -- * @irq_cfg: IRQ configuration -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpbp_set_irq(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- struct dpbp_irq_cfg *irq_cfg) --{ -- struct mc_command cmd = { 0 }; -- struct dpbp_cmd_set_irq *cmd_params; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_IRQ, -- cmd_flags, token); -- cmd_params = (struct dpbp_cmd_set_irq *)cmd.params; -- cmd_params->irq_index = irq_index; -- cmd_params->irq_val = cpu_to_le32(irq_cfg->val); -- cmd_params->irq_addr = cpu_to_le64(irq_cfg->addr); -- cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num); -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} -- --/** -- * dpbp_get_irq() - Get IRQ information from the DPBP. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPBP object -- * @irq_index: The interrupt index to configure -- * @type: Interrupt type: 0 represents message interrupt -- * type (both irq_addr and irq_val are valid) -- * @irq_cfg: IRQ attributes -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpbp_get_irq(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- int *type, -- struct dpbp_irq_cfg *irq_cfg) --{ -- struct mc_command cmd = { 0 }; -- struct dpbp_cmd_get_irq *cmd_params; -- struct dpbp_rsp_get_irq *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ, -- cmd_flags, token); -- cmd_params = (struct dpbp_cmd_get_irq *)cmd.params; -- cmd_params->irq_index = irq_index; -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dpbp_rsp_get_irq *)cmd.params; -- irq_cfg->val = le32_to_cpu(rsp_params->irq_val); -- irq_cfg->addr = le64_to_cpu(rsp_params->irq_addr); -- irq_cfg->irq_num = le32_to_cpu(rsp_params->irq_num); -- *type = le32_to_cpu(rsp_params->type); -- -- return 0; --} -- --/** -- * dpbp_set_irq_enable() - Set overall interrupt state. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPBP object -- * @irq_index: The interrupt index to configure -- * @en: Interrupt state - enable = 1, disable = 0 -- * -- * Allows GPP software to control when interrupts are generated. -- * Each interrupt can have up to 32 causes. The enable/disable control's the -- * overall interrupt state. if the interrupt is disabled no causes will cause -- * an interrupt. -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpbp_set_irq_enable(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u8 en) --{ -- struct mc_command cmd = { 0 }; -- struct dpbp_cmd_set_irq_enable *cmd_params; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_IRQ_ENABLE, -- cmd_flags, token); -- cmd_params = (struct dpbp_cmd_set_irq_enable *)cmd.params; -- cmd_params->enable = en & DPBP_ENABLE; -- cmd_params->irq_index = irq_index; -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} -- --/** -- * dpbp_get_irq_enable() - Get overall interrupt state -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPBP object -- * @irq_index: The interrupt index to configure -- * @en: Returned interrupt state - enable = 1, disable = 0 -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpbp_get_irq_enable(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u8 *en) --{ -- struct mc_command cmd = { 0 }; -- struct dpbp_cmd_get_irq_enable *cmd_params; -- struct dpbp_rsp_get_irq_enable *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_ENABLE, -- cmd_flags, token); -- cmd_params = (struct dpbp_cmd_get_irq_enable *)cmd.params; -- cmd_params->irq_index = irq_index; -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dpbp_rsp_get_irq_enable *)cmd.params; -- *en = rsp_params->enabled & DPBP_ENABLE; -- return 0; --} -- --/** -- * dpbp_set_irq_mask() - Set interrupt mask. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPBP object -- * @irq_index: The interrupt index to configure -- * @mask: Event mask to trigger interrupt; -- * each bit: -- * 0 = ignore event -- * 1 = consider event for asserting IRQ -- * -- * Every interrupt can have up to 32 causes and the interrupt model supports -- * masking/unmasking each cause independently -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpbp_set_irq_mask(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u32 mask) --{ -- struct mc_command cmd = { 0 }; -- struct dpbp_cmd_set_irq_mask *cmd_params; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_IRQ_MASK, -- cmd_flags, token); -- cmd_params = (struct dpbp_cmd_set_irq_mask *)cmd.params; -- cmd_params->mask = cpu_to_le32(mask); -- cmd_params->irq_index = irq_index; -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} -- --/** -- * dpbp_get_irq_mask() - Get interrupt mask. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPBP object -- * @irq_index: The interrupt index to configure -- * @mask: Returned event mask to trigger interrupt -- * -- * Every interrupt can have up to 32 causes and the interrupt model supports -- * masking/unmasking each cause independently -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpbp_get_irq_mask(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u32 *mask) --{ -- struct mc_command cmd = { 0 }; -- struct dpbp_cmd_get_irq_mask *cmd_params; -- struct dpbp_rsp_get_irq_mask *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_MASK, -- cmd_flags, token); -- cmd_params = (struct dpbp_cmd_get_irq_mask *)cmd.params; -- cmd_params->irq_index = irq_index; -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dpbp_rsp_get_irq_mask *)cmd.params; -- *mask = le32_to_cpu(rsp_params->mask); -- -- return 0; --} -- --/** -- * dpbp_get_irq_status() - Get the current status of any pending interrupts. -- * -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPBP object -- * @irq_index: The interrupt index to configure -- * @status: Returned interrupts status - one bit per cause: -- * 0 = no interrupt pending -- * 1 = interrupt pending -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpbp_get_irq_status(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u32 *status) --{ -- struct mc_command cmd = { 0 }; -- struct dpbp_cmd_get_irq_status *cmd_params; -- struct dpbp_rsp_get_irq_status *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_STATUS, -- cmd_flags, token); -- cmd_params = (struct dpbp_cmd_get_irq_status *)cmd.params; -- cmd_params->status = cpu_to_le32(*status); -- cmd_params->irq_index = irq_index; -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dpbp_rsp_get_irq_status *)cmd.params; -- *status = le32_to_cpu(rsp_params->status); -- -- return 0; --} -- --/** -- * dpbp_clear_irq_status() - Clear a pending interrupt's status -- * -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPBP object -- * @irq_index: The interrupt index to configure -- * @status: Bits to clear (W1C) - one bit per cause: -- * 0 = don't change -- * 1 = clear status bit -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpbp_clear_irq_status(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u32 status) --{ -- struct mc_command cmd = { 0 }; -- struct dpbp_cmd_clear_irq_status *cmd_params; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLEAR_IRQ_STATUS, -- cmd_flags, token); -- cmd_params = (struct dpbp_cmd_clear_irq_status *)cmd.params; -- cmd_params->status = cpu_to_le32(status); -- cmd_params->irq_index = irq_index; -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} -- --/** -- * dpbp_get_attributes - Retrieve DPBP attributes. -- * -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPBP object -- * @attr: Returned object's attributes -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpbp_get_attributes(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- struct dpbp_attr *attr) --{ -- struct mc_command cmd = { 0 }; -- struct dpbp_rsp_get_attributes *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_ATTR, -- cmd_flags, token); -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dpbp_rsp_get_attributes *)cmd.params; -- attr->bpid = le16_to_cpu(rsp_params->bpid); -- attr->id = le32_to_cpu(rsp_params->id); -- attr->version.major = le16_to_cpu(rsp_params->version_major); -- attr->version.minor = le16_to_cpu(rsp_params->version_minor); -- -- return 0; --} --EXPORT_SYMBOL(dpbp_get_attributes); -- --/** -- * dpbp_set_notifications() - Set notifications towards software -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPBP object -- * @cfg: notifications configuration -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpbp_set_notifications(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- struct dpbp_notification_cfg *cfg) --{ -- struct mc_command cmd = { 0 }; -- struct dpbp_cmd_set_notifications *cmd_params; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_NOTIFICATIONS, -- cmd_flags, token); -- cmd_params = (struct dpbp_cmd_set_notifications *)cmd.params; -- cmd_params->depletion_entry = cpu_to_le32(cfg->depletion_entry); -- cmd_params->depletion_exit = cpu_to_le32(cfg->depletion_exit); -- cmd_params->surplus_entry = cpu_to_le32(cfg->surplus_entry); -- cmd_params->surplus_exit = cpu_to_le32(cfg->surplus_exit); -- cmd_params->options = cpu_to_le16(cfg->options); -- cmd_params->message_ctx = cpu_to_le64(cfg->message_ctx); -- cmd_params->message_iova = cpu_to_le64(cfg->message_iova); -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} -- --/** -- * dpbp_get_notifications() - Get the notifications configuration -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPBP object -- * @cfg: notifications configuration -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpbp_get_notifications(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- struct dpbp_notification_cfg *cfg) --{ -- struct mc_command cmd = { 0 }; -- struct dpbp_rsp_get_notifications *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_NOTIFICATIONS, -- cmd_flags, -- token); -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dpbp_rsp_get_notifications *)cmd.params; -- cfg->depletion_entry = le32_to_cpu(rsp_params->depletion_entry); -- cfg->depletion_exit = le32_to_cpu(rsp_params->depletion_exit); -- cfg->surplus_entry = le32_to_cpu(rsp_params->surplus_entry); -- cfg->surplus_exit = le32_to_cpu(rsp_params->surplus_exit); -- cfg->options = le16_to_cpu(rsp_params->options); -- cfg->message_ctx = le64_to_cpu(rsp_params->message_ctx); -- cfg->message_iova = le64_to_cpu(rsp_params->message_iova); -- -- return 0; --} ---- /dev/null -+++ b/drivers/staging/fsl-mc/bus/dpio/Makefile -@@ -0,0 +1,8 @@ -+# SPDX-License-Identifier: GPL-2.0 -+# -+# QorIQ DPAA2 DPIO driver -+# -+ -+obj-$(CONFIG_FSL_MC_DPIO) += fsl-mc-dpio.o -+ -+fsl-mc-dpio-objs := dpio.o qbman-portal.o dpio-service.o dpio-driver.o ---- /dev/null -+++ b/drivers/staging/fsl-mc/bus/dpio/dpio-cmd.h -@@ -0,0 +1,50 @@ -+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ -+/* -+ * Copyright 2013-2016 Freescale Semiconductor Inc. -+ * Copyright 2016 NXP -+ * -+ */ -+#ifndef _FSL_DPIO_CMD_H -+#define _FSL_DPIO_CMD_H -+ -+/* DPIO Version */ -+#define DPIO_VER_MAJOR 4 -+#define DPIO_VER_MINOR 2 -+ -+/* Command Versioning */ -+ -+#define DPIO_CMD_ID_OFFSET 4 -+#define DPIO_CMD_BASE_VERSION 1 -+ -+#define DPIO_CMD(id) (((id) << DPIO_CMD_ID_OFFSET) | DPIO_CMD_BASE_VERSION) -+ -+/* Command IDs */ -+#define DPIO_CMDID_CLOSE DPIO_CMD(0x800) -+#define DPIO_CMDID_OPEN DPIO_CMD(0x803) -+#define DPIO_CMDID_GET_API_VERSION DPIO_CMD(0xa03) -+#define DPIO_CMDID_ENABLE DPIO_CMD(0x002) -+#define DPIO_CMDID_DISABLE DPIO_CMD(0x003) -+#define DPIO_CMDID_GET_ATTR DPIO_CMD(0x004) -+#define DPIO_CMDID_RESET DPIO_CMD(0x005) -+ -+struct dpio_cmd_open { -+ __le32 dpio_id; -+}; -+ -+#define DPIO_CHANNEL_MODE_MASK 0x3 -+ -+struct dpio_rsp_get_attr { -+ /* cmd word 0 */ -+ __le32 id; -+ __le16 qbman_portal_id; -+ u8 num_priorities; -+ u8 channel_mode; -+ /* cmd word 1 */ -+ __le64 qbman_portal_ce_addr; -+ /* cmd word 2 */ -+ __le64 qbman_portal_ci_addr; -+ /* cmd word 3 */ -+ __le32 qbman_version; -+}; -+ -+#endif /* _FSL_DPIO_CMD_H */ ---- /dev/null -+++ b/drivers/staging/fsl-mc/bus/dpio/dpio-driver.c -@@ -0,0 +1,278 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright 2014-2016 Freescale Semiconductor Inc. -+ * Copyright 2016 NXP -+ * -+ */ -+ -+#include <linux/types.h> -+#include <linux/init.h> -+#include <linux/module.h> -+#include <linux/platform_device.h> -+#include <linux/interrupt.h> -+#include <linux/msi.h> -+#include <linux/dma-mapping.h> -+#include <linux/delay.h> -+ -+#include <linux/fsl/mc.h> -+#include "../../include/dpaa2-io.h" -+ -+#include "qbman-portal.h" -+#include "dpio.h" -+#include "dpio-cmd.h" -+ -+MODULE_LICENSE("Dual BSD/GPL"); -+MODULE_AUTHOR("Freescale Semiconductor, Inc"); -+MODULE_DESCRIPTION("DPIO Driver"); -+ -+struct dpio_priv { -+ struct dpaa2_io *io; -+}; -+ -+static irqreturn_t dpio_irq_handler(int irq_num, void *arg) -+{ -+ struct device *dev = (struct device *)arg; -+ struct dpio_priv *priv = dev_get_drvdata(dev); -+ -+ return dpaa2_io_irq(priv->io); -+} -+ -+static void unregister_dpio_irq_handlers(struct fsl_mc_device *dpio_dev) -+{ -+ struct fsl_mc_device_irq *irq; -+ -+ irq = dpio_dev->irqs[0]; -+ -+ /* clear the affinity hint */ -+ irq_set_affinity_hint(irq->msi_desc->irq, NULL); -+} -+ -+static int register_dpio_irq_handlers(struct fsl_mc_device *dpio_dev, int cpu) -+{ -+ struct dpio_priv *priv; -+ int error; -+ struct fsl_mc_device_irq *irq; -+ cpumask_t mask; -+ -+ priv = dev_get_drvdata(&dpio_dev->dev); -+ -+ irq = dpio_dev->irqs[0]; -+ error = devm_request_irq(&dpio_dev->dev, -+ irq->msi_desc->irq, -+ dpio_irq_handler, -+ 0, -+ dev_name(&dpio_dev->dev), -+ &dpio_dev->dev); -+ if (error < 0) { -+ dev_err(&dpio_dev->dev, -+ "devm_request_irq() failed: %d\n", -+ error); -+ return error; -+ } -+ -+ /* set the affinity hint */ -+ cpumask_clear(&mask); -+ cpumask_set_cpu(cpu, &mask); -+ if (irq_set_affinity_hint(irq->msi_desc->irq, &mask)) -+ dev_err(&dpio_dev->dev, -+ "irq_set_affinity failed irq %d cpu %d\n", -+ irq->msi_desc->irq, cpu); -+ -+ return 0; -+} -+ -+static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev) -+{ -+ struct dpio_attr dpio_attrs; -+ struct dpaa2_io_desc desc; -+ struct dpio_priv *priv; -+ int err = -ENOMEM; -+ struct device *dev = &dpio_dev->dev; -+ static int next_cpu = -1; -+ -+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ goto err_priv_alloc; -+ -+ dev_set_drvdata(dev, priv); -+ -+ err = fsl_mc_portal_allocate(dpio_dev, 0, &dpio_dev->mc_io); -+ if (err) { -+ dev_dbg(dev, "MC portal allocation failed\n"); -+ err = -EPROBE_DEFER; -+ goto err_mcportal; -+ } -+ -+ err = dpio_open(dpio_dev->mc_io, 0, dpio_dev->obj_desc.id, -+ &dpio_dev->mc_handle); -+ if (err) { -+ dev_err(dev, "dpio_open() failed\n"); -+ goto err_open; -+ } -+ -+ err = dpio_reset(dpio_dev->mc_io, 0, dpio_dev->mc_handle); -+ if (err) { -+ dev_err(dev, "dpio_reset() failed\n"); -+ goto err_reset; -+ } -+ -+ err = dpio_get_attributes(dpio_dev->mc_io, 0, dpio_dev->mc_handle, -+ &dpio_attrs); -+ if (err) { -+ dev_err(dev, "dpio_get_attributes() failed %d\n", err); -+ goto err_get_attr; -+ } -+ desc.qman_version = dpio_attrs.qbman_version; -+ -+ err = dpio_enable(dpio_dev->mc_io, 0, dpio_dev->mc_handle); -+ if (err) { -+ dev_err(dev, "dpio_enable() failed %d\n", err); -+ goto err_get_attr; -+ } -+ -+ /* initialize DPIO descriptor */ -+ desc.receives_notifications = dpio_attrs.num_priorities ? 1 : 0; -+ desc.has_8prio = dpio_attrs.num_priorities == 8 ? 1 : 0; -+ desc.dpio_id = dpio_dev->obj_desc.id; -+ -+ /* get the cpu to use for the affinity hint */ -+ if (next_cpu == -1) -+ next_cpu = cpumask_first(cpu_online_mask); -+ else -+ next_cpu = cpumask_next(next_cpu, cpu_online_mask); -+ -+ if (!cpu_possible(next_cpu)) { -+ dev_err(dev, "probe failed. Number of DPIOs exceeds NR_CPUS.\n"); -+ err = -ERANGE; -+ goto err_allocate_irqs; -+ } -+ desc.cpu = next_cpu; -+ -+ /* -+ * Set the CENA regs to be the cache enabled area of the portal to -+ * achieve the best performance. -+ */ -+ desc.regs_cena = ioremap_cache_ns(dpio_dev->regions[0].start, -+ resource_size(&dpio_dev->regions[0])); -+ desc.regs_cinh = ioremap(dpio_dev->regions[1].start, -+ resource_size(&dpio_dev->regions[1])); -+ -+ err = fsl_mc_allocate_irqs(dpio_dev); -+ if (err) { -+ dev_err(dev, "fsl_mc_allocate_irqs failed. err=%d\n", err); -+ goto err_allocate_irqs; -+ } -+ -+ err = register_dpio_irq_handlers(dpio_dev, desc.cpu); -+ if (err) -+ goto err_register_dpio_irq; -+ -+ priv->io = dpaa2_io_create(&desc); -+ if (!priv->io) { -+ dev_err(dev, "dpaa2_io_create failed\n"); -+ goto err_dpaa2_io_create; -+ } -+ -+ dev_info(dev, "probed\n"); -+ dev_dbg(dev, " receives_notifications = %d\n", -+ desc.receives_notifications); -+ dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle); -+ fsl_mc_portal_free(dpio_dev->mc_io); -+ -+ return 0; -+ -+err_dpaa2_io_create: -+ unregister_dpio_irq_handlers(dpio_dev); -+err_register_dpio_irq: -+ fsl_mc_free_irqs(dpio_dev); -+err_allocate_irqs: -+ dpio_disable(dpio_dev->mc_io, 0, dpio_dev->mc_handle); -+err_get_attr: -+err_reset: -+ dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle); -+err_open: -+ fsl_mc_portal_free(dpio_dev->mc_io); -+err_mcportal: -+ dev_set_drvdata(dev, NULL); -+err_priv_alloc: -+ return err; -+} -+ -+/* Tear down interrupts for a given DPIO object */ -+static void dpio_teardown_irqs(struct fsl_mc_device *dpio_dev) -+{ -+ unregister_dpio_irq_handlers(dpio_dev); -+ fsl_mc_free_irqs(dpio_dev); -+} -+ -+static int dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev) -+{ -+ struct device *dev; -+ struct dpio_priv *priv; -+ int err; -+ -+ dev = &dpio_dev->dev; -+ priv = dev_get_drvdata(dev); -+ -+ dpaa2_io_down(priv->io); -+ -+ dpio_teardown_irqs(dpio_dev); -+ -+ err = fsl_mc_portal_allocate(dpio_dev, 0, &dpio_dev->mc_io); -+ if (err) { -+ dev_err(dev, "MC portal allocation failed\n"); -+ goto err_mcportal; -+ } -+ -+ err = dpio_open(dpio_dev->mc_io, 0, dpio_dev->obj_desc.id, -+ &dpio_dev->mc_handle); -+ if (err) { -+ dev_err(dev, "dpio_open() failed\n"); -+ goto err_open; -+ } -+ -+ dpio_disable(dpio_dev->mc_io, 0, dpio_dev->mc_handle); -+ -+ dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle); -+ -+ fsl_mc_portal_free(dpio_dev->mc_io); -+ -+ dev_set_drvdata(dev, NULL); -+ -+ return 0; -+ -+err_open: -+ fsl_mc_portal_free(dpio_dev->mc_io); -+err_mcportal: -+ return err; -+} -+ -+static const struct fsl_mc_device_id dpaa2_dpio_match_id_table[] = { -+ { -+ .vendor = FSL_MC_VENDOR_FREESCALE, -+ .obj_type = "dpio", -+ }, -+ { .vendor = 0x0 } -+}; -+ -+static struct fsl_mc_driver dpaa2_dpio_driver = { -+ .driver = { -+ .name = KBUILD_MODNAME, -+ .owner = THIS_MODULE, -+ }, -+ .probe = dpaa2_dpio_probe, -+ .remove = dpaa2_dpio_remove, -+ .match_id_table = dpaa2_dpio_match_id_table -+}; -+ -+static int dpio_driver_init(void) -+{ -+ return fsl_mc_driver_register(&dpaa2_dpio_driver); -+} -+ -+static void dpio_driver_exit(void) -+{ -+ fsl_mc_driver_unregister(&dpaa2_dpio_driver); -+} -+module_init(dpio_driver_init); -+module_exit(dpio_driver_exit); ---- /dev/null -+++ b/drivers/staging/fsl-mc/bus/dpio/dpio-service.c -@@ -0,0 +1,780 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright 2014-2016 Freescale Semiconductor Inc. -+ * Copyright 2016 NXP -+ * -+ */ -+#include <linux/types.h> -+#include <linux/fsl/mc.h> -+#include "../../include/dpaa2-io.h" -+#include <linux/init.h> -+#include <linux/module.h> -+#include <linux/platform_device.h> -+#include <linux/interrupt.h> -+#include <linux/dma-mapping.h> -+#include <linux/slab.h> -+ -+#include "dpio.h" -+#include "qbman-portal.h" -+ -+struct dpaa2_io { -+ struct dpaa2_io_desc dpio_desc; -+ struct qbman_swp_desc swp_desc; -+ struct qbman_swp *swp; -+ struct list_head node; -+ /* protect against multiple management commands */ -+ spinlock_t lock_mgmt_cmd; -+ /* protect notifications list */ -+ spinlock_t lock_notifications; -+ struct list_head notifications; -+}; -+ -+struct dpaa2_io_store { -+ unsigned int max; -+ dma_addr_t paddr; -+ struct dpaa2_dq *vaddr; -+ void *alloced_addr; /* unaligned value from kmalloc() */ -+ unsigned int idx; /* position of the next-to-be-returned entry */ -+ struct qbman_swp *swp; /* portal used to issue VDQCR */ -+ struct device *dev; /* device used for DMA mapping */ -+}; -+ -+/* keep a per cpu array of DPIOs for fast access */ -+static struct dpaa2_io *dpio_by_cpu[NR_CPUS]; -+static struct list_head dpio_list = LIST_HEAD_INIT(dpio_list); -+static DEFINE_SPINLOCK(dpio_list_lock); -+ -+static inline struct dpaa2_io *service_select_by_cpu(struct dpaa2_io *d, -+ int cpu) -+{ -+ if (d) -+ return d; -+ -+ if (cpu != DPAA2_IO_ANY_CPU && cpu >= num_possible_cpus()) -+ return NULL; -+ -+ /* -+ * If cpu == -1, choose the current cpu, with no guarantees about -+ * potentially being migrated away. -+ */ -+ if (cpu < 0) -+ cpu = smp_processor_id(); -+ -+ /* If a specific cpu was requested, pick it up immediately */ -+ return dpio_by_cpu[cpu]; -+} -+ -+static inline struct dpaa2_io *service_select(struct dpaa2_io *d) -+{ -+ if (d) -+ return d; -+ -+ d = service_select_by_cpu(d, -1); -+ if (d) -+ return d; -+ -+ spin_lock(&dpio_list_lock); -+ d = list_entry(dpio_list.next, struct dpaa2_io, node); -+ list_del(&d->node); -+ list_add_tail(&d->node, &dpio_list); -+ spin_unlock(&dpio_list_lock); -+ -+ return d; -+} -+ -+/** -+ * dpaa2_io_service_select() - return a dpaa2_io service affined to this cpu -+ * @cpu: the cpu id -+ * -+ * Return the affine dpaa2_io service, or NULL if there is no service affined -+ * to the specified cpu. If DPAA2_IO_ANY_CPU is used, return the next available -+ * service. -+ */ -+struct dpaa2_io *dpaa2_io_service_select(int cpu) -+{ -+ if (cpu == DPAA2_IO_ANY_CPU) -+ return service_select(NULL); -+ -+ return service_select_by_cpu(NULL, cpu); -+} -+EXPORT_SYMBOL_GPL(dpaa2_io_service_select); -+ -+/** -+ * dpaa2_io_create() - create a dpaa2_io object. -+ * @desc: the dpaa2_io descriptor -+ * -+ * Activates a "struct dpaa2_io" corresponding to the given config of an actual -+ * DPIO object. -+ * -+ * Return a valid dpaa2_io object for success, or NULL for failure. -+ */ -+struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc) -+{ -+ struct dpaa2_io *obj = kmalloc(sizeof(*obj), GFP_KERNEL); -+ -+ if (!obj) -+ return NULL; -+ -+ /* check if CPU is out of range (-1 means any cpu) */ -+ if (desc->cpu != DPAA2_IO_ANY_CPU && desc->cpu >= num_possible_cpus()) { -+ kfree(obj); -+ return NULL; -+ } -+ -+ obj->dpio_desc = *desc; -+ obj->swp_desc.cena_bar = obj->dpio_desc.regs_cena; -+ obj->swp_desc.cinh_bar = obj->dpio_desc.regs_cinh; -+ obj->swp_desc.qman_version = obj->dpio_desc.qman_version; -+ obj->swp = qbman_swp_init(&obj->swp_desc); -+ -+ if (!obj->swp) { -+ kfree(obj); -+ return NULL; -+ } -+ -+ INIT_LIST_HEAD(&obj->node); -+ spin_lock_init(&obj->lock_mgmt_cmd); -+ spin_lock_init(&obj->lock_notifications); -+ INIT_LIST_HEAD(&obj->notifications); -+ -+ /* For now only enable DQRR interrupts */ -+ qbman_swp_interrupt_set_trigger(obj->swp, -+ QBMAN_SWP_INTERRUPT_DQRI); -+ qbman_swp_interrupt_clear_status(obj->swp, 0xffffffff); -+ if (obj->dpio_desc.receives_notifications) -+ qbman_swp_push_set(obj->swp, 0, 1); -+ -+ spin_lock(&dpio_list_lock); -+ list_add_tail(&obj->node, &dpio_list); -+ if (desc->cpu >= 0 && !dpio_by_cpu[desc->cpu]) -+ dpio_by_cpu[desc->cpu] = obj; -+ spin_unlock(&dpio_list_lock); -+ -+ return obj; -+} -+ -+/** -+ * dpaa2_io_down() - release the dpaa2_io object. -+ * @d: the dpaa2_io object to be released. -+ * -+ * The "struct dpaa2_io" type can represent an individual DPIO object (as -+ * described by "struct dpaa2_io_desc") or an instance of a "DPIO service", -+ * which can be used to group/encapsulate multiple DPIO objects. In all cases, -+ * each handle obtained should be released using this function. -+ */ -+void dpaa2_io_down(struct dpaa2_io *d) -+{ -+ kfree(d); -+} -+ -+#define DPAA_POLL_MAX 32 -+ -+/** -+ * dpaa2_io_irq() - ISR for DPIO interrupts -+ * -+ * @obj: the given DPIO object. -+ * -+ * Return IRQ_HANDLED for success or IRQ_NONE if there -+ * were no pending interrupts. -+ */ -+irqreturn_t dpaa2_io_irq(struct dpaa2_io *obj) -+{ -+ const struct dpaa2_dq *dq; -+ int max = 0; -+ struct qbman_swp *swp; -+ u32 status; -+ -+ swp = obj->swp; -+ status = qbman_swp_interrupt_read_status(swp); -+ if (!status) -+ return IRQ_NONE; -+ -+ dq = qbman_swp_dqrr_next(swp); -+ while (dq) { -+ if (qbman_result_is_SCN(dq)) { -+ struct dpaa2_io_notification_ctx *ctx; -+ u64 q64; -+ -+ q64 = qbman_result_SCN_ctx(dq); -+ ctx = (void *)(uintptr_t)q64; -+ ctx->cb(ctx); -+ } else { -+ pr_crit("fsl-mc-dpio: Unrecognised/ignored DQRR entry\n"); -+ } -+ qbman_swp_dqrr_consume(swp, dq); -+ ++max; -+ if (max > DPAA_POLL_MAX) -+ goto done; -+ dq = qbman_swp_dqrr_next(swp); -+ } -+done: -+ qbman_swp_interrupt_clear_status(swp, status); -+ qbman_swp_interrupt_set_inhibit(swp, 0); -+ return IRQ_HANDLED; -+} -+ -+/** -+ * dpaa2_io_service_register() - Prepare for servicing of FQDAN or CDAN -+ * notifications on the given DPIO service. -+ * @d: the given DPIO service. -+ * @ctx: the notification context. -+ * -+ * The caller should make the MC command to attach a DPAA2 object to -+ * a DPIO after this function completes successfully. In that way: -+ * (a) The DPIO service is "ready" to handle a notification arrival -+ * (which might happen before the "attach" command to MC has -+ * returned control of execution back to the caller) -+ * (b) The DPIO service can provide back to the caller the 'dpio_id' and -+ * 'qman64' parameters that it should pass along in the MC command -+ * in order for the object to be configured to produce the right -+ * notification fields to the DPIO service. -+ * -+ * Return 0 for success, or -ENODEV for failure. -+ */ -+int dpaa2_io_service_register(struct dpaa2_io *d, -+ struct dpaa2_io_notification_ctx *ctx) -+{ -+ unsigned long irqflags; -+ -+ d = service_select_by_cpu(d, ctx->desired_cpu); -+ if (!d) -+ return -ENODEV; -+ -+ ctx->dpio_id = d->dpio_desc.dpio_id; -+ ctx->qman64 = (u64)(uintptr_t)ctx; -+ ctx->dpio_private = d; -+ spin_lock_irqsave(&d->lock_notifications, irqflags); -+ list_add(&ctx->node, &d->notifications); -+ spin_unlock_irqrestore(&d->lock_notifications, irqflags); -+ -+ /* Enable the generation of CDAN notifications */ -+ if (ctx->is_cdan) -+ return qbman_swp_CDAN_set_context_enable(d->swp, -+ (u16)ctx->id, -+ ctx->qman64); -+ return 0; -+} -+EXPORT_SYMBOL_GPL(dpaa2_io_service_register); -+ -+/** -+ * dpaa2_io_service_deregister - The opposite of 'register'. -+ * @service: the given DPIO service. -+ * @ctx: the notification context. -+ * -+ * This function should be called only after sending the MC command to -+ * to detach the notification-producing device from the DPIO. -+ */ -+void dpaa2_io_service_deregister(struct dpaa2_io *service, -+ struct dpaa2_io_notification_ctx *ctx) -+{ -+ struct dpaa2_io *d = ctx->dpio_private; -+ unsigned long irqflags; -+ -+ if (ctx->is_cdan) -+ qbman_swp_CDAN_disable(d->swp, (u16)ctx->id); -+ -+ spin_lock_irqsave(&d->lock_notifications, irqflags); -+ list_del(&ctx->node); -+ spin_unlock_irqrestore(&d->lock_notifications, irqflags); -+} -+EXPORT_SYMBOL_GPL(dpaa2_io_service_deregister); -+ -+/** -+ * dpaa2_io_service_rearm() - Rearm the notification for the given DPIO service. -+ * @d: the given DPIO service. -+ * @ctx: the notification context. -+ * -+ * Once a FQDAN/CDAN has been produced, the corresponding FQ/channel is -+ * considered "disarmed". Ie. the user can issue pull dequeue operations on that -+ * traffic source for as long as it likes. Eventually it may wish to "rearm" -+ * that source to allow it to produce another FQDAN/CDAN, that's what this -+ * function achieves. -+ * -+ * Return 0 for success. -+ */ -+int dpaa2_io_service_rearm(struct dpaa2_io *d, -+ struct dpaa2_io_notification_ctx *ctx) -+{ -+ unsigned long irqflags; -+ int err; -+ -+ d = service_select_by_cpu(d, ctx->desired_cpu); -+ if (!unlikely(d)) -+ return -ENODEV; -+ -+ spin_lock_irqsave(&d->lock_mgmt_cmd, irqflags); -+ if (ctx->is_cdan) -+ err = qbman_swp_CDAN_enable(d->swp, (u16)ctx->id); -+ else -+ err = qbman_swp_fq_schedule(d->swp, ctx->id); -+ spin_unlock_irqrestore(&d->lock_mgmt_cmd, irqflags); -+ -+ return err; -+} -+EXPORT_SYMBOL_GPL(dpaa2_io_service_rearm); -+ -+/** -+ * dpaa2_io_service_pull_fq() - pull dequeue functions from a fq. -+ * @d: the given DPIO service. -+ * @fqid: the given frame queue id. -+ * @s: the dpaa2_io_store object for the result. -+ * -+ * Return 0 for success, or error code for failure. -+ */ -+int dpaa2_io_service_pull_fq(struct dpaa2_io *d, u32 fqid, -+ struct dpaa2_io_store *s) -+{ -+ struct qbman_pull_desc pd; -+ int err; -+ -+ qbman_pull_desc_clear(&pd); -+ qbman_pull_desc_set_storage(&pd, s->vaddr, s->paddr, 1); -+ qbman_pull_desc_set_numframes(&pd, (u8)s->max); -+ qbman_pull_desc_set_fq(&pd, fqid); -+ -+ d = service_select(d); -+ if (!d) -+ return -ENODEV; -+ s->swp = d->swp; -+ err = qbman_swp_pull(d->swp, &pd); -+ if (err) -+ s->swp = NULL; -+ -+ return err; -+} -+EXPORT_SYMBOL(dpaa2_io_service_pull_fq); -+ -+/** -+ * dpaa2_io_service_pull_channel() - pull dequeue functions from a channel. -+ * @d: the given DPIO service. -+ * @channelid: the given channel id. -+ * @s: the dpaa2_io_store object for the result. -+ * -+ * Return 0 for success, or error code for failure. -+ */ -+int dpaa2_io_service_pull_channel(struct dpaa2_io *d, u32 channelid, -+ struct dpaa2_io_store *s) -+{ -+ struct qbman_pull_desc pd; -+ int err; -+ -+ qbman_pull_desc_clear(&pd); -+ qbman_pull_desc_set_storage(&pd, s->vaddr, s->paddr, 1); -+ qbman_pull_desc_set_numframes(&pd, (u8)s->max); -+ qbman_pull_desc_set_channel(&pd, channelid, qbman_pull_type_prio); -+ -+ d = service_select(d); -+ if (!d) -+ return -ENODEV; -+ -+ s->swp = d->swp; -+ err = qbman_swp_pull(d->swp, &pd); -+ if (err) -+ s->swp = NULL; -+ -+ return err; -+} -+EXPORT_SYMBOL_GPL(dpaa2_io_service_pull_channel); -+ -+/** -+ * dpaa2_io_service_enqueue_fq() - Enqueue a frame to a frame queue. -+ * @d: the given DPIO service. -+ * @fqid: the given frame queue id. -+ * @fd: the frame descriptor which is enqueued. -+ * -+ * Return 0 for successful enqueue, -EBUSY if the enqueue ring is not ready, -+ * or -ENODEV if there is no dpio service. -+ */ -+int dpaa2_io_service_enqueue_fq(struct dpaa2_io *d, -+ u32 fqid, -+ const struct dpaa2_fd *fd) -+{ -+ struct qbman_eq_desc ed; -+ -+ d = service_select(d); -+ if (!d) -+ return -ENODEV; -+ -+ qbman_eq_desc_clear(&ed); -+ qbman_eq_desc_set_no_orp(&ed, 0); -+ qbman_eq_desc_set_fq(&ed, fqid); -+ -+ return qbman_swp_enqueue(d->swp, &ed, fd); -+} -+EXPORT_SYMBOL(dpaa2_io_service_enqueue_fq); -+ -+/** -+ * dpaa2_io_service_enqueue_qd() - Enqueue a frame to a QD. -+ * @d: the given DPIO service. -+ * @qdid: the given queuing destination id. -+ * @prio: the given queuing priority. -+ * @qdbin: the given queuing destination bin. -+ * @fd: the frame descriptor which is enqueued. -+ * -+ * Return 0 for successful enqueue, or -EBUSY if the enqueue ring is not ready, -+ * or -ENODEV if there is no dpio service. -+ */ -+int dpaa2_io_service_enqueue_qd(struct dpaa2_io *d, -+ u32 qdid, u8 prio, u16 qdbin, -+ const struct dpaa2_fd *fd) -+{ -+ struct qbman_eq_desc ed; -+ -+ d = service_select(d); -+ if (!d) -+ return -ENODEV; -+ -+ qbman_eq_desc_clear(&ed); -+ qbman_eq_desc_set_no_orp(&ed, 0); -+ qbman_eq_desc_set_qd(&ed, qdid, qdbin, prio); -+ -+ return qbman_swp_enqueue(d->swp, &ed, fd); -+} -+EXPORT_SYMBOL_GPL(dpaa2_io_service_enqueue_qd); -+ -+/** -+ * dpaa2_io_service_release() - Release buffers to a buffer pool. -+ * @d: the given DPIO object. -+ * @bpid: the buffer pool id. -+ * @buffers: the buffers to be released. -+ * @num_buffers: the number of the buffers to be released. -+ * -+ * Return 0 for success, and negative error code for failure. -+ */ -+int dpaa2_io_service_release(struct dpaa2_io *d, -+ u32 bpid, -+ const u64 *buffers, -+ unsigned int num_buffers) -+{ -+ struct qbman_release_desc rd; -+ -+ d = service_select(d); -+ if (!d) -+ return -ENODEV; -+ -+ qbman_release_desc_clear(&rd); -+ qbman_release_desc_set_bpid(&rd, bpid); -+ -+ return qbman_swp_release(d->swp, &rd, buffers, num_buffers); -+} -+EXPORT_SYMBOL_GPL(dpaa2_io_service_release); -+ -+/** -+ * dpaa2_io_service_acquire() - Acquire buffers from a buffer pool. -+ * @d: the given DPIO object. -+ * @bpid: the buffer pool id. -+ * @buffers: the buffer addresses for acquired buffers. -+ * @num_buffers: the expected number of the buffers to acquire. -+ * -+ * Return a negative error code if the command failed, otherwise it returns -+ * the number of buffers acquired, which may be less than the number requested. -+ * Eg. if the buffer pool is empty, this will return zero. -+ */ -+int dpaa2_io_service_acquire(struct dpaa2_io *d, -+ u32 bpid, -+ u64 *buffers, -+ unsigned int num_buffers) -+{ -+ unsigned long irqflags; -+ int err; -+ -+ d = service_select(d); -+ if (!d) -+ return -ENODEV; -+ -+ spin_lock_irqsave(&d->lock_mgmt_cmd, irqflags); -+ err = qbman_swp_acquire(d->swp, bpid, buffers, num_buffers); -+ spin_unlock_irqrestore(&d->lock_mgmt_cmd, irqflags); -+ -+ return err; -+} -+EXPORT_SYMBOL_GPL(dpaa2_io_service_acquire); -+ -+/* -+ * 'Stores' are reusable memory blocks for holding dequeue results, and to -+ * assist with parsing those results. -+ */ -+ -+/** -+ * dpaa2_io_store_create() - Create the dma memory storage for dequeue result. -+ * @max_frames: the maximum number of dequeued result for frames, must be <= 16. -+ * @dev: the device to allow mapping/unmapping the DMAable region. -+ * -+ * The size of the storage is "max_frames*sizeof(struct dpaa2_dq)". -+ * The 'dpaa2_io_store' returned is a DPIO service managed object. -+ * -+ * Return pointer to dpaa2_io_store struct for successfuly created storage -+ * memory, or NULL on error. -+ */ -+struct dpaa2_io_store *dpaa2_io_store_create(unsigned int max_frames, -+ struct device *dev) -+{ -+ struct dpaa2_io_store *ret; -+ size_t size; -+ -+ if (!max_frames || (max_frames > 16)) -+ return NULL; -+ -+ ret = kmalloc(sizeof(*ret), GFP_KERNEL); -+ if (!ret) -+ return NULL; -+ -+ ret->max = max_frames; -+ size = max_frames * sizeof(struct dpaa2_dq) + 64; -+ ret->alloced_addr = kzalloc(size, GFP_KERNEL); -+ if (!ret->alloced_addr) { -+ kfree(ret); -+ return NULL; -+ } -+ -+ ret->vaddr = PTR_ALIGN(ret->alloced_addr, 64); -+ ret->paddr = dma_map_single(dev, ret->vaddr, -+ sizeof(struct dpaa2_dq) * max_frames, -+ DMA_FROM_DEVICE); -+ if (dma_mapping_error(dev, ret->paddr)) { -+ kfree(ret->alloced_addr); -+ kfree(ret); -+ return NULL; -+ } -+ -+ ret->idx = 0; -+ ret->dev = dev; -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(dpaa2_io_store_create); -+ -+/** -+ * dpaa2_io_store_destroy() - Frees the dma memory storage for dequeue -+ * result. -+ * @s: the storage memory to be destroyed. -+ */ -+void dpaa2_io_store_destroy(struct dpaa2_io_store *s) -+{ -+ dma_unmap_single(s->dev, s->paddr, sizeof(struct dpaa2_dq) * s->max, -+ DMA_FROM_DEVICE); -+ kfree(s->alloced_addr); -+ kfree(s); -+} -+EXPORT_SYMBOL_GPL(dpaa2_io_store_destroy); -+ -+/** -+ * dpaa2_io_store_next() - Determine when the next dequeue result is available. -+ * @s: the dpaa2_io_store object. -+ * @is_last: indicate whether this is the last frame in the pull command. -+ * -+ * When an object driver performs dequeues to a dpaa2_io_store, this function -+ * can be used to determine when the next frame result is available. Once -+ * this function returns non-NULL, a subsequent call to it will try to find -+ * the next dequeue result. -+ * -+ * Note that if a pull-dequeue has a NULL result because the target FQ/channel -+ * was empty, then this function will also return NULL (rather than expecting -+ * the caller to always check for this. As such, "is_last" can be used to -+ * differentiate between "end-of-empty-dequeue" and "still-waiting". -+ * -+ * Return dequeue result for a valid dequeue result, or NULL for empty dequeue. -+ */ -+struct dpaa2_dq *dpaa2_io_store_next(struct dpaa2_io_store *s, int *is_last) -+{ -+ int match; -+ struct dpaa2_dq *ret = &s->vaddr[s->idx]; -+ -+ match = qbman_result_has_new_result(s->swp, ret); -+ if (!match) { -+ *is_last = 0; -+ return NULL; -+ } -+ -+ s->idx++; -+ -+ if (dpaa2_dq_is_pull_complete(ret)) { -+ *is_last = 1; -+ s->idx = 0; -+ /* -+ * If we get an empty dequeue result to terminate a zero-results -+ * vdqcr, return NULL to the caller rather than expecting him to -+ * check non-NULL results every time. -+ */ -+ if (!(dpaa2_dq_flags(ret) & DPAA2_DQ_STAT_VALIDFRAME)) -+ ret = NULL; -+ } else { -+ *is_last = 0; -+ } -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(dpaa2_io_store_next); -+ -+/** -+ * dpaa2_io_query_fq_count() - Get the frame and byte count for a given fq. -+ * @d: the given DPIO object. -+ * @fqid: the id of frame queue to be queried. -+ * @fcnt: the queried frame count. -+ * @bcnt: the queried byte count. -+ * -+ * Knowing the FQ count at run-time can be useful in debugging situations. -+ * The instantaneous frame- and byte-count are hereby returned. -+ * -+ * Return 0 for a successful query, and negative error code if query fails. -+ */ -+int dpaa2_io_query_fq_count(struct dpaa2_io *d, u32 fqid, -+ u32 *fcnt, u32 *bcnt) -+{ -+ struct qbman_fq_query_np_rslt state; -+ struct qbman_swp *swp; -+ unsigned long irqflags; -+ int ret; -+ -+ d = service_select(d); -+ if (!d) -+ return -ENODEV; -+ -+ swp = d->swp; -+ spin_lock_irqsave(&d->lock_mgmt_cmd, irqflags); -+ ret = qbman_fq_query_state(swp, fqid, &state); -+ spin_unlock_irqrestore(&d->lock_mgmt_cmd, irqflags); -+ if (ret) -+ return ret; -+ *fcnt = qbman_fq_state_frame_count(&state); -+ *bcnt = qbman_fq_state_byte_count(&state); -+ -+ return 0; -+} -+EXPORT_SYMBOL(dpaa2_io_query_fq_count); -+ -+/** -+ * dpaa2_io_query_bp_count() - Query the number of buffers currently in a -+ * buffer pool. -+ * @d: the given DPIO object. -+ * @bpid: the index of buffer pool to be queried. -+ * @num: the queried number of buffers in the buffer pool. -+ * -+ * Return 0 for a successful query, and negative error code if query fails. -+ */ -+int dpaa2_io_query_bp_count(struct dpaa2_io *d, u32 bpid, u32 *num) -+{ -+ struct qbman_bp_query_rslt state; -+ struct qbman_swp *swp; -+ unsigned long irqflags; -+ int ret; -+ -+ d = service_select(d); -+ if (!d) -+ return -ENODEV; -+ -+ swp = d->swp; -+ spin_lock_irqsave(&d->lock_mgmt_cmd, irqflags); -+ ret = qbman_bp_query(swp, bpid, &state); -+ spin_unlock_irqrestore(&d->lock_mgmt_cmd, irqflags); -+ if (ret) -+ return ret; -+ *num = qbman_bp_info_num_free_bufs(&state); -+ return 0; -+} -+EXPORT_SYMBOL(dpaa2_io_query_bp_count); -+ -+/** -+ * dpaa2_io_service_enqueue_orp_fq() - Enqueue a frame to a frame queue with -+ * order restoration -+ * @d: the given DPIO service. -+ * @fqid: the given frame queue id. -+ * @fd: the frame descriptor which is enqueued. -+ * @orpid: the order restoration point ID -+ * @seqnum: the order sequence number -+ * @last: must be set for the final frame if seqnum is shared (spilt frame) -+ * -+ * Performs an enqueue to a frame queue using the specified order restoration -+ * point. The QMan device will ensure the order of frames placed on the -+ * queue will be ordered as per the sequence number. -+ * -+ * In the case a frame is split it is possible to enqueue using the same -+ * sequence number more than once. The final frame in a shared sequence number -+ * most be indicated by setting last = 1. For non shared sequence numbers -+ * last = 1 must always be set. -+ * -+ * Return 0 for successful enqueue, or -EBUSY if the enqueue ring is not ready, -+ * or -ENODEV if there is no dpio service. -+ */ -+int dpaa2_io_service_enqueue_orp_fq(struct dpaa2_io *d, u32 fqid, -+ const struct dpaa2_fd *fd, u16 orpid, -+ u16 seqnum, int last) -+{ -+ struct qbman_eq_desc ed; -+ -+ d = service_select(d); -+ if (!d) -+ return -ENODEV; -+ qbman_eq_desc_clear(&ed); -+ qbman_eq_desc_set_orp(&ed, 0, orpid, seqnum, !last); -+ qbman_eq_desc_set_fq(&ed, fqid); -+ return qbman_swp_enqueue(d->swp, &ed, fd); -+} -+EXPORT_SYMBOL(dpaa2_io_service_enqueue_orp_fq); -+ -+/** -+ * dpaa2_io_service_enqueue_orp_qd() - Enqueue a frame to a queueing destination -+ * with order restoration -+ * @d: the given DPIO service. -+ * @qdid: the given queuing destination id. -+ * @fd: the frame descriptor which is enqueued. -+ * @orpid: the order restoration point ID -+ * @seqnum: the order sequence number -+ * @last: must be set for the final frame if seqnum is shared (spilt frame) -+ * -+ * Performs an enqueue to a frame queue using the specified order restoration -+ * point. The QMan device will ensure the order of frames placed on the -+ * queue will be ordered as per the sequence number. -+ * -+ * In the case a frame is split it is possible to enqueue using the same -+ * sequence number more than once. The final frame in a shared sequence number -+ * most be indicated by setting last = 1. For non shared sequence numbers -+ * last = 1 must always be set. -+ * -+ * Return 0 for successful enqueue, or -EBUSY if the enqueue ring is not ready, -+ * or -ENODEV if there is no dpio service. -+ */ -+int dpaa2_io_service_enqueue_orp_qd(struct dpaa2_io *d, u32 qdid, u8 prio, -+ u16 qdbin, const struct dpaa2_fd *fd, -+ u16 orpid, u16 seqnum, int last) -+{ -+ struct qbman_eq_desc ed; -+ -+ d = service_select(d); -+ if (!d) -+ return -ENODEV; -+ qbman_eq_desc_clear(&ed); -+ qbman_eq_desc_set_orp(&ed, 0, orpid, seqnum, !last); -+ qbman_eq_desc_set_qd(&ed, qdid, qdbin, prio); -+ return qbman_swp_enqueue(d->swp, &ed, fd); -+} -+EXPORT_SYMBOL_GPL(dpaa2_io_service_enqueue_orp_qd); -+ -+/** -+ * dpaa2_io_service_orp_seqnum_drop() - Remove a sequence number from -+ * an order restoration list -+ * @d: the given DPIO service. -+ * @orpid: Order restoration point to remove a sequence number from -+ * @seqnum: Sequence number to remove -+ * -+ * Removes a frames sequence number from an order restoration point without -+ * enqueing the frame. Used to indicate that the order restoration hardware -+ * should not expect to see this sequence number. Typically used to indicate -+ * a frame was terminated or dropped from a flow. -+ * -+ * Return 0 for successful enqueue, or -EBUSY if the enqueue ring is not ready, -+ * or -ENODEV if there is no dpio service. -+ */ -+int dpaa2_io_service_orp_seqnum_drop(struct dpaa2_io *d, u16 orpid, u16 seqnum) -+{ -+ struct qbman_eq_desc ed; -+ struct dpaa2_fd fd; -+ -+ d = service_select(d); -+ if (!d) -+ return -ENODEV; -+ qbman_eq_desc_clear(&ed); -+ qbman_eq_desc_set_orp_hole(&ed, orpid, seqnum); -+ return qbman_swp_enqueue(d->swp, &ed, &fd); -+} -+EXPORT_SYMBOL_GPL(dpaa2_io_service_orp_seqnum_drop); ---- /dev/null -+++ b/drivers/staging/fsl-mc/bus/dpio/dpio.c -@@ -0,0 +1,221 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright 2013-2016 Freescale Semiconductor Inc. -+ * Copyright 2016 NXP -+ * -+ */ -+#include <linux/kernel.h> -+#include <linux/fsl/mc.h> -+ -+#include "dpio.h" -+#include "dpio-cmd.h" -+ -+/* -+ * Data Path I/O Portal API -+ * Contains initialization APIs and runtime control APIs for DPIO -+ */ -+ -+/** -+ * dpio_open() - Open a control session for the specified object -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @dpio_id: DPIO unique ID -+ * @token: Returned token; use in subsequent API calls -+ * -+ * This function can be used to open a control session for an -+ * already created object; an object may have been declared in -+ * the DPL or by calling the dpio_create() function. -+ * This function returns a unique authentication token, -+ * associated with the specific object ID and the specific MC -+ * portal; this token must be used in all subsequent commands for -+ * this specific object. -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpio_open(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ int dpio_id, -+ u16 *token) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpio_cmd_open *dpio_cmd; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPIO_CMDID_OPEN, -+ cmd_flags, -+ 0); -+ dpio_cmd = (struct dpio_cmd_open *)cmd.params; -+ dpio_cmd->dpio_id = cpu_to_le32(dpio_id); -+ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ *token = mc_cmd_hdr_read_token(&cmd); -+ -+ return 0; -+} -+ -+/** -+ * dpio_close() - Close the control session of the object -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPIO object -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpio_close(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPIO_CMDID_CLOSE, -+ cmd_flags, -+ token); -+ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpio_enable() - Enable the DPIO, allow I/O portal operations. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPIO object -+ * -+ * Return: '0' on Success; Error code otherwise -+ */ -+int dpio_enable(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPIO_CMDID_ENABLE, -+ cmd_flags, -+ token); -+ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpio_disable() - Disable the DPIO, stop any I/O portal operation. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPIO object -+ * -+ * Return: '0' on Success; Error code otherwise -+ */ -+int dpio_disable(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPIO_CMDID_DISABLE, -+ cmd_flags, -+ token); -+ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpio_get_attributes() - Retrieve DPIO attributes -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPIO object -+ * @attr: Returned object's attributes -+ * -+ * Return: '0' on Success; Error code otherwise -+ */ -+int dpio_get_attributes(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ struct dpio_attr *attr) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpio_rsp_get_attr *dpio_rsp; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_ATTR, -+ cmd_flags, -+ token); -+ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ dpio_rsp = (struct dpio_rsp_get_attr *)cmd.params; -+ attr->id = le32_to_cpu(dpio_rsp->id); -+ attr->qbman_portal_id = le16_to_cpu(dpio_rsp->qbman_portal_id); -+ attr->num_priorities = dpio_rsp->num_priorities; -+ attr->channel_mode = dpio_rsp->channel_mode & DPIO_CHANNEL_MODE_MASK; -+ attr->qbman_portal_ce_offset = -+ le64_to_cpu(dpio_rsp->qbman_portal_ce_addr); -+ attr->qbman_portal_ci_offset = -+ le64_to_cpu(dpio_rsp->qbman_portal_ci_addr); -+ attr->qbman_version = le32_to_cpu(dpio_rsp->qbman_version); -+ -+ return 0; -+} -+ -+/** -+ * dpio_get_api_version - Get Data Path I/O API version -+ * @mc_io: Pointer to MC portal's DPIO object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @major_ver: Major version of DPIO API -+ * @minor_ver: Minor version of DPIO API -+ * -+ * Return: '0' on Success; Error code otherwise -+ */ -+int dpio_get_api_version(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 *major_ver, -+ u16 *minor_ver) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_API_VERSION, -+ cmd_flags, 0); -+ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ mc_cmd_read_api_version(&cmd, major_ver, minor_ver); -+ -+ return 0; -+} -+ -+/** -+ * dpio_reset() - Reset the DPIO, returns the object to initial state. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPIO object -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpio_reset(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPIO_CMDID_RESET, -+ cmd_flags, -+ token); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} ---- /dev/null -+++ b/drivers/staging/fsl-mc/bus/dpio/dpio.h -@@ -0,0 +1,87 @@ -+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ -+/* -+ * Copyright 2013-2016 Freescale Semiconductor Inc. -+ * Copyright 2016 NXP -+ * -+ */ -+#ifndef __FSL_DPIO_H -+#define __FSL_DPIO_H -+ -+struct fsl_mc_io; -+ -+int dpio_open(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ int dpio_id, -+ u16 *token); -+ -+int dpio_close(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token); -+ -+/** -+ * enum dpio_channel_mode - DPIO notification channel mode -+ * @DPIO_NO_CHANNEL: No support for notification channel -+ * @DPIO_LOCAL_CHANNEL: Notifications on data availability can be received by a -+ * dedicated channel in the DPIO; user should point the queue's -+ * destination in the relevant interface to this DPIO -+ */ -+enum dpio_channel_mode { -+ DPIO_NO_CHANNEL = 0, -+ DPIO_LOCAL_CHANNEL = 1, -+}; -+ -+/** -+ * struct dpio_cfg - Structure representing DPIO configuration -+ * @channel_mode: Notification channel mode -+ * @num_priorities: Number of priorities for the notification channel (1-8); -+ * relevant only if 'channel_mode = DPIO_LOCAL_CHANNEL' -+ */ -+struct dpio_cfg { -+ enum dpio_channel_mode channel_mode; -+ u8 num_priorities; -+}; -+ -+int dpio_enable(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token); -+ -+int dpio_disable(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token); -+ -+/** -+ * struct dpio_attr - Structure representing DPIO attributes -+ * @id: DPIO object ID -+ * @qbman_portal_ce_offset: offset of the software portal cache-enabled area -+ * @qbman_portal_ci_offset: offset of the software portal cache-inhibited area -+ * @qbman_portal_id: Software portal ID -+ * @channel_mode: Notification channel mode -+ * @num_priorities: Number of priorities for the notification channel (1-8); -+ * relevant only if 'channel_mode = DPIO_LOCAL_CHANNEL' -+ * @qbman_version: QBMAN version -+ */ -+struct dpio_attr { -+ int id; -+ u64 qbman_portal_ce_offset; -+ u64 qbman_portal_ci_offset; -+ u16 qbman_portal_id; -+ enum dpio_channel_mode channel_mode; -+ u8 num_priorities; -+ u32 qbman_version; -+}; -+ -+int dpio_get_attributes(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ struct dpio_attr *attr); -+ -+int dpio_get_api_version(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 *major_ver, -+ u16 *minor_ver); -+ -+int dpio_reset(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token); -+ -+#endif /* __FSL_DPIO_H */ ---- /dev/null -+++ b/drivers/staging/fsl-mc/bus/dpio/qbman-portal.c -@@ -0,0 +1,1164 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. -+ * Copyright 2016 NXP -+ * -+ */ -+ -+#include <asm/cacheflush.h> -+#include <linux/io.h> -+#include <linux/slab.h> -+#include "../../include/dpaa2-global.h" -+ -+#include "qbman-portal.h" -+ -+#define QMAN_REV_4000 0x04000000 -+#define QMAN_REV_4100 0x04010000 -+#define QMAN_REV_4101 0x04010001 -+#define QMAN_REV_MASK 0xffff0000 -+ -+/* All QBMan command and result structures use this "valid bit" encoding */ -+#define QB_VALID_BIT ((u32)0x80) -+ -+/* QBMan portal management command codes */ -+#define QBMAN_MC_ACQUIRE 0x30 -+#define QBMAN_WQCHAN_CONFIGURE 0x46 -+ -+/* CINH register offsets */ -+#define QBMAN_CINH_SWP_EQAR 0x8c0 -+#define QBMAN_CINH_SWP_DQPI 0xa00 -+#define QBMAN_CINH_SWP_DCAP 0xac0 -+#define QBMAN_CINH_SWP_SDQCR 0xb00 -+#define QBMAN_CINH_SWP_RAR 0xcc0 -+#define QBMAN_CINH_SWP_ISR 0xe00 -+#define QBMAN_CINH_SWP_IER 0xe40 -+#define QBMAN_CINH_SWP_ISDR 0xe80 -+#define QBMAN_CINH_SWP_IIR 0xec0 -+ -+/* CENA register offsets */ -+#define QBMAN_CENA_SWP_EQCR(n) (0x000 + ((u32)(n) << 6)) -+#define QBMAN_CENA_SWP_DQRR(n) (0x200 + ((u32)(n) << 6)) -+#define QBMAN_CENA_SWP_RCR(n) (0x400 + ((u32)(n) << 6)) -+#define QBMAN_CENA_SWP_CR 0x600 -+#define QBMAN_CENA_SWP_RR(vb) (0x700 + ((u32)(vb) >> 1)) -+#define QBMAN_CENA_SWP_VDQCR 0x780 -+ -+/* Reverse mapping of QBMAN_CENA_SWP_DQRR() */ -+#define QBMAN_IDX_FROM_DQRR(p) (((unsigned long)(p) & 0x1ff) >> 6) -+ -+/* Define token used to determine if response written to memory is valid */ -+#define QMAN_DQ_TOKEN_VALID 1 -+ -+/* SDQCR attribute codes */ -+#define QB_SDQCR_FC_SHIFT 29 -+#define QB_SDQCR_FC_MASK 0x1 -+#define QB_SDQCR_DCT_SHIFT 24 -+#define QB_SDQCR_DCT_MASK 0x3 -+#define QB_SDQCR_TOK_SHIFT 16 -+#define QB_SDQCR_TOK_MASK 0xff -+#define QB_SDQCR_SRC_SHIFT 0 -+#define QB_SDQCR_SRC_MASK 0xffff -+ -+/* opaque token for static dequeues */ -+#define QMAN_SDQCR_TOKEN 0xbb -+ -+enum qbman_sdqcr_dct { -+ qbman_sdqcr_dct_null = 0, -+ qbman_sdqcr_dct_prio_ics, -+ qbman_sdqcr_dct_active_ics, -+ qbman_sdqcr_dct_active -+}; -+ -+enum qbman_sdqcr_fc { -+ qbman_sdqcr_fc_one = 0, -+ qbman_sdqcr_fc_up_to_3 = 1 -+}; -+ -+#define dccvac(p) { asm volatile("dc cvac, %0;" : : "r" (p) : "memory"); } -+#define dcivac(p) { asm volatile("dc ivac, %0" : : "r"(p) : "memory"); } -+static inline void qbman_inval_prefetch(struct qbman_swp *p, uint32_t offset) -+{ -+ dcivac(p->addr_cena + offset); -+ prefetch(p->addr_cena + offset); -+} -+ -+/* Portal Access */ -+ -+static inline u32 qbman_read_register(struct qbman_swp *p, u32 offset) -+{ -+ return readl_relaxed(p->addr_cinh + offset); -+} -+ -+static inline void qbman_write_register(struct qbman_swp *p, u32 offset, -+ u32 value) -+{ -+ writel_relaxed(value, p->addr_cinh + offset); -+} -+ -+static inline void *qbman_get_cmd(struct qbman_swp *p, u32 offset) -+{ -+ return p->addr_cena + offset; -+} -+ -+#define QBMAN_CINH_SWP_CFG 0xd00 -+ -+#define SWP_CFG_DQRR_MF_SHIFT 20 -+#define SWP_CFG_EST_SHIFT 16 -+#define SWP_CFG_WN_SHIFT 14 -+#define SWP_CFG_RPM_SHIFT 12 -+#define SWP_CFG_DCM_SHIFT 10 -+#define SWP_CFG_EPM_SHIFT 8 -+#define SWP_CFG_SD_SHIFT 5 -+#define SWP_CFG_SP_SHIFT 4 -+#define SWP_CFG_SE_SHIFT 3 -+#define SWP_CFG_DP_SHIFT 2 -+#define SWP_CFG_DE_SHIFT 1 -+#define SWP_CFG_EP_SHIFT 0 -+ -+static inline u32 qbman_set_swp_cfg(u8 max_fill, u8 wn, u8 est, u8 rpm, u8 dcm, -+ u8 epm, int sd, int sp, int se, -+ int dp, int de, int ep) -+{ -+ return (max_fill << SWP_CFG_DQRR_MF_SHIFT | -+ est << SWP_CFG_EST_SHIFT | -+ wn << SWP_CFG_WN_SHIFT | -+ rpm << SWP_CFG_RPM_SHIFT | -+ dcm << SWP_CFG_DCM_SHIFT | -+ epm << SWP_CFG_EPM_SHIFT | -+ sd << SWP_CFG_SD_SHIFT | -+ sp << SWP_CFG_SP_SHIFT | -+ se << SWP_CFG_SE_SHIFT | -+ dp << SWP_CFG_DP_SHIFT | -+ de << SWP_CFG_DE_SHIFT | -+ ep << SWP_CFG_EP_SHIFT); -+} -+ -+/** -+ * qbman_swp_init() - Create a functional object representing the given -+ * QBMan portal descriptor. -+ * @d: the given qbman swp descriptor -+ * -+ * Return qbman_swp portal for success, NULL if the object cannot -+ * be created. -+ */ -+struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) -+{ -+ struct qbman_swp *p = kmalloc(sizeof(*p), GFP_KERNEL); -+ u32 reg; -+ -+ if (!p) -+ return NULL; -+ p->desc = d; -+ p->mc.valid_bit = QB_VALID_BIT; -+ p->sdq = 0; -+ p->sdq |= qbman_sdqcr_dct_prio_ics << QB_SDQCR_DCT_SHIFT; -+ p->sdq |= qbman_sdqcr_fc_up_to_3 << QB_SDQCR_FC_SHIFT; -+ p->sdq |= QMAN_SDQCR_TOKEN << QB_SDQCR_TOK_SHIFT; -+ -+ atomic_set(&p->vdq.available, 1); -+ p->vdq.valid_bit = QB_VALID_BIT; -+ p->dqrr.next_idx = 0; -+ p->dqrr.valid_bit = QB_VALID_BIT; -+ -+ if ((p->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_4100) { -+ p->dqrr.dqrr_size = 4; -+ p->dqrr.reset_bug = 1; -+ } else { -+ p->dqrr.dqrr_size = 8; -+ p->dqrr.reset_bug = 0; -+ } -+ -+ p->addr_cena = d->cena_bar; -+ p->addr_cinh = d->cinh_bar; -+ -+ reg = qbman_set_swp_cfg(p->dqrr.dqrr_size, -+ 0, /* Writes cacheable */ -+ 0, /* EQCR_CI stashing threshold */ -+ 3, /* RPM: Valid bit mode, RCR in array mode */ -+ 2, /* DCM: Discrete consumption ack mode */ -+ 3, /* EPM: Valid bit mode, EQCR in array mode */ -+ 0, /* mem stashing drop enable == FALSE */ -+ 1, /* mem stashing priority == TRUE */ -+ 0, /* mem stashing enable == FALSE */ -+ 1, /* dequeue stashing priority == TRUE */ -+ 0, /* dequeue stashing enable == FALSE */ -+ 0); /* EQCR_CI stashing priority == FALSE */ -+ -+ qbman_write_register(p, QBMAN_CINH_SWP_CFG, reg); -+ reg = qbman_read_register(p, QBMAN_CINH_SWP_CFG); -+ if (!reg) { -+ pr_err("qbman: the portal is not enabled!\n"); -+ return NULL; -+ } -+ -+ /* -+ * SDQCR needs to be initialized to 0 when no channels are -+ * being dequeued from or else the QMan HW will indicate an -+ * error. The values that were calculated above will be -+ * applied when dequeues from a specific channel are enabled. -+ */ -+ qbman_write_register(p, QBMAN_CINH_SWP_SDQCR, 0); -+ return p; -+} -+ -+/** -+ * qbman_swp_finish() - Create and destroy a functional object representing -+ * the given QBMan portal descriptor. -+ * @p: the qbman_swp object to be destroyed -+ */ -+void qbman_swp_finish(struct qbman_swp *p) -+{ -+ kfree(p); -+} -+ -+/** -+ * qbman_swp_interrupt_read_status() -+ * @p: the given software portal -+ * -+ * Return the value in the SWP_ISR register. -+ */ -+u32 qbman_swp_interrupt_read_status(struct qbman_swp *p) -+{ -+ return qbman_read_register(p, QBMAN_CINH_SWP_ISR); -+} -+ -+/** -+ * qbman_swp_interrupt_clear_status() -+ * @p: the given software portal -+ * @mask: The mask to clear in SWP_ISR register -+ */ -+void qbman_swp_interrupt_clear_status(struct qbman_swp *p, u32 mask) -+{ -+ qbman_write_register(p, QBMAN_CINH_SWP_ISR, mask); -+} -+ -+/** -+ * qbman_swp_interrupt_get_trigger() - read interrupt enable register -+ * @p: the given software portal -+ * -+ * Return the value in the SWP_IER register. -+ */ -+u32 qbman_swp_interrupt_get_trigger(struct qbman_swp *p) -+{ -+ return qbman_read_register(p, QBMAN_CINH_SWP_IER); -+} -+ -+/** -+ * qbman_swp_interrupt_set_trigger() - enable interrupts for a swp -+ * @p: the given software portal -+ * @mask: The mask of bits to enable in SWP_IER -+ */ -+void qbman_swp_interrupt_set_trigger(struct qbman_swp *p, u32 mask) -+{ -+ qbman_write_register(p, QBMAN_CINH_SWP_IER, mask); -+} -+ -+/** -+ * qbman_swp_interrupt_get_inhibit() - read interrupt mask register -+ * @p: the given software portal object -+ * -+ * Return the value in the SWP_IIR register. -+ */ -+int qbman_swp_interrupt_get_inhibit(struct qbman_swp *p) -+{ -+ return qbman_read_register(p, QBMAN_CINH_SWP_IIR); -+} -+ -+/** -+ * qbman_swp_interrupt_set_inhibit() - write interrupt mask register -+ * @p: the given software portal object -+ * @mask: The mask to set in SWP_IIR register -+ */ -+void qbman_swp_interrupt_set_inhibit(struct qbman_swp *p, int inhibit) -+{ -+ qbman_write_register(p, QBMAN_CINH_SWP_IIR, inhibit ? 0xffffffff : 0); -+} -+ -+/* -+ * Different management commands all use this common base layer of code to issue -+ * commands and poll for results. -+ */ -+ -+/* -+ * Returns a pointer to where the caller should fill in their management command -+ * (caller should ignore the verb byte) -+ */ -+void *qbman_swp_mc_start(struct qbman_swp *p) -+{ -+ return qbman_get_cmd(p, QBMAN_CENA_SWP_CR); -+} -+ -+/* -+ * Commits merges in the caller-supplied command verb (which should not include -+ * the valid-bit) and submits the command to hardware -+ */ -+void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, u8 cmd_verb) -+{ -+ u8 *v = cmd; -+ -+ dma_wmb(); -+ *v = cmd_verb | p->mc.valid_bit; -+ dccvac(cmd); -+} -+ -+/* -+ * Checks for a completed response (returns non-NULL if only if the response -+ * is complete). -+ */ -+void *qbman_swp_mc_result(struct qbman_swp *p) -+{ -+ u32 *ret, verb; -+ -+ qbman_inval_prefetch(p, QBMAN_CENA_SWP_RR(p->mc.valid_bit)); -+ ret = qbman_get_cmd(p, QBMAN_CENA_SWP_RR(p->mc.valid_bit)); -+ -+ /* Remove the valid-bit - command completed if the rest is non-zero */ -+ verb = ret[0] & ~QB_VALID_BIT; -+ if (!verb) -+ return NULL; -+ p->mc.valid_bit ^= QB_VALID_BIT; -+ return ret; -+} -+ -+#define QB_ENQUEUE_CMD_OPTIONS_SHIFT 0 -+enum qb_enqueue_commands { -+ enqueue_empty = 0, -+ enqueue_response_always = 1, -+ enqueue_rejects_to_fq = 2 -+}; -+ -+#define QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT 2 -+#define QB_ENQUEUE_CMD_IRQ_ON_DISPATCH_SHIFT 3 -+#define QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT 4 -+ -+/** -+ * qbman_eq_desc_clear() - Clear the contents of a descriptor to -+ * default/starting state. -+ */ -+void qbman_eq_desc_clear(struct qbman_eq_desc *d) -+{ -+ memset(d, 0, sizeof(*d)); -+} -+ -+/** -+ * qbman_eq_desc_set_no_orp() - Set enqueue descriptor without orp -+ * @d: the enqueue descriptor. -+ * @response_success: 1 = enqueue with response always; 0 = enqueue with -+ * rejections returned on a FQ. -+ */ -+void qbman_eq_desc_set_no_orp(struct qbman_eq_desc *d, int respond_success) -+{ -+ d->verb &= ~(1 << QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT); -+ if (respond_success) -+ d->verb |= enqueue_response_always; -+ else -+ d->verb |= enqueue_rejects_to_fq; -+} -+ -+/** -+ * qbman_eq_desc_set_orp() - Set order-restoration in the enqueue descriptor -+ * @d: the enqueue descriptor. -+ * @response_success: 1 = enqueue with response always; 0 = enqueue with -+ * rejections returned on a FQ. -+ * @oprid: the order point record id. -+ * @seqnum: the order restoration sequence number. -+ * @incomplete: indicates whether this is the last fragments using the same -+ * sequence number. -+ */ -+void qbman_eq_desc_set_orp(struct qbman_eq_desc *d, int respond_success, -+ u16 oprid, u16 seqnum, int incomplete) -+{ -+ d->verb |= (1 << QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT); -+ if (respond_success) -+ d->verb |= enqueue_response_always; -+ else -+ d->verb |= enqueue_rejects_to_fq; -+ d->orpid = cpu_to_le16(oprid); -+ d->seqnum = cpu_to_le16((!!incomplete << 14) | seqnum); -+} -+ -+/** -+ * qbman_eq_desc_set_orp_hole() - fill a hole in the order-restoration sequence -+ * without any enqueue -+ * @d: the enqueue descriptor. -+ * @oprid: the order point record id. -+ * @seqnum: the order restoration sequence number. -+ */ -+void qbman_eq_desc_set_orp_hole(struct qbman_eq_desc *d, u16 oprid, -+ u16 seqnum) -+{ -+ d->verb |= (1 << QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT) | enqueue_empty; -+ d->orpid = cpu_to_le16(oprid); -+ d->seqnum = cpu_to_le16(seqnum); -+} -+ -+/* -+ * Exactly one of the following descriptor "targets" should be set. (Calling any -+ * one of these will replace the effect of any prior call to one of these.) -+ * -enqueue to a frame queue -+ * -enqueue to a queuing destination -+ */ -+ -+/** -+ * qbman_eq_desc_set_fq() - set the FQ for the enqueue command -+ * @d: the enqueue descriptor -+ * @fqid: the id of the frame queue to be enqueued -+ */ -+void qbman_eq_desc_set_fq(struct qbman_eq_desc *d, u32 fqid) -+{ -+ d->verb &= ~(1 << QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT); -+ d->tgtid = cpu_to_le32(fqid); -+} -+ -+/** -+ * qbman_eq_desc_set_qd() - Set Queuing Destination for the enqueue command -+ * @d: the enqueue descriptor -+ * @qdid: the id of the queuing destination to be enqueued -+ * @qd_bin: the queuing destination bin -+ * @qd_prio: the queuing destination priority -+ */ -+void qbman_eq_desc_set_qd(struct qbman_eq_desc *d, u32 qdid, -+ u32 qd_bin, u32 qd_prio) -+{ -+ d->verb |= 1 << QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT; -+ d->tgtid = cpu_to_le32(qdid); -+ d->qdbin = cpu_to_le16(qd_bin); -+ d->qpri = qd_prio; -+} -+ -+#define EQAR_IDX(eqar) ((eqar) & 0x7) -+#define EQAR_VB(eqar) ((eqar) & 0x80) -+#define EQAR_SUCCESS(eqar) ((eqar) & 0x100) -+ -+/** -+ * qbman_swp_enqueue() - Issue an enqueue command -+ * @s: the software portal used for enqueue -+ * @d: the enqueue descriptor -+ * @fd: the frame descriptor to be enqueued -+ * -+ * Please note that 'fd' should only be NULL if the "action" of the -+ * descriptor is "orp_hole" or "orp_nesn". -+ * -+ * Return 0 for successful enqueue, -EBUSY if the EQCR is not ready. -+ */ -+int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d, -+ const struct dpaa2_fd *fd) -+{ -+ struct qbman_eq_desc *p; -+ u32 eqar = qbman_read_register(s, QBMAN_CINH_SWP_EQAR); -+ -+ if (!EQAR_SUCCESS(eqar)) -+ return -EBUSY; -+ -+ p = qbman_get_cmd(s, QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar))); -+ /* This is mapped as DEVICE type memory, writes are -+ * with address alignment: -+ * desc.dca address alignment = 1 -+ * desc.seqnum address alignment = 2 -+ * desc.orpid address alignment = 4 -+ * desc.tgtid address alignment = 8 -+ */ -+ p->dca = d->dca; -+ p->seqnum = d->seqnum; -+ p->orpid = d->orpid; -+ memcpy(&p->tgtid, &d->tgtid, 24); -+ memcpy(&p->fd, fd, sizeof(*fd)); -+ -+ /* Set the verb byte, have to substitute in the valid-bit */ -+ dma_wmb(); -+ p->verb = d->verb | EQAR_VB(eqar); -+ dccvac(p); -+ -+ return 0; -+} -+ -+/* Static (push) dequeue */ -+ -+/** -+ * qbman_swp_push_get() - Get the push dequeue setup -+ * @p: the software portal object -+ * @channel_idx: the channel index to query -+ * @enabled: returned boolean to show whether the push dequeue is enabled -+ * for the given channel -+ */ -+void qbman_swp_push_get(struct qbman_swp *s, u8 channel_idx, int *enabled) -+{ -+ u16 src = (s->sdq >> QB_SDQCR_SRC_SHIFT) & QB_SDQCR_SRC_MASK; -+ -+ WARN_ON(channel_idx > 15); -+ *enabled = src | (1 << channel_idx); -+} -+ -+/** -+ * qbman_swp_push_set() - Enable or disable push dequeue -+ * @p: the software portal object -+ * @channel_idx: the channel index (0 to 15) -+ * @enable: enable or disable push dequeue -+ */ -+void qbman_swp_push_set(struct qbman_swp *s, u8 channel_idx, int enable) -+{ -+ u16 dqsrc; -+ -+ WARN_ON(channel_idx > 15); -+ if (enable) -+ s->sdq |= 1 << channel_idx; -+ else -+ s->sdq &= ~(1 << channel_idx); -+ -+ /* Read make the complete src map. If no channels are enabled -+ * the SDQCR must be 0 or else QMan will assert errors -+ */ -+ dqsrc = (s->sdq >> QB_SDQCR_SRC_SHIFT) & QB_SDQCR_SRC_MASK; -+ if (dqsrc != 0) -+ qbman_write_register(s, QBMAN_CINH_SWP_SDQCR, s->sdq); -+ else -+ qbman_write_register(s, QBMAN_CINH_SWP_SDQCR, 0); -+} -+ -+#define QB_VDQCR_VERB_DCT_SHIFT 0 -+#define QB_VDQCR_VERB_DT_SHIFT 2 -+#define QB_VDQCR_VERB_RLS_SHIFT 4 -+#define QB_VDQCR_VERB_WAE_SHIFT 5 -+ -+enum qb_pull_dt_e { -+ qb_pull_dt_channel, -+ qb_pull_dt_workqueue, -+ qb_pull_dt_framequeue -+}; -+ -+/** -+ * qbman_pull_desc_clear() - Clear the contents of a descriptor to -+ * default/starting state -+ * @d: the pull dequeue descriptor to be cleared -+ */ -+void qbman_pull_desc_clear(struct qbman_pull_desc *d) -+{ -+ memset(d, 0, sizeof(*d)); -+} -+ -+/** -+ * qbman_pull_desc_set_storage()- Set the pull dequeue storage -+ * @d: the pull dequeue descriptor to be set -+ * @storage: the pointer of the memory to store the dequeue result -+ * @storage_phys: the physical address of the storage memory -+ * @stash: to indicate whether write allocate is enabled -+ * -+ * If not called, or if called with 'storage' as NULL, the result pull dequeues -+ * will produce results to DQRR. If 'storage' is non-NULL, then results are -+ * produced to the given memory location (using the DMA address which -+ * the caller provides in 'storage_phys'), and 'stash' controls whether or not -+ * those writes to main-memory express a cache-warming attribute. -+ */ -+void qbman_pull_desc_set_storage(struct qbman_pull_desc *d, -+ struct dpaa2_dq *storage, -+ dma_addr_t storage_phys, -+ int stash) -+{ -+ /* save the virtual address */ -+ d->rsp_addr_virt = (u64)(uintptr_t)storage; -+ -+ if (!storage) { -+ d->verb &= ~(1 << QB_VDQCR_VERB_RLS_SHIFT); -+ return; -+ } -+ d->verb |= 1 << QB_VDQCR_VERB_RLS_SHIFT; -+ if (stash) -+ d->verb |= 1 << QB_VDQCR_VERB_WAE_SHIFT; -+ else -+ d->verb &= ~(1 << QB_VDQCR_VERB_WAE_SHIFT); -+ -+ d->rsp_addr = cpu_to_le64(storage_phys); -+} -+ -+/** -+ * qbman_pull_desc_set_numframes() - Set the number of frames to be dequeued -+ * @d: the pull dequeue descriptor to be set -+ * @numframes: number of frames to be set, must be between 1 and 16, inclusive -+ */ -+void qbman_pull_desc_set_numframes(struct qbman_pull_desc *d, u8 numframes) -+{ -+ d->numf = numframes - 1; -+} -+ -+void qbman_pull_desc_set_token(struct qbman_pull_desc *d, u8 token) -+{ -+ d->tok = token; -+} -+ -+/* -+ * Exactly one of the following descriptor "actions" should be set. (Calling any -+ * one of these will replace the effect of any prior call to one of these.) -+ * - pull dequeue from the given frame queue (FQ) -+ * - pull dequeue from any FQ in the given work queue (WQ) -+ * - pull dequeue from any FQ in any WQ in the given channel -+ */ -+ -+/** -+ * qbman_pull_desc_set_fq() - Set fqid from which the dequeue command dequeues -+ * @fqid: the frame queue index of the given FQ -+ */ -+void qbman_pull_desc_set_fq(struct qbman_pull_desc *d, u32 fqid) -+{ -+ d->verb |= 1 << QB_VDQCR_VERB_DCT_SHIFT; -+ d->verb |= qb_pull_dt_framequeue << QB_VDQCR_VERB_DT_SHIFT; -+ d->dq_src = cpu_to_le32(fqid); -+} -+ -+/** -+ * qbman_pull_desc_set_wq() - Set wqid from which the dequeue command dequeues -+ * @wqid: composed of channel id and wqid within the channel -+ * @dct: the dequeue command type -+ */ -+void qbman_pull_desc_set_wq(struct qbman_pull_desc *d, u32 wqid, -+ enum qbman_pull_type_e dct) -+{ -+ d->verb |= dct << QB_VDQCR_VERB_DCT_SHIFT; -+ d->verb |= qb_pull_dt_workqueue << QB_VDQCR_VERB_DT_SHIFT; -+ d->dq_src = cpu_to_le32(wqid); -+} -+ -+/** -+ * qbman_pull_desc_set_channel() - Set channelid from which the dequeue command -+ * dequeues -+ * @chid: the channel id to be dequeued -+ * @dct: the dequeue command type -+ */ -+void qbman_pull_desc_set_channel(struct qbman_pull_desc *d, u32 chid, -+ enum qbman_pull_type_e dct) -+{ -+ d->verb |= dct << QB_VDQCR_VERB_DCT_SHIFT; -+ d->verb |= qb_pull_dt_channel << QB_VDQCR_VERB_DT_SHIFT; -+ d->dq_src = cpu_to_le32(chid); -+} -+ -+/** -+ * qbman_swp_pull() - Issue the pull dequeue command -+ * @s: the software portal object -+ * @d: the software portal descriptor which has been configured with -+ * the set of qbman_pull_desc_set_*() calls -+ * -+ * Return 0 for success, and -EBUSY if the software portal is not ready -+ * to do pull dequeue. -+ */ -+int qbman_swp_pull(struct qbman_swp *s, struct qbman_pull_desc *d) -+{ -+ struct qbman_pull_desc *p; -+ -+ if (!atomic_dec_and_test(&s->vdq.available)) { -+ atomic_inc(&s->vdq.available); -+ return -EBUSY; -+ } -+ s->vdq.storage = (void *)(uintptr_t)d->rsp_addr_virt; -+ p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR); -+ p->numf = d->numf; -+ p->tok = QMAN_DQ_TOKEN_VALID; -+ p->dq_src = d->dq_src; -+ p->rsp_addr = d->rsp_addr; -+ p->rsp_addr_virt = d->rsp_addr_virt; -+ dma_wmb(); -+ -+ /* Set the verb byte, have to substitute in the valid-bit */ -+ p->verb = d->verb | s->vdq.valid_bit; -+ s->vdq.valid_bit ^= QB_VALID_BIT; -+ dccvac(p); -+ -+ return 0; -+} -+ -+#define QMAN_DQRR_PI_MASK 0xf -+ -+/** -+ * qbman_swp_dqrr_next() - Get an valid DQRR entry -+ * @s: the software portal object -+ * -+ * Return NULL if there are no unconsumed DQRR entries. Return a DQRR entry -+ * only once, so repeated calls can return a sequence of DQRR entries, without -+ * requiring they be consumed immediately or in any particular order. -+ */ -+const struct dpaa2_dq *qbman_swp_dqrr_next(struct qbman_swp *s) -+{ -+ u32 verb; -+ u32 response_verb; -+ u32 flags; -+ struct dpaa2_dq *p; -+ -+ /* Before using valid-bit to detect if something is there, we have to -+ * handle the case of the DQRR reset bug... -+ */ -+ if (unlikely(s->dqrr.reset_bug)) { -+ /* -+ * We pick up new entries by cache-inhibited producer index, -+ * which means that a non-coherent mapping would require us to -+ * invalidate and read *only* once that PI has indicated that -+ * there's an entry here. The first trip around the DQRR ring -+ * will be much less efficient than all subsequent trips around -+ * it... -+ */ -+ u8 pi = qbman_read_register(s, QBMAN_CINH_SWP_DQPI) & -+ QMAN_DQRR_PI_MASK; -+ -+ /* there are new entries if pi != next_idx */ -+ if (pi == s->dqrr.next_idx) -+ return NULL; -+ -+ /* -+ * if next_idx is/was the last ring index, and 'pi' is -+ * different, we can disable the workaround as all the ring -+ * entries have now been DMA'd to so valid-bit checking is -+ * repaired. Note: this logic needs to be based on next_idx -+ * (which increments one at a time), rather than on pi (which -+ * can burst and wrap-around between our snapshots of it). -+ */ -+ if (s->dqrr.next_idx == (s->dqrr.dqrr_size - 1)) { -+ pr_debug("next_idx=%d, pi=%d, clear reset bug\n", -+ s->dqrr.next_idx, pi); -+ s->dqrr.reset_bug = 0; -+ } -+ qbman_inval_prefetch(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)); -+ } -+ -+ p = qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)); -+ verb = p->dq.verb; -+ -+ /* -+ * If the valid-bit isn't of the expected polarity, nothing there. Note, -+ * in the DQRR reset bug workaround, we shouldn't need to skip these -+ * check, because we've already determined that a new entry is available -+ * and we've invalidated the cacheline before reading it, so the -+ * valid-bit behaviour is repaired and should tell us what we already -+ * knew from reading PI. -+ */ -+ if ((verb & QB_VALID_BIT) != s->dqrr.valid_bit) { -+ qbman_inval_prefetch(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)); -+ return NULL; -+ } -+ /* -+ * There's something there. Move "next_idx" attention to the next ring -+ * entry (and prefetch it) before returning what we found. -+ */ -+ s->dqrr.next_idx++; -+ s->dqrr.next_idx &= s->dqrr.dqrr_size - 1; /* Wrap around */ -+ if (!s->dqrr.next_idx) -+ s->dqrr.valid_bit ^= QB_VALID_BIT; -+ -+ /* -+ * If this is the final response to a volatile dequeue command -+ * indicate that the vdq is available -+ */ -+ flags = p->dq.stat; -+ response_verb = verb & QBMAN_RESULT_MASK; -+ if ((response_verb == QBMAN_RESULT_DQ) && -+ (flags & DPAA2_DQ_STAT_VOLATILE) && -+ (flags & DPAA2_DQ_STAT_EXPIRED)) -+ atomic_inc(&s->vdq.available); -+ -+ qbman_inval_prefetch(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)); -+ -+ return p; -+} -+ -+/** -+ * qbman_swp_dqrr_consume() - Consume DQRR entries previously returned from -+ * qbman_swp_dqrr_next(). -+ * @s: the software portal object -+ * @dq: the DQRR entry to be consumed -+ */ -+void qbman_swp_dqrr_consume(struct qbman_swp *s, const struct dpaa2_dq *dq) -+{ -+ qbman_write_register(s, QBMAN_CINH_SWP_DCAP, QBMAN_IDX_FROM_DQRR(dq)); -+} -+ -+/** -+ * qbman_result_has_new_result() - Check and get the dequeue response from the -+ * dq storage memory set in pull dequeue command -+ * @s: the software portal object -+ * @dq: the dequeue result read from the memory -+ * -+ * Return 1 for getting a valid dequeue result, or 0 for not getting a valid -+ * dequeue result. -+ * -+ * Only used for user-provided storage of dequeue results, not DQRR. For -+ * efficiency purposes, the driver will perform any required endianness -+ * conversion to ensure that the user's dequeue result storage is in host-endian -+ * format. As such, once the user has called qbman_result_has_new_result() and -+ * been returned a valid dequeue result, they should not call it again on -+ * the same memory location (except of course if another dequeue command has -+ * been executed to produce a new result to that location). -+ */ -+int qbman_result_has_new_result(struct qbman_swp *s, const struct dpaa2_dq *dq) -+{ -+ if (dq->dq.tok != QMAN_DQ_TOKEN_VALID) -+ return 0; -+ -+ /* -+ * Set token to be 0 so we will detect change back to 1 -+ * next time the looping is traversed. Const is cast away here -+ * as we want users to treat the dequeue responses as read only. -+ */ -+ ((struct dpaa2_dq *)dq)->dq.tok = 0; -+ -+ /* -+ * Determine whether VDQCR is available based on whether the -+ * current result is sitting in the first storage location of -+ * the busy command. -+ */ -+ if (s->vdq.storage == dq) { -+ s->vdq.storage = NULL; -+ atomic_inc(&s->vdq.available); -+ } -+ -+ return 1; -+} -+ -+/** -+ * qbman_release_desc_clear() - Clear the contents of a descriptor to -+ * default/starting state. -+ */ -+void qbman_release_desc_clear(struct qbman_release_desc *d) -+{ -+ memset(d, 0, sizeof(*d)); -+ d->verb = 1 << 5; /* Release Command Valid */ -+} -+ -+/** -+ * qbman_release_desc_set_bpid() - Set the ID of the buffer pool to release to -+ */ -+void qbman_release_desc_set_bpid(struct qbman_release_desc *d, u16 bpid) -+{ -+ d->bpid = cpu_to_le16(bpid); -+} -+ -+/** -+ * qbman_release_desc_set_rcdi() - Determines whether or not the portal's RCDI -+ * interrupt source should be asserted after the release command is completed. -+ */ -+void qbman_release_desc_set_rcdi(struct qbman_release_desc *d, int enable) -+{ -+ if (enable) -+ d->verb |= 1 << 6; -+ else -+ d->verb &= ~(1 << 6); -+} -+ -+#define RAR_IDX(rar) ((rar) & 0x7) -+#define RAR_VB(rar) ((rar) & 0x80) -+#define RAR_SUCCESS(rar) ((rar) & 0x100) -+ -+/** -+ * qbman_swp_release() - Issue a buffer release command -+ * @s: the software portal object -+ * @d: the release descriptor -+ * @buffers: a pointer pointing to the buffer address to be released -+ * @num_buffers: number of buffers to be released, must be less than 8 -+ * -+ * Return 0 for success, -EBUSY if the release command ring is not ready. -+ */ -+int qbman_swp_release(struct qbman_swp *s, const struct qbman_release_desc *d, -+ const u64 *buffers, unsigned int num_buffers) -+{ -+ int i; -+ struct qbman_release_desc *p; -+ u32 rar; -+ -+ if (!num_buffers || (num_buffers > 7)) -+ return -EINVAL; -+ -+ rar = qbman_read_register(s, QBMAN_CINH_SWP_RAR); -+ if (!RAR_SUCCESS(rar)) -+ return -EBUSY; -+ -+ /* Start the release command */ -+ p = qbman_get_cmd(s, QBMAN_CENA_SWP_RCR(RAR_IDX(rar))); -+ /* Copy the caller's buffer pointers to the command */ -+ for (i = 0; i < num_buffers; i++) -+ p->buf[i] = cpu_to_le64(buffers[i]); -+ p->bpid = d->bpid; -+ -+ /* -+ * Set the verb byte, have to substitute in the valid-bit and the number -+ * of buffers. -+ */ -+ dma_wmb(); -+ p->verb = d->verb | RAR_VB(rar) | num_buffers; -+ dccvac(p); -+ -+ return 0; -+} -+ -+struct qbman_acquire_desc { -+ u8 verb; -+ u8 reserved; -+ __le16 bpid; -+ u8 num; -+ u8 reserved2[59]; -+}; -+ -+struct qbman_acquire_rslt { -+ u8 verb; -+ u8 rslt; -+ __le16 reserved; -+ u8 num; -+ u8 reserved2[3]; -+ __le64 buf[7]; -+}; -+ -+/** -+ * qbman_swp_acquire() - Issue a buffer acquire command -+ * @s: the software portal object -+ * @bpid: the buffer pool index -+ * @buffers: a pointer pointing to the acquired buffer addresses -+ * @num_buffers: number of buffers to be acquired, must be less than 8 -+ * -+ * Return 0 for success, or negative error code if the acquire command -+ * fails. -+ */ -+int qbman_swp_acquire(struct qbman_swp *s, u16 bpid, u64 *buffers, -+ unsigned int num_buffers) -+{ -+ struct qbman_acquire_desc *p; -+ struct qbman_acquire_rslt *r; -+ int i; -+ -+ if (!num_buffers || (num_buffers > 7)) -+ return -EINVAL; -+ -+ /* Start the management command */ -+ p = qbman_swp_mc_start(s); -+ -+ if (!p) -+ return -EBUSY; -+ -+ /* Encode the caller-provided attributes */ -+ p->bpid = cpu_to_le16(bpid); -+ p->num = num_buffers; -+ -+ /* Complete the management command */ -+ r = qbman_swp_mc_complete(s, p, QBMAN_MC_ACQUIRE); -+ if (unlikely(!r)) { -+ pr_err("qbman: acquire from BPID %d failed, no response\n", -+ bpid); -+ return -EIO; -+ } -+ -+ /* Decode the outcome */ -+ WARN_ON((r->verb & 0x7f) != QBMAN_MC_ACQUIRE); -+ -+ /* Determine success or failure */ -+ if (unlikely(r->rslt != QBMAN_MC_RSLT_OK)) { -+ pr_err("qbman: acquire from BPID 0x%x failed, code=0x%02x\n", -+ bpid, r->rslt); -+ return -EIO; -+ } -+ -+ WARN_ON(r->num > num_buffers); -+ -+ /* Copy the acquired buffers to the caller's array */ -+ for (i = 0; i < r->num; i++) -+ buffers[i] = le64_to_cpu(r->buf[i]); -+ -+ return (int)r->num; -+} -+ -+struct qbman_alt_fq_state_desc { -+ u8 verb; -+ u8 reserved[3]; -+ __le32 fqid; -+ u8 reserved2[56]; -+}; -+ -+struct qbman_alt_fq_state_rslt { -+ u8 verb; -+ u8 rslt; -+ u8 reserved[62]; -+}; -+ -+#define ALT_FQ_FQID_MASK 0x00FFFFFF -+ -+int qbman_swp_alt_fq_state(struct qbman_swp *s, u32 fqid, -+ u8 alt_fq_verb) -+{ -+ struct qbman_alt_fq_state_desc *p; -+ struct qbman_alt_fq_state_rslt *r; -+ -+ /* Start the management command */ -+ p = qbman_swp_mc_start(s); -+ if (!p) -+ return -EBUSY; -+ -+ p->fqid = cpu_to_le32(fqid & ALT_FQ_FQID_MASK); -+ -+ /* Complete the management command */ -+ r = qbman_swp_mc_complete(s, p, alt_fq_verb); -+ if (unlikely(!r)) { -+ pr_err("qbman: mgmt cmd failed, no response (verb=0x%x)\n", -+ alt_fq_verb); -+ return -EIO; -+ } -+ -+ /* Decode the outcome */ -+ WARN_ON((r->verb & QBMAN_RESULT_MASK) != alt_fq_verb); -+ -+ /* Determine success or failure */ -+ if (unlikely(r->rslt != QBMAN_MC_RSLT_OK)) { -+ pr_err("qbman: ALT FQID %d failed: verb = 0x%08x code = 0x%02x\n", -+ fqid, r->verb, r->rslt); -+ return -EIO; -+ } -+ -+ return 0; -+} -+ -+struct qbman_cdan_ctrl_desc { -+ u8 verb; -+ u8 reserved; -+ __le16 ch; -+ u8 we; -+ u8 ctrl; -+ __le16 reserved2; -+ __le64 cdan_ctx; -+ u8 reserved3[48]; -+ -+}; -+ -+struct qbman_cdan_ctrl_rslt { -+ u8 verb; -+ u8 rslt; -+ __le16 ch; -+ u8 reserved[60]; -+}; -+ -+int qbman_swp_CDAN_set(struct qbman_swp *s, u16 channelid, -+ u8 we_mask, u8 cdan_en, -+ u64 ctx) -+{ -+ struct qbman_cdan_ctrl_desc *p = NULL; -+ struct qbman_cdan_ctrl_rslt *r = NULL; -+ -+ /* Start the management command */ -+ p = qbman_swp_mc_start(s); -+ if (!p) -+ return -EBUSY; -+ -+ /* Encode the caller-provided attributes */ -+ p->ch = cpu_to_le16(channelid); -+ p->we = we_mask; -+ if (cdan_en) -+ p->ctrl = 1; -+ else -+ p->ctrl = 0; -+ p->cdan_ctx = cpu_to_le64(ctx); -+ -+ /* Complete the management command */ -+ r = qbman_swp_mc_complete(s, p, QBMAN_WQCHAN_CONFIGURE); -+ if (unlikely(!r)) { -+ pr_err("qbman: wqchan config failed, no response\n"); -+ return -EIO; -+ } -+ -+ WARN_ON((r->verb & 0x7f) != QBMAN_WQCHAN_CONFIGURE); -+ -+ /* Determine success or failure */ -+ if (unlikely(r->rslt != QBMAN_MC_RSLT_OK)) { -+ pr_err("qbman: CDAN cQID %d failed: code = 0x%02x\n", -+ channelid, r->rslt); -+ return -EIO; -+ } -+ -+ return 0; -+} -+ -+#define QBMAN_RESPONSE_VERB_MASK 0x7f -+#define QBMAN_FQ_QUERY_NP 0x45 -+#define QBMAN_BP_QUERY 0x32 -+ -+struct qbman_fq_query_desc { -+ u8 verb; -+ u8 reserved[3]; -+ u32 fqid; -+ u8 reserved2[56]; -+}; -+ -+int qbman_fq_query_state(struct qbman_swp *s, u32 fqid, -+ struct qbman_fq_query_np_rslt *r) -+{ -+ struct qbman_fq_query_desc *p; -+ void *resp; -+ -+ p = (struct qbman_fq_query_desc *)qbman_swp_mc_start(s); -+ if (!p) -+ return -EBUSY; -+ -+ /* FQID is a 24 bit value */ -+ p->fqid = cpu_to_le32(fqid) & 0x00FFFFFF; -+ resp = qbman_swp_mc_complete(s, p, QBMAN_FQ_QUERY_NP); -+ if (!resp) { -+ pr_err("qbman: Query FQID %d NP fields failed, no response\n", -+ fqid); -+ return -EIO; -+ } -+ *r = *(struct qbman_fq_query_np_rslt *)resp; -+ /* Decode the outcome */ -+ WARN_ON((r->verb & QBMAN_RESPONSE_VERB_MASK) != QBMAN_FQ_QUERY_NP); -+ -+ /* Determine success or failure */ -+ if (r->rslt != QBMAN_MC_RSLT_OK) { -+ pr_err("Query NP fields of FQID 0x%x failed, code=0x%02x\n", -+ p->fqid, r->rslt); -+ return -EIO; -+ } -+ -+ return 0; -+} -+ -+u32 qbman_fq_state_frame_count(const struct qbman_fq_query_np_rslt *r) -+{ -+ return (r->frm_cnt & 0x00FFFFFF); -+} -+ -+u32 qbman_fq_state_byte_count(const struct qbman_fq_query_np_rslt *r) -+{ -+ return r->byte_cnt; -+} -+ -+struct qbman_bp_query_desc { -+ u8 verb; -+ u8 reserved; -+ u16 bpid; -+ u8 reserved2[60]; -+}; -+ -+int qbman_bp_query(struct qbman_swp *s, u32 bpid, -+ struct qbman_bp_query_rslt *r) -+{ -+ struct qbman_bp_query_desc *p; -+ void *resp; -+ -+ p = (struct qbman_bp_query_desc *)qbman_swp_mc_start(s); -+ if (!p) -+ return -EBUSY; -+ -+ p->bpid = bpid; -+ resp = qbman_swp_mc_complete(s, p, QBMAN_BP_QUERY); -+ if (!resp) { -+ pr_err("qbman: Query BPID %d fields failed, no response\n", -+ bpid); -+ return -EIO; -+ } -+ *r = *(struct qbman_bp_query_rslt *)resp; -+ /* Decode the outcome */ -+ WARN_ON((r->verb & QBMAN_RESPONSE_VERB_MASK) != QBMAN_BP_QUERY); -+ -+ /* Determine success or failure */ -+ if (r->rslt != QBMAN_MC_RSLT_OK) { -+ pr_err("Query fields of BPID 0x%x failed, code=0x%02x\n", -+ bpid, r->rslt); -+ return -EIO; -+ } -+ -+ return 0; -+} -+ -+u32 qbman_bp_info_num_free_bufs(struct qbman_bp_query_rslt *a) -+{ -+ return a->fill; -+} ---- /dev/null -+++ b/drivers/staging/fsl-mc/bus/dpio/qbman-portal.h -@@ -0,0 +1,505 @@ -+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ -+/* -+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. -+ * Copyright 2016 NXP -+ * -+ */ -+#ifndef __FSL_QBMAN_PORTAL_H -+#define __FSL_QBMAN_PORTAL_H -+ -+#include "../../include/dpaa2-fd.h" -+ -+struct dpaa2_dq; -+struct qbman_swp; -+ -+/* qbman software portal descriptor structure */ -+struct qbman_swp_desc { -+ void *cena_bar; /* Cache-enabled portal base address */ -+ void *cinh_bar; /* Cache-inhibited portal base address */ -+ u32 qman_version; -+}; -+ -+#define QBMAN_SWP_INTERRUPT_EQRI 0x01 -+#define QBMAN_SWP_INTERRUPT_EQDI 0x02 -+#define QBMAN_SWP_INTERRUPT_DQRI 0x04 -+#define QBMAN_SWP_INTERRUPT_RCRI 0x08 -+#define QBMAN_SWP_INTERRUPT_RCDI 0x10 -+#define QBMAN_SWP_INTERRUPT_VDCI 0x20 -+ -+/* the structure for pull dequeue descriptor */ -+struct qbman_pull_desc { -+ u8 verb; -+ u8 numf; -+ u8 tok; -+ u8 reserved; -+ __le32 dq_src; -+ __le64 rsp_addr; -+ u64 rsp_addr_virt; -+ u8 padding[40]; -+}; -+ -+enum qbman_pull_type_e { -+ /* dequeue with priority precedence, respect intra-class scheduling */ -+ qbman_pull_type_prio = 1, -+ /* dequeue with active FQ precedence, respect ICS */ -+ qbman_pull_type_active, -+ /* dequeue with active FQ precedence, no ICS */ -+ qbman_pull_type_active_noics -+}; -+ -+/* Definitions for parsing dequeue entries */ -+#define QBMAN_RESULT_MASK 0x7f -+#define QBMAN_RESULT_DQ 0x60 -+#define QBMAN_RESULT_FQRN 0x21 -+#define QBMAN_RESULT_FQRNI 0x22 -+#define QBMAN_RESULT_FQPN 0x24 -+#define QBMAN_RESULT_FQDAN 0x25 -+#define QBMAN_RESULT_CDAN 0x26 -+#define QBMAN_RESULT_CSCN_MEM 0x27 -+#define QBMAN_RESULT_CGCU 0x28 -+#define QBMAN_RESULT_BPSCN 0x29 -+#define QBMAN_RESULT_CSCN_WQ 0x2a -+ -+/* QBMan FQ management command codes */ -+#define QBMAN_FQ_SCHEDULE 0x48 -+#define QBMAN_FQ_FORCE 0x49 -+#define QBMAN_FQ_XON 0x4d -+#define QBMAN_FQ_XOFF 0x4e -+ -+/* structure of enqueue descriptor */ -+struct qbman_eq_desc { -+ u8 verb; -+ u8 dca; -+ __le16 seqnum; -+ __le16 orpid; -+ __le16 reserved1; -+ __le32 tgtid; -+ __le32 tag; -+ __le16 qdbin; -+ u8 qpri; -+ u8 reserved[3]; -+ u8 wae; -+ u8 rspid; -+ __le64 rsp_addr; -+ u8 fd[32]; -+}; -+ -+/* buffer release descriptor */ -+struct qbman_release_desc { -+ u8 verb; -+ u8 reserved; -+ __le16 bpid; -+ __le32 reserved2; -+ __le64 buf[7]; -+}; -+ -+/* Management command result codes */ -+#define QBMAN_MC_RSLT_OK 0xf0 -+ -+#define CODE_CDAN_WE_EN 0x1 -+#define CODE_CDAN_WE_CTX 0x4 -+ -+/* portal data structure */ -+struct qbman_swp { -+ const struct qbman_swp_desc *desc; -+ void __iomem *addr_cena; -+ void __iomem *addr_cinh; -+ -+ /* Management commands */ -+ struct { -+ u32 valid_bit; /* 0x00 or 0x80 */ -+ } mc; -+ -+ /* Push dequeues */ -+ u32 sdq; -+ -+ /* Volatile dequeues */ -+ struct { -+ atomic_t available; /* indicates if a command can be sent */ -+ u32 valid_bit; /* 0x00 or 0x80 */ -+ struct dpaa2_dq *storage; /* NULL if DQRR */ -+ } vdq; -+ -+ /* DQRR */ -+ struct { -+ u32 next_idx; -+ u32 valid_bit; -+ u8 dqrr_size; -+ int reset_bug; /* indicates dqrr reset workaround is needed */ -+ } dqrr; -+}; -+ -+struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d); -+void qbman_swp_finish(struct qbman_swp *p); -+u32 qbman_swp_interrupt_read_status(struct qbman_swp *p); -+void qbman_swp_interrupt_clear_status(struct qbman_swp *p, u32 mask); -+u32 qbman_swp_interrupt_get_trigger(struct qbman_swp *p); -+void qbman_swp_interrupt_set_trigger(struct qbman_swp *p, u32 mask); -+int qbman_swp_interrupt_get_inhibit(struct qbman_swp *p); -+void qbman_swp_interrupt_set_inhibit(struct qbman_swp *p, int inhibit); -+ -+void qbman_swp_push_get(struct qbman_swp *p, u8 channel_idx, int *enabled); -+void qbman_swp_push_set(struct qbman_swp *p, u8 channel_idx, int enable); -+ -+void qbman_pull_desc_clear(struct qbman_pull_desc *d); -+void qbman_pull_desc_set_storage(struct qbman_pull_desc *d, -+ struct dpaa2_dq *storage, -+ dma_addr_t storage_phys, -+ int stash); -+void qbman_pull_desc_set_numframes(struct qbman_pull_desc *d, u8 numframes); -+void qbman_pull_desc_set_fq(struct qbman_pull_desc *d, u32 fqid); -+void qbman_pull_desc_set_wq(struct qbman_pull_desc *d, u32 wqid, -+ enum qbman_pull_type_e dct); -+void qbman_pull_desc_set_channel(struct qbman_pull_desc *d, u32 chid, -+ enum qbman_pull_type_e dct); -+ -+int qbman_swp_pull(struct qbman_swp *p, struct qbman_pull_desc *d); -+ -+const struct dpaa2_dq *qbman_swp_dqrr_next(struct qbman_swp *s); -+void qbman_swp_dqrr_consume(struct qbman_swp *s, const struct dpaa2_dq *dq); -+ -+int qbman_result_has_new_result(struct qbman_swp *p, const struct dpaa2_dq *dq); -+ -+void qbman_eq_desc_clear(struct qbman_eq_desc *d); -+void qbman_eq_desc_set_no_orp(struct qbman_eq_desc *d, int respond_success); -+void qbman_eq_desc_set_orp(struct qbman_eq_desc *d, int respond_success, -+ u16 oprid, u16 seqnum, int incomplete); -+void qbman_eq_desc_set_orp_hole(struct qbman_eq_desc *d, u16 oprid, u16 seqnum); -+void qbman_eq_desc_set_token(struct qbman_eq_desc *d, u8 token); -+void qbman_eq_desc_set_fq(struct qbman_eq_desc *d, u32 fqid); -+void qbman_eq_desc_set_qd(struct qbman_eq_desc *d, u32 qdid, -+ u32 qd_bin, u32 qd_prio); -+ -+int qbman_swp_enqueue(struct qbman_swp *p, const struct qbman_eq_desc *d, -+ const struct dpaa2_fd *fd); -+ -+void qbman_release_desc_clear(struct qbman_release_desc *d); -+void qbman_release_desc_set_bpid(struct qbman_release_desc *d, u16 bpid); -+void qbman_release_desc_set_rcdi(struct qbman_release_desc *d, int enable); -+ -+int qbman_swp_release(struct qbman_swp *s, const struct qbman_release_desc *d, -+ const u64 *buffers, unsigned int num_buffers); -+int qbman_swp_acquire(struct qbman_swp *s, u16 bpid, u64 *buffers, -+ unsigned int num_buffers); -+int qbman_swp_alt_fq_state(struct qbman_swp *s, u32 fqid, -+ u8 alt_fq_verb); -+int qbman_swp_CDAN_set(struct qbman_swp *s, u16 channelid, -+ u8 we_mask, u8 cdan_en, -+ u64 ctx); -+ -+void *qbman_swp_mc_start(struct qbman_swp *p); -+void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, u8 cmd_verb); -+void *qbman_swp_mc_result(struct qbman_swp *p); -+ -+/** -+ * qbman_result_is_DQ() - check if the dequeue result is a dequeue response -+ * @dq: the dequeue result to be checked -+ * -+ * DQRR entries may contain non-dequeue results, ie. notifications -+ */ -+static inline int qbman_result_is_DQ(const struct dpaa2_dq *dq) -+{ -+ return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_DQ); -+} -+ -+/** -+ * qbman_result_is_SCN() - Check the dequeue result is notification or not -+ * @dq: the dequeue result to be checked -+ * -+ */ -+static inline int qbman_result_is_SCN(const struct dpaa2_dq *dq) -+{ -+ return !qbman_result_is_DQ(dq); -+} -+ -+/* FQ Data Availability */ -+static inline int qbman_result_is_FQDAN(const struct dpaa2_dq *dq) -+{ -+ return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_FQDAN); -+} -+ -+/* Channel Data Availability */ -+static inline int qbman_result_is_CDAN(const struct dpaa2_dq *dq) -+{ -+ return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_CDAN); -+} -+ -+/* Congestion State Change */ -+static inline int qbman_result_is_CSCN(const struct dpaa2_dq *dq) -+{ -+ return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_CSCN_WQ); -+} -+ -+/* Buffer Pool State Change */ -+static inline int qbman_result_is_BPSCN(const struct dpaa2_dq *dq) -+{ -+ return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_BPSCN); -+} -+ -+/* Congestion Group Count Update */ -+static inline int qbman_result_is_CGCU(const struct dpaa2_dq *dq) -+{ -+ return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_CGCU); -+} -+ -+/* Retirement */ -+static inline int qbman_result_is_FQRN(const struct dpaa2_dq *dq) -+{ -+ return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_FQRN); -+} -+ -+/* Retirement Immediate */ -+static inline int qbman_result_is_FQRNI(const struct dpaa2_dq *dq) -+{ -+ return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_FQRNI); -+} -+ -+ /* Park */ -+static inline int qbman_result_is_FQPN(const struct dpaa2_dq *dq) -+{ -+ return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_FQPN); -+} -+ -+/** -+ * qbman_result_SCN_state() - Get the state field in State-change notification -+ */ -+static inline u8 qbman_result_SCN_state(const struct dpaa2_dq *scn) -+{ -+ return scn->scn.state; -+} -+ -+#define SCN_RID_MASK 0x00FFFFFF -+ -+/** -+ * qbman_result_SCN_rid() - Get the resource id in State-change notification -+ */ -+static inline u32 qbman_result_SCN_rid(const struct dpaa2_dq *scn) -+{ -+ return le32_to_cpu(scn->scn.rid_tok) & SCN_RID_MASK; -+} -+ -+/** -+ * qbman_result_SCN_ctx() - Get the context data in State-change notification -+ */ -+static inline u64 qbman_result_SCN_ctx(const struct dpaa2_dq *scn) -+{ -+ return le64_to_cpu(scn->scn.ctx); -+} -+ -+/** -+ * qbman_swp_fq_schedule() - Move the fq to the scheduled state -+ * @s: the software portal object -+ * @fqid: the index of frame queue to be scheduled -+ * -+ * There are a couple of different ways that a FQ can end up parked state, -+ * This schedules it. -+ * -+ * Return 0 for success, or negative error code for failure. -+ */ -+static inline int qbman_swp_fq_schedule(struct qbman_swp *s, u32 fqid) -+{ -+ return qbman_swp_alt_fq_state(s, fqid, QBMAN_FQ_SCHEDULE); -+} -+ -+/** -+ * qbman_swp_fq_force() - Force the FQ to fully scheduled state -+ * @s: the software portal object -+ * @fqid: the index of frame queue to be forced -+ * -+ * Force eligible will force a tentatively-scheduled FQ to be fully-scheduled -+ * and thus be available for selection by any channel-dequeuing behaviour (push -+ * or pull). If the FQ is subsequently "dequeued" from the channel and is still -+ * empty at the time this happens, the resulting dq_entry will have no FD. -+ * (qbman_result_DQ_fd() will return NULL.) -+ * -+ * Return 0 for success, or negative error code for failure. -+ */ -+static inline int qbman_swp_fq_force(struct qbman_swp *s, u32 fqid) -+{ -+ return qbman_swp_alt_fq_state(s, fqid, QBMAN_FQ_FORCE); -+} -+ -+/** -+ * qbman_swp_fq_xon() - sets FQ flow-control to XON -+ * @s: the software portal object -+ * @fqid: the index of frame queue -+ * -+ * This setting doesn't affect enqueues to the FQ, just dequeues. -+ * -+ * Return 0 for success, or negative error code for failure. -+ */ -+static inline int qbman_swp_fq_xon(struct qbman_swp *s, u32 fqid) -+{ -+ return qbman_swp_alt_fq_state(s, fqid, QBMAN_FQ_XON); -+} -+ -+/** -+ * qbman_swp_fq_xoff() - sets FQ flow-control to XOFF -+ * @s: the software portal object -+ * @fqid: the index of frame queue -+ * -+ * This setting doesn't affect enqueues to the FQ, just dequeues. -+ * XOFF FQs will remain in the tenatively-scheduled state, even when -+ * non-empty, meaning they won't be selected for scheduled dequeuing. -+ * If a FQ is changed to XOFF after it had already become truly-scheduled -+ * to a channel, and a pull dequeue of that channel occurs that selects -+ * that FQ for dequeuing, then the resulting dq_entry will have no FD. -+ * (qbman_result_DQ_fd() will return NULL.) -+ * -+ * Return 0 for success, or negative error code for failure. -+ */ -+static inline int qbman_swp_fq_xoff(struct qbman_swp *s, u32 fqid) -+{ -+ return qbman_swp_alt_fq_state(s, fqid, QBMAN_FQ_XOFF); -+} -+ -+/* If the user has been allocated a channel object that is going to generate -+ * CDANs to another channel, then the qbman_swp_CDAN* functions will be -+ * necessary. -+ * -+ * CDAN-enabled channels only generate a single CDAN notification, after which -+ * they need to be reenabled before they'll generate another. The idea is -+ * that pull dequeuing will occur in reaction to the CDAN, followed by a -+ * reenable step. Each function generates a distinct command to hardware, so a -+ * combination function is provided if the user wishes to modify the "context" -+ * (which shows up in each CDAN message) each time they reenable, as a single -+ * command to hardware. -+ */ -+ -+/** -+ * qbman_swp_CDAN_set_context() - Set CDAN context -+ * @s: the software portal object -+ * @channelid: the channel index -+ * @ctx: the context to be set in CDAN -+ * -+ * Return 0 for success, or negative error code for failure. -+ */ -+static inline int qbman_swp_CDAN_set_context(struct qbman_swp *s, u16 channelid, -+ u64 ctx) -+{ -+ return qbman_swp_CDAN_set(s, channelid, -+ CODE_CDAN_WE_CTX, -+ 0, ctx); -+} -+ -+/** -+ * qbman_swp_CDAN_enable() - Enable CDAN for the channel -+ * @s: the software portal object -+ * @channelid: the index of the channel to generate CDAN -+ * -+ * Return 0 for success, or negative error code for failure. -+ */ -+static inline int qbman_swp_CDAN_enable(struct qbman_swp *s, u16 channelid) -+{ -+ return qbman_swp_CDAN_set(s, channelid, -+ CODE_CDAN_WE_EN, -+ 1, 0); -+} -+ -+/** -+ * qbman_swp_CDAN_disable() - disable CDAN for the channel -+ * @s: the software portal object -+ * @channelid: the index of the channel to generate CDAN -+ * -+ * Return 0 for success, or negative error code for failure. -+ */ -+static inline int qbman_swp_CDAN_disable(struct qbman_swp *s, u16 channelid) -+{ -+ return qbman_swp_CDAN_set(s, channelid, -+ CODE_CDAN_WE_EN, -+ 0, 0); -+} -+ -+/** -+ * qbman_swp_CDAN_set_context_enable() - Set CDAN contest and enable CDAN -+ * @s: the software portal object -+ * @channelid: the index of the channel to generate CDAN -+ * @ctx:i the context set in CDAN -+ * -+ * Return 0 for success, or negative error code for failure. -+ */ -+static inline int qbman_swp_CDAN_set_context_enable(struct qbman_swp *s, -+ u16 channelid, -+ u64 ctx) -+{ -+ return qbman_swp_CDAN_set(s, channelid, -+ CODE_CDAN_WE_EN | CODE_CDAN_WE_CTX, -+ 1, ctx); -+} -+ -+/* Wraps up submit + poll-for-result */ -+static inline void *qbman_swp_mc_complete(struct qbman_swp *swp, void *cmd, -+ u8 cmd_verb) -+{ -+ int loopvar = 1000; -+ -+ qbman_swp_mc_submit(swp, cmd, cmd_verb); -+ -+ do { -+ cmd = qbman_swp_mc_result(swp); -+ } while (!cmd && loopvar--); -+ -+ WARN_ON(!loopvar); -+ -+ return cmd; -+} -+ -+/* Query APIs */ -+struct qbman_fq_query_np_rslt { -+ u8 verb; -+ u8 rslt; -+ u8 st1; -+ u8 st2; -+ u8 reserved[2]; -+ u16 od1_sfdr; -+ u16 od2_sfdr; -+ u16 od3_sfdr; -+ u16 ra1_sfdr; -+ u16 ra2_sfdr; -+ u32 pfdr_hptr; -+ u32 pfdr_tptr; -+ u32 frm_cnt; -+ u32 byte_cnt; -+ u16 ics_surp; -+ u8 is; -+ u8 reserved2[29]; -+}; -+ -+int qbman_fq_query_state(struct qbman_swp *s, u32 fqid, -+ struct qbman_fq_query_np_rslt *r); -+u32 qbman_fq_state_frame_count(const struct qbman_fq_query_np_rslt *r); -+u32 qbman_fq_state_byte_count(const struct qbman_fq_query_np_rslt *r); -+ -+struct qbman_bp_query_rslt { -+ u8 verb; -+ u8 rslt; -+ u8 reserved[4]; -+ u8 bdi; -+ u8 state; -+ u32 fill; -+ u32 hdotr; -+ u16 swdet; -+ u16 swdxt; -+ u16 hwdet; -+ u16 hwdxt; -+ u16 swset; -+ u16 swsxt; -+ u16 vbpid; -+ u16 icid; -+ u64 bpscn_addr; -+ u64 bpscn_ctx; -+ u16 hw_targ; -+ u8 dbe; -+ u8 reserved2; -+ u8 sdcnt; -+ u8 hdcnt; -+ u8 sscnt; -+ u8 reserved3[9]; -+}; -+ -+int qbman_bp_query(struct qbman_swp *s, u32 bpid, -+ struct qbman_bp_query_rslt *r); -+ -+u32 qbman_bp_info_num_free_bufs(struct qbman_bp_query_rslt *a); -+ -+#endif /* __FSL_QBMAN_PORTAL_H */ ---- a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h -+++ /dev/null -@@ -1,140 +0,0 @@ --/* Copyright 2013-2016 Freescale Semiconductor Inc. -- * -- * Redistribution and use in source and binary forms, with or without -- * modification, are permitted provided that the following conditions are met: -- * * Redistributions of source code must retain the above copyright -- * notice, this list of conditions and the following disclaimer. -- * * Redistributions in binary form must reproduce the above copyright -- * notice, this list of conditions and the following disclaimer in the -- * documentation and/or other materials provided with the distribution. -- * * Neither the name of the above-listed copyright holders nor the -- * names of any contributors may be used to endorse or promote products -- * derived from this software without specific prior written permission. -- * -- * -- * ALTERNATIVELY, this software may be distributed under the terms of the -- * GNU General Public License ("GPL") as published by the Free Software -- * Foundation, either version 2 of that License or (at your option) any -- * later version. -- * -- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -- * POSSIBILITY OF SUCH DAMAGE. -- */ --#ifndef _FSL_DPMCP_CMD_H --#define _FSL_DPMCP_CMD_H -- --/* Minimal supported DPMCP Version */ --#define DPMCP_MIN_VER_MAJOR 3 --#define DPMCP_MIN_VER_MINOR 0 -- --/* Command IDs */ --#define DPMCP_CMDID_CLOSE 0x800 --#define DPMCP_CMDID_OPEN 0x80b --#define DPMCP_CMDID_CREATE 0x90b --#define DPMCP_CMDID_DESTROY 0x900 -- --#define DPMCP_CMDID_GET_ATTR 0x004 --#define DPMCP_CMDID_RESET 0x005 -- --#define DPMCP_CMDID_SET_IRQ 0x010 --#define DPMCP_CMDID_GET_IRQ 0x011 --#define DPMCP_CMDID_SET_IRQ_ENABLE 0x012 --#define DPMCP_CMDID_GET_IRQ_ENABLE 0x013 --#define DPMCP_CMDID_SET_IRQ_MASK 0x014 --#define DPMCP_CMDID_GET_IRQ_MASK 0x015 --#define DPMCP_CMDID_GET_IRQ_STATUS 0x016 -- --struct dpmcp_cmd_open { -- __le32 dpmcp_id; --}; -- --struct dpmcp_cmd_create { -- __le32 portal_id; --}; -- --struct dpmcp_cmd_set_irq { -- /* cmd word 0 */ -- u8 irq_index; -- u8 pad[3]; -- __le32 irq_val; -- /* cmd word 1 */ -- __le64 irq_addr; -- /* cmd word 2 */ -- __le32 irq_num; --}; -- --struct dpmcp_cmd_get_irq { -- __le32 pad; -- u8 irq_index; --}; -- --struct dpmcp_rsp_get_irq { -- /* cmd word 0 */ -- __le32 irq_val; -- __le32 pad; -- /* cmd word 1 */ -- __le64 irq_paddr; -- /* cmd word 2 */ -- __le32 irq_num; -- __le32 type; --}; -- --#define DPMCP_ENABLE 0x1 -- --struct dpmcp_cmd_set_irq_enable { -- u8 enable; -- u8 pad[3]; -- u8 irq_index; --}; -- --struct dpmcp_cmd_get_irq_enable { -- __le32 pad; -- u8 irq_index; --}; -- --struct dpmcp_rsp_get_irq_enable { -- u8 enabled; --}; -- --struct dpmcp_cmd_set_irq_mask { -- __le32 mask; -- u8 irq_index; --}; -- --struct dpmcp_cmd_get_irq_mask { -- __le32 pad; -- u8 irq_index; --}; -- --struct dpmcp_rsp_get_irq_mask { -- __le32 mask; --}; -- --struct dpmcp_cmd_get_irq_status { -- __le32 status; -- u8 irq_index; --}; -- --struct dpmcp_rsp_get_irq_status { -- __le32 status; --}; -- --struct dpmcp_rsp_get_attributes { -- /* response word 0 */ -- __le32 pad; -- __le32 id; -- /* response word 1 */ -- __le16 version_major; -- __le16 version_minor; --}; -- --#endif /* _FSL_DPMCP_CMD_H */ ---- a/drivers/staging/fsl-mc/bus/dpmcp.c -+++ /dev/null -@@ -1,504 +0,0 @@ --/* Copyright 2013-2016 Freescale Semiconductor Inc. -- * -- * Redistribution and use in source and binary forms, with or without -- * modification, are permitted provided that the following conditions are met: -- * * Redistributions of source code must retain the above copyright -- * notice, this list of conditions and the following disclaimer. -- * * Redistributions in binary form must reproduce the above copyright -- * notice, this list of conditions and the following disclaimer in the -- * documentation and/or other materials provided with the distribution. -- * * Neither the name of the above-listed copyright holders nor the -- * names of any contributors may be used to endorse or promote products -- * derived from this software without specific prior written permission. -- * -- * -- * ALTERNATIVELY, this software may be distributed under the terms of the -- * GNU General Public License ("GPL") as published by the Free Software -- * Foundation, either version 2 of that License or (at your option) any -- * later version. -- * -- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -- * POSSIBILITY OF SUCH DAMAGE. -- */ --#include "../include/mc-sys.h" --#include "../include/mc-cmd.h" -- --#include "dpmcp.h" --#include "dpmcp-cmd.h" -- --/** -- * dpmcp_open() - Open a control session for the specified object. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @dpmcp_id: DPMCP unique ID -- * @token: Returned token; use in subsequent API calls -- * -- * This function can be used to open a control session for an -- * already created object; an object may have been declared in -- * the DPL or by calling the dpmcp_create function. -- * This function returns a unique authentication token, -- * associated with the specific object ID and the specific MC -- * portal; this token must be used in all subsequent commands for -- * this specific object -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpmcp_open(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- int dpmcp_id, -- u16 *token) --{ -- struct mc_command cmd = { 0 }; -- struct dpmcp_cmd_open *cmd_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPMCP_CMDID_OPEN, -- cmd_flags, 0); -- cmd_params = (struct dpmcp_cmd_open *)cmd.params; -- cmd_params->dpmcp_id = cpu_to_le32(dpmcp_id); -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- *token = mc_cmd_hdr_read_token(&cmd); -- -- return err; --} -- --/** -- * dpmcp_close() - Close the control session of the object -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPMCP object -- * -- * After this function is called, no further operations are -- * allowed on the object without opening a new control session. -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpmcp_close(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token) --{ -- struct mc_command cmd = { 0 }; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CLOSE, -- cmd_flags, token); -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} -- --/** -- * dpmcp_create() - Create the DPMCP object. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @cfg: Configuration structure -- * @token: Returned token; use in subsequent API calls -- * -- * Create the DPMCP object, allocate required resources and -- * perform required initialization. -- * -- * The object can be created either by declaring it in the -- * DPL file, or by calling this function. -- * This function returns a unique authentication token, -- * associated with the specific object ID and the specific MC -- * portal; this token must be used in all subsequent calls to -- * this specific object. For objects that are created using the -- * DPL file, call dpmcp_open function to get an authentication -- * token first. -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpmcp_create(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- const struct dpmcp_cfg *cfg, -- u16 *token) --{ -- struct mc_command cmd = { 0 }; -- struct dpmcp_cmd_create *cmd_params; -- -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CREATE, -- cmd_flags, 0); -- cmd_params = (struct dpmcp_cmd_create *)cmd.params; -- cmd_params->portal_id = cpu_to_le32(cfg->portal_id); -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- *token = mc_cmd_hdr_read_token(&cmd); -- -- return 0; --} -- --/** -- * dpmcp_destroy() - Destroy the DPMCP object and release all its resources. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPMCP object -- * -- * Return: '0' on Success; error code otherwise. -- */ --int dpmcp_destroy(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token) --{ -- struct mc_command cmd = { 0 }; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPMCP_CMDID_DESTROY, -- cmd_flags, token); -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} -- --/** -- * dpmcp_reset() - Reset the DPMCP, returns the object to initial state. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPMCP object -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpmcp_reset(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token) --{ -- struct mc_command cmd = { 0 }; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPMCP_CMDID_RESET, -- cmd_flags, token); -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} -- --/** -- * dpmcp_set_irq() - Set IRQ information for the DPMCP to trigger an interrupt. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPMCP object -- * @irq_index: Identifies the interrupt index to configure -- * @irq_cfg: IRQ configuration -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpmcp_set_irq(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- struct dpmcp_irq_cfg *irq_cfg) --{ -- struct mc_command cmd = { 0 }; -- struct dpmcp_cmd_set_irq *cmd_params; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ, -- cmd_flags, token); -- cmd_params = (struct dpmcp_cmd_set_irq *)cmd.params; -- cmd_params->irq_index = irq_index; -- cmd_params->irq_val = cpu_to_le32(irq_cfg->val); -- cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr); -- cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num); -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} -- --/** -- * dpmcp_get_irq() - Get IRQ information from the DPMCP. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPMCP object -- * @irq_index: The interrupt index to configure -- * @type: Interrupt type: 0 represents message interrupt -- * type (both irq_addr and irq_val are valid) -- * @irq_cfg: IRQ attributes -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpmcp_get_irq(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- int *type, -- struct dpmcp_irq_cfg *irq_cfg) --{ -- struct mc_command cmd = { 0 }; -- struct dpmcp_cmd_get_irq *cmd_params; -- struct dpmcp_rsp_get_irq *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ, -- cmd_flags, token); -- cmd_params = (struct dpmcp_cmd_get_irq *)cmd.params; -- cmd_params->irq_index = irq_index; -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dpmcp_rsp_get_irq *)cmd.params; -- irq_cfg->val = le32_to_cpu(rsp_params->irq_val); -- irq_cfg->paddr = le64_to_cpu(rsp_params->irq_paddr); -- irq_cfg->irq_num = le32_to_cpu(rsp_params->irq_num); -- *type = le32_to_cpu(rsp_params->type); -- return 0; --} -- --/** -- * dpmcp_set_irq_enable() - Set overall interrupt state. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPMCP object -- * @irq_index: The interrupt index to configure -- * @en: Interrupt state - enable = 1, disable = 0 -- * -- * Allows GPP software to control when interrupts are generated. -- * Each interrupt can have up to 32 causes. The enable/disable control's the -- * overall interrupt state. if the interrupt is disabled no causes will cause -- * an interrupt. -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpmcp_set_irq_enable(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u8 en) --{ -- struct mc_command cmd = { 0 }; -- struct dpmcp_cmd_set_irq_enable *cmd_params; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ_ENABLE, -- cmd_flags, token); -- cmd_params = (struct dpmcp_cmd_set_irq_enable *)cmd.params; -- cmd_params->enable = en & DPMCP_ENABLE; -- cmd_params->irq_index = irq_index; -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} -- --/** -- * dpmcp_get_irq_enable() - Get overall interrupt state -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPMCP object -- * @irq_index: The interrupt index to configure -- * @en: Returned interrupt state - enable = 1, disable = 0 -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpmcp_get_irq_enable(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u8 *en) --{ -- struct mc_command cmd = { 0 }; -- struct dpmcp_cmd_get_irq_enable *cmd_params; -- struct dpmcp_rsp_get_irq_enable *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_ENABLE, -- cmd_flags, token); -- cmd_params = (struct dpmcp_cmd_get_irq_enable *)cmd.params; -- cmd_params->irq_index = irq_index; -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dpmcp_rsp_get_irq_enable *)cmd.params; -- *en = rsp_params->enabled & DPMCP_ENABLE; -- return 0; --} -- --/** -- * dpmcp_set_irq_mask() - Set interrupt mask. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPMCP object -- * @irq_index: The interrupt index to configure -- * @mask: Event mask to trigger interrupt; -- * each bit: -- * 0 = ignore event -- * 1 = consider event for asserting IRQ -- * -- * Every interrupt can have up to 32 causes and the interrupt model supports -- * masking/unmasking each cause independently -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpmcp_set_irq_mask(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u32 mask) --{ -- struct mc_command cmd = { 0 }; -- struct dpmcp_cmd_set_irq_mask *cmd_params; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ_MASK, -- cmd_flags, token); -- cmd_params = (struct dpmcp_cmd_set_irq_mask *)cmd.params; -- cmd_params->mask = cpu_to_le32(mask); -- cmd_params->irq_index = irq_index; -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} -- --/** -- * dpmcp_get_irq_mask() - Get interrupt mask. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPMCP object -- * @irq_index: The interrupt index to configure -- * @mask: Returned event mask to trigger interrupt -- * -- * Every interrupt can have up to 32 causes and the interrupt model supports -- * masking/unmasking each cause independently -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpmcp_get_irq_mask(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u32 *mask) --{ -- struct mc_command cmd = { 0 }; -- struct dpmcp_cmd_get_irq_mask *cmd_params; -- struct dpmcp_rsp_get_irq_mask *rsp_params; -- -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_MASK, -- cmd_flags, token); -- cmd_params = (struct dpmcp_cmd_get_irq_mask *)cmd.params; -- cmd_params->irq_index = irq_index; -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dpmcp_rsp_get_irq_mask *)cmd.params; -- *mask = le32_to_cpu(rsp_params->mask); -- -- return 0; --} -- --/** -- * dpmcp_get_irq_status() - Get the current status of any pending interrupts. -- * -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPMCP object -- * @irq_index: The interrupt index to configure -- * @status: Returned interrupts status - one bit per cause: -- * 0 = no interrupt pending -- * 1 = interrupt pending -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpmcp_get_irq_status(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u32 *status) --{ -- struct mc_command cmd = { 0 }; -- struct dpmcp_cmd_get_irq_status *cmd_params; -- struct dpmcp_rsp_get_irq_status *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_STATUS, -- cmd_flags, token); -- cmd_params = (struct dpmcp_cmd_get_irq_status *)cmd.params; -- cmd_params->status = cpu_to_le32(*status); -- cmd_params->irq_index = irq_index; -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dpmcp_rsp_get_irq_status *)cmd.params; -- *status = le32_to_cpu(rsp_params->status); -- -- return 0; --} -- --/** -- * dpmcp_get_attributes - Retrieve DPMCP attributes. -- * -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPMCP object -- * @attr: Returned object's attributes -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpmcp_get_attributes(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- struct dpmcp_attr *attr) --{ -- struct mc_command cmd = { 0 }; -- struct dpmcp_rsp_get_attributes *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_ATTR, -- cmd_flags, token); -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dpmcp_rsp_get_attributes *)cmd.params; -- attr->id = le32_to_cpu(rsp_params->id); -- attr->version.major = le16_to_cpu(rsp_params->version_major); -- attr->version.minor = le16_to_cpu(rsp_params->version_minor); -- -- return 0; --} ---- a/drivers/staging/fsl-mc/bus/dpmcp.h -+++ /dev/null -@@ -1,159 +0,0 @@ --/* Copyright 2013-2015 Freescale Semiconductor Inc. -- * -- * Redistribution and use in source and binary forms, with or without -- * modification, are permitted provided that the following conditions are met: -- * * Redistributions of source code must retain the above copyright -- * notice, this list of conditions and the following disclaimer. -- * * Redistributions in binary form must reproduce the above copyright -- * notice, this list of conditions and the following disclaimer in the -- * documentation and/or other materials provided with the distribution. -- * * Neither the name of the above-listed copyright holders nor the -- * names of any contributors may be used to endorse or promote products -- * derived from this software without specific prior written permission. -- * -- * -- * ALTERNATIVELY, this software may be distributed under the terms of the -- * GNU General Public License ("GPL") as published by the Free Software -- * Foundation, either version 2 of that License or (at your option) any -- * later version. -- * -- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -- * POSSIBILITY OF SUCH DAMAGE. -- */ --#ifndef __FSL_DPMCP_H --#define __FSL_DPMCP_H -- --/* Data Path Management Command Portal API -- * Contains initialization APIs and runtime control APIs for DPMCP -- */ -- --struct fsl_mc_io; -- --int dpmcp_open(struct fsl_mc_io *mc_io, -- uint32_t cmd_flags, -- int dpmcp_id, -- uint16_t *token); -- --/* Get portal ID from pool */ --#define DPMCP_GET_PORTAL_ID_FROM_POOL (-1) -- --int dpmcp_close(struct fsl_mc_io *mc_io, -- uint32_t cmd_flags, -- uint16_t token); -- --/** -- * struct dpmcp_cfg - Structure representing DPMCP configuration -- * @portal_id: Portal ID; 'DPMCP_GET_PORTAL_ID_FROM_POOL' to get the portal ID -- * from pool -- */ --struct dpmcp_cfg { -- int portal_id; --}; -- --int dpmcp_create(struct fsl_mc_io *mc_io, -- uint32_t cmd_flags, -- const struct dpmcp_cfg *cfg, -- uint16_t *token); -- --int dpmcp_destroy(struct fsl_mc_io *mc_io, -- uint32_t cmd_flags, -- uint16_t token); -- --int dpmcp_reset(struct fsl_mc_io *mc_io, -- uint32_t cmd_flags, -- uint16_t token); -- --/* IRQ */ --/* IRQ Index */ --#define DPMCP_IRQ_INDEX 0 --/* irq event - Indicates that the link state changed */ --#define DPMCP_IRQ_EVENT_CMD_DONE 0x00000001 -- --/** -- * struct dpmcp_irq_cfg - IRQ configuration -- * @paddr: Address that must be written to signal a message-based interrupt -- * @val: Value to write into irq_addr address -- * @irq_num: A user defined number associated with this IRQ -- */ --struct dpmcp_irq_cfg { -- uint64_t paddr; -- uint32_t val; -- int irq_num; --}; -- --int dpmcp_set_irq(struct fsl_mc_io *mc_io, -- uint32_t cmd_flags, -- uint16_t token, -- uint8_t irq_index, -- struct dpmcp_irq_cfg *irq_cfg); -- --int dpmcp_get_irq(struct fsl_mc_io *mc_io, -- uint32_t cmd_flags, -- uint16_t token, -- uint8_t irq_index, -- int *type, -- struct dpmcp_irq_cfg *irq_cfg); -- --int dpmcp_set_irq_enable(struct fsl_mc_io *mc_io, -- uint32_t cmd_flags, -- uint16_t token, -- uint8_t irq_index, -- uint8_t en); -- --int dpmcp_get_irq_enable(struct fsl_mc_io *mc_io, -- uint32_t cmd_flags, -- uint16_t token, -- uint8_t irq_index, -- uint8_t *en); -- --int dpmcp_set_irq_mask(struct fsl_mc_io *mc_io, -- uint32_t cmd_flags, -- uint16_t token, -- uint8_t irq_index, -- uint32_t mask); -- --int dpmcp_get_irq_mask(struct fsl_mc_io *mc_io, -- uint32_t cmd_flags, -- uint16_t token, -- uint8_t irq_index, -- uint32_t *mask); -- --int dpmcp_get_irq_status(struct fsl_mc_io *mc_io, -- uint32_t cmd_flags, -- uint16_t token, -- uint8_t irq_index, -- uint32_t *status); -- --/** -- * struct dpmcp_attr - Structure representing DPMCP attributes -- * @id: DPMCP object ID -- * @version: DPMCP version -- */ --struct dpmcp_attr { -- int id; -- /** -- * struct version - Structure representing DPMCP version -- * @major: DPMCP major version -- * @minor: DPMCP minor version -- */ -- struct { -- uint16_t major; -- uint16_t minor; -- } version; --}; -- --int dpmcp_get_attributes(struct fsl_mc_io *mc_io, -- uint32_t cmd_flags, -- uint16_t token, -- struct dpmcp_attr *attr); -- --#endif /* __FSL_DPMCP_H */ ---- a/drivers/staging/fsl-mc/bus/dpmng-cmd.h -+++ /dev/null -@@ -1,58 +0,0 @@ --/* -- * Copyright 2013-2016 Freescale Semiconductor Inc. -- * -- * Redistribution and use in source and binary forms, with or without -- * modification, are permitted provided that the following conditions are met: -- * * Redistributions of source code must retain the above copyright -- * notice, this list of conditions and the following disclaimer. -- * * Redistributions in binary form must reproduce the above copyright -- * notice, this list of conditions and the following disclaimer in the -- * documentation and/or other materials provided with the distribution. -- * * Neither the name of the above-listed copyright holders nor the -- * names of any contributors may be used to endorse or promote products -- * derived from this software without specific prior written permission. -- * -- * -- * ALTERNATIVELY, this software may be distributed under the terms of the -- * GNU General Public License ("GPL") as published by the Free Software -- * Foundation, either version 2 of that License or (at your option) any -- * later version. -- * -- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -- * POSSIBILITY OF SUCH DAMAGE. -- */ -- --/* -- * dpmng-cmd.h -- * -- * defines portal commands -- * -- */ -- --#ifndef __FSL_DPMNG_CMD_H --#define __FSL_DPMNG_CMD_H -- --/* Command IDs */ --#define DPMNG_CMDID_GET_CONT_ID 0x830 --#define DPMNG_CMDID_GET_VERSION 0x831 -- --struct dpmng_rsp_get_container_id { -- __le32 container_id; --}; -- --struct dpmng_rsp_get_version { -- __le32 revision; -- __le32 version_major; -- __le32 version_minor; --}; -- --#endif /* __FSL_DPMNG_CMD_H */ ---- a/drivers/staging/fsl-mc/bus/dpmng.c -+++ /dev/null -@@ -1,107 +0,0 @@ --/* Copyright 2013-2016 Freescale Semiconductor Inc. -- * -- * Redistribution and use in source and binary forms, with or without -- * modification, are permitted provided that the following conditions are met: -- * * Redistributions of source code must retain the above copyright -- * notice, this list of conditions and the following disclaimer. -- * * Redistributions in binary form must reproduce the above copyright -- * notice, this list of conditions and the following disclaimer in the -- * documentation and/or other materials provided with the distribution. -- * * Neither the name of the above-listed copyright holders nor the -- * names of any contributors may be used to endorse or promote products -- * derived from this software without specific prior written permission. -- * -- * -- * ALTERNATIVELY, this software may be distributed under the terms of the -- * GNU General Public License ("GPL") as published by the Free Software -- * Foundation, either version 2 of that License or (at your option) any -- * later version. -- * -- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -- * POSSIBILITY OF SUCH DAMAGE. -- */ --#include "../include/mc-sys.h" --#include "../include/mc-cmd.h" --#include "../include/dpmng.h" -- --#include "dpmng-cmd.h" -- --/** -- * mc_get_version() - Retrieves the Management Complex firmware -- * version information -- * @mc_io: Pointer to opaque I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @mc_ver_info: Returned version information structure -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int mc_get_version(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- struct mc_version *mc_ver_info) --{ -- struct mc_command cmd = { 0 }; -- struct dpmng_rsp_get_version *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_VERSION, -- cmd_flags, -- 0); -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dpmng_rsp_get_version *)cmd.params; -- mc_ver_info->revision = le32_to_cpu(rsp_params->revision); -- mc_ver_info->major = le32_to_cpu(rsp_params->version_major); -- mc_ver_info->minor = le32_to_cpu(rsp_params->version_minor); -- -- return 0; --} --EXPORT_SYMBOL(mc_get_version); -- --/** -- * dpmng_get_container_id() - Get container ID associated with a given portal. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @container_id: Requested container ID -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpmng_get_container_id(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- int *container_id) --{ -- struct mc_command cmd = { 0 }; -- struct dpmng_rsp_get_container_id *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_CONT_ID, -- cmd_flags, -- 0); -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dpmng_rsp_get_container_id *)cmd.params; -- *container_id = le32_to_cpu(rsp_params->container_id); -- -- return 0; --} -- ---- a/drivers/staging/fsl-mc/bus/dprc-cmd.h -+++ /dev/null -@@ -1,465 +0,0 @@ --/* -- * Copyright 2013-2016 Freescale Semiconductor Inc. -- * -- * Redistribution and use in source and binary forms, with or without -- * modification, are permitted provided that the following conditions are met: -- * * Redistributions of source code must retain the above copyright -- * notice, this list of conditions and the following disclaimer. -- * * Redistributions in binary form must reproduce the above copyright -- * notice, this list of conditions and the following disclaimer in the -- * documentation and/or other materials provided with the distribution. -- * * Neither the name of the above-listed copyright holders nor the -- * names of any contributors may be used to endorse or promote products -- * derived from this software without specific prior written permission. -- * -- * -- * ALTERNATIVELY, this software may be distributed under the terms of the -- * GNU General Public License ("GPL") as published by the Free Software -- * Foundation, either version 2 of that License or (at your option) any -- * later version. -- * -- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -- * POSSIBILITY OF SUCH DAMAGE. -- */ -- --/* -- * dprc-cmd.h -- * -- * defines dprc portal commands -- * -- */ -- --#ifndef _FSL_DPRC_CMD_H --#define _FSL_DPRC_CMD_H -- --/* Minimal supported DPRC Version */ --#define DPRC_MIN_VER_MAJOR 5 --#define DPRC_MIN_VER_MINOR 0 -- --/* Command IDs */ --#define DPRC_CMDID_CLOSE 0x800 --#define DPRC_CMDID_OPEN 0x805 --#define DPRC_CMDID_CREATE 0x905 -- --#define DPRC_CMDID_GET_ATTR 0x004 --#define DPRC_CMDID_RESET_CONT 0x005 -- --#define DPRC_CMDID_SET_IRQ 0x010 --#define DPRC_CMDID_GET_IRQ 0x011 --#define DPRC_CMDID_SET_IRQ_ENABLE 0x012 --#define DPRC_CMDID_GET_IRQ_ENABLE 0x013 --#define DPRC_CMDID_SET_IRQ_MASK 0x014 --#define DPRC_CMDID_GET_IRQ_MASK 0x015 --#define DPRC_CMDID_GET_IRQ_STATUS 0x016 --#define DPRC_CMDID_CLEAR_IRQ_STATUS 0x017 -- --#define DPRC_CMDID_CREATE_CONT 0x151 --#define DPRC_CMDID_DESTROY_CONT 0x152 --#define DPRC_CMDID_SET_RES_QUOTA 0x155 --#define DPRC_CMDID_GET_RES_QUOTA 0x156 --#define DPRC_CMDID_ASSIGN 0x157 --#define DPRC_CMDID_UNASSIGN 0x158 --#define DPRC_CMDID_GET_OBJ_COUNT 0x159 --#define DPRC_CMDID_GET_OBJ 0x15A --#define DPRC_CMDID_GET_RES_COUNT 0x15B --#define DPRC_CMDID_GET_RES_IDS 0x15C --#define DPRC_CMDID_GET_OBJ_REG 0x15E --#define DPRC_CMDID_SET_OBJ_IRQ 0x15F --#define DPRC_CMDID_GET_OBJ_IRQ 0x160 --#define DPRC_CMDID_SET_OBJ_LABEL 0x161 --#define DPRC_CMDID_GET_OBJ_DESC 0x162 -- --#define DPRC_CMDID_CONNECT 0x167 --#define DPRC_CMDID_DISCONNECT 0x168 --#define DPRC_CMDID_GET_POOL 0x169 --#define DPRC_CMDID_GET_POOL_COUNT 0x16A -- --#define DPRC_CMDID_GET_CONNECTION 0x16C -- --struct dprc_cmd_open { -- __le32 container_id; --}; -- --struct dprc_cmd_create_container { -- /* cmd word 0 */ -- __le32 options; -- __le16 icid; -- __le16 pad0; -- /* cmd word 1 */ -- __le32 pad1; -- __le32 portal_id; -- /* cmd words 2-3 */ -- u8 label[16]; --}; -- --struct dprc_rsp_create_container { -- /* response word 0 */ -- __le64 pad0; -- /* response word 1 */ -- __le32 child_container_id; -- __le32 pad1; -- /* response word 2 */ -- __le64 child_portal_addr; --}; -- --struct dprc_cmd_destroy_container { -- __le32 child_container_id; --}; -- --struct dprc_cmd_reset_container { -- __le32 child_container_id; --}; -- --struct dprc_cmd_set_irq { -- /* cmd word 0 */ -- __le32 irq_val; -- u8 irq_index; -- u8 pad[3]; -- /* cmd word 1 */ -- __le64 irq_addr; -- /* cmd word 2 */ -- __le32 irq_num; --}; -- --struct dprc_cmd_get_irq { -- __le32 pad; -- u8 irq_index; --}; -- --struct dprc_rsp_get_irq { -- /* response word 0 */ -- __le32 irq_val; -- __le32 pad; -- /* response word 1 */ -- __le64 irq_addr; -- /* response word 2 */ -- __le32 irq_num; -- __le32 type; --}; -- --#define DPRC_ENABLE 0x1 -- --struct dprc_cmd_set_irq_enable { -- u8 enable; -- u8 pad[3]; -- u8 irq_index; --}; -- --struct dprc_cmd_get_irq_enable { -- __le32 pad; -- u8 irq_index; --}; -- --struct dprc_rsp_get_irq_enable { -- u8 enabled; --}; -- --struct dprc_cmd_set_irq_mask { -- __le32 mask; -- u8 irq_index; --}; -- --struct dprc_cmd_get_irq_mask { -- __le32 pad; -- u8 irq_index; --}; -- --struct dprc_rsp_get_irq_mask { -- __le32 mask; --}; -- --struct dprc_cmd_get_irq_status { -- __le32 status; -- u8 irq_index; --}; -- --struct dprc_rsp_get_irq_status { -- __le32 status; --}; -- --struct dprc_cmd_clear_irq_status { -- __le32 status; -- u8 irq_index; --}; -- --struct dprc_rsp_get_attributes { -- /* response word 0 */ -- __le32 container_id; -- __le16 icid; -- __le16 pad; -- /* response word 1 */ -- __le32 options; -- __le32 portal_id; -- /* response word 2 */ -- __le16 version_major; -- __le16 version_minor; --}; -- --struct dprc_cmd_set_res_quota { -- /* cmd word 0 */ -- __le32 child_container_id; -- __le16 quota; -- __le16 pad; -- /* cmd words 1-2 */ -- u8 type[16]; --}; -- --struct dprc_cmd_get_res_quota { -- /* cmd word 0 */ -- __le32 child_container_id; -- __le32 pad; -- /* cmd word 1-2 */ -- u8 type[16]; --}; -- --struct dprc_rsp_get_res_quota { -- __le32 pad; -- __le16 quota; --}; -- --struct dprc_cmd_assign { -- /* cmd word 0 */ -- __le32 container_id; -- __le32 options; -- /* cmd word 1 */ -- __le32 num; -- __le32 id_base_align; -- /* cmd word 2-3 */ -- u8 type[16]; --}; -- --struct dprc_cmd_unassign { -- /* cmd word 0 */ -- __le32 child_container_id; -- __le32 options; -- /* cmd word 1 */ -- __le32 num; -- __le32 id_base_align; -- /* cmd word 2-3 */ -- u8 type[16]; --}; -- --struct dprc_rsp_get_pool_count { -- __le32 pool_count; --}; -- --struct dprc_cmd_get_pool { -- __le32 pool_index; --}; -- --struct dprc_rsp_get_pool { -- /* response word 0 */ -- __le64 pad; -- /* response word 1-2 */ -- u8 type[16]; --}; -- --struct dprc_rsp_get_obj_count { -- __le32 pad; -- __le32 obj_count; --}; -- --struct dprc_cmd_get_obj { -- __le32 obj_index; --}; -- --struct dprc_rsp_get_obj { -- /* response word 0 */ -- __le32 pad0; -- __le32 id; -- /* response word 1 */ -- __le16 vendor; -- u8 irq_count; -- u8 region_count; -- __le32 state; -- /* response word 2 */ -- __le16 version_major; -- __le16 version_minor; -- __le16 flags; -- __le16 pad1; -- /* response word 3-4 */ -- u8 type[16]; -- /* response word 5-6 */ -- u8 label[16]; --}; -- --struct dprc_cmd_get_obj_desc { -- /* cmd word 0 */ -- __le32 obj_id; -- __le32 pad; -- /* cmd word 1-2 */ -- u8 type[16]; --}; -- --struct dprc_rsp_get_obj_desc { -- /* response word 0 */ -- __le32 pad0; -- __le32 id; -- /* response word 1 */ -- __le16 vendor; -- u8 irq_count; -- u8 region_count; -- __le32 state; -- /* response word 2 */ -- __le16 version_major; -- __le16 version_minor; -- __le16 flags; -- __le16 pad1; -- /* response word 3-4 */ -- u8 type[16]; -- /* response word 5-6 */ -- u8 label[16]; --}; -- --struct dprc_cmd_get_res_count { -- /* cmd word 0 */ -- __le64 pad; -- /* cmd word 1-2 */ -- u8 type[16]; --}; -- --struct dprc_rsp_get_res_count { -- __le32 res_count; --}; -- --struct dprc_cmd_get_res_ids { -- /* cmd word 0 */ -- u8 pad0[5]; -- u8 iter_status; -- __le16 pad1; -- /* cmd word 1 */ -- __le32 base_id; -- __le32 last_id; -- /* cmd word 2-3 */ -- u8 type[16]; --}; -- --struct dprc_rsp_get_res_ids { -- /* response word 0 */ -- u8 pad0[5]; -- u8 iter_status; -- __le16 pad1; -- /* response word 1 */ -- __le32 base_id; -- __le32 last_id; --}; -- --struct dprc_cmd_get_obj_region { -- /* cmd word 0 */ -- __le32 obj_id; -- __le16 pad0; -- u8 region_index; -- u8 pad1; -- /* cmd word 1-2 */ -- __le64 pad2[2]; -- /* cmd word 3-4 */ -- u8 obj_type[16]; --}; -- --struct dprc_rsp_get_obj_region { -- /* response word 0 */ -- __le64 pad; -- /* response word 1 */ -- __le64 base_addr; -- /* response word 2 */ -- __le32 size; --}; -- --struct dprc_cmd_set_obj_label { -- /* cmd word 0 */ -- __le32 obj_id; -- __le32 pad; -- /* cmd word 1-2 */ -- u8 label[16]; -- /* cmd word 3-4 */ -- u8 obj_type[16]; --}; -- --struct dprc_cmd_set_obj_irq { -- /* cmd word 0 */ -- __le32 irq_val; -- u8 irq_index; -- u8 pad[3]; -- /* cmd word 1 */ -- __le64 irq_addr; -- /* cmd word 2 */ -- __le32 irq_num; -- __le32 obj_id; -- /* cmd word 3-4 */ -- u8 obj_type[16]; --}; -- --struct dprc_cmd_get_obj_irq { -- /* cmd word 0 */ -- __le32 obj_id; -- u8 irq_index; -- u8 pad[3]; -- /* cmd word 1-2 */ -- u8 obj_type[16]; --}; -- --struct dprc_rsp_get_obj_irq { -- /* response word 0 */ -- __le32 irq_val; -- __le32 pad; -- /* response word 1 */ -- __le64 irq_addr; -- /* response word 2 */ -- __le32 irq_num; -- __le32 type; --}; -- --struct dprc_cmd_connect { -- /* cmd word 0 */ -- __le32 ep1_id; -- __le32 ep1_interface_id; -- /* cmd word 1 */ -- __le32 ep2_id; -- __le32 ep2_interface_id; -- /* cmd word 2-3 */ -- u8 ep1_type[16]; -- /* cmd word 4 */ -- __le32 max_rate; -- __le32 committed_rate; -- /* cmd word 5-6 */ -- u8 ep2_type[16]; --}; -- --struct dprc_cmd_disconnect { -- /* cmd word 0 */ -- __le32 id; -- __le32 interface_id; -- /* cmd word 1-2 */ -- u8 type[16]; --}; -- --struct dprc_cmd_get_connection { -- /* cmd word 0 */ -- __le32 ep1_id; -- __le32 ep1_interface_id; -- /* cmd word 1-2 */ -- u8 ep1_type[16]; --}; -- --struct dprc_rsp_get_connection { -- /* response word 0-2 */ -- __le64 pad[3]; -- /* response word 3 */ -- __le32 ep2_id; -- __le32 ep2_interface_id; -- /* response word 4-5 */ -- u8 ep2_type[16]; -- /* response word 6 */ -- __le32 state; --}; -- --#endif /* _FSL_DPRC_CMD_H */ ---- a/drivers/staging/fsl-mc/bus/dprc.c -+++ /dev/null -@@ -1,1388 +0,0 @@ --/* Copyright 2013-2016 Freescale Semiconductor Inc. -- * -- * Redistribution and use in source and binary forms, with or without -- * modification, are permitted provided that the following conditions are met: -- * * Redistributions of source code must retain the above copyright -- * notice, this list of conditions and the following disclaimer. -- * * Redistributions in binary form must reproduce the above copyright -- * notice, this list of conditions and the following disclaimer in the -- * documentation and/or other materials provided with the distribution. -- * * Neither the name of the above-listed copyright holders nor the -- * names of any contributors may be used to endorse or promote products -- * derived from this software without specific prior written permission. -- * -- * -- * ALTERNATIVELY, this software may be distributed under the terms of the -- * GNU General Public License ("GPL") as published by the Free Software -- * Foundation, either version 2 of that License or (at your option) any -- * later version. -- * -- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -- * POSSIBILITY OF SUCH DAMAGE. -- */ --#include "../include/mc-sys.h" --#include "../include/mc-cmd.h" --#include "../include/dprc.h" -- --#include "dprc-cmd.h" -- --/** -- * dprc_open() - Open DPRC object for use -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @container_id: Container ID to open -- * @token: Returned token of DPRC object -- * -- * Return: '0' on Success; Error code otherwise. -- * -- * @warning Required before any operation on the object. -- */ --int dprc_open(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- int container_id, -- u16 *token) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_open *cmd_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_OPEN, cmd_flags, -- 0); -- cmd_params = (struct dprc_cmd_open *)cmd.params; -- cmd_params->container_id = cpu_to_le32(container_id); -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- *token = mc_cmd_hdr_read_token(&cmd); -- -- return 0; --} --EXPORT_SYMBOL(dprc_open); -- --/** -- * dprc_close() - Close the control session of the object -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * -- * After this function is called, no further operations are -- * allowed on the object without opening a new control session. -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_close(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token) --{ -- struct mc_command cmd = { 0 }; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLOSE, cmd_flags, -- token); -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} --EXPORT_SYMBOL(dprc_close); -- --/** -- * dprc_create_container() - Create child container -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @cfg: Child container configuration -- * @child_container_id: Returned child container ID -- * @child_portal_offset: Returned child portal offset from MC portal base -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_create_container(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- struct dprc_cfg *cfg, -- int *child_container_id, -- u64 *child_portal_offset) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_create_container *cmd_params; -- struct dprc_rsp_create_container *rsp_params; -- int err; -- -- /* prepare command */ -- cmd_params = (struct dprc_cmd_create_container *)cmd.params; -- cmd_params->options = cpu_to_le32(cfg->options); -- cmd_params->icid = cpu_to_le16(cfg->icid); -- cmd_params->portal_id = cpu_to_le32(cfg->portal_id); -- strncpy(cmd_params->label, cfg->label, 16); -- cmd_params->label[15] = '\0'; -- -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_CREATE_CONT, -- cmd_flags, token); -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dprc_rsp_create_container *)cmd.params; -- *child_container_id = le32_to_cpu(rsp_params->child_container_id); -- *child_portal_offset = le64_to_cpu(rsp_params->child_portal_addr); -- -- return 0; --} -- --/** -- * dprc_destroy_container() - Destroy child container. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @child_container_id: ID of the container to destroy -- * -- * This function terminates the child container, so following this call the -- * child container ID becomes invalid. -- * -- * Notes: -- * - All resources and objects of the destroyed container are returned to the -- * parent container or destroyed if were created be the destroyed container. -- * - This function destroy all the child containers of the specified -- * container prior to destroying the container itself. -- * -- * warning: Only the parent container is allowed to destroy a child policy -- * Container 0 can't be destroyed -- * -- * Return: '0' on Success; Error code otherwise. -- * -- */ --int dprc_destroy_container(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- int child_container_id) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_destroy_container *cmd_params; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_DESTROY_CONT, -- cmd_flags, token); -- cmd_params = (struct dprc_cmd_destroy_container *)cmd.params; -- cmd_params->child_container_id = cpu_to_le32(child_container_id); -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} -- --/** -- * dprc_reset_container - Reset child container. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @child_container_id: ID of the container to reset -- * -- * In case a software context crashes or becomes non-responsive, the parent -- * may wish to reset its resources container before the software context is -- * restarted. -- * -- * This routine informs all objects assigned to the child container that the -- * container is being reset, so they may perform any cleanup operations that are -- * needed. All objects handles that were owned by the child container shall be -- * closed. -- * -- * Note that such request may be submitted even if the child software context -- * has not crashed, but the resulting object cleanup operations will not be -- * aware of that. -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_reset_container(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- int child_container_id) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_reset_container *cmd_params; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_RESET_CONT, -- cmd_flags, token); -- cmd_params = (struct dprc_cmd_reset_container *)cmd.params; -- cmd_params->child_container_id = cpu_to_le32(child_container_id); -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} -- --/** -- * dprc_get_irq() - Get IRQ information from the DPRC. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @irq_index: The interrupt index to configure -- * @type: Interrupt type: 0 represents message interrupt -- * type (both irq_addr and irq_val are valid) -- * @irq_cfg: IRQ attributes -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_get_irq(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- int *type, -- struct dprc_irq_cfg *irq_cfg) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_get_irq *cmd_params; -- struct dprc_rsp_get_irq *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ, -- cmd_flags, -- token); -- cmd_params = (struct dprc_cmd_get_irq *)cmd.params; -- cmd_params->irq_index = irq_index; -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dprc_rsp_get_irq *)cmd.params; -- irq_cfg->val = le32_to_cpu(rsp_params->irq_val); -- irq_cfg->paddr = le64_to_cpu(rsp_params->irq_addr); -- irq_cfg->irq_num = le32_to_cpu(rsp_params->irq_num); -- *type = le32_to_cpu(rsp_params->type); -- -- return 0; --} -- --/** -- * dprc_set_irq() - Set IRQ information for the DPRC to trigger an interrupt. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @irq_index: Identifies the interrupt index to configure -- * @irq_cfg: IRQ configuration -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_set_irq(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- struct dprc_irq_cfg *irq_cfg) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_set_irq *cmd_params; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ, -- cmd_flags, -- token); -- cmd_params = (struct dprc_cmd_set_irq *)cmd.params; -- cmd_params->irq_val = cpu_to_le32(irq_cfg->val); -- cmd_params->irq_index = irq_index; -- cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr); -- cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num); -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} -- --/** -- * dprc_get_irq_enable() - Get overall interrupt state. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @irq_index: The interrupt index to configure -- * @en: Returned interrupt state - enable = 1, disable = 0 -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_get_irq_enable(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u8 *en) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_get_irq_enable *cmd_params; -- struct dprc_rsp_get_irq_enable *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_ENABLE, -- cmd_flags, token); -- cmd_params = (struct dprc_cmd_get_irq_enable *)cmd.params; -- cmd_params->irq_index = irq_index; -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dprc_rsp_get_irq_enable *)cmd.params; -- *en = rsp_params->enabled & DPRC_ENABLE; -- -- return 0; --} -- --/** -- * dprc_set_irq_enable() - Set overall interrupt state. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @irq_index: The interrupt index to configure -- * @en: Interrupt state - enable = 1, disable = 0 -- * -- * Allows GPP software to control when interrupts are generated. -- * Each interrupt can have up to 32 causes. The enable/disable control's the -- * overall interrupt state. if the interrupt is disabled no causes will cause -- * an interrupt. -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_set_irq_enable(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u8 en) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_set_irq_enable *cmd_params; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_ENABLE, -- cmd_flags, token); -- cmd_params = (struct dprc_cmd_set_irq_enable *)cmd.params; -- cmd_params->enable = en & DPRC_ENABLE; -- cmd_params->irq_index = irq_index; -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} -- --/** -- * dprc_get_irq_mask() - Get interrupt mask. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @irq_index: The interrupt index to configure -- * @mask: Returned event mask to trigger interrupt -- * -- * Every interrupt can have up to 32 causes and the interrupt model supports -- * masking/unmasking each cause independently -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_get_irq_mask(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u32 *mask) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_get_irq_mask *cmd_params; -- struct dprc_rsp_get_irq_mask *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_MASK, -- cmd_flags, token); -- cmd_params = (struct dprc_cmd_get_irq_mask *)cmd.params; -- cmd_params->irq_index = irq_index; -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dprc_rsp_get_irq_mask *)cmd.params; -- *mask = le32_to_cpu(rsp_params->mask); -- -- return 0; --} -- --/** -- * dprc_set_irq_mask() - Set interrupt mask. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @irq_index: The interrupt index to configure -- * @mask: event mask to trigger interrupt; -- * each bit: -- * 0 = ignore event -- * 1 = consider event for asserting irq -- * -- * Every interrupt can have up to 32 causes and the interrupt model supports -- * masking/unmasking each cause independently -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_set_irq_mask(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u32 mask) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_set_irq_mask *cmd_params; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_MASK, -- cmd_flags, token); -- cmd_params = (struct dprc_cmd_set_irq_mask *)cmd.params; -- cmd_params->mask = cpu_to_le32(mask); -- cmd_params->irq_index = irq_index; -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} -- --/** -- * dprc_get_irq_status() - Get the current status of any pending interrupts. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @irq_index: The interrupt index to configure -- * @status: Returned interrupts status - one bit per cause: -- * 0 = no interrupt pending -- * 1 = interrupt pending -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_get_irq_status(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u32 *status) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_get_irq_status *cmd_params; -- struct dprc_rsp_get_irq_status *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_STATUS, -- cmd_flags, token); -- cmd_params = (struct dprc_cmd_get_irq_status *)cmd.params; -- cmd_params->status = cpu_to_le32(*status); -- cmd_params->irq_index = irq_index; -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dprc_rsp_get_irq_status *)cmd.params; -- *status = le32_to_cpu(rsp_params->status); -- -- return 0; --} -- --/** -- * dprc_clear_irq_status() - Clear a pending interrupt's status -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @irq_index: The interrupt index to configure -- * @status: bits to clear (W1C) - one bit per cause: -- * 0 = don't change -- * 1 = clear status bit -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_clear_irq_status(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u32 status) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_clear_irq_status *cmd_params; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLEAR_IRQ_STATUS, -- cmd_flags, token); -- cmd_params = (struct dprc_cmd_clear_irq_status *)cmd.params; -- cmd_params->status = cpu_to_le32(status); -- cmd_params->irq_index = irq_index; -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} -- --/** -- * dprc_get_attributes() - Obtains container attributes -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @attributes Returned container attributes -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_get_attributes(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- struct dprc_attributes *attr) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_rsp_get_attributes *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_ATTR, -- cmd_flags, -- token); -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dprc_rsp_get_attributes *)cmd.params; -- attr->container_id = le32_to_cpu(rsp_params->container_id); -- attr->icid = le16_to_cpu(rsp_params->icid); -- attr->options = le32_to_cpu(rsp_params->options); -- attr->portal_id = le32_to_cpu(rsp_params->portal_id); -- attr->version.major = le16_to_cpu(rsp_params->version_major); -- attr->version.minor = le16_to_cpu(rsp_params->version_minor); -- -- return 0; --} -- --/** -- * dprc_set_res_quota() - Set allocation policy for a specific resource/object -- * type in a child container -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @child_container_id: ID of the child container -- * @type: Resource/object type -- * @quota: Sets the maximum number of resources of the selected type -- * that the child container is allowed to allocate from its parent; -- * when quota is set to -1, the policy is the same as container's -- * general policy. -- * -- * Allocation policy determines whether or not a container may allocate -- * resources from its parent. Each container has a 'global' allocation policy -- * that is set when the container is created. -- * -- * This function sets allocation policy for a specific resource type. -- * The default policy for all resource types matches the container's 'global' -- * allocation policy. -- * -- * Return: '0' on Success; Error code otherwise. -- * -- * @warning Only the parent container is allowed to change a child policy. -- */ --int dprc_set_res_quota(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- int child_container_id, -- char *type, -- u16 quota) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_set_res_quota *cmd_params; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_RES_QUOTA, -- cmd_flags, token); -- cmd_params = (struct dprc_cmd_set_res_quota *)cmd.params; -- cmd_params->child_container_id = cpu_to_le32(child_container_id); -- cmd_params->quota = cpu_to_le16(quota); -- strncpy(cmd_params->type, type, 16); -- cmd_params->type[15] = '\0'; -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} -- --/** -- * dprc_get_res_quota() - Gets the allocation policy of a specific -- * resource/object type in a child container -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @child_container_id; ID of the child container -- * @type: resource/object type -- * @quota: Returnes the maximum number of resources of the selected type -- * that the child container is allowed to allocate from the parent; -- * when quota is set to -1, the policy is the same as container's -- * general policy. -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_get_res_quota(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- int child_container_id, -- char *type, -- u16 *quota) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_get_res_quota *cmd_params; -- struct dprc_rsp_get_res_quota *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_QUOTA, -- cmd_flags, token); -- cmd_params = (struct dprc_cmd_get_res_quota *)cmd.params; -- cmd_params->child_container_id = cpu_to_le32(child_container_id); -- strncpy(cmd_params->type, type, 16); -- cmd_params->type[15] = '\0'; -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dprc_rsp_get_res_quota *)cmd.params; -- *quota = le16_to_cpu(rsp_params->quota); -- -- return 0; --} -- --/** -- * dprc_assign() - Assigns objects or resource to a child container. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @container_id: ID of the child container -- * @res_req: Describes the type and amount of resources to -- * assign to the given container -- * -- * Assignment is usually done by a parent (this DPRC) to one of its child -- * containers. -- * -- * According to the DPRC allocation policy, the assigned resources may be taken -- * (allocated) from the container's ancestors, if not enough resources are -- * available in the container itself. -- * -- * The type of assignment depends on the dprc_res_req options, as follows: -- * - DPRC_RES_REQ_OPT_EXPLICIT: indicates that assigned resources should have -- * the explicit base ID specified at the id_base_align field of res_req. -- * - DPRC_RES_REQ_OPT_ALIGNED: indicates that the assigned resources should be -- * aligned to the value given at id_base_align field of res_req. -- * - DPRC_RES_REQ_OPT_PLUGGED: Relevant only for object assignment, -- * and indicates that the object must be set to the plugged state. -- * -- * A container may use this function with its own ID in order to change a -- * object state to plugged or unplugged. -- * -- * If IRQ information has been set in the child DPRC, it will signal an -- * interrupt following every change in its object assignment. -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_assign(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- int container_id, -- struct dprc_res_req *res_req) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_assign *cmd_params; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_ASSIGN, -- cmd_flags, token); -- cmd_params = (struct dprc_cmd_assign *)cmd.params; -- cmd_params->container_id = cpu_to_le32(container_id); -- cmd_params->options = cpu_to_le32(res_req->options); -- cmd_params->num = cpu_to_le32(res_req->num); -- cmd_params->id_base_align = cpu_to_le32(res_req->id_base_align); -- strncpy(cmd_params->type, res_req->type, 16); -- cmd_params->type[15] = '\0'; -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} -- --/** -- * dprc_unassign() - Un-assigns objects or resources from a child container -- * and moves them into this (parent) DPRC. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @child_container_id: ID of the child container -- * @res_req: Describes the type and amount of resources to un-assign from -- * the child container -- * -- * Un-assignment of objects can succeed only if the object is not in the -- * plugged or opened state. -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_unassign(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- int child_container_id, -- struct dprc_res_req *res_req) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_unassign *cmd_params; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_UNASSIGN, -- cmd_flags, -- token); -- cmd_params = (struct dprc_cmd_unassign *)cmd.params; -- cmd_params->child_container_id = cpu_to_le32(child_container_id); -- cmd_params->options = cpu_to_le32(res_req->options); -- cmd_params->num = cpu_to_le32(res_req->num); -- cmd_params->id_base_align = cpu_to_le32(res_req->id_base_align); -- strncpy(cmd_params->type, res_req->type, 16); -- cmd_params->type[15] = '\0'; -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} -- --/** -- * dprc_get_pool_count() - Get the number of dprc's pools -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @mc_io: Pointer to MC portal's I/O object -- * @token: Token of DPRC object -- * @pool_count: Returned number of resource pools in the dprc -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_get_pool_count(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- int *pool_count) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_rsp_get_pool_count *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_POOL_COUNT, -- cmd_flags, token); -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dprc_rsp_get_pool_count *)cmd.params; -- *pool_count = le32_to_cpu(rsp_params->pool_count); -- -- return 0; --} -- --/** -- * dprc_get_pool() - Get the type (string) of a certain dprc's pool -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @pool_index; Index of the pool to be queried (< pool_count) -- * @type: The type of the pool -- * -- * The pool types retrieved one by one by incrementing -- * pool_index up to (not including) the value of pool_count returned -- * from dprc_get_pool_count(). dprc_get_pool_count() must -- * be called prior to dprc_get_pool(). -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_get_pool(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- int pool_index, -- char *type) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_get_pool *cmd_params; -- struct dprc_rsp_get_pool *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_POOL, -- cmd_flags, -- token); -- cmd_params = (struct dprc_cmd_get_pool *)cmd.params; -- cmd_params->pool_index = cpu_to_le32(pool_index); -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dprc_rsp_get_pool *)cmd.params; -- strncpy(type, rsp_params->type, 16); -- type[15] = '\0'; -- -- return 0; --} -- --/** -- * dprc_get_obj_count() - Obtains the number of objects in the DPRC -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @obj_count: Number of objects assigned to the DPRC -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_get_obj_count(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- int *obj_count) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_rsp_get_obj_count *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_COUNT, -- cmd_flags, token); -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dprc_rsp_get_obj_count *)cmd.params; -- *obj_count = le32_to_cpu(rsp_params->obj_count); -- -- return 0; --} --EXPORT_SYMBOL(dprc_get_obj_count); -- --/** -- * dprc_get_obj() - Get general information on an object -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @obj_index: Index of the object to be queried (< obj_count) -- * @obj_desc: Returns the requested object descriptor -- * -- * The object descriptors are retrieved one by one by incrementing -- * obj_index up to (not including) the value of obj_count returned -- * from dprc_get_obj_count(). dprc_get_obj_count() must -- * be called prior to dprc_get_obj(). -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_get_obj(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- int obj_index, -- struct dprc_obj_desc *obj_desc) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_get_obj *cmd_params; -- struct dprc_rsp_get_obj *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ, -- cmd_flags, -- token); -- cmd_params = (struct dprc_cmd_get_obj *)cmd.params; -- cmd_params->obj_index = cpu_to_le32(obj_index); -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dprc_rsp_get_obj *)cmd.params; -- obj_desc->id = le32_to_cpu(rsp_params->id); -- obj_desc->vendor = le16_to_cpu(rsp_params->vendor); -- obj_desc->irq_count = rsp_params->irq_count; -- obj_desc->region_count = rsp_params->region_count; -- obj_desc->state = le32_to_cpu(rsp_params->state); -- obj_desc->ver_major = le16_to_cpu(rsp_params->version_major); -- obj_desc->ver_minor = le16_to_cpu(rsp_params->version_minor); -- obj_desc->flags = le16_to_cpu(rsp_params->flags); -- strncpy(obj_desc->type, rsp_params->type, 16); -- obj_desc->type[15] = '\0'; -- strncpy(obj_desc->label, rsp_params->label, 16); -- obj_desc->label[15] = '\0'; -- return 0; --} --EXPORT_SYMBOL(dprc_get_obj); -- --/** -- * dprc_get_obj_desc() - Get object descriptor. -- * -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @obj_type: The type of the object to get its descriptor. -- * @obj_id: The id of the object to get its descriptor -- * @obj_desc: The returned descriptor to fill and return to the user -- * -- * Return: '0' on Success; Error code otherwise. -- * -- */ --int dprc_get_obj_desc(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- char *obj_type, -- int obj_id, -- struct dprc_obj_desc *obj_desc) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_get_obj_desc *cmd_params; -- struct dprc_rsp_get_obj_desc *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_DESC, -- cmd_flags, -- token); -- cmd_params = (struct dprc_cmd_get_obj_desc *)cmd.params; -- cmd_params->obj_id = cpu_to_le32(obj_id); -- strncpy(cmd_params->type, obj_type, 16); -- cmd_params->type[15] = '\0'; -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dprc_rsp_get_obj_desc *)cmd.params; -- obj_desc->id = le32_to_cpu(rsp_params->id); -- obj_desc->vendor = le16_to_cpu(rsp_params->vendor); -- obj_desc->irq_count = rsp_params->irq_count; -- obj_desc->region_count = rsp_params->region_count; -- obj_desc->state = le32_to_cpu(rsp_params->state); -- obj_desc->ver_major = le16_to_cpu(rsp_params->version_major); -- obj_desc->ver_minor = le16_to_cpu(rsp_params->version_minor); -- obj_desc->flags = le16_to_cpu(rsp_params->flags); -- strncpy(obj_desc->type, rsp_params->type, 16); -- obj_desc->type[15] = '\0'; -- strncpy(obj_desc->label, rsp_params->label, 16); -- obj_desc->label[15] = '\0'; -- -- return 0; --} --EXPORT_SYMBOL(dprc_get_obj_desc); -- --/** -- * dprc_set_obj_irq() - Set IRQ information for object to trigger an interrupt. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @obj_type: Type of the object to set its IRQ -- * @obj_id: ID of the object to set its IRQ -- * @irq_index: The interrupt index to configure -- * @irq_cfg: IRQ configuration -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_set_obj_irq(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- char *obj_type, -- int obj_id, -- u8 irq_index, -- struct dprc_irq_cfg *irq_cfg) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_set_obj_irq *cmd_params; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_OBJ_IRQ, -- cmd_flags, -- token); -- cmd_params = (struct dprc_cmd_set_obj_irq *)cmd.params; -- cmd_params->irq_val = cpu_to_le32(irq_cfg->val); -- cmd_params->irq_index = irq_index; -- cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr); -- cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num); -- cmd_params->obj_id = cpu_to_le32(obj_id); -- strncpy(cmd_params->obj_type, obj_type, 16); -- cmd_params->obj_type[15] = '\0'; -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} --EXPORT_SYMBOL(dprc_set_obj_irq); -- --/** -- * dprc_get_obj_irq() - Get IRQ information from object. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @obj_type: Type od the object to get its IRQ -- * @obj_id: ID of the object to get its IRQ -- * @irq_index: The interrupt index to configure -- * @type: Interrupt type: 0 represents message interrupt -- * type (both irq_addr and irq_val are valid) -- * @irq_cfg: The returned IRQ attributes -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_get_obj_irq(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- char *obj_type, -- int obj_id, -- u8 irq_index, -- int *type, -- struct dprc_irq_cfg *irq_cfg) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_get_obj_irq *cmd_params; -- struct dprc_rsp_get_obj_irq *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_IRQ, -- cmd_flags, -- token); -- cmd_params = (struct dprc_cmd_get_obj_irq *)cmd.params; -- cmd_params->obj_id = cpu_to_le32(obj_id); -- cmd_params->irq_index = irq_index; -- strncpy(cmd_params->obj_type, obj_type, 16); -- cmd_params->obj_type[15] = '\0'; -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dprc_rsp_get_obj_irq *)cmd.params; -- irq_cfg->val = le32_to_cpu(rsp_params->irq_val); -- irq_cfg->paddr = le64_to_cpu(rsp_params->irq_addr); -- irq_cfg->irq_num = le32_to_cpu(rsp_params->irq_num); -- *type = le32_to_cpu(rsp_params->type); -- -- return 0; --} --EXPORT_SYMBOL(dprc_get_obj_irq); -- --/** -- * dprc_get_res_count() - Obtains the number of free resources that are assigned -- * to this container, by pool type -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @type: pool type -- * @res_count: Returned number of free resources of the given -- * resource type that are assigned to this DPRC -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_get_res_count(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- char *type, -- int *res_count) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_get_res_count *cmd_params; -- struct dprc_rsp_get_res_count *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_COUNT, -- cmd_flags, token); -- cmd_params = (struct dprc_cmd_get_res_count *)cmd.params; -- strncpy(cmd_params->type, type, 16); -- cmd_params->type[15] = '\0'; -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dprc_rsp_get_res_count *)cmd.params; -- *res_count = le32_to_cpu(rsp_params->res_count); -- -- return 0; --} --EXPORT_SYMBOL(dprc_get_res_count); -- --/** -- * dprc_get_res_ids() - Obtains IDs of free resources in the container -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @type: pool type -- * @range_desc: range descriptor -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_get_res_ids(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- char *type, -- struct dprc_res_ids_range_desc *range_desc) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_get_res_ids *cmd_params; -- struct dprc_rsp_get_res_ids *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_IDS, -- cmd_flags, token); -- cmd_params = (struct dprc_cmd_get_res_ids *)cmd.params; -- cmd_params->iter_status = range_desc->iter_status; -- cmd_params->base_id = cpu_to_le32(range_desc->base_id); -- cmd_params->last_id = cpu_to_le32(range_desc->last_id); -- strncpy(cmd_params->type, type, 16); -- cmd_params->type[15] = '\0'; -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dprc_rsp_get_res_ids *)cmd.params; -- range_desc->iter_status = rsp_params->iter_status; -- range_desc->base_id = le32_to_cpu(rsp_params->base_id); -- range_desc->last_id = le32_to_cpu(rsp_params->last_id); -- -- return 0; --} --EXPORT_SYMBOL(dprc_get_res_ids); -- --/** -- * dprc_get_obj_region() - Get region information for a specified object. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @obj_type; Object type as returned in dprc_get_obj() -- * @obj_id: Unique object instance as returned in dprc_get_obj() -- * @region_index: The specific region to query -- * @region_desc: Returns the requested region descriptor -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_get_obj_region(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- char *obj_type, -- int obj_id, -- u8 region_index, -- struct dprc_region_desc *region_desc) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_get_obj_region *cmd_params; -- struct dprc_rsp_get_obj_region *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG, -- cmd_flags, token); -- cmd_params = (struct dprc_cmd_get_obj_region *)cmd.params; -- cmd_params->obj_id = cpu_to_le32(obj_id); -- cmd_params->region_index = region_index; -- strncpy(cmd_params->obj_type, obj_type, 16); -- cmd_params->obj_type[15] = '\0'; -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dprc_rsp_get_obj_region *)cmd.params; -- region_desc->base_offset = le64_to_cpu(rsp_params->base_addr); -- region_desc->size = le32_to_cpu(rsp_params->size); -- -- return 0; --} --EXPORT_SYMBOL(dprc_get_obj_region); -- --/** -- * dprc_set_obj_label() - Set object label. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @obj_type: Object's type -- * @obj_id: Object's ID -- * @label: The required label. The maximum length is 16 chars. -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_set_obj_label(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- char *obj_type, -- int obj_id, -- char *label) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_set_obj_label *cmd_params; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_OBJ_LABEL, -- cmd_flags, -- token); -- cmd_params = (struct dprc_cmd_set_obj_label *)cmd.params; -- cmd_params->obj_id = cpu_to_le32(obj_id); -- strncpy(cmd_params->label, label, 16); -- cmd_params->label[15] = '\0'; -- strncpy(cmd_params->obj_type, obj_type, 16); -- cmd_params->obj_type[15] = '\0'; -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} --EXPORT_SYMBOL(dprc_set_obj_label); -- --/** -- * dprc_connect() - Connect two endpoints to create a network link between them -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @endpoint1: Endpoint 1 configuration parameters -- * @endpoint2: Endpoint 2 configuration parameters -- * @cfg: Connection configuration. The connection configuration is ignored for -- * connections made to DPMAC objects, where rate is retrieved from the -- * MAC configuration. -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_connect(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- const struct dprc_endpoint *endpoint1, -- const struct dprc_endpoint *endpoint2, -- const struct dprc_connection_cfg *cfg) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_connect *cmd_params; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_CONNECT, -- cmd_flags, -- token); -- cmd_params = (struct dprc_cmd_connect *)cmd.params; -- cmd_params->ep1_id = cpu_to_le32(endpoint1->id); -- cmd_params->ep1_interface_id = cpu_to_le32(endpoint1->if_id); -- cmd_params->ep2_id = cpu_to_le32(endpoint2->id); -- cmd_params->ep2_interface_id = cpu_to_le32(endpoint2->if_id); -- strncpy(cmd_params->ep1_type, endpoint1->type, 16); -- cmd_params->ep1_type[15] = '\0'; -- cmd_params->max_rate = cpu_to_le32(cfg->max_rate); -- cmd_params->committed_rate = cpu_to_le32(cfg->committed_rate); -- strncpy(cmd_params->ep2_type, endpoint2->type, 16); -- cmd_params->ep2_type[15] = '\0'; -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} -- --/** -- * dprc_disconnect() - Disconnect one endpoint to remove its network connection -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @endpoint: Endpoint configuration parameters -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dprc_disconnect(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- const struct dprc_endpoint *endpoint) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_disconnect *cmd_params; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_DISCONNECT, -- cmd_flags, -- token); -- cmd_params = (struct dprc_cmd_disconnect *)cmd.params; -- cmd_params->id = cpu_to_le32(endpoint->id); -- cmd_params->interface_id = cpu_to_le32(endpoint->if_id); -- strncpy(cmd_params->type, endpoint->type, 16); -- cmd_params->type[15] = '\0'; -- -- /* send command to mc*/ -- return mc_send_command(mc_io, &cmd); --} -- --/** -- * dprc_get_connection() - Get connected endpoint and link status if connection -- * exists. -- * @mc_io: Pointer to MC portal's I/O object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @token: Token of DPRC object -- * @endpoint1: Endpoint 1 configuration parameters -- * @endpoint2: Returned endpoint 2 configuration parameters -- * @state: Returned link state: -- * 1 - link is up; -- * 0 - link is down; -- * -1 - no connection (endpoint2 information is irrelevant) -- * -- * Return: '0' on Success; -ENAVAIL if connection does not exist. -- */ --int dprc_get_connection(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- const struct dprc_endpoint *endpoint1, -- struct dprc_endpoint *endpoint2, -- int *state) --{ -- struct mc_command cmd = { 0 }; -- struct dprc_cmd_get_connection *cmd_params; -- struct dprc_rsp_get_connection *rsp_params; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONNECTION, -- cmd_flags, -- token); -- cmd_params = (struct dprc_cmd_get_connection *)cmd.params; -- cmd_params->ep1_id = cpu_to_le32(endpoint1->id); -- cmd_params->ep1_interface_id = cpu_to_le32(endpoint1->if_id); -- strncpy(cmd_params->ep1_type, endpoint1->type, 16); -- cmd_params->ep1_type[15] = '\0'; -- -- /* send command to mc*/ -- err = mc_send_command(mc_io, &cmd); -- if (err) -- return err; -- -- /* retrieve response parameters */ -- rsp_params = (struct dprc_rsp_get_connection *)cmd.params; -- endpoint2->id = le32_to_cpu(rsp_params->ep2_id); -- endpoint2->if_id = le32_to_cpu(rsp_params->ep2_interface_id); -- strncpy(endpoint2->type, rsp_params->ep2_type, 16); -- endpoint2->type[15] = '\0'; -- *state = le32_to_cpu(rsp_params->state); -- -- return 0; --} ---- a/drivers/staging/fsl-mc/bus/fsl-mc-private.h -+++ /dev/null -@@ -1,52 +0,0 @@ --/* -- * Freescale Management Complex (MC) bus private declarations -- * -- * Copyright (C) 2016 Freescale Semiconductor, Inc. -- * -- * This file is licensed under the terms of the GNU General Public -- * License version 2. This program is licensed "as is" without any -- * warranty of any kind, whether express or implied. -- */ --#ifndef _FSL_MC_PRIVATE_H_ --#define _FSL_MC_PRIVATE_H_ -- --int __must_check fsl_mc_device_add(struct dprc_obj_desc *obj_desc, -- struct fsl_mc_io *mc_io, -- struct device *parent_dev, -- struct fsl_mc_device **new_mc_dev); -- --void fsl_mc_device_remove(struct fsl_mc_device *mc_dev); -- --int __init dprc_driver_init(void); -- --void dprc_driver_exit(void); -- --int __init fsl_mc_allocator_driver_init(void); -- --void fsl_mc_allocator_driver_exit(void); -- --int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, -- enum fsl_mc_pool_type pool_type, -- struct fsl_mc_resource -- **new_resource); -- --void fsl_mc_resource_free(struct fsl_mc_resource *resource); -- --int fsl_mc_msi_domain_alloc_irqs(struct device *dev, -- unsigned int irq_count); -- --void fsl_mc_msi_domain_free_irqs(struct device *dev); -- --int __init its_fsl_mc_msi_init(void); -- --void its_fsl_mc_msi_cleanup(void); -- --int __must_check fsl_create_mc_io(struct device *dev, -- phys_addr_t mc_portal_phys_addr, -- u32 mc_portal_size, -- struct fsl_mc_device *dpmcp_dev, -- u32 flags, struct fsl_mc_io **new_mc_io); -- --void fsl_destroy_mc_io(struct fsl_mc_io *mc_io); -- --#endif /* _FSL_MC_PRIVATE_H_ */ ---- /dev/null -+++ b/drivers/staging/fsl-mc/include/dpaa2-fd.h -@@ -0,0 +1,681 @@ -+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ -+/* -+ * Copyright 2014-2016 Freescale Semiconductor Inc. -+ * Copyright 2016 NXP -+ * -+ */ -+#ifndef __FSL_DPAA2_FD_H -+#define __FSL_DPAA2_FD_H -+ -+#include <linux/kernel.h> -+ -+/** -+ * DOC: DPAA2 FD - Frame Descriptor APIs for DPAA2 -+ * -+ * Frame Descriptors (FDs) are used to describe frame data in the DPAA2. -+ * Frames can be enqueued and dequeued to Frame Queues (FQs) which are consumed -+ * by the various DPAA accelerators (WRIOP, SEC, PME, DCE) -+ * -+ * There are three types of frames: single, scatter gather, and frame lists. -+ * -+ * The set of APIs in this file must be used to create, manipulate and -+ * query Frame Descriptors. -+ */ -+ -+/** -+ * struct dpaa2_fd - Struct describing FDs -+ * @words: for easier/faster copying the whole FD structure -+ * @addr: address in the FD -+ * @len: length in the FD -+ * @bpid: buffer pool ID -+ * @format_offset: format, offset, and short-length fields -+ * @frc: frame context -+ * @ctrl: control bits...including dd, sc, va, err, etc -+ * @flc: flow context address -+ * -+ * This structure represents the basic Frame Descriptor used in the system. -+ */ -+struct dpaa2_fd { -+ union { -+ u32 words[8]; -+ struct dpaa2_fd_simple { -+ __le64 addr; -+ __le32 len; -+ __le16 bpid; -+ __le16 format_offset; -+ __le32 frc; -+ __le32 ctrl; -+ __le64 flc; -+ } simple; -+ }; -+}; -+ -+#define FD_SHORT_LEN_FLAG_MASK 0x1 -+#define FD_SHORT_LEN_FLAG_SHIFT 14 -+#define FD_SHORT_LEN_MASK 0x3FFFF -+#define FD_OFFSET_MASK 0x0FFF -+#define FD_FORMAT_MASK 0x3 -+#define FD_FORMAT_SHIFT 12 -+#define FD_BPID_MASK 0x3FFF -+#define SG_SHORT_LEN_FLAG_MASK 0x1 -+#define SG_SHORT_LEN_FLAG_SHIFT 14 -+#define SG_SHORT_LEN_MASK 0x1FFFF -+#define SG_OFFSET_MASK 0x0FFF -+#define SG_FORMAT_MASK 0x3 -+#define SG_FORMAT_SHIFT 12 -+#define SG_BPID_MASK 0x3FFF -+#define SG_FINAL_FLAG_MASK 0x1 -+#define SG_FINAL_FLAG_SHIFT 15 -+#define FL_SHORT_LEN_FLAG_MASK 0x1 -+#define FL_SHORT_LEN_FLAG_SHIFT 14 -+#define FL_SHORT_LEN_MASK 0x3FFFF -+#define FL_OFFSET_MASK 0x0FFF -+#define FL_FORMAT_MASK 0x3 -+#define FL_FORMAT_SHIFT 12 -+#define FL_BPID_MASK 0x3FFF -+#define FL_FINAL_FLAG_MASK 0x1 -+#define FL_FINAL_FLAG_SHIFT 15 -+ -+/* Error bits in FD CTRL */ -+#define FD_CTRL_ERR_MASK 0x000000FF -+#define FD_CTRL_UFD 0x00000004 -+#define FD_CTRL_SBE 0x00000008 -+#define FD_CTRL_FLC 0x00000010 -+#define FD_CTRL_FSE 0x00000020 -+#define FD_CTRL_FAERR 0x00000040 -+ -+/* Annotation bits in FD CTRL */ -+#define FD_CTRL_PTA 0x00800000 -+#define FD_CTRL_PTV1 0x00400000 -+ -+enum dpaa2_fd_format { -+ dpaa2_fd_single = 0, -+ dpaa2_fd_list, -+ dpaa2_fd_sg -+}; -+ -+/** -+ * dpaa2_fd_get_addr() - get the addr field of frame descriptor -+ * @fd: the given frame descriptor -+ * -+ * Return the address in the frame descriptor. -+ */ -+static inline dma_addr_t dpaa2_fd_get_addr(const struct dpaa2_fd *fd) -+{ -+ return (dma_addr_t)le64_to_cpu(fd->simple.addr); -+} -+ -+/** -+ * dpaa2_fd_set_addr() - Set the addr field of frame descriptor -+ * @fd: the given frame descriptor -+ * @addr: the address needs to be set in frame descriptor -+ */ -+static inline void dpaa2_fd_set_addr(struct dpaa2_fd *fd, dma_addr_t addr) -+{ -+ fd->simple.addr = cpu_to_le64(addr); -+} -+ -+/** -+ * dpaa2_fd_get_frc() - Get the frame context in the frame descriptor -+ * @fd: the given frame descriptor -+ * -+ * Return the frame context field in the frame descriptor. -+ */ -+static inline u32 dpaa2_fd_get_frc(const struct dpaa2_fd *fd) -+{ -+ return le32_to_cpu(fd->simple.frc); -+} -+ -+/** -+ * dpaa2_fd_set_frc() - Set the frame context in the frame descriptor -+ * @fd: the given frame descriptor -+ * @frc: the frame context needs to be set in frame descriptor -+ */ -+static inline void dpaa2_fd_set_frc(struct dpaa2_fd *fd, u32 frc) -+{ -+ fd->simple.frc = cpu_to_le32(frc); -+} -+ -+/** -+ * dpaa2_fd_get_ctrl() - Get the control bits in the frame descriptor -+ * @fd: the given frame descriptor -+ * -+ * Return the control bits field in the frame descriptor. -+ */ -+static inline u32 dpaa2_fd_get_ctrl(const struct dpaa2_fd *fd) -+{ -+ return le32_to_cpu(fd->simple.ctrl); -+} -+ -+/** -+ * dpaa2_fd_set_ctrl() - Set the control bits in the frame descriptor -+ * @fd: the given frame descriptor -+ * @ctrl: the control bits to be set in the frame descriptor -+ */ -+static inline void dpaa2_fd_set_ctrl(struct dpaa2_fd *fd, u32 ctrl) -+{ -+ fd->simple.ctrl = cpu_to_le32(ctrl); -+} -+ -+/** -+ * dpaa2_fd_get_flc() - Get the flow context in the frame descriptor -+ * @fd: the given frame descriptor -+ * -+ * Return the flow context in the frame descriptor. -+ */ -+static inline dma_addr_t dpaa2_fd_get_flc(const struct dpaa2_fd *fd) -+{ -+ return (dma_addr_t)le64_to_cpu(fd->simple.flc); -+} -+ -+/** -+ * dpaa2_fd_set_flc() - Set the flow context field of frame descriptor -+ * @fd: the given frame descriptor -+ * @flc_addr: the flow context needs to be set in frame descriptor -+ */ -+static inline void dpaa2_fd_set_flc(struct dpaa2_fd *fd, dma_addr_t flc_addr) -+{ -+ fd->simple.flc = cpu_to_le64(flc_addr); -+} -+ -+static inline bool dpaa2_fd_short_len(const struct dpaa2_fd *fd) -+{ -+ return !!((le16_to_cpu(fd->simple.format_offset) >> -+ FD_SHORT_LEN_FLAG_SHIFT) & FD_SHORT_LEN_FLAG_MASK); -+} -+ -+/** -+ * dpaa2_fd_get_len() - Get the length in the frame descriptor -+ * @fd: the given frame descriptor -+ * -+ * Return the length field in the frame descriptor. -+ */ -+static inline u32 dpaa2_fd_get_len(const struct dpaa2_fd *fd) -+{ -+ if (dpaa2_fd_short_len(fd)) -+ return le32_to_cpu(fd->simple.len) & FD_SHORT_LEN_MASK; -+ -+ return le32_to_cpu(fd->simple.len); -+} -+ -+/** -+ * dpaa2_fd_set_len() - Set the length field of frame descriptor -+ * @fd: the given frame descriptor -+ * @len: the length needs to be set in frame descriptor -+ */ -+static inline void dpaa2_fd_set_len(struct dpaa2_fd *fd, u32 len) -+{ -+ fd->simple.len = cpu_to_le32(len); -+} -+ -+/** -+ * dpaa2_fd_get_offset() - Get the offset field in the frame descriptor -+ * @fd: the given frame descriptor -+ * -+ * Return the offset. -+ */ -+static inline uint16_t dpaa2_fd_get_offset(const struct dpaa2_fd *fd) -+{ -+ return le16_to_cpu(fd->simple.format_offset) & FD_OFFSET_MASK; -+} -+ -+/** -+ * dpaa2_fd_set_offset() - Set the offset field of frame descriptor -+ * @fd: the given frame descriptor -+ * @offset: the offset needs to be set in frame descriptor -+ */ -+static inline void dpaa2_fd_set_offset(struct dpaa2_fd *fd, uint16_t offset) -+{ -+ fd->simple.format_offset &= cpu_to_le16(~FD_OFFSET_MASK); -+ fd->simple.format_offset |= cpu_to_le16(offset); -+} -+ -+/** -+ * dpaa2_fd_get_format() - Get the format field in the frame descriptor -+ * @fd: the given frame descriptor -+ * -+ * Return the format. -+ */ -+static inline enum dpaa2_fd_format dpaa2_fd_get_format( -+ const struct dpaa2_fd *fd) -+{ -+ return (enum dpaa2_fd_format)((le16_to_cpu(fd->simple.format_offset) -+ >> FD_FORMAT_SHIFT) & FD_FORMAT_MASK); -+} -+ -+/** -+ * dpaa2_fd_set_format() - Set the format field of frame descriptor -+ * @fd: the given frame descriptor -+ * @format: the format needs to be set in frame descriptor -+ */ -+static inline void dpaa2_fd_set_format(struct dpaa2_fd *fd, -+ enum dpaa2_fd_format format) -+{ -+ fd->simple.format_offset &= -+ cpu_to_le16(~(FD_FORMAT_MASK << FD_FORMAT_SHIFT)); -+ fd->simple.format_offset |= cpu_to_le16(format << FD_FORMAT_SHIFT); -+} -+ -+/** -+ * dpaa2_fd_get_bpid() - Get the bpid field in the frame descriptor -+ * @fd: the given frame descriptor -+ * -+ * Return the buffer pool id. -+ */ -+static inline uint16_t dpaa2_fd_get_bpid(const struct dpaa2_fd *fd) -+{ -+ return le16_to_cpu(fd->simple.bpid) & FD_BPID_MASK; -+} -+ -+/** -+ * dpaa2_fd_set_bpid() - Set the bpid field of frame descriptor -+ * @fd: the given frame descriptor -+ * @bpid: buffer pool id to be set -+ */ -+static inline void dpaa2_fd_set_bpid(struct dpaa2_fd *fd, uint16_t bpid) -+{ -+ fd->simple.bpid &= cpu_to_le16(~(FD_BPID_MASK)); -+ fd->simple.bpid |= cpu_to_le16(bpid); -+} -+ -+/** -+ * struct dpaa2_sg_entry - the scatter-gathering structure -+ * @addr: address of the sg entry -+ * @len: length in this sg entry -+ * @bpid: buffer pool id -+ * @format_offset: format and offset fields -+ */ -+struct dpaa2_sg_entry { -+ __le64 addr; -+ __le32 len; -+ __le16 bpid; -+ __le16 format_offset; -+}; -+ -+enum dpaa2_sg_format { -+ dpaa2_sg_single = 0, -+ dpaa2_sg_frame_data, -+ dpaa2_sg_sgt_ext -+}; -+ -+/* Accessors for SG entry fields */ -+ -+/** -+ * dpaa2_sg_get_addr() - Get the address from SG entry -+ * @sg: the given scatter-gathering object -+ * -+ * Return the address. -+ */ -+static inline dma_addr_t dpaa2_sg_get_addr(const struct dpaa2_sg_entry *sg) -+{ -+ return (dma_addr_t)le64_to_cpu(sg->addr); -+} -+ -+/** -+ * dpaa2_sg_set_addr() - Set the address in SG entry -+ * @sg: the given scatter-gathering object -+ * @addr: the address to be set -+ */ -+static inline void dpaa2_sg_set_addr(struct dpaa2_sg_entry *sg, dma_addr_t addr) -+{ -+ sg->addr = cpu_to_le64(addr); -+} -+ -+static inline bool dpaa2_sg_short_len(const struct dpaa2_sg_entry *sg) -+{ -+ return !!((le16_to_cpu(sg->format_offset) >> SG_SHORT_LEN_FLAG_SHIFT) -+ & SG_SHORT_LEN_FLAG_MASK); -+} -+ -+/** -+ * dpaa2_sg_get_len() - Get the length in SG entry -+ * @sg: the given scatter-gathering object -+ * -+ * Return the length. -+ */ -+static inline u32 dpaa2_sg_get_len(const struct dpaa2_sg_entry *sg) -+{ -+ if (dpaa2_sg_short_len(sg)) -+ return le32_to_cpu(sg->len) & SG_SHORT_LEN_MASK; -+ -+ return le32_to_cpu(sg->len); -+} -+ -+/** -+ * dpaa2_sg_set_len() - Set the length in SG entry -+ * @sg: the given scatter-gathering object -+ * @len: the length to be set -+ */ -+static inline void dpaa2_sg_set_len(struct dpaa2_sg_entry *sg, u32 len) -+{ -+ sg->len = cpu_to_le32(len); -+} -+ -+/** -+ * dpaa2_sg_get_offset() - Get the offset in SG entry -+ * @sg: the given scatter-gathering object -+ * -+ * Return the offset. -+ */ -+static inline u16 dpaa2_sg_get_offset(const struct dpaa2_sg_entry *sg) -+{ -+ return le16_to_cpu(sg->format_offset) & SG_OFFSET_MASK; -+} -+ -+/** -+ * dpaa2_sg_set_offset() - Set the offset in SG entry -+ * @sg: the given scatter-gathering object -+ * @offset: the offset to be set -+ */ -+static inline void dpaa2_sg_set_offset(struct dpaa2_sg_entry *sg, -+ u16 offset) -+{ -+ sg->format_offset &= cpu_to_le16(~SG_OFFSET_MASK); -+ sg->format_offset |= cpu_to_le16(offset); -+} -+ -+/** -+ * dpaa2_sg_get_format() - Get the SG format in SG entry -+ * @sg: the given scatter-gathering object -+ * -+ * Return the format. -+ */ -+static inline enum dpaa2_sg_format -+ dpaa2_sg_get_format(const struct dpaa2_sg_entry *sg) -+{ -+ return (enum dpaa2_sg_format)((le16_to_cpu(sg->format_offset) -+ >> SG_FORMAT_SHIFT) & SG_FORMAT_MASK); -+} -+ -+/** -+ * dpaa2_sg_set_format() - Set the SG format in SG entry -+ * @sg: the given scatter-gathering object -+ * @format: the format to be set -+ */ -+static inline void dpaa2_sg_set_format(struct dpaa2_sg_entry *sg, -+ enum dpaa2_sg_format format) -+{ -+ sg->format_offset &= cpu_to_le16(~(SG_FORMAT_MASK << SG_FORMAT_SHIFT)); -+ sg->format_offset |= cpu_to_le16(format << SG_FORMAT_SHIFT); -+} -+ -+/** -+ * dpaa2_sg_get_bpid() - Get the buffer pool id in SG entry -+ * @sg: the given scatter-gathering object -+ * -+ * Return the bpid. -+ */ -+static inline u16 dpaa2_sg_get_bpid(const struct dpaa2_sg_entry *sg) -+{ -+ return le16_to_cpu(sg->bpid) & SG_BPID_MASK; -+} -+ -+/** -+ * dpaa2_sg_set_bpid() - Set the buffer pool id in SG entry -+ * @sg: the given scatter-gathering object -+ * @bpid: the bpid to be set -+ */ -+static inline void dpaa2_sg_set_bpid(struct dpaa2_sg_entry *sg, u16 bpid) -+{ -+ sg->bpid &= cpu_to_le16(~(SG_BPID_MASK)); -+ sg->bpid |= cpu_to_le16(bpid); -+} -+ -+/** -+ * dpaa2_sg_is_final() - Check final bit in SG entry -+ * @sg: the given scatter-gathering object -+ * -+ * Return bool. -+ */ -+static inline bool dpaa2_sg_is_final(const struct dpaa2_sg_entry *sg) -+{ -+ return !!(le16_to_cpu(sg->format_offset) >> SG_FINAL_FLAG_SHIFT); -+} -+ -+/** -+ * dpaa2_sg_set_final() - Set the final bit in SG entry -+ * @sg: the given scatter-gathering object -+ * @final: the final boolean to be set -+ */ -+static inline void dpaa2_sg_set_final(struct dpaa2_sg_entry *sg, bool final) -+{ -+ sg->format_offset &= cpu_to_le16((~(SG_FINAL_FLAG_MASK -+ << SG_FINAL_FLAG_SHIFT)) & 0xFFFF); -+ sg->format_offset |= cpu_to_le16(final << SG_FINAL_FLAG_SHIFT); -+} -+ -+/** -+ * struct dpaa2_fl_entry - structure for frame list entry. -+ * @addr: address in the FLE -+ * @len: length in the FLE -+ * @bpid: buffer pool ID -+ * @format_offset: format, offset, and short-length fields -+ * @frc: frame context -+ * @ctrl: control bits...including pta, pvt1, pvt2, err, etc -+ * @flc: flow context address -+ */ -+struct dpaa2_fl_entry { -+ __le64 addr; -+ __le32 len; -+ __le16 bpid; -+ __le16 format_offset; -+ __le32 frc; -+ __le32 ctrl; -+ __le64 flc; -+}; -+ -+enum dpaa2_fl_format { -+ dpaa2_fl_single = 0, -+ dpaa2_fl_res, -+ dpaa2_fl_sg -+}; -+ -+/** -+ * dpaa2_fl_get_addr() - get the addr field of FLE -+ * @fle: the given frame list entry -+ * -+ * Return the address in the frame list entry. -+ */ -+static inline dma_addr_t dpaa2_fl_get_addr(const struct dpaa2_fl_entry *fle) -+{ -+ return (dma_addr_t)le64_to_cpu(fle->addr); -+} -+ -+/** -+ * dpaa2_fl_set_addr() - Set the addr field of FLE -+ * @fle: the given frame list entry -+ * @addr: the address needs to be set in frame list entry -+ */ -+static inline void dpaa2_fl_set_addr(struct dpaa2_fl_entry *fle, -+ dma_addr_t addr) -+{ -+ fle->addr = cpu_to_le64(addr); -+} -+ -+/** -+ * dpaa2_fl_get_frc() - Get the frame context in the FLE -+ * @fle: the given frame list entry -+ * -+ * Return the frame context field in the frame lsit entry. -+ */ -+static inline u32 dpaa2_fl_get_frc(const struct dpaa2_fl_entry *fle) -+{ -+ return le32_to_cpu(fle->frc); -+} -+ -+/** -+ * dpaa2_fl_set_frc() - Set the frame context in the FLE -+ * @fle: the given frame list entry -+ * @frc: the frame context needs to be set in frame list entry -+ */ -+static inline void dpaa2_fl_set_frc(struct dpaa2_fl_entry *fle, u32 frc) -+{ -+ fle->frc = cpu_to_le32(frc); -+} -+ -+/** -+ * dpaa2_fl_get_ctrl() - Get the control bits in the FLE -+ * @fle: the given frame list entry -+ * -+ * Return the control bits field in the frame list entry. -+ */ -+static inline u32 dpaa2_fl_get_ctrl(const struct dpaa2_fl_entry *fle) -+{ -+ return le32_to_cpu(fle->ctrl); -+} -+ -+/** -+ * dpaa2_fl_set_ctrl() - Set the control bits in the FLE -+ * @fle: the given frame list entry -+ * @ctrl: the control bits to be set in the frame list entry -+ */ -+static inline void dpaa2_fl_set_ctrl(struct dpaa2_fl_entry *fle, u32 ctrl) -+{ -+ fle->ctrl = cpu_to_le32(ctrl); -+} -+ -+/** -+ * dpaa2_fl_get_flc() - Get the flow context in the FLE -+ * @fle: the given frame list entry -+ * -+ * Return the flow context in the frame list entry. -+ */ -+static inline dma_addr_t dpaa2_fl_get_flc(const struct dpaa2_fl_entry *fle) -+{ -+ return (dma_addr_t)le64_to_cpu(fle->flc); -+} -+ -+/** -+ * dpaa2_fl_set_flc() - Set the flow context field of FLE -+ * @fle: the given frame list entry -+ * @flc_addr: the flow context needs to be set in frame list entry -+ */ -+static inline void dpaa2_fl_set_flc(struct dpaa2_fl_entry *fle, -+ dma_addr_t flc_addr) -+{ -+ fle->flc = cpu_to_le64(flc_addr); -+} -+ -+static inline bool dpaa2_fl_short_len(const struct dpaa2_fl_entry *fle) -+{ -+ return !!((le16_to_cpu(fle->format_offset) >> -+ FL_SHORT_LEN_FLAG_SHIFT) & FL_SHORT_LEN_FLAG_MASK); -+} -+ -+/** -+ * dpaa2_fl_get_len() - Get the length in the FLE -+ * @fle: the given frame list entry -+ * -+ * Return the length field in the frame list entry. -+ */ -+static inline u32 dpaa2_fl_get_len(const struct dpaa2_fl_entry *fle) -+{ -+ if (dpaa2_fl_short_len(fle)) -+ return le32_to_cpu(fle->len) & FL_SHORT_LEN_MASK; -+ -+ return le32_to_cpu(fle->len); -+} -+ -+/** -+ * dpaa2_fl_set_len() - Set the length field of FLE -+ * @fle: the given frame list entry -+ * @len: the length needs to be set in frame list entry -+ */ -+static inline void dpaa2_fl_set_len(struct dpaa2_fl_entry *fle, u32 len) -+{ -+ fle->len = cpu_to_le32(len); -+} -+ -+/** -+ * dpaa2_fl_get_offset() - Get the offset field in the frame list entry -+ * @fle: the given frame list entry -+ * -+ * Return the offset. -+ */ -+static inline u16 dpaa2_fl_get_offset(const struct dpaa2_fl_entry *fle) -+{ -+ return le16_to_cpu(fle->format_offset) & FL_OFFSET_MASK; -+} -+ -+/** -+ * dpaa2_fl_set_offset() - Set the offset field of FLE -+ * @fle: the given frame list entry -+ * @offset: the offset needs to be set in frame list entry -+ */ -+static inline void dpaa2_fl_set_offset(struct dpaa2_fl_entry *fle, u16 offset) -+{ -+ fle->format_offset &= cpu_to_le16(~FL_OFFSET_MASK); -+ fle->format_offset |= cpu_to_le16(offset); -+} -+ -+/** -+ * dpaa2_fl_get_format() - Get the format field in the FLE -+ * @fle: the given frame list entry -+ * -+ * Return the format. -+ */ -+static inline enum dpaa2_fl_format dpaa2_fl_get_format( -+ const struct dpaa2_fl_entry *fle) -+{ -+ return (enum dpaa2_fl_format)((le16_to_cpu(fle->format_offset) >> -+ FL_FORMAT_SHIFT) & FL_FORMAT_MASK); -+} -+ -+/** -+ * dpaa2_fl_set_format() - Set the format field of FLE -+ * @fle: the given frame list entry -+ * @format: the format needs to be set in frame list entry -+ */ -+static inline void dpaa2_fl_set_format(struct dpaa2_fl_entry *fle, -+ enum dpaa2_fl_format format) -+{ -+ fle->format_offset &= cpu_to_le16(~(FL_FORMAT_MASK << FL_FORMAT_SHIFT)); -+ fle->format_offset |= cpu_to_le16(format << FL_FORMAT_SHIFT); -+} -+ -+/** -+ * dpaa2_fl_get_bpid() - Get the bpid field in the FLE -+ * @fle: the given frame list entry -+ * -+ * Return the buffer pool id. -+ */ -+static inline u16 dpaa2_fl_get_bpid(const struct dpaa2_fl_entry *fle) -+{ -+ return le16_to_cpu(fle->bpid) & FL_BPID_MASK; -+} -+ -+/** -+ * dpaa2_fl_set_bpid() - Set the bpid field of FLE -+ * @fle: the given frame list entry -+ * @bpid: buffer pool id to be set -+ */ -+static inline void dpaa2_fl_set_bpid(struct dpaa2_fl_entry *fle, u16 bpid) -+{ -+ fle->bpid &= cpu_to_le16(~(FL_BPID_MASK)); -+ fle->bpid |= cpu_to_le16(bpid); -+} -+ -+/** -+ * dpaa2_fl_is_final() - Check final bit in FLE -+ * @fle: the given frame list entry -+ * -+ * Return bool. -+ */ -+static inline bool dpaa2_fl_is_final(const struct dpaa2_fl_entry *fle) -+{ -+ return !!(le16_to_cpu(fle->format_offset) >> FL_FINAL_FLAG_SHIFT); -+} -+ -+/** -+ * dpaa2_fl_set_final() - Set the final bit in FLE -+ * @fle: the given frame list entry -+ * @final: the final boolean to be set -+ */ -+static inline void dpaa2_fl_set_final(struct dpaa2_fl_entry *fle, bool final) -+{ -+ fle->format_offset &= cpu_to_le16(~(FL_FINAL_FLAG_MASK << -+ FL_FINAL_FLAG_SHIFT)); -+ fle->format_offset |= cpu_to_le16(final << FL_FINAL_FLAG_SHIFT); -+} -+ -+#endif /* __FSL_DPAA2_FD_H */ ---- /dev/null -+++ b/drivers/staging/fsl-mc/include/dpaa2-global.h -@@ -0,0 +1,177 @@ -+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ -+/* -+ * Copyright 2014-2016 Freescale Semiconductor Inc. -+ * Copyright 2016 NXP -+ * -+ */ -+#ifndef __FSL_DPAA2_GLOBAL_H -+#define __FSL_DPAA2_GLOBAL_H -+ -+#include <linux/types.h> -+#include <linux/cpumask.h> -+#include "dpaa2-fd.h" -+ -+struct dpaa2_dq { -+ union { -+ struct common { -+ u8 verb; -+ u8 reserved[63]; -+ } common; -+ struct dq { -+ u8 verb; -+ u8 stat; -+ __le16 seqnum; -+ __le16 oprid; -+ u8 reserved; -+ u8 tok; -+ __le32 fqid; -+ u32 reserved2; -+ __le32 fq_byte_cnt; -+ __le32 fq_frm_cnt; -+ __le64 fqd_ctx; -+ u8 fd[32]; -+ } dq; -+ struct scn { -+ u8 verb; -+ u8 stat; -+ u8 state; -+ u8 reserved; -+ __le32 rid_tok; -+ __le64 ctx; -+ } scn; -+ }; -+}; -+ -+/* Parsing frame dequeue results */ -+/* FQ empty */ -+#define DPAA2_DQ_STAT_FQEMPTY 0x80 -+/* FQ held active */ -+#define DPAA2_DQ_STAT_HELDACTIVE 0x40 -+/* FQ force eligible */ -+#define DPAA2_DQ_STAT_FORCEELIGIBLE 0x20 -+/* valid frame */ -+#define DPAA2_DQ_STAT_VALIDFRAME 0x10 -+/* FQ ODP enable */ -+#define DPAA2_DQ_STAT_ODPVALID 0x04 -+/* volatile dequeue */ -+#define DPAA2_DQ_STAT_VOLATILE 0x02 -+/* volatile dequeue command is expired */ -+#define DPAA2_DQ_STAT_EXPIRED 0x01 -+ -+#define DQ_FQID_MASK 0x00FFFFFF -+#define DQ_FRAME_COUNT_MASK 0x00FFFFFF -+ -+/** -+ * dpaa2_dq_flags() - Get the stat field of dequeue response -+ * @dq: the dequeue result. -+ */ -+static inline u32 dpaa2_dq_flags(const struct dpaa2_dq *dq) -+{ -+ return dq->dq.stat; -+} -+ -+/** -+ * dpaa2_dq_is_pull() - Check whether the dq response is from a pull -+ * command. -+ * @dq: the dequeue result -+ * -+ * Return 1 for volatile(pull) dequeue, 0 for static dequeue. -+ */ -+static inline int dpaa2_dq_is_pull(const struct dpaa2_dq *dq) -+{ -+ return (int)(dpaa2_dq_flags(dq) & DPAA2_DQ_STAT_VOLATILE); -+} -+ -+/** -+ * dpaa2_dq_is_pull_complete() - Check whether the pull command is completed. -+ * @dq: the dequeue result -+ * -+ * Return boolean. -+ */ -+static inline bool dpaa2_dq_is_pull_complete(const struct dpaa2_dq *dq) -+{ -+ return !!(dpaa2_dq_flags(dq) & DPAA2_DQ_STAT_EXPIRED); -+} -+ -+/** -+ * dpaa2_dq_seqnum() - Get the seqnum field in dequeue response -+ * @dq: the dequeue result -+ * -+ * seqnum is valid only if VALIDFRAME flag is TRUE -+ * -+ * Return seqnum. -+ */ -+static inline u16 dpaa2_dq_seqnum(const struct dpaa2_dq *dq) -+{ -+ return le16_to_cpu(dq->dq.seqnum); -+} -+ -+/** -+ * dpaa2_dq_odpid() - Get the odpid field in dequeue response -+ * @dq: the dequeue result -+ * -+ * odpid is valid only if ODPVALID flag is TRUE. -+ * -+ * Return odpid. -+ */ -+static inline u16 dpaa2_dq_odpid(const struct dpaa2_dq *dq) -+{ -+ return le16_to_cpu(dq->dq.oprid); -+} -+ -+/** -+ * dpaa2_dq_fqid() - Get the fqid in dequeue response -+ * @dq: the dequeue result -+ * -+ * Return fqid. -+ */ -+static inline u32 dpaa2_dq_fqid(const struct dpaa2_dq *dq) -+{ -+ return le32_to_cpu(dq->dq.fqid) & DQ_FQID_MASK; -+} -+ -+/** -+ * dpaa2_dq_byte_count() - Get the byte count in dequeue response -+ * @dq: the dequeue result -+ * -+ * Return the byte count remaining in the FQ. -+ */ -+static inline u32 dpaa2_dq_byte_count(const struct dpaa2_dq *dq) -+{ -+ return le32_to_cpu(dq->dq.fq_byte_cnt); -+} -+ -+/** -+ * dpaa2_dq_frame_count() - Get the frame count in dequeue response -+ * @dq: the dequeue result -+ * -+ * Return the frame count remaining in the FQ. -+ */ -+static inline u32 dpaa2_dq_frame_count(const struct dpaa2_dq *dq) -+{ -+ return le32_to_cpu(dq->dq.fq_frm_cnt) & DQ_FRAME_COUNT_MASK; -+} -+ -+/** -+ * dpaa2_dq_fd_ctx() - Get the frame queue context in dequeue response -+ * @dq: the dequeue result -+ * -+ * Return the frame queue context. -+ */ -+static inline u64 dpaa2_dq_fqd_ctx(const struct dpaa2_dq *dq) -+{ -+ return le64_to_cpu(dq->dq.fqd_ctx); -+} -+ -+/** -+ * dpaa2_dq_fd() - Get the frame descriptor in dequeue response -+ * @dq: the dequeue result -+ * -+ * Return the frame descriptor. -+ */ -+static inline const struct dpaa2_fd *dpaa2_dq_fd(const struct dpaa2_dq *dq) -+{ -+ return (const struct dpaa2_fd *)&dq->dq.fd[0]; -+} -+ -+#endif /* __FSL_DPAA2_GLOBAL_H */ ---- /dev/null -+++ b/drivers/staging/fsl-mc/include/dpaa2-io.h -@@ -0,0 +1,178 @@ -+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ -+/* -+ * Copyright 2014-2016 Freescale Semiconductor Inc. -+ * Copyright 2017 NXP -+ * -+ */ -+#ifndef __FSL_DPAA2_IO_H -+#define __FSL_DPAA2_IO_H -+ -+#include <linux/types.h> -+#include <linux/cpumask.h> -+ -+#include "dpaa2-fd.h" -+#include "dpaa2-global.h" -+ -+struct dpaa2_io; -+struct dpaa2_io_store; -+struct device; -+ -+/** -+ * DOC: DPIO Service -+ * -+ * The DPIO service provides APIs for users to interact with the datapath -+ * by enqueueing and dequeing frame descriptors. -+ * -+ * The following set of APIs can be used to enqueue and dequeue frames -+ * as well as producing notification callbacks when data is available -+ * for dequeue. -+ */ -+ -+#define DPAA2_IO_ANY_CPU -1 -+ -+/** -+ * struct dpaa2_io_desc - The DPIO descriptor -+ * @receives_notifications: Use notificaton mode. Non-zero if the DPIO -+ * has a channel. -+ * @has_8prio: Set to non-zero for channel with 8 priority WQs. Ignored -+ * unless receives_notification is TRUE. -+ * @cpu: The cpu index that at least interrupt handlers will -+ * execute on. -+ * @stash_affinity: The stash affinity for this portal favour 'cpu' -+ * @regs_cena: The cache enabled regs. -+ * @regs_cinh: The cache inhibited regs -+ * @dpio_id: The dpio index -+ * @qman_version: The qman version -+ * -+ * Describes the attributes and features of the DPIO object. -+ */ -+struct dpaa2_io_desc { -+ int receives_notifications; -+ int has_8prio; -+ int cpu; -+ void *regs_cena; -+ void *regs_cinh; -+ int dpio_id; -+ u32 qman_version; -+}; -+ -+struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc); -+ -+void dpaa2_io_down(struct dpaa2_io *d); -+ -+irqreturn_t dpaa2_io_irq(struct dpaa2_io *obj); -+ -+struct dpaa2_io *dpaa2_io_service_select(int cpu); -+ -+/** -+ * struct dpaa2_io_notification_ctx - The DPIO notification context structure -+ * @cb: The callback to be invoked when the notification arrives -+ * @is_cdan: Zero for FQDAN, non-zero for CDAN -+ * @id: FQID or channel ID, needed for rearm -+ * @desired_cpu: The cpu on which the notifications will show up. Use -+ * DPAA2_IO_ANY_CPU if don't care -+ * @dpio_id: The dpio index -+ * @qman64: The 64-bit context value shows up in the FQDAN/CDAN. -+ * @node: The list node -+ * @dpio_private: The dpio object internal to dpio_service -+ * -+ * Used when a FQDAN/CDAN registration is made by drivers. -+ */ -+struct dpaa2_io_notification_ctx { -+ void (*cb)(struct dpaa2_io_notification_ctx *ctx); -+ int is_cdan; -+ u32 id; -+ int desired_cpu; -+ int dpio_id; -+ u64 qman64; -+ struct list_head node; -+ void *dpio_private; -+}; -+ -+int dpaa2_io_service_register(struct dpaa2_io *service, -+ struct dpaa2_io_notification_ctx *ctx); -+void dpaa2_io_service_deregister(struct dpaa2_io *service, -+ struct dpaa2_io_notification_ctx *ctx); -+int dpaa2_io_service_rearm(struct dpaa2_io *service, -+ struct dpaa2_io_notification_ctx *ctx); -+ -+int dpaa2_io_service_pull_fq(struct dpaa2_io *d, u32 fqid, -+ struct dpaa2_io_store *s); -+int dpaa2_io_service_pull_channel(struct dpaa2_io *d, u32 channelid, -+ struct dpaa2_io_store *s); -+ -+int dpaa2_io_service_enqueue_fq(struct dpaa2_io *d, u32 fqid, -+ const struct dpaa2_fd *fd); -+int dpaa2_io_service_enqueue_qd(struct dpaa2_io *d, u32 qdid, u8 prio, -+ u16 qdbin, const struct dpaa2_fd *fd); -+int dpaa2_io_service_release(struct dpaa2_io *d, u32 bpid, -+ const u64 *buffers, unsigned int num_buffers); -+int dpaa2_io_service_acquire(struct dpaa2_io *d, u32 bpid, -+ u64 *buffers, unsigned int num_buffers); -+ -+struct dpaa2_io_store *dpaa2_io_store_create(unsigned int max_frames, -+ struct device *dev); -+void dpaa2_io_store_destroy(struct dpaa2_io_store *s); -+struct dpaa2_dq *dpaa2_io_store_next(struct dpaa2_io_store *s, int *is_last); -+ -+/* Order Restoration Support */ -+int dpaa2_io_service_enqueue_orp_fq(struct dpaa2_io *d, u32 fqid, -+ const struct dpaa2_fd *fd, u16 orpid, -+ u16 seqnum, int last); -+ -+int dpaa2_io_service_enqueue_orp_qd(struct dpaa2_io *d, u32 qdid, u8 prio, -+ u16 qdbin, const struct dpaa2_fd *fd, -+ u16 orpid, u16 seqnum, int last); -+ -+int dpaa2_io_service_orp_seqnum_drop(struct dpaa2_io *d, u16 orpid, -+ u16 seqnum); -+ -+/***************/ -+/* CSCN */ -+/***************/ -+ -+/** -+ * struct dpaa2_cscn - The CSCN message format -+ * @verb: identifies the type of message (should be 0x27). -+ * @stat: status bits related to dequeuing response (not used) -+ * @state: bit 0 = 0/1 if CG is no/is congested -+ * @reserved: reserved byte -+ * @cgid: congest grp ID - the first 16 bits -+ * @ctx: context data -+ * -+ * Congestion management can be implemented in software through -+ * the use of Congestion State Change Notifications (CSCN). These -+ * are messages written by DPAA2 hardware to memory whenever the -+ * instantaneous count (I_CNT field in the CG) exceeds the -+ * Congestion State (CS) entrance threshold, signifying congestion -+ * entrance, or when the instantaneous count returns below exit -+ * threshold, signifying congestion exit. The format of the message -+ * is given by the dpaa2_cscn structure. Bit 0 of the state field -+ * represents congestion state written by the hardware. -+ */ -+struct dpaa2_cscn { -+ u8 verb; -+ u8 stat; -+ u8 state; -+ u8 reserved; -+ __le32 cgid; -+ __le64 ctx; -+}; -+ -+#define DPAA2_CSCN_SIZE 64 -+#define DPAA2_CSCN_ALIGN 16 -+ -+#define DPAA2_CSCN_STATE_MASK 0x1 -+#define DPAA2_CSCN_CONGESTED 1 -+ -+static inline bool dpaa2_cscn_state_congested(struct dpaa2_cscn *cscn) -+{ -+ return ((cscn->state & DPAA2_CSCN_STATE_MASK) == DPAA2_CSCN_CONGESTED); -+} -+ -+int dpaa2_io_query_fq_count(struct dpaa2_io *d, u32 fqid, -+ u32 *fcnt, u32 *bcnt); -+int dpaa2_io_query_bp_count(struct dpaa2_io *d, u32 bpid, -+ u32 *num); -+ -+#endif /* __FSL_DPAA2_IO_H */ ---- a/drivers/staging/fsl-mc/include/dpbp-cmd.h -+++ /dev/null -@@ -1,185 +0,0 @@ --/* Copyright 2013-2016 Freescale Semiconductor Inc. -- * -- * Redistribution and use in source and binary forms, with or without -- * modification, are permitted provided that the following conditions are met: -- * * Redistributions of source code must retain the above copyright -- * notice, this list of conditions and the following disclaimer. -- * * Redistributions in binary form must reproduce the above copyright -- * notice, this list of conditions and the following disclaimer in the -- * documentation and/or other materials provided with the distribution. -- * * Neither the name of the above-listed copyright holders nor the -- * names of any contributors may be used to endorse or promote products -- * derived from this software without specific prior written permission. -- * -- * -- * ALTERNATIVELY, this software may be distributed under the terms of the -- * GNU General Public License ("GPL") as published by the Free Software -- * Foundation, either version 2 of that License or (at your option) any -- * later version. -- * -- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -- * POSSIBILITY OF SUCH DAMAGE. -- */ --#ifndef _FSL_DPBP_CMD_H --#define _FSL_DPBP_CMD_H -- --/* DPBP Version */ --#define DPBP_VER_MAJOR 2 --#define DPBP_VER_MINOR 2 -- --/* Command IDs */ --#define DPBP_CMDID_CLOSE 0x800 --#define DPBP_CMDID_OPEN 0x804 --#define DPBP_CMDID_CREATE 0x904 --#define DPBP_CMDID_DESTROY 0x900 -- --#define DPBP_CMDID_ENABLE 0x002 --#define DPBP_CMDID_DISABLE 0x003 --#define DPBP_CMDID_GET_ATTR 0x004 --#define DPBP_CMDID_RESET 0x005 --#define DPBP_CMDID_IS_ENABLED 0x006 -- --#define DPBP_CMDID_SET_IRQ 0x010 --#define DPBP_CMDID_GET_IRQ 0x011 --#define DPBP_CMDID_SET_IRQ_ENABLE 0x012 --#define DPBP_CMDID_GET_IRQ_ENABLE 0x013 --#define DPBP_CMDID_SET_IRQ_MASK 0x014 --#define DPBP_CMDID_GET_IRQ_MASK 0x015 --#define DPBP_CMDID_GET_IRQ_STATUS 0x016 --#define DPBP_CMDID_CLEAR_IRQ_STATUS 0x017 -- --#define DPBP_CMDID_SET_NOTIFICATIONS 0x01b0 --#define DPBP_CMDID_GET_NOTIFICATIONS 0x01b1 -- --struct dpbp_cmd_open { -- __le32 dpbp_id; --}; -- --#define DPBP_ENABLE 0x1 -- --struct dpbp_rsp_is_enabled { -- u8 enabled; --}; -- --struct dpbp_cmd_set_irq { -- /* cmd word 0 */ -- u8 irq_index; -- u8 pad[3]; -- __le32 irq_val; -- /* cmd word 1 */ -- __le64 irq_addr; -- /* cmd word 2 */ -- __le32 irq_num; --}; -- --struct dpbp_cmd_get_irq { -- __le32 pad; -- u8 irq_index; --}; -- --struct dpbp_rsp_get_irq { -- /* response word 0 */ -- __le32 irq_val; -- __le32 pad; -- /* response word 1 */ -- __le64 irq_addr; -- /* response word 2 */ -- __le32 irq_num; -- __le32 type; --}; -- --struct dpbp_cmd_set_irq_enable { -- u8 enable; -- u8 pad[3]; -- u8 irq_index; --}; -- --struct dpbp_cmd_get_irq_enable { -- __le32 pad; -- u8 irq_index; --}; -- --struct dpbp_rsp_get_irq_enable { -- u8 enabled; --}; -- --struct dpbp_cmd_set_irq_mask { -- __le32 mask; -- u8 irq_index; --}; -- --struct dpbp_cmd_get_irq_mask { -- __le32 pad; -- u8 irq_index; --}; -- --struct dpbp_rsp_get_irq_mask { -- __le32 mask; --}; -- --struct dpbp_cmd_get_irq_status { -- __le32 status; -- u8 irq_index; --}; -- --struct dpbp_rsp_get_irq_status { -- __le32 status; --}; -- --struct dpbp_cmd_clear_irq_status { -- __le32 status; -- u8 irq_index; --}; -- --struct dpbp_rsp_get_attributes { -- /* response word 0 */ -- __le16 pad; -- __le16 bpid; -- __le32 id; -- /* response word 1 */ -- __le16 version_major; -- __le16 version_minor; --}; -- --struct dpbp_cmd_set_notifications { -- /* cmd word 0 */ -- __le32 depletion_entry; -- __le32 depletion_exit; -- /* cmd word 1 */ -- __le32 surplus_entry; -- __le32 surplus_exit; -- /* cmd word 2 */ -- __le16 options; -- __le16 pad[3]; -- /* cmd word 3 */ -- __le64 message_ctx; -- /* cmd word 4 */ -- __le64 message_iova; --}; -- --struct dpbp_rsp_get_notifications { -- /* response word 0 */ -- __le32 depletion_entry; -- __le32 depletion_exit; -- /* response word 1 */ -- __le32 surplus_entry; -- __le32 surplus_exit; -- /* response word 2 */ -- __le16 options; -- __le16 pad[3]; -- /* response word 3 */ -- __le64 message_ctx; -- /* response word 4 */ -- __le64 message_iova; --}; -- --#endif /* _FSL_DPBP_CMD_H */ ---- a/drivers/staging/fsl-mc/include/dpbp.h -+++ /dev/null -@@ -1,220 +0,0 @@ --/* Copyright 2013-2015 Freescale Semiconductor Inc. -- * -- * Redistribution and use in source and binary forms, with or without -- * modification, are permitted provided that the following conditions are met: -- * * Redistributions of source code must retain the above copyright -- * notice, this list of conditions and the following disclaimer. -- * * Redistributions in binary form must reproduce the above copyright -- * notice, this list of conditions and the following disclaimer in the -- * documentation and/or other materials provided with the distribution. -- * * Neither the name of the above-listed copyright holders nor the -- * names of any contributors may be used to endorse or promote products -- * derived from this software without specific prior written permission. -- * -- * -- * ALTERNATIVELY, this software may be distributed under the terms of the -- * GNU General Public License ("GPL") as published by the Free Software -- * Foundation, either version 2 of that License or (at your option) any -- * later version. -- * -- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -- * POSSIBILITY OF SUCH DAMAGE. -- */ --#ifndef __FSL_DPBP_H --#define __FSL_DPBP_H -- --/* Data Path Buffer Pool API -- * Contains initialization APIs and runtime control APIs for DPBP -- */ -- --struct fsl_mc_io; -- --int dpbp_open(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- int dpbp_id, -- u16 *token); -- --int dpbp_close(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token); -- --/** -- * struct dpbp_cfg - Structure representing DPBP configuration -- * @options: place holder -- */ --struct dpbp_cfg { -- u32 options; --}; -- --int dpbp_create(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- const struct dpbp_cfg *cfg, -- u16 *token); -- --int dpbp_destroy(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token); -- --int dpbp_enable(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token); -- --int dpbp_disable(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token); -- --int dpbp_is_enabled(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- int *en); -- --int dpbp_reset(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token); -- --/** -- * struct dpbp_irq_cfg - IRQ configuration -- * @addr: Address that must be written to signal a message-based interrupt -- * @val: Value to write into irq_addr address -- * @irq_num: A user defined number associated with this IRQ -- */ --struct dpbp_irq_cfg { -- u64 addr; -- u32 val; -- int irq_num; --}; -- --int dpbp_set_irq(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- struct dpbp_irq_cfg *irq_cfg); -- --int dpbp_get_irq(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- int *type, -- struct dpbp_irq_cfg *irq_cfg); -- --int dpbp_set_irq_enable(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u8 en); -- --int dpbp_get_irq_enable(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u8 *en); -- --int dpbp_set_irq_mask(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u32 mask); -- --int dpbp_get_irq_mask(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u32 *mask); -- --int dpbp_get_irq_status(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u32 *status); -- --int dpbp_clear_irq_status(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u32 status); -- --/** -- * struct dpbp_attr - Structure representing DPBP attributes -- * @id: DPBP object ID -- * @version: DPBP version -- * @bpid: Hardware buffer pool ID; should be used as an argument in -- * acquire/release operations on buffers -- */ --struct dpbp_attr { -- int id; -- /** -- * struct version - Structure representing DPBP version -- * @major: DPBP major version -- * @minor: DPBP minor version -- */ -- struct { -- u16 major; -- u16 minor; -- } version; -- u16 bpid; --}; -- --int dpbp_get_attributes(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- struct dpbp_attr *attr); -- --/** -- * DPBP notifications options -- */ -- --/** -- * BPSCN write will attempt to allocate into a cache (coherent write) -- */ --#define DPBP_NOTIF_OPT_COHERENT_WRITE 0x00000001 -- --/** -- * struct dpbp_notification_cfg - Structure representing DPBP notifications -- * towards software -- * @depletion_entry: below this threshold the pool is "depleted"; -- * set it to '0' to disable it -- * @depletion_exit: greater than or equal to this threshold the pool exit its -- * "depleted" state -- * @surplus_entry: above this threshold the pool is in "surplus" state; -- * set it to '0' to disable it -- * @surplus_exit: less than or equal to this threshold the pool exit its -- * "surplus" state -- * @message_iova: MUST be given if either 'depletion_entry' or 'surplus_entry' -- * is not '0' (enable); I/O virtual address (must be in DMA-able memory), -- * must be 16B aligned. -- * @message_ctx: The context that will be part of the BPSCN message and will -- * be written to 'message_iova' -- * @options: Mask of available options; use 'DPBP_NOTIF_OPT_<X>' values -- */ --struct dpbp_notification_cfg { -- u32 depletion_entry; -- u32 depletion_exit; -- u32 surplus_entry; -- u32 surplus_exit; -- u64 message_iova; -- u64 message_ctx; -- u16 options; --}; -- --int dpbp_set_notifications(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- struct dpbp_notification_cfg *cfg); -- --int dpbp_get_notifications(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- struct dpbp_notification_cfg *cfg); -- --/** @} */ -- --#endif /* __FSL_DPBP_H */ ---- a/drivers/staging/fsl-mc/include/dpcon-cmd.h -+++ /dev/null -@@ -1,62 +0,0 @@ --/* Copyright 2013-2015 Freescale Semiconductor Inc. -- * -- * Redistribution and use in source and binary forms, with or without -- * modification, are permitted provided that the following conditions are met: -- * * Redistributions of source code must retain the above copyright -- * notice, this list of conditions and the following disclaimer. -- * * Redistributions in binary form must reproduce the above copyright -- * notice, this list of conditions and the following disclaimer in the -- * documentation and/or other materials provided with the distribution. -- * * Neither the name of the above-listed copyright holders nor the -- * names of any contributors may be used to endorse or promote products -- * derived from this software without specific prior written permission. -- * -- * -- * ALTERNATIVELY, this software may be distributed under the terms of the -- * GNU General Public License ("GPL") as published by the Free Software -- * Foundation, either version 2 of that License or (at your option) any -- * later version. -- * -- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -- * POSSIBILITY OF SUCH DAMAGE. -- */ --#ifndef _FSL_DPCON_CMD_H --#define _FSL_DPCON_CMD_H -- --/* DPCON Version */ --#define DPCON_VER_MAJOR 2 --#define DPCON_VER_MINOR 1 -- --/* Command IDs */ --#define DPCON_CMDID_CLOSE 0x800 --#define DPCON_CMDID_OPEN 0x808 --#define DPCON_CMDID_CREATE 0x908 --#define DPCON_CMDID_DESTROY 0x900 -- --#define DPCON_CMDID_ENABLE 0x002 --#define DPCON_CMDID_DISABLE 0x003 --#define DPCON_CMDID_GET_ATTR 0x004 --#define DPCON_CMDID_RESET 0x005 --#define DPCON_CMDID_IS_ENABLED 0x006 -- --#define DPCON_CMDID_SET_IRQ 0x010 --#define DPCON_CMDID_GET_IRQ 0x011 --#define DPCON_CMDID_SET_IRQ_ENABLE 0x012 --#define DPCON_CMDID_GET_IRQ_ENABLE 0x013 --#define DPCON_CMDID_SET_IRQ_MASK 0x014 --#define DPCON_CMDID_GET_IRQ_MASK 0x015 --#define DPCON_CMDID_GET_IRQ_STATUS 0x016 --#define DPCON_CMDID_CLEAR_IRQ_STATUS 0x017 -- --#define DPCON_CMDID_SET_NOTIFICATION 0x100 -- --#endif /* _FSL_DPCON_CMD_H */ ---- a/drivers/staging/fsl-mc/include/dpmng.h -+++ /dev/null -@@ -1,69 +0,0 @@ --/* Copyright 2013-2015 Freescale Semiconductor Inc. -- * -- * Redistribution and use in source and binary forms, with or without -- * modification, are permitted provided that the following conditions are met: -- * * Redistributions of source code must retain the above copyright -- * notice, this list of conditions and the following disclaimer. -- * * Redistributions in binary form must reproduce the above copyright -- * notice, this list of conditions and the following disclaimer in the -- * documentation and/or other materials provided with the distribution. -- * * Neither the name of the above-listed copyright holders nor the -- * names of any contributors may be used to endorse or promote products -- * derived from this software without specific prior written permission. -- * -- * -- * ALTERNATIVELY, this software may be distributed under the terms of the -- * GNU General Public License ("GPL") as published by the Free Software -- * Foundation, either version 2 of that License or (at your option) any -- * later version. -- * -- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -- * POSSIBILITY OF SUCH DAMAGE. -- */ --#ifndef __FSL_DPMNG_H --#define __FSL_DPMNG_H -- --/* Management Complex General API -- * Contains general API for the Management Complex firmware -- */ -- --struct fsl_mc_io; -- --/** -- * Management Complex firmware version information -- */ --#define MC_VER_MAJOR 8 --#define MC_VER_MINOR 0 -- --/** -- * struct mc_version -- * @major: Major version number: incremented on API compatibility changes -- * @minor: Minor version number: incremented on API additions (that are -- * backward compatible); reset when major version is incremented -- * @revision: Internal revision number: incremented on implementation changes -- * and/or bug fixes that have no impact on API -- */ --struct mc_version { -- u32 major; -- u32 minor; -- u32 revision; --}; -- --int mc_get_version(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- struct mc_version *mc_ver_info); -- --int dpmng_get_container_id(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- int *container_id); -- --#endif /* __FSL_DPMNG_H */ ---- /dev/null -+++ b/drivers/staging/fsl-mc/include/dpopr.h -@@ -0,0 +1,112 @@ -+/* -+ * Copyright 2017 NXP -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are met: -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * * Neither the name of the above-listed copyright holders nor the -+ * names of any contributors may be used to endorse or promote products -+ * derived from this software without specific prior written permission. -+ * -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") as published by the Free Software -+ * Foundation, either version 2 of that License or (at your option) any -+ * later version. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. -+ */ -+#ifndef __FSL_DPOPR_H_ -+#define __FSL_DPOPR_H_ -+ -+#include <linux/types.h> -+ -+/* Data Path Order Restoration API -+ * Contains initialization APIs and runtime APIs for the Order Restoration -+ */ -+ -+/** Order Restoration properties */ -+ -+/** -+ * Create a new Order Point Record option -+ */ -+#define OPR_OPT_CREATE 0x1 -+/** -+ * Retire an existing Order Point Record option -+ */ -+#define OPR_OPT_RETIRE 0x2 -+ -+/** -+ * struct opr_cfg - Structure representing OPR configuration -+ * @oprrws: Order point record (OPR) restoration window size (0 to 5) -+ * 0 - Window size is 32 frames. -+ * 1 - Window size is 64 frames. -+ * 2 - Window size is 128 frames. -+ * 3 - Window size is 256 frames. -+ * 4 - Window size is 512 frames. -+ * 5 - Window size is 1024 frames. -+ * @oa: OPR auto advance NESN window size (0 disabled, 1 enabled) -+ * @olws: OPR acceptable late arrival window size (0 to 3) -+ * 0 - Disabled. Late arrivals are always rejected. -+ * 1 - Window size is 32 frames. -+ * 2 - Window size is the same as the OPR restoration -+ * window size configured in the OPRRWS field. -+ * 3 - Window size is 8192 frames. Late arrivals are -+ * always accepted. -+ * @oeane: Order restoration list (ORL) resource exhaustion -+ * advance NESN enable (0 disabled, 1 enabled) -+ * @oloe: OPR loose ordering enable (0 disabled, 1 enabled) -+ */ -+struct opr_cfg { -+ u8 oprrws; -+ u8 oa; -+ u8 olws; -+ u8 oeane; -+ u8 oloe; -+}; -+ -+/** -+ * struct opr_qry - Structure representing OPR configuration -+ * @enable: Enabled state -+ * @rip: Retirement In Progress -+ * @ndsn: Next dispensed sequence number -+ * @nesn: Next expected sequence number -+ * @ea_hseq: Early arrival head sequence number -+ * @hseq_nlis: HSEQ not last in sequence -+ * @ea_tseq: Early arrival tail sequence number -+ * @tseq_nlis: TSEQ not last in sequence -+ * @ea_tptr: Early arrival tail pointer -+ * @ea_hptr: Early arrival head pointer -+ * @opr_id: Order Point Record ID -+ * @opr_vid: Order Point Record Virtual ID -+ */ -+struct opr_qry { -+ char enable; -+ char rip; -+ u16 ndsn; -+ u16 nesn; -+ u16 ea_hseq; -+ char hseq_nlis; -+ u16 ea_tseq; -+ char tseq_nlis; -+ u16 ea_tptr; -+ u16 ea_hptr; -+ u16 opr_id; -+ u16 opr_vid; -+}; -+ -+#endif /* __FSL_DPOPR_H_ */ ---- a/drivers/staging/fsl-mc/include/dprc.h -+++ /dev/null -@@ -1,544 +0,0 @@ --/* Copyright 2013-2015 Freescale Semiconductor Inc. -- * -- * Redistribution and use in source and binary forms, with or without -- * modification, are permitted provided that the following conditions are met: -- * * Redistributions of source code must retain the above copyright -- * notice, this list of conditions and the following disclaimer. -- * * Redistributions in binary form must reproduce the above copyright -- * notice, this list of conditions and the following disclaimer in the -- * documentation and/or other materials provided with the distribution. -- * * Neither the name of the above-listed copyright holders nor the -- * names of any contributors may be used to endorse or promote products -- * derived from this software without specific prior written permission. -- * -- * -- * ALTERNATIVELY, this software may be distributed under the terms of the -- * GNU General Public License ("GPL") as published by the Free Software -- * Foundation, either version 2 of that License or (at your option) any -- * later version. -- * -- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -- * POSSIBILITY OF SUCH DAMAGE. -- */ --#ifndef _FSL_DPRC_H --#define _FSL_DPRC_H -- --#include "mc-cmd.h" -- --/* Data Path Resource Container API -- * Contains DPRC API for managing and querying DPAA resources -- */ -- --struct fsl_mc_io; -- --/** -- * Set this value as the icid value in dprc_cfg structure when creating a -- * container, in case the ICID is not selected by the user and should be -- * allocated by the DPRC from the pool of ICIDs. -- */ --#define DPRC_GET_ICID_FROM_POOL (u16)(~(0)) -- --/** -- * Set this value as the portal_id value in dprc_cfg structure when creating a -- * container, in case the portal ID is not specifically selected by the -- * user and should be allocated by the DPRC from the pool of portal ids. -- */ --#define DPRC_GET_PORTAL_ID_FROM_POOL (int)(~(0)) -- --int dprc_open(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- int container_id, -- u16 *token); -- --int dprc_close(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token); -- --/** -- * Container general options -- * -- * These options may be selected at container creation by the container creator -- * and can be retrieved using dprc_get_attributes() -- */ -- --/* Spawn Policy Option allowed - Indicates that the new container is allowed -- * to spawn and have its own child containers. -- */ --#define DPRC_CFG_OPT_SPAWN_ALLOWED 0x00000001 -- --/* General Container allocation policy - Indicates that the new container is -- * allowed to allocate requested resources from its parent container; if not -- * set, the container is only allowed to use resources in its own pools; Note -- * that this is a container's global policy, but the parent container may -- * override it and set specific quota per resource type. -- */ --#define DPRC_CFG_OPT_ALLOC_ALLOWED 0x00000002 -- --/* Object initialization allowed - software context associated with this -- * container is allowed to invoke object initialization operations. -- */ --#define DPRC_CFG_OPT_OBJ_CREATE_ALLOWED 0x00000004 -- --/* Topology change allowed - software context associated with this -- * container is allowed to invoke topology operations, such as attach/detach -- * of network objects. -- */ --#define DPRC_CFG_OPT_TOPOLOGY_CHANGES_ALLOWED 0x00000008 -- --/* AIOP - Indicates that container belongs to AIOP. */ --#define DPRC_CFG_OPT_AIOP 0x00000020 -- --/* IRQ Config - Indicates that the container allowed to configure its IRQs. */ --#define DPRC_CFG_OPT_IRQ_CFG_ALLOWED 0x00000040 -- --/** -- * struct dprc_cfg - Container configuration options -- * @icid: Container's ICID; if set to 'DPRC_GET_ICID_FROM_POOL', a free -- * ICID value is allocated by the DPRC -- * @portal_id: Portal ID; if set to 'DPRC_GET_PORTAL_ID_FROM_POOL', a free -- * portal ID is allocated by the DPRC -- * @options: Combination of 'DPRC_CFG_OPT_<X>' options -- * @label: Object's label -- */ --struct dprc_cfg { -- u16 icid; -- int portal_id; -- u64 options; -- char label[16]; --}; -- --int dprc_create_container(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- struct dprc_cfg *cfg, -- int *child_container_id, -- u64 *child_portal_offset); -- --int dprc_destroy_container(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- int child_container_id); -- --int dprc_reset_container(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- int child_container_id); -- --/* IRQ */ -- --/* IRQ index */ --#define DPRC_IRQ_INDEX 0 -- --/* Number of dprc's IRQs */ --#define DPRC_NUM_OF_IRQS 1 -- --/* DPRC IRQ events */ -- --/* IRQ event - Indicates that a new object added to the container */ --#define DPRC_IRQ_EVENT_OBJ_ADDED 0x00000001 --/* IRQ event - Indicates that an object was removed from the container */ --#define DPRC_IRQ_EVENT_OBJ_REMOVED 0x00000002 --/* IRQ event - Indicates that resources added to the container */ --#define DPRC_IRQ_EVENT_RES_ADDED 0x00000004 --/* IRQ event - Indicates that resources removed from the container */ --#define DPRC_IRQ_EVENT_RES_REMOVED 0x00000008 --/* IRQ event - Indicates that one of the descendant containers that opened by -- * this container is destroyed -- */ --#define DPRC_IRQ_EVENT_CONTAINER_DESTROYED 0x00000010 -- --/* IRQ event - Indicates that on one of the container's opened object is -- * destroyed -- */ --#define DPRC_IRQ_EVENT_OBJ_DESTROYED 0x00000020 -- --/* Irq event - Indicates that object is created at the container */ --#define DPRC_IRQ_EVENT_OBJ_CREATED 0x00000040 -- --/** -- * struct dprc_irq_cfg - IRQ configuration -- * @paddr: Address that must be written to signal a message-based interrupt -- * @val: Value to write into irq_addr address -- * @irq_num: A user defined number associated with this IRQ -- */ --struct dprc_irq_cfg { -- phys_addr_t paddr; -- u32 val; -- int irq_num; --}; -- --int dprc_set_irq(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- struct dprc_irq_cfg *irq_cfg); -- --int dprc_get_irq(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- int *type, -- struct dprc_irq_cfg *irq_cfg); -- --int dprc_set_irq_enable(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u8 en); -- --int dprc_get_irq_enable(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u8 *en); -- --int dprc_set_irq_mask(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u32 mask); -- --int dprc_get_irq_mask(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u32 *mask); -- --int dprc_get_irq_status(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u32 *status); -- --int dprc_clear_irq_status(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- u8 irq_index, -- u32 status); -- --/** -- * struct dprc_attributes - Container attributes -- * @container_id: Container's ID -- * @icid: Container's ICID -- * @portal_id: Container's portal ID -- * @options: Container's options as set at container's creation -- * @version: DPRC version -- */ --struct dprc_attributes { -- int container_id; -- u16 icid; -- int portal_id; -- u64 options; -- /** -- * struct version - DPRC version -- * @major: DPRC major version -- * @minor: DPRC minor version -- */ -- struct { -- u16 major; -- u16 minor; -- } version; --}; -- --int dprc_get_attributes(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- struct dprc_attributes *attributes); -- --int dprc_set_res_quota(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- int child_container_id, -- char *type, -- u16 quota); -- --int dprc_get_res_quota(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- int child_container_id, -- char *type, -- u16 *quota); -- --/* Resource request options */ -- --/* Explicit resource ID request - The requested objects/resources -- * are explicit and sequential (in case of resources). -- * The base ID is given at res_req at base_align field -- */ --#define DPRC_RES_REQ_OPT_EXPLICIT 0x00000001 -- --/* Aligned resources request - Relevant only for resources -- * request (and not objects). Indicates that resources base ID should be -- * sequential and aligned to the value given at dprc_res_req base_align field -- */ --#define DPRC_RES_REQ_OPT_ALIGNED 0x00000002 -- --/* Plugged Flag - Relevant only for object assignment request. -- * Indicates that after all objects assigned. An interrupt will be invoked at -- * the relevant GPP. The assigned object will be marked as plugged. -- * plugged objects can't be assigned from their container -- */ --#define DPRC_RES_REQ_OPT_PLUGGED 0x00000004 -- --/** -- * struct dprc_res_req - Resource request descriptor, to be used in assignment -- * or un-assignment of resources and objects. -- * @type: Resource/object type: Represent as a NULL terminated string. -- * This string may received by using dprc_get_pool() to get resource -- * type and dprc_get_obj() to get object type; -- * Note: it is not possible to assign/un-assign DPRC objects -- * @num: Number of resources -- * @options: Request options: combination of DPRC_RES_REQ_OPT_ options -- * @id_base_align: In case of explicit assignment (DPRC_RES_REQ_OPT_EXPLICIT -- * is set at option), this field represents the required base ID -- * for resource allocation; In case of aligned assignment -- * (DPRC_RES_REQ_OPT_ALIGNED is set at option), this field -- * indicates the required alignment for the resource ID(s) - -- * use 0 if there is no alignment or explicit ID requirements -- */ --struct dprc_res_req { -- char type[16]; -- u32 num; -- u32 options; -- int id_base_align; --}; -- --int dprc_assign(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- int container_id, -- struct dprc_res_req *res_req); -- --int dprc_unassign(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- int child_container_id, -- struct dprc_res_req *res_req); -- --int dprc_get_pool_count(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- int *pool_count); -- --int dprc_get_pool(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- int pool_index, -- char *type); -- --int dprc_get_obj_count(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- int *obj_count); -- --/* Objects Attributes Flags */ -- --/* Opened state - Indicates that an object is open by at least one owner */ --#define DPRC_OBJ_STATE_OPEN 0x00000001 --/* Plugged state - Indicates that the object is plugged */ --#define DPRC_OBJ_STATE_PLUGGED 0x00000002 -- --/** -- * Shareability flag - Object flag indicating no memory shareability. -- * the object generates memory accesses that are non coherent with other -- * masters; -- * user is responsible for proper memory handling through IOMMU configuration. -- */ --#define DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY 0x0001 -- --/** -- * struct dprc_obj_desc - Object descriptor, returned from dprc_get_obj() -- * @type: Type of object: NULL terminated string -- * @id: ID of logical object resource -- * @vendor: Object vendor identifier -- * @ver_major: Major version number -- * @ver_minor: Minor version number -- * @irq_count: Number of interrupts supported by the object -- * @region_count: Number of mappable regions supported by the object -- * @state: Object state: combination of DPRC_OBJ_STATE_ states -- * @label: Object label -- * @flags: Object's flags -- */ --struct dprc_obj_desc { -- char type[16]; -- int id; -- u16 vendor; -- u16 ver_major; -- u16 ver_minor; -- u8 irq_count; -- u8 region_count; -- u32 state; -- char label[16]; -- u16 flags; --}; -- --int dprc_get_obj(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- int obj_index, -- struct dprc_obj_desc *obj_desc); -- --int dprc_get_obj_desc(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- char *obj_type, -- int obj_id, -- struct dprc_obj_desc *obj_desc); -- --int dprc_set_obj_irq(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- char *obj_type, -- int obj_id, -- u8 irq_index, -- struct dprc_irq_cfg *irq_cfg); -- --int dprc_get_obj_irq(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- char *obj_type, -- int obj_id, -- u8 irq_index, -- int *type, -- struct dprc_irq_cfg *irq_cfg); -- --int dprc_get_res_count(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- char *type, -- int *res_count); -- --/** -- * enum dprc_iter_status - Iteration status -- * @DPRC_ITER_STATUS_FIRST: Perform first iteration -- * @DPRC_ITER_STATUS_MORE: Indicates more/next iteration is needed -- * @DPRC_ITER_STATUS_LAST: Indicates last iteration -- */ --enum dprc_iter_status { -- DPRC_ITER_STATUS_FIRST = 0, -- DPRC_ITER_STATUS_MORE = 1, -- DPRC_ITER_STATUS_LAST = 2 --}; -- --/** -- * struct dprc_res_ids_range_desc - Resource ID range descriptor -- * @base_id: Base resource ID of this range -- * @last_id: Last resource ID of this range -- * @iter_status: Iteration status - should be set to DPRC_ITER_STATUS_FIRST at -- * first iteration; while the returned marker is DPRC_ITER_STATUS_MORE, -- * additional iterations are needed, until the returned marker is -- * DPRC_ITER_STATUS_LAST -- */ --struct dprc_res_ids_range_desc { -- int base_id; -- int last_id; -- enum dprc_iter_status iter_status; --}; -- --int dprc_get_res_ids(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- char *type, -- struct dprc_res_ids_range_desc *range_desc); -- --/* Region flags */ --/* Cacheable - Indicates that region should be mapped as cacheable */ --#define DPRC_REGION_CACHEABLE 0x00000001 -- --/** -- * enum dprc_region_type - Region type -- * @DPRC_REGION_TYPE_MC_PORTAL: MC portal region -- * @DPRC_REGION_TYPE_QBMAN_PORTAL: Qbman portal region -- */ --enum dprc_region_type { -- DPRC_REGION_TYPE_MC_PORTAL, -- DPRC_REGION_TYPE_QBMAN_PORTAL --}; -- --/** -- * struct dprc_region_desc - Mappable region descriptor -- * @base_offset: Region offset from region's base address. -- * For DPMCP and DPRC objects, region base is offset from SoC MC portals -- * base address; For DPIO, region base is offset from SoC QMan portals -- * base address -- * @size: Region size (in bytes) -- * @flags: Region attributes -- * @type: Portal region type -- */ --struct dprc_region_desc { -- u32 base_offset; -- u32 size; -- u32 flags; -- enum dprc_region_type type; --}; -- --int dprc_get_obj_region(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- char *obj_type, -- int obj_id, -- u8 region_index, -- struct dprc_region_desc *region_desc); -- --int dprc_set_obj_label(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- char *obj_type, -- int obj_id, -- char *label); -- --/** -- * struct dprc_endpoint - Endpoint description for link connect/disconnect -- * operations -- * @type: Endpoint object type: NULL terminated string -- * @id: Endpoint object ID -- * @if_id: Interface ID; should be set for endpoints with multiple -- * interfaces ("dpsw", "dpdmux"); for others, always set to 0 -- */ --struct dprc_endpoint { -- char type[16]; -- int id; -- int if_id; --}; -- --/** -- * struct dprc_connection_cfg - Connection configuration. -- * Used for virtual connections only -- * @committed_rate: Committed rate (Mbits/s) -- * @max_rate: Maximum rate (Mbits/s) -- */ --struct dprc_connection_cfg { -- u32 committed_rate; -- u32 max_rate; --}; -- --int dprc_connect(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- const struct dprc_endpoint *endpoint1, -- const struct dprc_endpoint *endpoint2, -- const struct dprc_connection_cfg *cfg); -- --int dprc_disconnect(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- const struct dprc_endpoint *endpoint); -- --int dprc_get_connection(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- const struct dprc_endpoint *endpoint1, -- struct dprc_endpoint *endpoint2, -- int *state); -- --#endif /* _FSL_DPRC_H */ -- ---- a/drivers/staging/fsl-mc/include/mc-bus.h -+++ /dev/null -@@ -1,111 +0,0 @@ --/* -- * Freescale Management Complex (MC) bus declarations -- * -- * Copyright (C) 2014 Freescale Semiconductor, Inc. -- * Author: German Rivera <German.Rivera@freescale.com> -- * -- * This file is licensed under the terms of the GNU General Public -- * License version 2. This program is licensed "as is" without any -- * warranty of any kind, whether express or implied. -- */ --#ifndef _FSL_MC_MCBUS_H_ --#define _FSL_MC_MCBUS_H_ -- --#include "../include/mc.h" --#include <linux/mutex.h> -- --struct irq_domain; --struct msi_domain_info; -- --/** -- * Maximum number of total IRQs that can be pre-allocated for an MC bus' -- * IRQ pool -- */ --#define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256 -- --#ifdef CONFIG_FSL_MC_BUS --#define dev_is_fsl_mc(_dev) ((_dev)->bus == &fsl_mc_bus_type) --#else --/* If fsl-mc bus is not present device cannot belong to fsl-mc bus */ --#define dev_is_fsl_mc(_dev) (0) --#endif -- --/** -- * struct fsl_mc_resource_pool - Pool of MC resources of a given -- * type -- * @type: type of resources in the pool -- * @max_count: maximum number of resources in the pool -- * @free_count: number of free resources in the pool -- * @mutex: mutex to serialize access to the pool's free list -- * @free_list: anchor node of list of free resources in the pool -- * @mc_bus: pointer to the MC bus that owns this resource pool -- */ --struct fsl_mc_resource_pool { -- enum fsl_mc_pool_type type; -- int16_t max_count; -- int16_t free_count; -- struct mutex mutex; /* serializes access to free_list */ -- struct list_head free_list; -- struct fsl_mc_bus *mc_bus; --}; -- --/** -- * struct fsl_mc_bus - logical bus that corresponds to a physical DPRC -- * @mc_dev: fsl-mc device for the bus device itself. -- * @resource_pools: array of resource pools (one pool per resource type) -- * for this MC bus. These resources represent allocatable entities -- * from the physical DPRC. -- * @irq_resources: Pointer to array of IRQ objects for the IRQ pool -- * @scan_mutex: Serializes bus scanning -- * @dprc_attr: DPRC attributes -- */ --struct fsl_mc_bus { -- struct fsl_mc_device mc_dev; -- struct fsl_mc_resource_pool resource_pools[FSL_MC_NUM_POOL_TYPES]; -- struct fsl_mc_device_irq *irq_resources; -- struct mutex scan_mutex; /* serializes bus scanning */ -- struct dprc_attributes dprc_attr; --}; -- --#define to_fsl_mc_bus(_mc_dev) \ -- container_of(_mc_dev, struct fsl_mc_bus, mc_dev) -- --int dprc_scan_container(struct fsl_mc_device *mc_bus_dev); -- --int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, -- unsigned int *total_irq_count); -- --int __init dprc_driver_init(void); -- --void dprc_driver_exit(void); -- --int __init fsl_mc_allocator_driver_init(void); -- --void fsl_mc_allocator_driver_exit(void); -- --struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode, -- struct msi_domain_info *info, -- struct irq_domain *parent); -- --int fsl_mc_find_msi_domain(struct device *mc_platform_dev, -- struct irq_domain **mc_msi_domain); -- --int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, -- unsigned int irq_count); -- --void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus); -- --void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev); -- --void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev); -- --bool fsl_mc_bus_exists(void); -- --void fsl_mc_get_root_dprc(struct device *dev, -- struct device **root_dprc_dev); -- --bool fsl_mc_is_root_dprc(struct device *dev); -- --extern struct bus_type fsl_mc_bus_type; -- --#endif /* _FSL_MC_MCBUS_H_ */ ---- a/drivers/staging/fsl-mc/include/mc-cmd.h -+++ /dev/null -@@ -1,108 +0,0 @@ --/* Copyright 2013-2015 Freescale Semiconductor Inc. -- * -- * Redistribution and use in source and binary forms, with or without -- * modification, are permitted provided that the following conditions are met: -- * * Redistributions of source code must retain the above copyright -- * notice, this list of conditions and the following disclaimer. -- * * Redistributions in binary form must reproduce the above copyright -- * notice, this list of conditions and the following disclaimer in the -- * documentation and/or other materials provided with the distribution. -- * * Neither the name of the above-listed copyright holders nor the -- * names of any contributors may be used to endorse or promote products -- * derived from this software without specific prior written permission. -- * -- * -- * ALTERNATIVELY, this software may be distributed under the terms of the -- * GNU General Public License ("GPL") as published by the Free Software -- * Foundation, either version 2 of that License or (at your option) any -- * later version. -- * -- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -- * POSSIBILITY OF SUCH DAMAGE. -- */ --#ifndef __FSL_MC_CMD_H --#define __FSL_MC_CMD_H -- --#define MC_CMD_NUM_OF_PARAMS 7 -- --struct mc_cmd_header { -- u8 src_id; -- u8 flags_hw; -- u8 status; -- u8 flags_sw; -- __le16 token; -- __le16 cmd_id; --}; -- --struct mc_command { -- u64 header; -- u64 params[MC_CMD_NUM_OF_PARAMS]; --}; -- --enum mc_cmd_status { -- MC_CMD_STATUS_OK = 0x0, /* Completed successfully */ -- MC_CMD_STATUS_READY = 0x1, /* Ready to be processed */ -- MC_CMD_STATUS_AUTH_ERR = 0x3, /* Authentication error */ -- MC_CMD_STATUS_NO_PRIVILEGE = 0x4, /* No privilege */ -- MC_CMD_STATUS_DMA_ERR = 0x5, /* DMA or I/O error */ -- MC_CMD_STATUS_CONFIG_ERR = 0x6, /* Configuration error */ -- MC_CMD_STATUS_TIMEOUT = 0x7, /* Operation timed out */ -- MC_CMD_STATUS_NO_RESOURCE = 0x8, /* No resources */ -- MC_CMD_STATUS_NO_MEMORY = 0x9, /* No memory available */ -- MC_CMD_STATUS_BUSY = 0xA, /* Device is busy */ -- MC_CMD_STATUS_UNSUPPORTED_OP = 0xB, /* Unsupported operation */ -- MC_CMD_STATUS_INVALID_STATE = 0xC /* Invalid state */ --}; -- --/* -- * MC command flags -- */ -- --/* High priority flag */ --#define MC_CMD_FLAG_PRI 0x80 --/* Command completion flag */ --#define MC_CMD_FLAG_INTR_DIS 0x01 -- --#define MC_CMD_HDR_CMDID_MASK 0xFFF0 --#define MC_CMD_HDR_CMDID_SHIFT 4 --#define MC_CMD_HDR_TOKEN_MASK 0xFFC0 --#define MC_CMD_HDR_TOKEN_SHIFT 6 -- --static inline u64 mc_encode_cmd_header(u16 cmd_id, -- u32 cmd_flags, -- u16 token) --{ -- u64 header = 0; -- struct mc_cmd_header *hdr = (struct mc_cmd_header *)&header; -- -- hdr->cmd_id = cpu_to_le16((cmd_id << MC_CMD_HDR_CMDID_SHIFT) & -- MC_CMD_HDR_CMDID_MASK); -- hdr->token = cpu_to_le16((token << MC_CMD_HDR_TOKEN_SHIFT) & -- MC_CMD_HDR_TOKEN_MASK); -- hdr->status = MC_CMD_STATUS_READY; -- if (cmd_flags & MC_CMD_FLAG_PRI) -- hdr->flags_hw = MC_CMD_FLAG_PRI; -- if (cmd_flags & MC_CMD_FLAG_INTR_DIS) -- hdr->flags_sw = MC_CMD_FLAG_INTR_DIS; -- -- return header; --} -- --static inline u16 mc_cmd_hdr_read_token(struct mc_command *cmd) --{ -- struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header; -- u16 token = le16_to_cpu(hdr->token); -- -- return (token & MC_CMD_HDR_TOKEN_MASK) >> MC_CMD_HDR_TOKEN_SHIFT; --} -- --#endif /* __FSL_MC_CMD_H */ ---- a/drivers/staging/fsl-mc/include/mc-sys.h -+++ /dev/null -@@ -1,98 +0,0 @@ --/* Copyright 2013-2014 Freescale Semiconductor Inc. -- * -- * Interface of the I/O services to send MC commands to the MC hardware -- * -- * Redistribution and use in source and binary forms, with or without -- * modification, are permitted provided that the following conditions are met: -- * * Redistributions of source code must retain the above copyright -- * notice, this list of conditions and the following disclaimer. -- * * Redistributions in binary form must reproduce the above copyright -- * notice, this list of conditions and the following disclaimer in the -- * documentation and/or other materials provided with the distribution. -- * * Neither the name of the above-listed copyright holders nor the -- * names of any contributors may be used to endorse or promote products -- * derived from this software without specific prior written permission. -- * -- * -- * ALTERNATIVELY, this software may be distributed under the terms of the -- * GNU General Public License ("GPL") as published by the Free Software -- * Foundation, either version 2 of that License or (at your option) any -- * later version. -- * -- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -- * POSSIBILITY OF SUCH DAMAGE. -- */ -- --#ifndef _FSL_MC_SYS_H --#define _FSL_MC_SYS_H -- --#include <linux/types.h> --#include <linux/errno.h> --#include <linux/mutex.h> --#include <linux/spinlock.h> -- --/** -- * Bit masks for a MC I/O object (struct fsl_mc_io) flags -- */ --#define FSL_MC_IO_ATOMIC_CONTEXT_PORTAL 0x0001 -- --struct fsl_mc_resource; --struct mc_command; -- --/** -- * struct fsl_mc_io - MC I/O object to be passed-in to mc_send_command() -- * @dev: device associated with this Mc I/O object -- * @flags: flags for mc_send_command() -- * @portal_size: MC command portal size in bytes -- * @portal_phys_addr: MC command portal physical address -- * @portal_virt_addr: MC command portal virtual address -- * @dpmcp_dev: pointer to the DPMCP device associated with the MC portal. -- * -- * Fields are only meaningful if the FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is not -- * set: -- * @mutex: Mutex to serialize mc_send_command() calls that use the same MC -- * portal, if the fsl_mc_io object was created with the -- * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag off. mc_send_command() calls for this -- * fsl_mc_io object must be made only from non-atomic context. -- * -- * Fields are only meaningful if the FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is -- * set: -- * @spinlock: Spinlock to serialize mc_send_command() calls that use the same MC -- * portal, if the fsl_mc_io object was created with the -- * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag on. mc_send_command() calls for this -- * fsl_mc_io object can be made from atomic or non-atomic context. -- */ --struct fsl_mc_io { -- struct device *dev; -- u16 flags; -- u16 portal_size; -- phys_addr_t portal_phys_addr; -- void __iomem *portal_virt_addr; -- struct fsl_mc_device *dpmcp_dev; -- union { -- /* -- * This field is only meaningful if the -- * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is not set -- */ -- struct mutex mutex; /* serializes mc_send_command() */ -- -- /* -- * This field is only meaningful if the -- * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is set -- */ -- spinlock_t spinlock; /* serializes mc_send_command() */ -- }; --}; -- --int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd); -- --#endif /* _FSL_MC_SYS_H */ ---- a/drivers/staging/fsl-mc/include/mc.h -+++ /dev/null -@@ -1,201 +0,0 @@ --/* -- * Freescale Management Complex (MC) bus public interface -- * -- * Copyright (C) 2014 Freescale Semiconductor, Inc. -- * Author: German Rivera <German.Rivera@freescale.com> -- * -- * This file is licensed under the terms of the GNU General Public -- * License version 2. This program is licensed "as is" without any -- * warranty of any kind, whether express or implied. -- */ --#ifndef _FSL_MC_H_ --#define _FSL_MC_H_ -- --#include <linux/device.h> --#include <linux/mod_devicetable.h> --#include <linux/interrupt.h> --#include "../include/dprc.h" -- --#define FSL_MC_VENDOR_FREESCALE 0x1957 -- --struct fsl_mc_device; --struct fsl_mc_io; -- --/** -- * struct fsl_mc_driver - MC object device driver object -- * @driver: Generic device driver -- * @match_id_table: table of supported device matching Ids -- * @probe: Function called when a device is added -- * @remove: Function called when a device is removed -- * @shutdown: Function called at shutdown time to quiesce the device -- * @suspend: Function called when a device is stopped -- * @resume: Function called when a device is resumed -- * -- * Generic DPAA device driver object for device drivers that are registered -- * with a DPRC bus. This structure is to be embedded in each device-specific -- * driver structure. -- */ --struct fsl_mc_driver { -- struct device_driver driver; -- const struct fsl_mc_device_id *match_id_table; -- int (*probe)(struct fsl_mc_device *dev); -- int (*remove)(struct fsl_mc_device *dev); -- void (*shutdown)(struct fsl_mc_device *dev); -- int (*suspend)(struct fsl_mc_device *dev, pm_message_t state); -- int (*resume)(struct fsl_mc_device *dev); --}; -- --#define to_fsl_mc_driver(_drv) \ -- container_of(_drv, struct fsl_mc_driver, driver) -- --/** -- * enum fsl_mc_pool_type - Types of allocatable MC bus resources -- * -- * Entries in these enum are used as indices in the array of resource -- * pools of an fsl_mc_bus object. -- */ --enum fsl_mc_pool_type { -- FSL_MC_POOL_DPMCP = 0x0, /* corresponds to "dpmcp" in the MC */ -- FSL_MC_POOL_DPBP, /* corresponds to "dpbp" in the MC */ -- FSL_MC_POOL_DPCON, /* corresponds to "dpcon" in the MC */ -- FSL_MC_POOL_IRQ, -- -- /* -- * NOTE: New resource pool types must be added before this entry -- */ -- FSL_MC_NUM_POOL_TYPES --}; -- --/** -- * struct fsl_mc_resource - MC generic resource -- * @type: type of resource -- * @id: unique MC resource Id within the resources of the same type -- * @data: pointer to resource-specific data if the resource is currently -- * allocated, or NULL if the resource is not currently allocated. -- * @parent_pool: pointer to the parent resource pool from which this -- * resource is allocated from. -- * @node: Node in the free list of the corresponding resource pool -- * -- * NOTE: This structure is to be embedded as a field of specific -- * MC resource structures. -- */ --struct fsl_mc_resource { -- enum fsl_mc_pool_type type; -- int32_t id; -- void *data; -- struct fsl_mc_resource_pool *parent_pool; -- struct list_head node; --}; -- --/** -- * struct fsl_mc_device_irq - MC object device message-based interrupt -- * @msi_desc: pointer to MSI descriptor allocated by fsl_mc_msi_alloc_descs() -- * @mc_dev: MC object device that owns this interrupt -- * @dev_irq_index: device-relative IRQ index -- * @resource: MC generic resource associated with the interrupt -- */ --struct fsl_mc_device_irq { -- struct msi_desc *msi_desc; -- struct fsl_mc_device *mc_dev; -- u8 dev_irq_index; -- struct fsl_mc_resource resource; --}; -- --#define to_fsl_mc_irq(_mc_resource) \ -- container_of(_mc_resource, struct fsl_mc_device_irq, resource) -- --/** -- * Bit masks for a MC object device (struct fsl_mc_device) flags -- */ --#define FSL_MC_IS_DPRC 0x0001 -- --/** -- * struct fsl_mc_device - MC object device object -- * @dev: Linux driver model device object -- * @dma_mask: Default DMA mask -- * @flags: MC object device flags -- * @icid: Isolation context ID for the device -- * @mc_handle: MC handle for the corresponding MC object opened -- * @mc_io: Pointer to MC IO object assigned to this device or -- * NULL if none. -- * @obj_desc: MC description of the DPAA device -- * @regions: pointer to array of MMIO region entries -- * @irqs: pointer to array of pointers to interrupts allocated to this device -- * @resource: generic resource associated with this MC object device, if any. -- * -- * Generic device object for MC object devices that are "attached" to a -- * MC bus. -- * -- * NOTES: -- * - For a non-DPRC object its icid is the same as its parent DPRC's icid. -- * - The SMMU notifier callback gets invoked after device_add() has been -- * called for an MC object device, but before the device-specific probe -- * callback gets called. -- * - DP_OBJ_DPRC objects are the only MC objects that have built-in MC -- * portals. For all other MC objects, their device drivers are responsible for -- * allocating MC portals for them by calling fsl_mc_portal_allocate(). -- * - Some types of MC objects (e.g., DP_OBJ_DPBP, DP_OBJ_DPCON) are -- * treated as resources that can be allocated/deallocated from the -- * corresponding resource pool in the object's parent DPRC, using the -- * fsl_mc_object_allocate()/fsl_mc_object_free() functions. These MC objects -- * are known as "allocatable" objects. For them, the corresponding -- * fsl_mc_device's 'resource' points to the associated resource object. -- * For MC objects that are not allocatable (e.g., DP_OBJ_DPRC, DP_OBJ_DPNI), -- * 'resource' is NULL. -- */ --struct fsl_mc_device { -- struct device dev; -- u64 dma_mask; -- u16 flags; -- u16 icid; -- u16 mc_handle; -- struct fsl_mc_io *mc_io; -- struct dprc_obj_desc obj_desc; -- struct resource *regions; -- struct fsl_mc_device_irq **irqs; -- struct fsl_mc_resource *resource; --}; -- --#define to_fsl_mc_device(_dev) \ -- container_of(_dev, struct fsl_mc_device, dev) -- --/* -- * module_fsl_mc_driver() - Helper macro for drivers that don't do -- * anything special in module init/exit. This eliminates a lot of -- * boilerplate. Each module may only use this macro once, and -- * calling it replaces module_init() and module_exit() -- */ --#define module_fsl_mc_driver(__fsl_mc_driver) \ -- module_driver(__fsl_mc_driver, fsl_mc_driver_register, \ -- fsl_mc_driver_unregister) -- --/* -- * Macro to avoid include chaining to get THIS_MODULE -- */ --#define fsl_mc_driver_register(drv) \ -- __fsl_mc_driver_register(drv, THIS_MODULE) -- --int __must_check __fsl_mc_driver_register(struct fsl_mc_driver *fsl_mc_driver, -- struct module *owner); -- --void fsl_mc_driver_unregister(struct fsl_mc_driver *driver); -- --int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, -- u16 mc_io_flags, -- struct fsl_mc_io **new_mc_io); -- --void fsl_mc_portal_free(struct fsl_mc_io *mc_io); -- --int fsl_mc_portal_reset(struct fsl_mc_io *mc_io); -- --int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev, -- enum fsl_mc_pool_type pool_type, -- struct fsl_mc_device **new_mc_adev); -- --void fsl_mc_object_free(struct fsl_mc_device *mc_adev); -- --int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev); -- --void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev); -- --#endif /* _FSL_MC_H_ */ ---- /dev/null -+++ b/include/linux/fsl/mc.h -@@ -0,0 +1,1025 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Freescale Management Complex (MC) bus public interface -+ * -+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. -+ * Author: German Rivera <German.Rivera@freescale.com> -+ * -+ */ -+#ifndef _FSL_MC_H_ -+#define _FSL_MC_H_ -+ -+#include <linux/device.h> -+#include <linux/mod_devicetable.h> -+#include <linux/interrupt.h> -+#include <linux/cdev.h> -+#include <uapi/linux/fsl_mc.h> -+ -+#define FSL_MC_VENDOR_FREESCALE 0x1957 -+ -+struct irq_domain; -+struct msi_domain_info; -+ -+struct fsl_mc_device; -+struct fsl_mc_io; -+ -+/** -+ * struct fsl_mc_driver - MC object device driver object -+ * @driver: Generic device driver -+ * @match_id_table: table of supported device matching Ids -+ * @probe: Function called when a device is added -+ * @remove: Function called when a device is removed -+ * @shutdown: Function called at shutdown time to quiesce the device -+ * @suspend: Function called when a device is stopped -+ * @resume: Function called when a device is resumed -+ * -+ * Generic DPAA device driver object for device drivers that are registered -+ * with a DPRC bus. This structure is to be embedded in each device-specific -+ * driver structure. -+ */ -+struct fsl_mc_driver { -+ struct device_driver driver; -+ const struct fsl_mc_device_id *match_id_table; -+ int (*probe)(struct fsl_mc_device *dev); -+ int (*remove)(struct fsl_mc_device *dev); -+ void (*shutdown)(struct fsl_mc_device *dev); -+ int (*suspend)(struct fsl_mc_device *dev, pm_message_t state); -+ int (*resume)(struct fsl_mc_device *dev); -+}; -+ -+#define to_fsl_mc_driver(_drv) \ -+ container_of(_drv, struct fsl_mc_driver, driver) -+ -+#define to_fsl_mc_bus(_mc_dev) \ -+ container_of(_mc_dev, struct fsl_mc_bus, mc_dev) -+ -+/** -+ * enum fsl_mc_pool_type - Types of allocatable MC bus resources -+ * -+ * Entries in these enum are used as indices in the array of resource -+ * pools of an fsl_mc_bus object. -+ */ -+enum fsl_mc_pool_type { -+ FSL_MC_POOL_DPMCP = 0x0, /* corresponds to "dpmcp" in the MC */ -+ FSL_MC_POOL_DPBP, /* corresponds to "dpbp" in the MC */ -+ FSL_MC_POOL_DPCON, /* corresponds to "dpcon" in the MC */ -+ FSL_MC_POOL_IRQ, -+ -+ /* -+ * NOTE: New resource pool types must be added before this entry -+ */ -+ FSL_MC_NUM_POOL_TYPES -+}; -+ -+/** -+ * struct fsl_mc_resource - MC generic resource -+ * @type: type of resource -+ * @id: unique MC resource Id within the resources of the same type -+ * @data: pointer to resource-specific data if the resource is currently -+ * allocated, or NULL if the resource is not currently allocated. -+ * @parent_pool: pointer to the parent resource pool from which this -+ * resource is allocated from. -+ * @node: Node in the free list of the corresponding resource pool -+ * -+ * NOTE: This structure is to be embedded as a field of specific -+ * MC resource structures. -+ */ -+struct fsl_mc_resource { -+ enum fsl_mc_pool_type type; -+ s32 id; -+ void *data; -+ struct fsl_mc_resource_pool *parent_pool; -+ struct list_head node; -+}; -+ -+/** -+ * struct fsl_mc_device_irq - MC object device message-based interrupt -+ * @msi_desc: pointer to MSI descriptor allocated by fsl_mc_msi_alloc_descs() -+ * @mc_dev: MC object device that owns this interrupt -+ * @dev_irq_index: device-relative IRQ index -+ * @resource: MC generic resource associated with the interrupt -+ */ -+struct fsl_mc_device_irq { -+ struct msi_desc *msi_desc; -+ struct fsl_mc_device *mc_dev; -+ u8 dev_irq_index; -+ struct fsl_mc_resource resource; -+}; -+ -+#define to_fsl_mc_irq(_mc_resource) \ -+ container_of(_mc_resource, struct fsl_mc_device_irq, resource) -+ -+/* Opened state - Indicates that an object is open by at least one owner */ -+#define FSL_MC_OBJ_STATE_OPEN 0x00000001 -+/* Plugged state - Indicates that the object is plugged */ -+#define FSL_MC_OBJ_STATE_PLUGGED 0x00000002 -+ -+/** -+ * Shareability flag - Object flag indicating no memory shareability. -+ * the object generates memory accesses that are non coherent with other -+ * masters; -+ * user is responsible for proper memory handling through IOMMU configuration. -+ */ -+#define FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY 0x0001 -+ -+/** -+ * struct fsl_mc_obj_desc - Object descriptor -+ * @type: Type of object: NULL terminated string -+ * @id: ID of logical object resource -+ * @vendor: Object vendor identifier -+ * @ver_major: Major version number -+ * @ver_minor: Minor version number -+ * @irq_count: Number of interrupts supported by the object -+ * @region_count: Number of mappable regions supported by the object -+ * @state: Object state: combination of FSL_MC_OBJ_STATE_ states -+ * @label: Object label: NULL terminated string -+ * @flags: Object's flags -+ */ -+struct fsl_mc_obj_desc { -+ char type[16]; -+ int id; -+ u16 vendor; -+ u16 ver_major; -+ u16 ver_minor; -+ u8 irq_count; -+ u8 region_count; -+ u32 state; -+ char label[16]; -+ u16 flags; -+}; -+ -+/** -+ * Bit masks for a MC object device (struct fsl_mc_device) flags -+ */ -+#define FSL_MC_IS_DPRC 0x0001 -+ -+/** -+ * struct fsl_mc_device - MC object device object -+ * @dev: Linux driver model device object -+ * @dma_mask: Default DMA mask -+ * @flags: MC object device flags -+ * @icid: Isolation context ID for the device -+ * @mc_handle: MC handle for the corresponding MC object opened -+ * @mc_io: Pointer to MC IO object assigned to this device or -+ * NULL if none. -+ * @obj_desc: MC description of the DPAA device -+ * @regions: pointer to array of MMIO region entries -+ * @irqs: pointer to array of pointers to interrupts allocated to this device -+ * @resource: generic resource associated with this MC object device, if any. -+ * @driver_override: Driver name to force a match -+ * -+ * Generic device object for MC object devices that are "attached" to a -+ * MC bus. -+ * -+ * NOTES: -+ * - For a non-DPRC object its icid is the same as its parent DPRC's icid. -+ * - The SMMU notifier callback gets invoked after device_add() has been -+ * called for an MC object device, but before the device-specific probe -+ * callback gets called. -+ * - DP_OBJ_DPRC objects are the only MC objects that have built-in MC -+ * portals. For all other MC objects, their device drivers are responsible for -+ * allocating MC portals for them by calling fsl_mc_portal_allocate(). -+ * - Some types of MC objects (e.g., DP_OBJ_DPBP, DP_OBJ_DPCON) are -+ * treated as resources that can be allocated/deallocated from the -+ * corresponding resource pool in the object's parent DPRC, using the -+ * fsl_mc_object_allocate()/fsl_mc_object_free() functions. These MC objects -+ * are known as "allocatable" objects. For them, the corresponding -+ * fsl_mc_device's 'resource' points to the associated resource object. -+ * For MC objects that are not allocatable (e.g., DP_OBJ_DPRC, DP_OBJ_DPNI), -+ * 'resource' is NULL. -+ */ -+struct fsl_mc_device { -+ struct device dev; -+ u64 dma_mask; -+ u16 flags; -+ u32 icid; -+ u16 mc_handle; -+ struct fsl_mc_io *mc_io; -+ struct fsl_mc_obj_desc obj_desc; -+ struct resource *regions; -+ struct fsl_mc_device_irq **irqs; -+ struct fsl_mc_resource *resource; -+ const char *driver_override; -+}; -+ -+#define to_fsl_mc_device(_dev) \ -+ container_of(_dev, struct fsl_mc_device, dev) -+ -+struct mc_cmd_header { -+ u8 src_id; -+ u8 flags_hw; -+ u8 status; -+ u8 flags_sw; -+ __le16 token; -+ __le16 cmd_id; -+}; -+ -+enum mc_cmd_status { -+ MC_CMD_STATUS_OK = 0x0, /* Completed successfully */ -+ MC_CMD_STATUS_READY = 0x1, /* Ready to be processed */ -+ MC_CMD_STATUS_AUTH_ERR = 0x3, /* Authentication error */ -+ MC_CMD_STATUS_NO_PRIVILEGE = 0x4, /* No privilege */ -+ MC_CMD_STATUS_DMA_ERR = 0x5, /* DMA or I/O error */ -+ MC_CMD_STATUS_CONFIG_ERR = 0x6, /* Configuration error */ -+ MC_CMD_STATUS_TIMEOUT = 0x7, /* Operation timed out */ -+ MC_CMD_STATUS_NO_RESOURCE = 0x8, /* No resources */ -+ MC_CMD_STATUS_NO_MEMORY = 0x9, /* No memory available */ -+ MC_CMD_STATUS_BUSY = 0xA, /* Device is busy */ -+ MC_CMD_STATUS_UNSUPPORTED_OP = 0xB, /* Unsupported operation */ -+ MC_CMD_STATUS_INVALID_STATE = 0xC /* Invalid state */ -+}; -+ -+/* -+ * MC command flags -+ */ -+ -+/* High priority flag */ -+#define MC_CMD_FLAG_PRI 0x80 -+/* Command completion flag */ -+#define MC_CMD_FLAG_INTR_DIS 0x01 -+ -+static inline u64 mc_encode_cmd_header(u16 cmd_id, -+ u32 cmd_flags, -+ u16 token) -+{ -+ u64 header = 0; -+ struct mc_cmd_header *hdr = (struct mc_cmd_header *)&header; -+ -+ hdr->cmd_id = cpu_to_le16(cmd_id); -+ hdr->token = cpu_to_le16(token); -+ hdr->status = MC_CMD_STATUS_READY; -+ if (cmd_flags & MC_CMD_FLAG_PRI) -+ hdr->flags_hw = MC_CMD_FLAG_PRI; -+ if (cmd_flags & MC_CMD_FLAG_INTR_DIS) -+ hdr->flags_sw = MC_CMD_FLAG_INTR_DIS; -+ -+ return header; -+} -+ -+static inline u16 mc_cmd_hdr_read_token(struct fsl_mc_command *cmd) -+{ -+ struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header; -+ u16 token = le16_to_cpu(hdr->token); -+ -+ return token; -+} -+ -+struct mc_rsp_create { -+ __le32 object_id; -+}; -+ -+struct mc_rsp_api_ver { -+ __le16 major_ver; -+ __le16 minor_ver; -+}; -+ -+static inline u32 mc_cmd_read_object_id(struct fsl_mc_command *cmd) -+{ -+ struct mc_rsp_create *rsp_params; -+ -+ rsp_params = (struct mc_rsp_create *)cmd->params; -+ return le32_to_cpu(rsp_params->object_id); -+} -+ -+static inline void mc_cmd_read_api_version(struct fsl_mc_command *cmd, -+ u16 *major_ver, -+ u16 *minor_ver) -+{ -+ struct mc_rsp_api_ver *rsp_params; -+ -+ rsp_params = (struct mc_rsp_api_ver *)cmd->params; -+ *major_ver = le16_to_cpu(rsp_params->major_ver); -+ *minor_ver = le16_to_cpu(rsp_params->minor_ver); -+} -+ -+/** -+ * Bit masks for a MC I/O object (struct fsl_mc_io) flags -+ */ -+#define FSL_MC_IO_ATOMIC_CONTEXT_PORTAL 0x0001 -+ -+/** -+ * struct fsl_mc_io - MC I/O object to be passed-in to mc_send_command() -+ * @dev: device associated with this Mc I/O object -+ * @flags: flags for mc_send_command() -+ * @portal_size: MC command portal size in bytes -+ * @portal_phys_addr: MC command portal physical address -+ * @portal_virt_addr: MC command portal virtual address -+ * @dpmcp_dev: pointer to the DPMCP device associated with the MC portal. -+ * -+ * Fields are only meaningful if the FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is not -+ * set: -+ * @mutex: Mutex to serialize mc_send_command() calls that use the same MC -+ * portal, if the fsl_mc_io object was created with the -+ * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag off. mc_send_command() calls for this -+ * fsl_mc_io object must be made only from non-atomic context. -+ * -+ * Fields are only meaningful if the FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is -+ * set: -+ * @spinlock: Spinlock to serialize mc_send_command() calls that use the same MC -+ * portal, if the fsl_mc_io object was created with the -+ * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag on. mc_send_command() calls for this -+ * fsl_mc_io object can be made from atomic or non-atomic context. -+ */ -+struct fsl_mc_io { -+ struct device *dev; -+ u16 flags; -+ u32 portal_size; -+ phys_addr_t portal_phys_addr; -+ void __iomem *portal_virt_addr; -+ struct fsl_mc_device *dpmcp_dev; -+ union { -+ /* -+ * This field is only meaningful if the -+ * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is not set -+ */ -+ struct mutex mutex; /* serializes mc_send_command() */ -+ -+ /* -+ * This field is only meaningful if the -+ * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is set -+ */ -+ spinlock_t spinlock; /* serializes mc_send_command() */ -+ }; -+}; -+ -+int mc_send_command(struct fsl_mc_io *mc_io, struct fsl_mc_command *cmd); -+ -+#ifdef CONFIG_FSL_MC_BUS -+#define dev_is_fsl_mc(_dev) ((_dev)->bus == &fsl_mc_bus_type) -+#else -+/* If fsl-mc bus is not present device cannot belong to fsl-mc bus */ -+#define dev_is_fsl_mc(_dev) (0) -+#endif -+ -+/* Macro to check if a device is a container device */ -+#define fsl_mc_is_cont_dev(_dev) (to_fsl_mc_device(_dev)->flags & \ -+ FSL_MC_IS_DPRC) -+ -+/* Macro to get the container device of a MC device */ -+#define fsl_mc_cont_dev(_dev) (fsl_mc_is_cont_dev(_dev) ? \ -+ (_dev) : (_dev)->parent) -+ -+#define fsl_mc_is_dev_coherent(_dev) \ -+ (!((to_fsl_mc_device(_dev))->obj_desc.flags & \ -+ FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY)) -+ -+/* -+ * module_fsl_mc_driver() - Helper macro for drivers that don't do -+ * anything special in module init/exit. This eliminates a lot of -+ * boilerplate. Each module may only use this macro once, and -+ * calling it replaces module_init() and module_exit() -+ */ -+#define module_fsl_mc_driver(__fsl_mc_driver) \ -+ module_driver(__fsl_mc_driver, fsl_mc_driver_register, \ -+ fsl_mc_driver_unregister) -+ -+void fsl_mc_device_remove(struct fsl_mc_device *mc_dev); -+ -+/* -+ * Macro to avoid include chaining to get THIS_MODULE -+ */ -+#define fsl_mc_driver_register(drv) \ -+ __fsl_mc_driver_register(drv, THIS_MODULE) -+ -+int __must_check __fsl_mc_driver_register(struct fsl_mc_driver *fsl_mc_driver, -+ struct module *owner); -+ -+void fsl_mc_driver_unregister(struct fsl_mc_driver *driver); -+ -+int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, -+ u16 mc_io_flags, -+ struct fsl_mc_io **new_mc_io); -+ -+void fsl_mc_portal_free(struct fsl_mc_io *mc_io); -+ -+int fsl_mc_portal_reset(struct fsl_mc_io *mc_io); -+ -+int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev, -+ enum fsl_mc_pool_type pool_type, -+ struct fsl_mc_device **new_mc_adev); -+ -+void fsl_mc_object_free(struct fsl_mc_device *mc_adev); -+ -+struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode, -+ struct msi_domain_info *info, -+ struct irq_domain *parent); -+ -+int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev); -+ -+void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev); -+ -+void fsl_mc_dma_configure(struct fsl_mc_device *mc_dev, -+ struct device_node *fsl_mc_platform_node, int coherent); -+ -+extern struct bus_type fsl_mc_bus_type; -+ -+extern struct device_type fsl_mc_bus_dprc_type; -+extern struct device_type fsl_mc_bus_dpni_type; -+extern struct device_type fsl_mc_bus_dpio_type; -+extern struct device_type fsl_mc_bus_dpsw_type; -+extern struct device_type fsl_mc_bus_dpdmux_type; -+extern struct device_type fsl_mc_bus_dpbp_type; -+extern struct device_type fsl_mc_bus_dpcon_type; -+extern struct device_type fsl_mc_bus_dpmcp_type; -+extern struct device_type fsl_mc_bus_dpmac_type; -+extern struct device_type fsl_mc_bus_dprtc_type; -+extern struct device_type fsl_mc_bus_dpseci_type; -+extern struct device_type fsl_mc_bus_dpdcei_type; -+extern struct device_type fsl_mc_bus_dpaiop_type; -+extern struct device_type fsl_mc_bus_dpci_type; -+extern struct device_type fsl_mc_bus_dpdmai_type; -+ -+static inline bool is_fsl_mc_bus_dprc(const struct fsl_mc_device *mc_dev) -+{ -+ return mc_dev->dev.type == &fsl_mc_bus_dprc_type; -+} -+ -+static inline bool is_fsl_mc_bus_dpni(const struct fsl_mc_device *mc_dev) -+{ -+ return mc_dev->dev.type == &fsl_mc_bus_dpni_type; -+} -+ -+static inline bool is_fsl_mc_bus_dpio(const struct fsl_mc_device *mc_dev) -+{ -+ return mc_dev->dev.type == &fsl_mc_bus_dpio_type; -+} -+ -+static inline bool is_fsl_mc_bus_dpsw(const struct fsl_mc_device *mc_dev) -+{ -+ return mc_dev->dev.type == &fsl_mc_bus_dpsw_type; -+} -+ -+static inline bool is_fsl_mc_bus_dpdmux(const struct fsl_mc_device *mc_dev) -+{ -+ return mc_dev->dev.type == &fsl_mc_bus_dpdmux_type; -+} -+ -+static inline bool is_fsl_mc_bus_dpbp(const struct fsl_mc_device *mc_dev) -+{ -+ return mc_dev->dev.type == &fsl_mc_bus_dpbp_type; -+} -+ -+static inline bool is_fsl_mc_bus_dpcon(const struct fsl_mc_device *mc_dev) -+{ -+ return mc_dev->dev.type == &fsl_mc_bus_dpcon_type; -+} -+ -+static inline bool is_fsl_mc_bus_dpmcp(const struct fsl_mc_device *mc_dev) -+{ -+ return mc_dev->dev.type == &fsl_mc_bus_dpmcp_type; -+} -+ -+static inline bool is_fsl_mc_bus_dpmac(const struct fsl_mc_device *mc_dev) -+{ -+ return mc_dev->dev.type == &fsl_mc_bus_dpmac_type; -+} -+ -+static inline bool is_fsl_mc_bus_dprtc(const struct fsl_mc_device *mc_dev) -+{ -+ return mc_dev->dev.type == &fsl_mc_bus_dprtc_type; -+} -+ -+static inline bool is_fsl_mc_bus_dpseci(const struct fsl_mc_device *mc_dev) -+{ -+ return mc_dev->dev.type == &fsl_mc_bus_dpseci_type; -+} -+ -+static inline bool is_fsl_mc_bus_dpdcei(const struct fsl_mc_device *mc_dev) -+{ -+ return mc_dev->dev.type == &fsl_mc_bus_dpdcei_type; -+} -+ -+static inline bool is_fsl_mc_bus_dpaiop(const struct fsl_mc_device *mc_dev) -+{ -+ return mc_dev->dev.type == &fsl_mc_bus_dpaiop_type; -+} -+ -+static inline bool is_fsl_mc_bus_dpci(const struct fsl_mc_device *mc_dev) -+{ -+ return mc_dev->dev.type == &fsl_mc_bus_dpci_type; -+} -+ -+static inline bool is_fsl_mc_bus_dpdmai(const struct fsl_mc_device *mc_dev) -+{ -+ return mc_dev->dev.type == &fsl_mc_bus_dpdmai_type; -+} -+ -+/* -+ * Data Path Resource Container (DPRC) API -+ */ -+ -+/* Minimal supported DPRC Version */ -+#define DPRC_MIN_VER_MAJOR 6 -+#define DPRC_MIN_VER_MINOR 0 -+ -+/* DPRC command versioning */ -+#define DPRC_CMD_BASE_VERSION 1 -+#define DPRC_CMD_ID_OFFSET 4 -+ -+#define DPRC_CMD(id) (((id) << DPRC_CMD_ID_OFFSET) | DPRC_CMD_BASE_VERSION) -+ -+/* DPRC command IDs */ -+#define DPRC_CMDID_CLOSE DPRC_CMD(0x800) -+#define DPRC_CMDID_OPEN DPRC_CMD(0x805) -+#define DPRC_CMDID_GET_API_VERSION DPRC_CMD(0xa05) -+ -+#define DPRC_CMDID_GET_ATTR DPRC_CMD(0x004) -+#define DPRC_CMDID_RESET_CONT DPRC_CMD(0x005) -+ -+#define DPRC_CMDID_SET_IRQ DPRC_CMD(0x010) -+#define DPRC_CMDID_SET_IRQ_ENABLE DPRC_CMD(0x012) -+#define DPRC_CMDID_SET_IRQ_MASK DPRC_CMD(0x014) -+#define DPRC_CMDID_GET_IRQ_STATUS DPRC_CMD(0x016) -+#define DPRC_CMDID_CLEAR_IRQ_STATUS DPRC_CMD(0x017) -+ -+#define DPRC_CMDID_GET_CONT_ID DPRC_CMD(0x830) -+#define DPRC_CMDID_GET_OBJ_COUNT DPRC_CMD(0x159) -+#define DPRC_CMDID_GET_OBJ DPRC_CMD(0x15A) -+#define DPRC_CMDID_GET_OBJ_REG DPRC_CMD(0x15E) -+#define DPRC_CMDID_SET_OBJ_IRQ DPRC_CMD(0x15F) -+ -+struct dprc_cmd_open { -+ __le32 container_id; -+}; -+ -+struct dprc_cmd_reset_container { -+ __le32 child_container_id; -+}; -+ -+struct dprc_cmd_set_irq { -+ /* cmd word 0 */ -+ __le32 irq_val; -+ u8 irq_index; -+ u8 pad[3]; -+ /* cmd word 1 */ -+ __le64 irq_addr; -+ /* cmd word 2 */ -+ __le32 irq_num; -+}; -+ -+#define DPRC_ENABLE 0x1 -+ -+struct dprc_cmd_set_irq_enable { -+ u8 enable; -+ u8 pad[3]; -+ u8 irq_index; -+}; -+ -+struct dprc_cmd_set_irq_mask { -+ __le32 mask; -+ u8 irq_index; -+}; -+ -+struct dprc_cmd_get_irq_status { -+ __le32 status; -+ u8 irq_index; -+}; -+ -+struct dprc_rsp_get_irq_status { -+ __le32 status; -+}; -+ -+struct dprc_cmd_clear_irq_status { -+ __le32 status; -+ u8 irq_index; -+}; -+ -+struct dprc_rsp_get_attributes { -+ /* response word 0 */ -+ __le32 container_id; -+ __le32 icid; -+ /* response word 1 */ -+ __le32 options; -+ __le32 portal_id; -+}; -+ -+struct dprc_rsp_get_obj_count { -+ __le32 pad; -+ __le32 obj_count; -+}; -+ -+struct dprc_cmd_get_obj { -+ __le32 obj_index; -+}; -+ -+struct dprc_rsp_get_obj { -+ /* response word 0 */ -+ __le32 pad0; -+ __le32 id; -+ /* response word 1 */ -+ __le16 vendor; -+ u8 irq_count; -+ u8 region_count; -+ __le32 state; -+ /* response word 2 */ -+ __le16 version_major; -+ __le16 version_minor; -+ __le16 flags; -+ __le16 pad1; -+ /* response word 3-4 */ -+ u8 type[16]; -+ /* response word 5-6 */ -+ u8 label[16]; -+}; -+ -+struct dprc_cmd_get_obj_region { -+ /* cmd word 0 */ -+ __le32 obj_id; -+ __le16 pad0; -+ u8 region_index; -+ u8 pad1; -+ /* cmd word 1-2 */ -+ __le64 pad2[2]; -+ /* cmd word 3-4 */ -+ u8 obj_type[16]; -+}; -+ -+struct dprc_rsp_get_obj_region { -+ /* response word 0 */ -+ __le64 pad0; -+ /* response word 1 */ -+ __le32 base_addr; -+ __le32 pad1; -+ /* response word 2 */ -+ __le32 size; -+ u8 type; -+ u8 pad2[3]; -+ /* response word 3 */ -+ __le32 flags; -+}; -+ -+struct dprc_cmd_set_obj_irq { -+ /* cmd word 0 */ -+ __le32 irq_val; -+ u8 irq_index; -+ u8 pad[3]; -+ /* cmd word 1 */ -+ __le64 irq_addr; -+ /* cmd word 2 */ -+ __le32 irq_num; -+ __le32 obj_id; -+ /* cmd word 3-4 */ -+ u8 obj_type[16]; -+}; -+ -+/* -+ * DPRC API for managing and querying DPAA resources -+ */ -+int dprc_open(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ int container_id, -+ u16 *token); -+ -+int dprc_close(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token); -+ -+/* DPRC IRQ events */ -+ -+/* IRQ event - Indicates that a new object added to the container */ -+#define DPRC_IRQ_EVENT_OBJ_ADDED 0x00000001 -+/* IRQ event - Indicates that an object was removed from the container */ -+#define DPRC_IRQ_EVENT_OBJ_REMOVED 0x00000002 -+/* -+ * IRQ event - Indicates that one of the descendant containers that opened by -+ * this container is destroyed -+ */ -+#define DPRC_IRQ_EVENT_CONTAINER_DESTROYED 0x00000010 -+ -+/* -+ * IRQ event - Indicates that on one of the container's opened object is -+ * destroyed -+ */ -+#define DPRC_IRQ_EVENT_OBJ_DESTROYED 0x00000020 -+ -+/* Irq event - Indicates that object is created at the container */ -+#define DPRC_IRQ_EVENT_OBJ_CREATED 0x00000040 -+ -+/** -+ * struct dprc_irq_cfg - IRQ configuration -+ * @paddr: Address that must be written to signal a message-based interrupt -+ * @val: Value to write into irq_addr address -+ * @irq_num: A user defined number associated with this IRQ -+ */ -+struct dprc_irq_cfg { -+ phys_addr_t paddr; -+ u32 val; -+ int irq_num; -+}; -+ -+int dprc_set_irq(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u8 irq_index, -+ struct dprc_irq_cfg *irq_cfg); -+ -+int dprc_set_irq_enable(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u8 irq_index, -+ u8 en); -+ -+int dprc_set_irq_mask(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u8 irq_index, -+ u32 mask); -+ -+int dprc_get_irq_status(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u8 irq_index, -+ u32 *status); -+ -+int dprc_clear_irq_status(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u8 irq_index, -+ u32 status); -+ -+/** -+ * struct dprc_attributes - Container attributes -+ * @container_id: Container's ID -+ * @icid: Container's ICID -+ * @portal_id: Container's portal ID -+ * @options: Container's options as set at container's creation -+ */ -+struct dprc_attributes { -+ int container_id; -+ u32 icid; -+ int portal_id; -+ u64 options; -+}; -+ -+int dprc_get_attributes(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ struct dprc_attributes *attributes); -+ -+int dprc_get_obj_count(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ int *obj_count); -+ -+int dprc_get_obj(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ int obj_index, -+ struct fsl_mc_obj_desc *obj_desc); -+ -+int dprc_set_obj_irq(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ char *obj_type, -+ int obj_id, -+ u8 irq_index, -+ struct dprc_irq_cfg *irq_cfg); -+ -+/* Region flags */ -+/* Cacheable - Indicates that region should be mapped as cacheable */ -+#define DPRC_REGION_CACHEABLE 0x00000001 -+ -+/** -+ * enum dprc_region_type - Region type -+ * @DPRC_REGION_TYPE_MC_PORTAL: MC portal region -+ * @DPRC_REGION_TYPE_QBMAN_PORTAL: Qbman portal region -+ */ -+enum dprc_region_type { -+ DPRC_REGION_TYPE_MC_PORTAL, -+ DPRC_REGION_TYPE_QBMAN_PORTAL -+}; -+ -+#define DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY 0x0001 -+ -+/** -+ * struct dprc_region_desc - Mappable region descriptor -+ * @base_offset: Region offset from region's base address. -+ * For DPMCP and DPRC objects, region base is offset from SoC MC portals -+ * base address; For DPIO, region base is offset from SoC QMan portals -+ * base address -+ * @size: Region size (in bytes) -+ * @flags: Region attributes -+ * @type: Portal region type -+ */ -+struct dprc_region_desc { -+ u32 base_offset; -+ u32 size; -+ u32 flags; -+ enum dprc_region_type type; -+}; -+ -+int dprc_get_obj_region(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ char *obj_type, -+ int obj_id, -+ u8 region_index, -+ struct dprc_region_desc *region_desc); -+ -+int dprc_get_api_version(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 *major_ver, -+ u16 *minor_ver); -+ -+int dprc_get_container_id(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ int *container_id); -+ -+int dprc_reset_container(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ int child_container_id); -+ -+/* -+ * Data Path Buffer Pool (DPBP) API -+ * Contains initialization APIs and runtime control APIs for DPBP -+ */ -+ -+int dpbp_open(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ int dpbp_id, -+ u16 *token); -+ -+int dpbp_close(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token); -+ -+int dpbp_enable(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token); -+ -+int dpbp_disable(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token); -+ -+int dpbp_reset(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token); -+ -+/** -+ * struct dpbp_attr - Structure representing DPBP attributes -+ * @id: DPBP object ID -+ * @bpid: Hardware buffer pool ID; should be used as an argument in -+ * acquire/release operations on buffers -+ */ -+struct dpbp_attr { -+ int id; -+ u16 bpid; -+}; -+ -+int dpbp_get_attributes(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ struct dpbp_attr *attr); -+ -+/* Data Path Concentrator (DPCON) API -+ * Contains initialization APIs and runtime control APIs for DPCON -+ */ -+ -+/** -+ * Use it to disable notifications; see dpcon_set_notification() -+ */ -+#define DPCON_INVALID_DPIO_ID (int)(-1) -+ -+int dpcon_open(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ int dpcon_id, -+ u16 *token); -+ -+int dpcon_close(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token); -+ -+int dpcon_enable(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token); -+ -+int dpcon_disable(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token); -+ -+int dpcon_reset(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token); -+ -+/** -+ * struct dpcon_attr - Structure representing DPCON attributes -+ * @id: DPCON object ID -+ * @qbman_ch_id: Channel ID to be used by dequeue operation -+ * @num_priorities: Number of priorities for the DPCON channel (1-8) -+ */ -+struct dpcon_attr { -+ int id; -+ u16 qbman_ch_id; -+ u8 num_priorities; -+}; -+ -+int dpcon_get_attributes(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ struct dpcon_attr *attr); -+ -+/** -+ * struct dpcon_notification_cfg - Structure representing notification params -+ * @dpio_id: DPIO object ID; must be configured with a notification channel; -+ * to disable notifications set it to 'DPCON_INVALID_DPIO_ID'; -+ * @priority: Priority selection within the DPIO channel; valid values -+ * are 0-7, depending on the number of priorities in that channel -+ * @user_ctx: User context value provided with each CDAN message -+ */ -+struct dpcon_notification_cfg { -+ int dpio_id; -+ u8 priority; -+ u64 user_ctx; -+}; -+ -+int dpcon_set_notification(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ struct dpcon_notification_cfg *cfg); -+ -+struct irq_domain; -+struct msi_domain_info; -+ -+/** -+ * Maximum number of total IRQs that can be pre-allocated for an MC bus' -+ * IRQ pool -+ */ -+#define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256 -+ -+/** -+ * struct fsl_mc_resource_pool - Pool of MC resources of a given -+ * type -+ * @type: type of resources in the pool -+ * @max_count: maximum number of resources in the pool -+ * @free_count: number of free resources in the pool -+ * @mutex: mutex to serialize access to the pool's free list -+ * @free_list: anchor node of list of free resources in the pool -+ * @mc_bus: pointer to the MC bus that owns this resource pool -+ */ -+struct fsl_mc_resource_pool { -+ enum fsl_mc_pool_type type; -+ int max_count; -+ int free_count; -+ struct mutex mutex; /* serializes access to free_list */ -+ struct list_head free_list; -+ struct fsl_mc_bus *mc_bus; -+}; -+ -+/** -+ * struct fsl_mc_restool - information associated with a restool device file -+ * @cdev: struct char device linked to the root dprc -+ * @dev: dev_t for the char device to be added -+ * @device: newly created device in /dev -+ * @mutex: mutex lock to serialize the open/release operations -+ * @local_instance_in_use: local MC I/O instance in use or not -+ * @dynamic_instance_count: number of dynamically created MC I/O instances -+ */ -+struct fsl_mc_restool { -+ struct cdev cdev; -+ dev_t dev; -+ struct device *device; -+ struct mutex mutex; /* serialize open/release operations */ -+ bool local_instance_in_use; -+ u32 dynamic_instance_count; -+}; -+ -+/** -+ * struct fsl_mc_bus - logical bus that corresponds to a physical DPRC -+ * @mc_dev: fsl-mc device for the bus device itself. -+ * @resource_pools: array of resource pools (one pool per resource type) -+ * for this MC bus. These resources represent allocatable entities -+ * from the physical DPRC. -+ * @irq_resources: Pointer to array of IRQ objects for the IRQ pool -+ * @scan_mutex: Serializes bus scanning -+ * @dprc_attr: DPRC attributes -+ * @restool_misc: struct that abstracts the interaction with userspace restool -+ */ -+struct fsl_mc_bus { -+ struct fsl_mc_device mc_dev; -+ struct fsl_mc_resource_pool resource_pools[FSL_MC_NUM_POOL_TYPES]; -+ struct fsl_mc_device_irq *irq_resources; -+ struct mutex scan_mutex; /* serializes bus scanning */ -+ struct dprc_attributes dprc_attr; -+ struct fsl_mc_restool restool_misc; -+}; -+ -+int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, -+ const char *driver_override, -+ unsigned int *total_irq_count); -+ -+int fsl_mc_find_msi_domain(struct device *mc_platform_dev, -+ struct irq_domain **mc_msi_domain); -+ -+int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, -+ unsigned int irq_count); -+ -+void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus); -+ -+void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev); -+ -+void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev); -+ -+void fsl_mc_get_root_dprc(struct device *dev, struct device **root_dprc_dev); -+ -+#endif /* _FSL_MC_H_ */ ---- /dev/null -+++ b/include/uapi/linux/fsl_mc.h -@@ -0,0 +1,31 @@ -+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -+/* -+ * Management Complex (MC) userspace public interface -+ * -+ * Copyright 2018 NXP -+ * -+ */ -+#ifndef _UAPI_FSL_MC_H_ -+#define _UAPI_FSL_MC_H_ -+ -+#define MC_CMD_NUM_OF_PARAMS 7 -+ -+/** -+ * struct fsl_mc_command - Management Complex (MC) command structure -+ * @header: MC command header -+ * @params: MC command parameters -+ * -+ * Used by RESTOOL_SEND_MC_COMMAND -+ */ -+struct fsl_mc_command { -+ __u64 header; -+ __u64 params[MC_CMD_NUM_OF_PARAMS]; -+}; -+ -+#define RESTOOL_IOCTL_TYPE 'R' -+#define RESTOOL_IOCTL_SEQ 0xE0 -+ -+#define RESTOOL_SEND_MC_COMMAND \ -+ _IOWR(RESTOOL_IOCTL_TYPE, RESTOOL_IOCTL_SEQ, struct fsl_mc_command) -+ -+#endif /* _UAPI_FSL_MC_H_ */ |