[PATCH v3 03/11] staging: fsl-mc: Added generic MSI support for FSL-MC devices
Created an MSI domain for the fsl-mc bus-- including functions to create a domain, find a domain, alloc/free domain irqs, and bus specific overrides for domain and irq_chip ops. Signed-off-by: J. German Rivera --- CHANGE HISTORY Changes in v3: none - Addressed comments from Marc Zyngier: * Added WARN_ON in fsl_mc_msi_set_desc to check that caller does not set set_desc * Changed type of paddr in irq_cfg to be phys_addr_t * Added WARN_ON in fsl_mc_msi_update_chip_op() to check that caller does not set irq_write_msi_msg Changes in v2: none drivers/staging/fsl-mc/bus/Kconfig | 1 + drivers/staging/fsl-mc/bus/Makefile | 1 + drivers/staging/fsl-mc/bus/mc-msi.c | 285 drivers/staging/fsl-mc/include/dprc.h | 2 +- drivers/staging/fsl-mc/include/mc-private.h | 17 ++ drivers/staging/fsl-mc/include/mc.h | 17 ++ 6 files changed, 322 insertions(+), 1 deletion(-) create mode 100644 drivers/staging/fsl-mc/bus/mc-msi.c diff --git a/drivers/staging/fsl-mc/bus/Kconfig b/drivers/staging/fsl-mc/bus/Kconfig index 0d779d9..c498ac6 100644 --- a/drivers/staging/fsl-mc/bus/Kconfig +++ b/drivers/staging/fsl-mc/bus/Kconfig @@ -9,6 +9,7 @@ config FSL_MC_BUS tristate "Freescale Management Complex (MC) bus driver" depends on OF && ARM64 + select GENERIC_MSI_IRQ_DOMAIN help Driver to enable the bus infrastructure for the Freescale QorIQ Management Complex (fsl-mc). The fsl-mc is a hardware diff --git a/drivers/staging/fsl-mc/bus/Makefile b/drivers/staging/fsl-mc/bus/Makefile index 25433a9..a5f2ba4 100644 --- a/drivers/staging/fsl-mc/bus/Makefile +++ b/drivers/staging/fsl-mc/bus/Makefile @@ -13,5 +13,6 @@ mc-bus-driver-objs := mc-bus.o \ dpmng.o \ dprc-driver.o \ mc-allocator.o \ + mc-msi.o \ dpmcp.o \ dpbp.o diff --git a/drivers/staging/fsl-mc/bus/mc-msi.c b/drivers/staging/fsl-mc/bus/mc-msi.c new file mode 100644 index 000..d6ac465 --- /dev/null +++ b/drivers/staging/fsl-mc/bus/mc-msi.c @@ -0,0 +1,285 @@ +/* + * Freescale Management Complex (MC) bus driver MSI support + * + * Copyright (C) 2015 Freescale Semiconductor, Inc. + * Author: German Rivera + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include "../include/mc-private.h" +#include +#include +#include +#include +#include +#include +#include "../include/mc-sys.h" +#include "dprc-cmd.h" + +static void fsl_mc_msi_set_desc(msi_alloc_info_t *arg, + struct msi_desc *desc) +{ + arg->desc = desc; + arg->hwirq = (irq_hw_number_t)desc->fsl_mc.msi_index; +} + +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 (WARN_ON(ops->set_desc)) + return; + + 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.user_irq_id = 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, +_cfg); + if (error < 0) { + dev_err(_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, +
[PATCH v3 03/11] staging: fsl-mc: Added generic MSI support for FSL-MC devices
Created an MSI domain for the fsl-mc bus-- including functions to create a domain, find a domain, alloc/free domain irqs, and bus specific overrides for domain and irq_chip ops. Signed-off-by: J. German Rivera--- CHANGE HISTORY Changes in v3: none - Addressed comments from Marc Zyngier: * Added WARN_ON in fsl_mc_msi_set_desc to check that caller does not set set_desc * Changed type of paddr in irq_cfg to be phys_addr_t * Added WARN_ON in fsl_mc_msi_update_chip_op() to check that caller does not set irq_write_msi_msg Changes in v2: none drivers/staging/fsl-mc/bus/Kconfig | 1 + drivers/staging/fsl-mc/bus/Makefile | 1 + drivers/staging/fsl-mc/bus/mc-msi.c | 285 drivers/staging/fsl-mc/include/dprc.h | 2 +- drivers/staging/fsl-mc/include/mc-private.h | 17 ++ drivers/staging/fsl-mc/include/mc.h | 17 ++ 6 files changed, 322 insertions(+), 1 deletion(-) create mode 100644 drivers/staging/fsl-mc/bus/mc-msi.c diff --git a/drivers/staging/fsl-mc/bus/Kconfig b/drivers/staging/fsl-mc/bus/Kconfig index 0d779d9..c498ac6 100644 --- a/drivers/staging/fsl-mc/bus/Kconfig +++ b/drivers/staging/fsl-mc/bus/Kconfig @@ -9,6 +9,7 @@ config FSL_MC_BUS tristate "Freescale Management Complex (MC) bus driver" depends on OF && ARM64 + select GENERIC_MSI_IRQ_DOMAIN help Driver to enable the bus infrastructure for the Freescale QorIQ Management Complex (fsl-mc). The fsl-mc is a hardware diff --git a/drivers/staging/fsl-mc/bus/Makefile b/drivers/staging/fsl-mc/bus/Makefile index 25433a9..a5f2ba4 100644 --- a/drivers/staging/fsl-mc/bus/Makefile +++ b/drivers/staging/fsl-mc/bus/Makefile @@ -13,5 +13,6 @@ mc-bus-driver-objs := mc-bus.o \ dpmng.o \ dprc-driver.o \ mc-allocator.o \ + mc-msi.o \ dpmcp.o \ dpbp.o diff --git a/drivers/staging/fsl-mc/bus/mc-msi.c b/drivers/staging/fsl-mc/bus/mc-msi.c new file mode 100644 index 000..d6ac465 --- /dev/null +++ b/drivers/staging/fsl-mc/bus/mc-msi.c @@ -0,0 +1,285 @@ +/* + * Freescale Management Complex (MC) bus driver MSI support + * + * Copyright (C) 2015 Freescale Semiconductor, Inc. + * Author: German Rivera + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include "../include/mc-private.h" +#include +#include +#include +#include +#include +#include +#include "../include/mc-sys.h" +#include "dprc-cmd.h" + +static void fsl_mc_msi_set_desc(msi_alloc_info_t *arg, + struct msi_desc *desc) +{ + arg->desc = desc; + arg->hwirq = (irq_hw_number_t)desc->fsl_mc.msi_index; +} + +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 (WARN_ON(ops->set_desc)) + return; + + 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.user_irq_id = 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, +_cfg); + if (error < 0) { + dev_err(_mc_dev->dev, + "dprc_set_irq() failed: %d\n", error); + } + } else { + /* +* IRQ is for for a child device of mc_bus_dev +*/ +