1 // SPDX-License-Identifier: GPL-2.0
3 * Freescale Management Complex (MC) bus driver MSI support
5 * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
6 * Author: German Rivera <German.Rivera@freescale.com>
10 #include <linux/of_device.h>
11 #include <linux/of_address.h>
12 #include <linux/irq.h>
13 #include <linux/msi.h>
15 #include <linux/of_irq.h>
16 #include <linux/fsl/mc.h>
18 static struct irq_chip its_msi_irq_chip
= {
20 .irq_mask
= irq_chip_mask_parent
,
21 .irq_unmask
= irq_chip_unmask_parent
,
22 .irq_eoi
= irq_chip_eoi_parent
,
23 .irq_set_affinity
= msi_domain_set_affinity
26 static int its_fsl_mc_msi_prepare(struct irq_domain
*msi_domain
,
28 int nvec
, msi_alloc_info_t
*info
)
30 struct fsl_mc_device
*mc_bus_dev
;
31 struct msi_domain_info
*msi_info
;
33 if (!dev_is_fsl_mc(dev
))
36 mc_bus_dev
= to_fsl_mc_device(dev
);
37 if (!(mc_bus_dev
->flags
& FSL_MC_IS_DPRC
))
41 * Set the device Id to be passed to the GIC-ITS:
43 * NOTE: This device id corresponds to the IOMMU stream ID
44 * associated with the DPRC object (ICID).
46 info
->scratchpad
[0].ul
= mc_bus_dev
->icid
;
47 msi_info
= msi_get_domain_info(msi_domain
->parent
);
48 return msi_info
->ops
->msi_prepare(msi_domain
->parent
, dev
, nvec
, info
);
51 static struct msi_domain_ops its_fsl_mc_msi_ops __ro_after_init
= {
52 .msi_prepare
= its_fsl_mc_msi_prepare
,
55 static struct msi_domain_info its_fsl_mc_msi_domain_info
= {
56 .flags
= (MSI_FLAG_USE_DEF_DOM_OPS
| MSI_FLAG_USE_DEF_CHIP_OPS
),
57 .ops
= &its_fsl_mc_msi_ops
,
58 .chip
= &its_msi_irq_chip
,
61 static const struct of_device_id its_device_id
[] = {
62 { .compatible
= "arm,gic-v3-its", },
66 static int __init
its_fsl_mc_msi_init(void)
68 struct device_node
*np
;
69 struct irq_domain
*parent
;
70 struct irq_domain
*mc_msi_domain
;
72 for (np
= of_find_matching_node(NULL
, its_device_id
); np
;
73 np
= of_find_matching_node(np
, its_device_id
)) {
74 if (!of_device_is_available(np
))
76 if (!of_property_read_bool(np
, "msi-controller"))
79 parent
= irq_find_matching_host(np
, DOMAIN_BUS_NEXUS
);
80 if (!parent
|| !msi_get_domain_info(parent
)) {
81 pr_err("%pOF: unable to locate ITS domain\n", np
);
85 mc_msi_domain
= fsl_mc_msi_create_irq_domain(
86 of_node_to_fwnode(np
),
87 &its_fsl_mc_msi_domain_info
,
90 pr_err("%pOF: unable to create fsl-mc domain\n", np
);
94 pr_info("fsl-mc MSI: %pOF domain created\n", np
);
100 early_initcall(its_fsl_mc_msi_init
);