mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 03:27:30 -04:00
Merge tag 'soc_fsl-7.1-2' of https://git.kernel.org/pub/scm/linux/kernel/git/chleroy/linux into soc/drivers
FSL SOC Changes for 7.1 Freescale QUICC Engine: - Add missing cleanup on device removal and switch to irq_domain_create_linear() in interrupt controller for IO Ports - Panic on ioremap() failure in qe_reset() Freescale Management Complex: - Move fsl-mc over to device MSI infrastructure - Wait for the MC firmware to complete its boot Freescale Hypervisor: - Fix header kernel-doc warnings * tag 'soc_fsl-7.1-2' of https://git.kernel.org/pub/scm/linux/kernel/git/chleroy/linux: bus: fsl-mc: wait for the MC firmware to complete its boot soc: fsl: qe: panic on ioremap() failure in qe_reset() soc: fsl: qe_ports_ic: switch to irq_domain_create_linear() soc: fsl: qe_ports_ic: Add missing cleanup on device removal virt: fsl_hypervisor: fix header kernel-doc warnings platform-msi: Remove stale comment fsl-mc: Remove legacy MSI implementation fsl-mc: Switch over to per-device platform MSI irqchip/gic-v3-its: Add fsl_mc device plumbing to the msi-parent handling fsl-mc: Add minimal infrastructure to use platform MSI fsl-mc: Remove MSI domain propagation to sub-devices Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
@@ -61,10 +61,6 @@ static const struct msi_domain_template platform_msi_template = {
|
||||
* parent. The parent domain sets up the new domain. The domain has
|
||||
* a fixed size of @nvec. The domain is managed by devres and will
|
||||
* be removed when the device is removed.
|
||||
*
|
||||
* Note: For migration purposes this falls back to the original platform_msi code
|
||||
* up to the point where all platforms have been converted to the MSI
|
||||
* parent model.
|
||||
*/
|
||||
int platform_device_msi_init_and_alloc_irqs(struct device *dev, unsigned int nvec,
|
||||
irq_write_msi_msg_t write_msi_msg)
|
||||
|
||||
@@ -609,9 +609,8 @@ int dprc_setup(struct fsl_mc_device *mc_dev)
|
||||
{
|
||||
struct device *parent_dev = mc_dev->dev.parent;
|
||||
struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
|
||||
struct irq_domain *mc_msi_domain;
|
||||
struct irq_domain *mc_msi_domain = NULL;
|
||||
bool mc_io_created = false;
|
||||
bool msi_domain_set = false;
|
||||
bool uapi_created = false;
|
||||
u16 major_ver, minor_ver;
|
||||
size_t region_size;
|
||||
@@ -652,14 +651,12 @@ int dprc_setup(struct fsl_mc_device *mc_dev)
|
||||
uapi_created = true;
|
||||
}
|
||||
|
||||
mc_msi_domain = fsl_mc_find_msi_domain(&mc_dev->dev);
|
||||
if (!mc_msi_domain) {
|
||||
mc_msi_domain = fsl_mc_get_msi_parent(&mc_dev->dev);
|
||||
if (!mc_msi_domain)
|
||||
dev_warn(&mc_dev->dev,
|
||||
"WARNING: MC bus without interrupt support\n");
|
||||
} else {
|
||||
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);
|
||||
@@ -699,8 +696,7 @@ int dprc_setup(struct fsl_mc_device *mc_dev)
|
||||
(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);
|
||||
dev_set_msi_domain(&mc_dev->dev, NULL);
|
||||
|
||||
if (mc_io_created) {
|
||||
fsl_destroy_mc_io(mc_dev->mc_io);
|
||||
|
||||
@@ -66,6 +66,13 @@ struct fsl_mc_addr_translation_range {
|
||||
#define GCR1_P1_STOP BIT(31)
|
||||
#define GCR1_P2_STOP BIT(30)
|
||||
|
||||
#define FSL_MC_GSR 0x8
|
||||
#define FSL_MC_GSR_BOOT_DONE BIT(0)
|
||||
#define FSL_MC_GSR_MCS_MASK GENMASK(7, 0)
|
||||
#define FSL_MC_GSR_MCS_ERR_MASK GENMASK(7, 1)
|
||||
#define FSL_MC_GSR_BC_MASK GENMASK(15, 8)
|
||||
#define FSL_MC_GSR_BC_SHIFT 8
|
||||
|
||||
#define FSL_MC_FAPR 0x28
|
||||
#define MC_FAPR_PL BIT(18)
|
||||
#define MC_FAPR_BMT BIT(17)
|
||||
@@ -828,14 +835,12 @@ int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc,
|
||||
} else {
|
||||
/*
|
||||
* A non-DPRC object has to be a child of a DPRC, use the
|
||||
* parent's ICID and interrupt domain.
|
||||
* parent's ICID.
|
||||
*/
|
||||
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));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -992,6 +997,41 @@ static int get_mc_addr_translation_ranges(struct device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 fsl_mc_read_gsr(struct fsl_mc *mc)
|
||||
{
|
||||
return readl(mc->fsl_mc_regs + FSL_MC_GSR);
|
||||
}
|
||||
|
||||
static int fsl_mc_firmware_check(struct platform_device *pdev)
|
||||
{
|
||||
struct fsl_mc *mc = platform_get_drvdata(pdev);
|
||||
u32 gsr, boot_done, boot_code, mcs;
|
||||
|
||||
gsr = fsl_mc_read_gsr(mc);
|
||||
boot_code = (gsr & FSL_MC_GSR_BC_MASK) >> FSL_MC_GSR_BC_SHIFT;
|
||||
if (boot_code == 0xDD) {
|
||||
dev_err(&pdev->dev,
|
||||
"fsl-mc: DPL processing was not started, DPAA2 will not work!\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
boot_done = gsr & FSL_MC_GSR_BOOT_DONE;
|
||||
if (!boot_done) {
|
||||
dev_dbg(&pdev->dev,
|
||||
"fsl-mc: DPL processing in progress, defer probe\n");
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
mcs = gsr & FSL_MC_GSR_MCS_MASK;
|
||||
if (mcs & FSL_MC_GSR_MCS_ERR_MASK) {
|
||||
dev_err(&pdev->dev,
|
||||
"fsl-mc: MC boot completed with error 0x%x\n", mcs);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* fsl_mc_bus_probe - callback invoked when the root MC bus is being
|
||||
* added
|
||||
@@ -1056,6 +1096,10 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
|
||||
mc->fsl_mc_regs + FSL_MC_GCR1);
|
||||
}
|
||||
|
||||
error = fsl_mc_firmware_check(pdev);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/*
|
||||
* Get physical address of MC portal for the root DPRC:
|
||||
*/
|
||||
|
||||
@@ -15,53 +15,16 @@
|
||||
|
||||
#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)
|
||||
static void fsl_mc_write_msi_msg(struct msi_desc *msi_desc, struct msi_msg *msg)
|
||||
{
|
||||
/*
|
||||
* 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->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,
|
||||
struct msi_desc *msi_desc)
|
||||
{
|
||||
int error;
|
||||
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->msi_index];
|
||||
struct fsl_mc_device *owner_mc_dev = mc_dev_irq->mc_dev;
|
||||
struct dprc_irq_cfg irq_cfg;
|
||||
int error;
|
||||
|
||||
msi_desc->msg = *msg;
|
||||
|
||||
/*
|
||||
* msi_desc->msg.address is 0x0 when this function is invoked in
|
||||
@@ -110,118 +73,27 @@ static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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->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, msi_desc);
|
||||
}
|
||||
|
||||
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
|
||||
* @fwnode: Optional firmware 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 (WARN_ON((info->flags & MSI_FLAG_LEVEL_CAPABLE)))
|
||||
info->flags &= ~MSI_FLAG_LEVEL_CAPABLE;
|
||||
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);
|
||||
info->flags |= MSI_FLAG_ALLOC_SIMPLE_MSI_DESCS | MSI_FLAG_FREE_MSI_DESCS;
|
||||
|
||||
domain = msi_create_irq_domain(fwnode, info, parent);
|
||||
if (domain)
|
||||
irq_domain_update_bus_token(domain, DOMAIN_BUS_FSL_MC_MSI);
|
||||
|
||||
return domain;
|
||||
}
|
||||
|
||||
struct irq_domain *fsl_mc_find_msi_domain(struct device *dev)
|
||||
struct irq_domain *fsl_mc_get_msi_parent(struct device *dev)
|
||||
{
|
||||
struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
|
||||
struct device *root_dprc_dev;
|
||||
struct device *bus_dev;
|
||||
struct irq_domain *msi_domain;
|
||||
struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
|
||||
|
||||
fsl_mc_get_root_dprc(dev, &root_dprc_dev);
|
||||
bus_dev = root_dprc_dev->parent;
|
||||
|
||||
if (bus_dev->of_node) {
|
||||
msi_domain = of_msi_map_get_device_domain(dev,
|
||||
mc_dev->icid,
|
||||
DOMAIN_BUS_FSL_MC_MSI);
|
||||
|
||||
/*
|
||||
* if the msi-map property is missing assume that all the
|
||||
* child containers inherit the domain from the parent
|
||||
*/
|
||||
if (!msi_domain)
|
||||
|
||||
msi_domain = of_msi_get_domain(bus_dev,
|
||||
bus_dev->of_node,
|
||||
DOMAIN_BUS_FSL_MC_MSI);
|
||||
} else {
|
||||
msi_domain = iort_get_device_domain(dev, mc_dev->icid,
|
||||
DOMAIN_BUS_FSL_MC_MSI);
|
||||
}
|
||||
|
||||
return msi_domain;
|
||||
return (bus_dev->of_node ?
|
||||
of_msi_get_domain(bus_dev, bus_dev->of_node, DOMAIN_BUS_NEXUS) :
|
||||
iort_get_device_domain(bus_dev, mc_dev->icid, DOMAIN_BUS_NEXUS));
|
||||
}
|
||||
|
||||
int fsl_mc_msi_domain_alloc_irqs(struct device *dev, unsigned int irq_count)
|
||||
{
|
||||
int error = msi_setup_device_data(dev);
|
||||
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/*
|
||||
* NOTE: Calling this function will trigger the invocation of the
|
||||
* its_fsl_mc_msi_prepare() callback
|
||||
*/
|
||||
error = msi_domain_alloc_irqs_range(dev, MSI_DEFAULT_DOMAIN, 0, irq_count - 1);
|
||||
|
||||
error = platform_device_msi_init_and_alloc_irqs(dev, irq_count, fsl_mc_write_msi_msg);
|
||||
if (error)
|
||||
dev_err(dev, "Failed to allocate IRQs\n");
|
||||
return error;
|
||||
@@ -231,3 +103,15 @@ void fsl_mc_msi_domain_free_irqs(struct device *dev)
|
||||
{
|
||||
msi_domain_free_irqs_all(dev, MSI_DEFAULT_DOMAIN);
|
||||
}
|
||||
|
||||
u32 fsl_mc_get_msi_id(struct device *dev)
|
||||
{
|
||||
struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
|
||||
struct device *root_dprc_dev;
|
||||
|
||||
fsl_mc_get_root_dprc(dev, &root_dprc_dev);
|
||||
|
||||
return (root_dprc_dev->parent->of_node ?
|
||||
of_msi_xlate(dev, NULL, mc_dev->icid) :
|
||||
iort_msi_map_id(dev, mc_dev->icid));
|
||||
}
|
||||
|
||||
@@ -641,7 +641,7 @@ int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
|
||||
|
||||
void fsl_mc_msi_domain_free_irqs(struct device *dev);
|
||||
|
||||
struct irq_domain *fsl_mc_find_msi_domain(struct device *dev);
|
||||
struct irq_domain *fsl_mc_get_msi_parent(struct device *dev);
|
||||
|
||||
int __must_check fsl_create_mc_io(struct device *dev,
|
||||
phys_addr_t mc_portal_phys_addr,
|
||||
|
||||
@@ -51,12 +51,6 @@ config ARM_GIC_V3_ITS
|
||||
default ARM_GIC_V3
|
||||
select IRQ_MSI_IOMMU
|
||||
|
||||
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_GIC_V5
|
||||
bool
|
||||
select IRQ_DOMAIN_HIERARCHY
|
||||
|
||||
@@ -35,7 +35,6 @@ obj-$(CONFIG_ARM_GIC_V2M) += irq-gic-v2m.o
|
||||
obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-v3-mbi.o irq-gic-common.o
|
||||
obj-$(CONFIG_ARM_GIC_ITS_PARENT) += irq-gic-its-msi-parent.o
|
||||
obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o irq-gic-v4.o
|
||||
obj-$(CONFIG_ARM_GIC_V3_ITS_FSL_MC) += irq-gic-v3-its-fsl-mc-msi.o
|
||||
obj-$(CONFIG_ARM_GIC_V5) += irq-gic-v5.o irq-gic-v5-irs.o irq-gic-v5-its.o \
|
||||
irq-gic-v5-iwb.o
|
||||
obj-$(CONFIG_HISILICON_IRQ_MBIGEN) += irq-mbigen.o
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// Copyright (C) 2022 Intel
|
||||
|
||||
#include <linux/acpi_iort.h>
|
||||
#include <linux/fsl/mc.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
@@ -187,9 +188,11 @@ static int its_pmsi_prepare(struct irq_domain *domain, struct device *dev,
|
||||
{
|
||||
struct msi_domain_info *msi_info;
|
||||
u32 dev_id;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
if (dev->of_node)
|
||||
if (dev_is_fsl_mc(dev))
|
||||
dev_id = fsl_mc_get_msi_id(dev);
|
||||
else if (dev->of_node)
|
||||
ret = of_pmsi_get_msi_info(domain->parent, dev, &dev_id, NULL);
|
||||
else
|
||||
ret = iort_pmsi_get_msi_info(dev, &dev_id, NULL);
|
||||
|
||||
@@ -1,168 +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 <German.Rivera@freescale.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/acpi_iort.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/msi.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/fsl/mc.h>
|
||||
|
||||
static struct irq_chip its_msi_irq_chip = {
|
||||
.name = "ITS-fMSI",
|
||||
.irq_mask = irq_chip_mask_parent,
|
||||
.irq_unmask = irq_chip_unmask_parent,
|
||||
.irq_eoi = irq_chip_eoi_parent,
|
||||
.irq_set_affinity = msi_domain_set_affinity
|
||||
};
|
||||
|
||||
static u32 fsl_mc_msi_domain_get_msi_id(struct irq_domain *domain,
|
||||
struct fsl_mc_device *mc_dev)
|
||||
{
|
||||
struct device_node *of_node;
|
||||
u32 out_id;
|
||||
|
||||
of_node = irq_domain_get_of_node(domain);
|
||||
out_id = of_node ? of_msi_xlate(&mc_dev->dev, &of_node, mc_dev->icid) :
|
||||
iort_msi_map_id(&mc_dev->dev, mc_dev->icid);
|
||||
|
||||
return out_id;
|
||||
}
|
||||
|
||||
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 = fsl_mc_msi_domain_get_msi_id(msi_domain,
|
||||
mc_bus_dev);
|
||||
msi_info = msi_get_domain_info(msi_domain->parent);
|
||||
|
||||
/* Allocate at least 32 MSIs, and always as a power of 2 */
|
||||
nvec = max_t(int, 32, roundup_pow_of_two(nvec));
|
||||
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 void __init its_fsl_mc_msi_init_one(struct fwnode_handle *handle,
|
||||
const char *name)
|
||||
{
|
||||
struct irq_domain *parent;
|
||||
struct irq_domain *mc_msi_domain;
|
||||
|
||||
parent = irq_find_matching_fwnode(handle, DOMAIN_BUS_NEXUS);
|
||||
if (!parent || !msi_get_domain_info(parent)) {
|
||||
pr_err("%s: unable to locate ITS domain\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
mc_msi_domain = fsl_mc_msi_create_irq_domain(handle,
|
||||
&its_fsl_mc_msi_domain_info,
|
||||
parent);
|
||||
if (!mc_msi_domain) {
|
||||
pr_err("%s: unable to create fsl-mc domain\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
pr_info("fsl-mc MSI: %s domain created\n", name);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static int __init
|
||||
its_fsl_mc_msi_parse_madt(union acpi_subtable_headers *header,
|
||||
const unsigned long end)
|
||||
{
|
||||
struct acpi_madt_generic_translator *its_entry;
|
||||
struct fwnode_handle *dom_handle;
|
||||
const char *node_name;
|
||||
int err = 0;
|
||||
|
||||
its_entry = (struct acpi_madt_generic_translator *)header;
|
||||
node_name = kasprintf(GFP_KERNEL, "ITS@0x%lx",
|
||||
(long)its_entry->base_address);
|
||||
|
||||
dom_handle = iort_find_domain_token(its_entry->translation_id);
|
||||
if (!dom_handle) {
|
||||
pr_err("%s: Unable to locate ITS domain handle\n", node_name);
|
||||
err = -ENXIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
its_fsl_mc_msi_init_one(dom_handle, node_name);
|
||||
|
||||
out:
|
||||
kfree(node_name);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static void __init its_fsl_mc_acpi_msi_init(void)
|
||||
{
|
||||
acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_TRANSLATOR,
|
||||
its_fsl_mc_msi_parse_madt, 0);
|
||||
}
|
||||
#else
|
||||
static inline void its_fsl_mc_acpi_msi_init(void) { }
|
||||
#endif
|
||||
|
||||
static void __init its_fsl_mc_of_msi_init(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
for (np = of_find_matching_node(NULL, its_device_id); np;
|
||||
np = of_find_matching_node(np, its_device_id)) {
|
||||
if (!of_device_is_available(np))
|
||||
continue;
|
||||
if (!of_property_read_bool(np, "msi-controller"))
|
||||
continue;
|
||||
|
||||
its_fsl_mc_msi_init_one(of_fwnode_handle(np),
|
||||
np->full_name);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init its_fsl_mc_msi_init(void)
|
||||
{
|
||||
its_fsl_mc_of_msi_init();
|
||||
its_fsl_mc_acpi_msi_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
early_initcall(its_fsl_mc_msi_init);
|
||||
@@ -89,6 +89,9 @@ void qe_reset(void)
|
||||
if (qe_immr == NULL)
|
||||
qe_immr = ioremap(get_qe_base(), QE_IMMAP_SIZE);
|
||||
|
||||
if (!qe_immr)
|
||||
panic("QE:ioremap failed!");
|
||||
|
||||
qe_snums_init();
|
||||
|
||||
qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID,
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
struct qepic_data {
|
||||
void __iomem *reg;
|
||||
struct irq_domain *host;
|
||||
int irq;
|
||||
};
|
||||
|
||||
static void qepic_mask(struct irq_data *d)
|
||||
@@ -92,11 +93,18 @@ static const struct irq_domain_ops qepic_host_ops = {
|
||||
.map = qepic_host_map,
|
||||
};
|
||||
|
||||
static void qepic_remove(void *res)
|
||||
{
|
||||
struct qepic_data *data = res;
|
||||
|
||||
irq_set_chained_handler_and_data(data->irq, NULL, NULL);
|
||||
irq_domain_remove(data->host);
|
||||
}
|
||||
|
||||
static int qepic_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct qepic_data *data;
|
||||
int irq;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
@@ -106,17 +114,18 @@ static int qepic_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(data->reg))
|
||||
return PTR_ERR(data->reg);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
data->irq = platform_get_irq(pdev, 0);
|
||||
if (data->irq < 0)
|
||||
return data->irq;
|
||||
|
||||
data->host = irq_domain_add_linear(dev->of_node, 32, &qepic_host_ops, data);
|
||||
data->host = irq_domain_create_linear(dev_fwnode(dev), 32, &qepic_host_ops, data);
|
||||
if (!data->host)
|
||||
return -ENODEV;
|
||||
|
||||
irq_set_chained_handler_and_data(irq, qepic_cascade, data);
|
||||
irq_set_chained_handler_and_data(data->irq, qepic_cascade, data);
|
||||
|
||||
return devm_add_action_or_reset(dev, qepic_remove, data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id qepic_match[] = {
|
||||
|
||||
@@ -357,9 +357,11 @@ 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)
|
||||
u32 fsl_mc_get_msi_id(struct device *dev);
|
||||
#else
|
||||
/* If fsl-mc bus is not present device cannot belong to fsl-mc bus */
|
||||
#define dev_is_fsl_mc(_dev) (0)
|
||||
#define fsl_mc_get_msi_id(_dev) (0)
|
||||
#endif
|
||||
|
||||
/* Macro to check if a device is a container device */
|
||||
@@ -419,10 +421,6 @@ int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
|
||||
|
||||
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);
|
||||
|
||||
@@ -17,7 +17,6 @@ enum irq_domain_bus_token {
|
||||
DOMAIN_BUS_PLATFORM_MSI,
|
||||
DOMAIN_BUS_NEXUS,
|
||||
DOMAIN_BUS_IPI,
|
||||
DOMAIN_BUS_FSL_MC_MSI,
|
||||
DOMAIN_BUS_TI_SCI_INTA_MSI,
|
||||
DOMAIN_BUS_WAKEUP,
|
||||
DOMAIN_BUS_VMD_MSI,
|
||||
|
||||
@@ -114,9 +114,9 @@ struct fsl_hv_ioctl_stop {
|
||||
* @target: the partition ID of the target partition, or -1 for this
|
||||
* partition
|
||||
* @reserved: reserved, must be set to 0
|
||||
* @local_addr: user-space virtual address of a buffer in the local
|
||||
* @local_vaddr: user-space virtual address of a buffer in the local
|
||||
* partition
|
||||
* @remote_addr: guest physical address of a buffer in the
|
||||
* @remote_paddr: guest physical address of a buffer in the
|
||||
* remote partition
|
||||
* @count: the number of bytes to copy. Both the local and remote
|
||||
* buffers must be at least 'count' bytes long
|
||||
|
||||
Reference in New Issue
Block a user