}
}
-/*
- * NOTE: This function is invoked with interrupts disabled
- */
-static void fsl_mc_msi_write_msg(struct irq_data *irq_data,
- struct msi_msg *msg)
+static void fsl_mc_write_msi_msg(struct msi_desc *msi_desc, 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 =
__fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq, msi_desc);
}
+/*
+ * 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);
+
+ fsl_mc_write_msi_msg(msi_desc, msg);
+}
+
static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info)
{
struct irq_chip *chip = info->chip;
return msi_domain;
}
+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;
+
+ fsl_mc_get_root_dprc(dev, &root_dprc_dev);
+ bus_dev = root_dprc_dev->parent;
+
+ 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);
* 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);
-
+ if (!irq_domain_is_msi_parent(dev_get_msi_domain(dev)))
+ error = msi_domain_alloc_irqs_range(dev, MSI_DEFAULT_DOMAIN, 0, irq_count - 1);
+ else
+ 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;
{
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));
+}