From 4bbc0e735754acfd7c37eb87c2f2ceb46bafdb16 Mon Sep 17 00:00:00 2001 From: Yangbo Lu Date: Fri, 22 May 2020 15:08:54 +0800 Subject: layerscape: remove support for kernel 4.14 Remove support for kernel 4.14, and NXP Layerscape SDK had not supported kernel 4.14 since LSDK-20.04 either. Signed-off-by: Yangbo Lu --- .../708-mc-bus-support-layerscape.patch | 12074 ------------------- 1 file changed, 12074 deletions(-) delete mode 100644 target/linux/layerscape/patches-4.14/708-mc-bus-support-layerscape.patch (limited to 'target/linux/layerscape/patches-4.14/708-mc-bus-support-layerscape.patch') diff --git a/target/linux/layerscape/patches-4.14/708-mc-bus-support-layerscape.patch b/target/linux/layerscape/patches-4.14/708-mc-bus-support-layerscape.patch deleted file mode 100644 index 129b8ecc64..0000000000 --- a/target/linux/layerscape/patches-4.14/708-mc-bus-support-layerscape.patch +++ /dev/null @@ -1,12074 +0,0 @@ -From ab58c737bc723f52e787e1767bbbf0fcbe39a27b Mon Sep 17 00:00:00 2001 -From: Biwen Li -Date: Wed, 17 Apr 2019 18:58:43 +0800 -Subject: [PATCH] mc-bus: support layerscape -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This is an integrated patch of mc-bus for layerscape - -Signed-off-by: Bharat Bhushan -Signed-off-by: Biwen Li -Signed-off-by: Bogdan Purcareata -Signed-off-by: Cristian Sovaiala -Signed-off-by: Greg Kroah-Hartman -Signed-off-by: Guanhua Gao -Signed-off-by: Horia Geantă -Signed-off-by: Ioana Ciornei -Signed-off-by: Ioana Radulescu -Signed-off-by: J. German Rivera -Signed-off-by: Laurentiu Tudor -Signed-off-by: Lijun Pan -Signed-off-by: Nipun Gupta -Signed-off-by: Radu Alexe -Signed-off-by: Razvan Stefanescu -Signed-off-by: Roy Pledge -Signed-off-by: Stuart Yoder ---- - drivers/bus/Kconfig | 2 + - drivers/bus/Makefile | 4 + - drivers/bus/fsl-mc/Kconfig | 23 + - drivers/bus/fsl-mc/Makefile | 21 + - .../{staging/fsl-mc/bus => bus/fsl-mc}/dpbp.c | 97 +- - .../fsl-mc/bus => bus/fsl-mc}/dpcon.c | 103 +- - drivers/bus/fsl-mc/dpmcp.c | 99 ++ - .../fsl-mc/bus => bus/fsl-mc}/dprc-driver.c | 96 +- - .../{staging/fsl-mc/bus => bus/fsl-mc}/dprc.c | 289 +---- - .../bus => bus/fsl-mc}/fsl-mc-allocator.c | 123 +- - .../fsl-mc/bus => bus/fsl-mc}/fsl-mc-bus.c | 322 +++++- - .../fsl-mc/bus => bus/fsl-mc}/fsl-mc-msi.c | 16 +- - 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 | 51 +- - .../fsl-mc/bus => bus/fsl-mc}/mc-sys.c | 33 +- - drivers/irqchip/Kconfig | 6 + - drivers/irqchip/Makefile | 1 + - drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c | 98 ++ - .../staging/fsl-dpaa2/ethernet/dpaa2-eth.c | 2 +- - .../staging/fsl-dpaa2/ethernet/dpaa2-eth.h | 3 +- - drivers/staging/fsl-dpaa2/ethernet/dpni.c | 2 +- - drivers/staging/fsl-mc/bus/Kconfig | 15 +- - drivers/staging/fsl-mc/bus/Makefile | 13 - - drivers/staging/fsl-mc/bus/dpio/dpio-driver.c | 2 +- - .../staging/fsl-mc/bus/dpio/dpio-service.c | 2 +- - drivers/staging/fsl-mc/bus/dpio/dpio.c | 14 +- - drivers/staging/fsl-mc/bus/dpmcp-cmd.h | 56 - - drivers/staging/fsl-mc/bus/dpmcp.h | 60 - - drivers/staging/fsl-mc/bus/dpmng-cmd.h | 58 - - drivers/staging/fsl-mc/bus/dprc-cmd.h | 451 -------- - drivers/staging/fsl-mc/bus/dprc.h | 268 ----- - .../fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c | 1 + - include/linux/fsl/mc.h | 1029 +++++++++++++++++ - include/uapi/linux/fsl_mc.h | 31 + - 35 files changed, 2302 insertions(+), 1531 deletions(-) - create mode 100644 drivers/bus/fsl-mc/Kconfig - create mode 100644 drivers/bus/fsl-mc/Makefile - rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpbp.c (67%) - rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpcon.c (70%) - create mode 100644 drivers/bus/fsl-mc/dpmcp.c - rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dprc-driver.c (93%) - rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dprc.c (68%) - rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-allocator.c (84%) - rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-bus.c (75%) - rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-msi.c (96%) - 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 (89%) - rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/mc-sys.c (90%) - create mode 100644 drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c - delete mode 100644 drivers/staging/fsl-mc/bus/dpmcp-cmd.h - 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/dprc-cmd.h - delete mode 100644 drivers/staging/fsl-mc/bus/dprc.h - create mode 100644 include/linux/fsl/mc.h - create mode 100644 include/uapi/linux/fsl_mc.h - ---- a/drivers/bus/Kconfig -+++ b/drivers/bus/Kconfig -@@ -184,4 +184,6 @@ config DA8XX_MSTPRI - configuration. Allows to adjust the priorities of all master - peripherals. - -+source "drivers/bus/fsl-mc/Kconfig" -+ - endmenu ---- a/drivers/bus/Makefile -+++ b/drivers/bus/Makefile -@@ -8,6 +8,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,21 @@ -+# 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 -+ -+# MC restool kernel support -+obj-$(CONFIG_FSL_MC_RESTOOL) += fsl-mc-restool.o ---- a/drivers/staging/fsl-mc/bus/dpbp.c -+++ /dev/null -@@ -1,253 +0,0 @@ --// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) --/* -- * Copyright 2013-2016 Freescale Semiconductor Inc. -- * -- */ --#include --#include "../include/mc.h" --#include "../include/dpbp.h" -- --#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_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; --} --EXPORT_SYMBOL(dpbp_is_enabled); -- --/** -- * 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); --} --EXPORT_SYMBOL(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 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(dpbp_get_attributes); -- --/** -- * dpbp_get_api_version - Get Data Path Buffer Pool 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 Buffer Pool API -- * @minor_ver: Minor version of Buffer Pool API -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpbp_get_api_version(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 *major_ver, -- u16 *minor_ver) --{ -- struct mc_command cmd = { 0 }; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPBP_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; --} --EXPORT_SYMBOL(dpbp_get_api_version); ---- /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 -+#include -+#include -+ -+#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); ---- a/drivers/staging/fsl-mc/bus/dpcon.c -+++ /dev/null -@@ -1,291 +0,0 @@ --// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) --/* -- * Copyright 2013-2016 Freescale Semiconductor Inc. -- * -- */ --#include --#include "../include/mc.h" --#include "../include/dpcon.h" -- --#include "dpcon-cmd.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 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(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 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(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 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(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 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(dpcon_disable); -- --/** -- * dpcon_is_enabled() - Check if the DPCON 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 DPCON object -- * @en: Returns '1' if object is enabled; '0' otherwise -- * -- * Return: '0' on Success; Error code otherwise. -- */ --int dpcon_is_enabled(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- int *en) --{ -- struct mc_command cmd = { 0 }; -- struct dpcon_rsp_is_enabled *dpcon_rsp; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPCON_CMDID_IS_ENABLED, -- 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_is_enabled *)cmd.params; -- *en = dpcon_rsp->enabled & DPCON_ENABLE; -- -- return 0; --} --EXPORT_SYMBOL(dpcon_is_enabled); -- --/** -- * 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 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(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 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(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 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(dpcon_set_notification); -- --/** -- * dpcon_get_api_version - Get Data Path Concentrator API version -- * @mc_io: Pointer to MC portal's DPCON object -- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -- * @major_ver: Major version of DPCON API -- * @minor_ver: Minor version of DPCON API -- * -- * Return: '0' on Success; Error code otherwise -- */ --int dpcon_get_api_version(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 *major_ver, -- u16 *minor_ver) --{ -- struct mc_command cmd = { 0 }; -- int err; -- -- /* prepare command */ -- cmd.header = mc_encode_cmd_header(DPCON_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; --} --EXPORT_SYMBOL(dpcon_get_api_version); ---- /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 -+#include -+#include -+ -+#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 -+#include -+ -+#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,813 +0,0 @@ --// SPDX-License-Identifier: GPL-2.0 --/* -- * Freescale data path resource container (DPRC) driver -- * -- * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. -- * Author: German Rivera -- * -- */ -- --#include --#include --#include --#include --#include "../include/mc.h" -- --#include "dprc-cmd.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; -- -- WARN_ON(!dev); -- WARN_ON(!data); -- 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) --{ -- 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 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 -- * @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 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, -- &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. -- */ --static 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 fsl_mc_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 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); -- } -- } -- -- *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; --} -- --/** -- * 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; -- 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; --} -- --/** -- * 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, -- 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 (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 = 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 (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; -- } -- -- 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 (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 -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#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); -+} ---- a/drivers/staging/fsl-mc/bus/dprc.c -+++ /dev/null -@@ -1,757 +0,0 @@ --// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) --/* -- * Copyright 2013-2016 Freescale Semiconductor Inc. -- * -- */ --#include --#include "../include/mc.h" --#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_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); -- -- 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 fsl_mc_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_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_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_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 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 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; --} ---- /dev/null -+++ b/drivers/bus/fsl-mc/dprc.c -@@ -0,0 +1,576 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright 2013-2016 Freescale Semiconductor Inc. -+ * -+ */ -+#include -+#include -+ -+#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_offset); -+ region_desc->size = le32_to_cpu(rsp_params->size); -+ region_desc->type = rsp_params->type; -+ region_desc->flags = le32_to_cpu(rsp_params->flags); -+ region_desc->base_address = le64_to_cpu(rsp_params->base_addr); -+ -+ 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,663 +0,0 @@ --// SPDX-License-Identifier: GPL-2.0 --/* -- * fsl-mc object allocator driver -- * -- * Copyright (C) 2013-2016 Freescale Semiconductor, Inc. -- * -- */ -- --#include --#include --#include "../include/mc.h" -- --#include "fsl-mc-private.h" -- --static bool __must_check fsl_mc_is_allocatable(const char *obj_type) --{ -- return strcmp(obj_type, "dpbp") == 0 || -- strcmp(obj_type, "dpmcp") == 0 || -- strcmp(obj_type, "dpcon") == 0; --} -- --/** -- * 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 (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 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 (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 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 (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 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 (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); -- --/* -- * 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 (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 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 (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); -- --/** -- * 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 (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); -- --/* -- * 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 (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 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 (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 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); --} ---- /dev/null -+++ b/drivers/bus/fsl-mc/fsl-mc-allocator.c -@@ -0,0 +1,666 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * fsl-mc object allocator driver -+ * -+ * Copyright (C) 2013-2016 Freescale Semiconductor, Inc. -+ * -+ */ -+ -+#include -+#include -+#include -+ -+#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; -+ -+ mc_adev->consumer_link = device_link_add(&mc_dev->dev, -+ &mc_adev->dev, -+ DL_FLAG_AUTOREMOVE_CONSUMER); -+ if (!mc_adev->consumer_link) { -+ error = -EINVAL; -+ 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); -+ -+ device_link_del(mc_adev->consumer_link); -+ mc_adev->consumer_link = NULL; -+} -+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,900 +0,0 @@ --// SPDX-License-Identifier: GPL-2.0 --/* -- * Freescale Management Complex (MC) bus driver -- * -- * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. -- * Author: German Rivera -- * -- */ -- --#define pr_fmt(fmt) "fsl-mc: " fmt -- --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include "fsl-mc-private.h" --#include "dprc-cmd.h" --#include "dpmng-cmd.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; -- -- 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 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 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, "%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; -- -- if (WARN_ON(!dev->driver)) -- return -EINVAL; -- -- 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 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 -- */ --static 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; -- } --} -- --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 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 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 (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; --} -- --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 (strcmp(mc_dev->obj_desc.type, "dprc") == 0) -- 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, -- 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 = 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; -- 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; -- 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; -- } -- -- 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; -- 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 & FSL_MC_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; -- } -- -- 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) --{ -- /* -- * 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; -- 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, &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; -- -- 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 = 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: -- return error; --} --postcore_initcall(fsl_mc_bus_driver_init); ---- /dev/null -+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c -@@ -0,0 +1,1148 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Freescale Management Complex (MC) bus driver -+ * -+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. -+ * Author: German Rivera -+ * -+ */ -+ -+#define pr_fmt(fmt) "fsl-mc: " fmt -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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; -+ } -+ /* Older MC only returned region offset and no base address -+ * If base address is in the region_desc use it otherwise -+ * revert to old mechanism -+ */ -+ if (region_desc.base_address) -+ regions[i].start = region_desc.base_address + -+ region_desc.base_offset; -+ else -+ 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; -+ if (region_desc.flags & DPRC_REGION_SHAREABLE) -+ regions[i].flags |= IORESOURCE_MEM; -+ } -+ -+ 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; -+ -+ 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; -+ } -+ -+ /* -+ * 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); ---- a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c -+++ /dev/null -@@ -1,285 +0,0 @@ --// SPDX-License-Identifier: GPL-2.0 --/* -- * Freescale Management Complex (MC) bus driver MSI support -- * -- * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. -- * Author: German Rivera -- * -- */ -- --#include --#include --#include --#include --#include --#include --#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 (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) -- 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 (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 -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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 -+#include -+#include -+#include -+ -+/* -+ * 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 -+#include -+#include -+#include -+ -+#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,292 +0,0 @@ --// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) --/* -- * Copyright 2013-2016 Freescale Semiconductor Inc. -- * -- */ -- --#include --#include "../include/mc.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 %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 (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 = resource_size(dpmcp_dev->regions); -- -- 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,281 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright 2013-2016 Freescale Semiconductor Inc. -+ * -+ */ -+ -+#include -+#include -+ -+#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 (fsl_mc_is_root_dprc(&mc_dev->dev)) { -+ 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; -+ -+ dpmcp_dev->consumer_link = device_link_add(&mc_dev->dev, -+ &dpmcp_dev->dev, -+ DL_FLAG_AUTOREMOVE_CONSUMER); -+ if (!dpmcp_dev->consumer_link) { -+ error = -EINVAL; -+ goto error_cleanup_mc_io; -+ } -+ -+ *new_mc_io = mc_io; -+ return 0; -+ -+error_cleanup_mc_io: -+ fsl_destroy_mc_io(mc_io); -+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); -+ -+ device_link_del(dpmcp_dev->consumer_link); -+ dpmcp_dev->consumer_link = NULL; -+} -+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,297 +0,0 @@ --// 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 --#include --#include --#include --#include --#include --#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; --} -- --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++) -- /* -- * 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 mc_command __iomem * -- portal, -- struct 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 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 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 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: %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(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 -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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 -@@ -42,6 +42,12 @@ config ARM_GIC_V3_ITS - depends on PCI - depends on PCI_MSI - -+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 -@@ -30,6 +30,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 irq-gic-v4.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 ---- /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 -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+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-dpaa2/ethernet/dpaa2-eth.c -+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c -@@ -16,7 +16,7 @@ - #include - #include - #include --#include "../../fsl-mc/include/mc.h" -+#include - #include "dpaa2-eth.h" - #include "dpaa2-eth-ceetm.h" - ---- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h -+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h -@@ -9,12 +9,11 @@ - #include - #include - #include -+#include - #include - - #include "../../fsl-mc/include/dpaa2-io.h" - #include "../../fsl-mc/include/dpaa2-fd.h" --#include "../../fsl-mc/include/dpbp.h" --#include "../../fsl-mc/include/dpcon.h" - #include "dpni.h" - #include "dpni-cmd.h" - ---- a/drivers/staging/fsl-dpaa2/ethernet/dpni.c -+++ b/drivers/staging/fsl-dpaa2/ethernet/dpni.c -@@ -4,7 +4,7 @@ - */ - #include - #include --#include "../../fsl-mc/include/mc.h" -+#include - #include "dpni.h" - #include "dpni-cmd.h" - ---- a/drivers/staging/fsl-mc/bus/Kconfig -+++ b/drivers/staging/fsl-mc/bus/Kconfig -@@ -5,15 +5,6 @@ - # 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_LOCAL_APIC || 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_DPIO - tristate "QorIQ DPAA2 DPIO driver" -@@ -24,3 +15,9 @@ config FSL_MC_DPIO - 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 -@@ -4,19 +4,6 @@ - # - # 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 \ -- dprc.o \ -- dprc-driver.o \ -- fsl-mc-allocator.o \ -- fsl-mc-msi.o \ -- irq-gic-v3-its-fsl-mc-msi.o \ -- dpmcp.o \ -- dpbp.o \ -- dpcon.o - - # MC DPIO driver - obj-$(CONFIG_FSL_MC_DPIO) += dpio/ ---- a/drivers/staging/fsl-mc/bus/dpio/dpio-driver.c -+++ b/drivers/staging/fsl-mc/bus/dpio/dpio-driver.c -@@ -15,7 +15,7 @@ - #include - #include - --#include "../../include/mc.h" -+#include - #include "../../include/dpaa2-io.h" - - #include "qbman-portal.h" ---- a/drivers/staging/fsl-mc/bus/dpio/dpio-service.c -+++ b/drivers/staging/fsl-mc/bus/dpio/dpio-service.c -@@ -5,7 +5,7 @@ - * - */ - #include --#include "../../include/mc.h" -+#include - #include "../../include/dpaa2-io.h" - #include - #include ---- a/drivers/staging/fsl-mc/bus/dpio/dpio.c -+++ b/drivers/staging/fsl-mc/bus/dpio/dpio.c -@@ -5,7 +5,7 @@ - * - */ - #include --#include "../../include/mc.h" -+#include - - #include "dpio.h" - #include "dpio-cmd.h" -@@ -37,7 +37,7 @@ int dpio_open(struct fsl_mc_io *mc_io, - int dpio_id, - u16 *token) - { -- struct mc_command cmd = { 0 }; -+ struct fsl_mc_command cmd = { 0 }; - struct dpio_cmd_open *dpio_cmd; - int err; - -@@ -70,7 +70,7 @@ int dpio_close(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token) - { -- struct mc_command cmd = { 0 }; -+ struct fsl_mc_command cmd = { 0 }; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPIO_CMDID_CLOSE, -@@ -92,7 +92,7 @@ int dpio_enable(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token) - { -- struct mc_command cmd = { 0 }; -+ struct fsl_mc_command cmd = { 0 }; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPIO_CMDID_ENABLE, -@@ -114,7 +114,7 @@ int dpio_disable(struct fsl_mc_io *mc_io - u32 cmd_flags, - u16 token) - { -- struct mc_command cmd = { 0 }; -+ struct fsl_mc_command cmd = { 0 }; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPIO_CMDID_DISABLE, -@@ -138,7 +138,7 @@ int dpio_get_attributes(struct fsl_mc_io - u16 token, - struct dpio_attr *attr) - { -- struct mc_command cmd = { 0 }; -+ struct fsl_mc_command cmd = { 0 }; - struct dpio_rsp_get_attr *dpio_rsp; - int err; - -@@ -180,7 +180,7 @@ int dpio_get_api_version(struct fsl_mc_i - u16 *major_ver, - u16 *minor_ver) - { -- struct mc_command cmd = { 0 }; -+ struct fsl_mc_command cmd = { 0 }; - int err; - - /* prepare command */ ---- a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h -+++ /dev/null -@@ -1,56 +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 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) -- --/* Command IDs */ --#define DPMCP_CMDID_CLOSE DPMCP_CMD(0x800) --#define DPMCP_CMDID_OPEN DPMCP_CMD(0x80b) --#define DPMCP_CMDID_GET_API_VERSION DPMCP_CMD(0xa0b) -- --#define DPMCP_CMDID_RESET DPMCP_CMD(0x005) -- --struct dpmcp_cmd_open { -- __le32 dpmcp_id; --}; -- --#endif /* _FSL_DPMCP_CMD_H */ ---- a/drivers/staging/fsl-mc/bus/dpmcp.h -+++ /dev/null -@@ -1,60 +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_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, -- u32 cmd_flags, -- int dpmcp_id, -- u16 *token); -- --int dpmcp_close(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token); -- --int dpmcp_get_api_version(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 *major_ver, -- u16 *minor_ver); -- --int dpmcp_reset(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token); -- --#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 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) -- --/* Command IDs */ --#define DPMNG_CMDID_GET_VERSION DPMNG_CMD(0x831) -- --struct dpmng_rsp_get_version { -- __le32 revision; -- __le32 version_major; -- __le32 version_minor; --}; -- --#endif /* __FSL_DPMNG_CMD_H */ ---- a/drivers/staging/fsl-mc/bus/dprc-cmd.h -+++ /dev/null -@@ -1,451 +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 6 --#define DPRC_MIN_VER_MINOR 0 -- --/* 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) -- --/* 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_SET_IRQ DPRC_CMD(0x010) --#define DPRC_CMDID_GET_IRQ DPRC_CMD(0x011) --#define DPRC_CMDID_SET_IRQ_ENABLE DPRC_CMD(0x012) --#define DPRC_CMDID_GET_IRQ_ENABLE DPRC_CMD(0x013) --#define DPRC_CMDID_SET_IRQ_MASK DPRC_CMD(0x014) --#define DPRC_CMDID_GET_IRQ_MASK DPRC_CMD(0x015) --#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_RES_COUNT DPRC_CMD(0x15B) --#define DPRC_CMDID_GET_OBJ_REG DPRC_CMD(0x15E) --#define DPRC_CMDID_SET_OBJ_IRQ DPRC_CMD(0x15F) --#define DPRC_CMDID_GET_OBJ_IRQ DPRC_CMD(0x160) -- --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; --}; -- --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.h -+++ /dev/null -@@ -1,268 +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_DPRC_H --#define _FSL_DPRC_H -- --/* -- * Data Path Resource Container API -- * Contains DPRC API for managing and querying DPAA resources -- */ -- --struct fsl_mc_io; --struct fsl_mc_obj_desc; -- --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); -- --/* 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 -- */ --struct dprc_attributes { -- int container_id; -- u16 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_get_obj_desc(struct fsl_mc_io *mc_io, -- u32 cmd_flags, -- u16 token, -- char *obj_type, -- int obj_id, -- 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); -- --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 --}; -- --/* 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_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); -- --#endif /* _FSL_DPRC_H */ -- ---- a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c -+++ b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - #include "fsl-mc-private.h" - - static struct irq_chip its_msi_irq_chip = { ---- /dev/null -+++ b/include/linux/fsl/mc.h -@@ -0,0 +1,1029 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Freescale Management Complex (MC) bus public interface -+ * -+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. -+ * Author: German Rivera -+ * -+ */ -+#ifndef _FSL_MC_H_ -+#define _FSL_MC_H_ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#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; -+ struct device_link *consumer_link; -+}; -+ -+#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); -+ -+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_2ND_VERSION 2 -+#define DPRC_CMD_ID_OFFSET 4 -+ -+#define DPRC_CMD(id) (((id) << DPRC_CMD_ID_OFFSET) | DPRC_CMD_BASE_VERSION) -+#define DPRC_CMD_V2(id) (((id) << DPRC_CMD_ID_OFFSET) | DPRC_CMD_2ND_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_V2(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_offset; -+ __le32 pad1; -+ /* response word 2 */ -+ __le32 size; -+ u8 type; -+ u8 pad2[3]; -+ /* response word 3 */ -+ __le32 flags; -+ __le32 pad3; -+ /* response word 4 */ -+ __le64 base_addr; -+}; -+ -+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 -+#define DPRC_REGION_SHAREABLE 0x00000002 -+ -+/** -+ * 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, -+ DPRC_REGION_TYPE_QBMAN_MEM_BACKED_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; -+ u64 base_address; -+}; -+ -+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_ */ -- cgit v1.2.3