Blame view

drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c 2.64 KB
203e2de32   Bogdan Purcareata   staging: fsl-mc: ...
1
  // SPDX-License-Identifier: GPL-2.0
3a288fd51   J. German Rivera   staging: fsl-mc: ...
2
3
4
  /*
   * Freescale Management Complex (MC) bus driver MSI support
   *
6466dac79   Stuart Yoder   staging: fsl-mc: ...
5
   * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
3a288fd51   J. German Rivera   staging: fsl-mc: ...
6
7
   * Author: German Rivera <German.Rivera@freescale.com>
   *
3a288fd51   J. German Rivera   staging: fsl-mc: ...
8
   */
3a288fd51   J. German Rivera   staging: fsl-mc: ...
9
10
  #include <linux/of_device.h>
  #include <linux/of_address.h>
3a288fd51   J. German Rivera   staging: fsl-mc: ...
11
12
13
14
  #include <linux/irq.h>
  #include <linux/msi.h>
  #include <linux/of.h>
  #include <linux/of_irq.h>
6bd067c48   Bogdan Purcareata   staging: fsl-mc: ...
15
  #include <linux/fsl/mc.h>
3a288fd51   J. German Rivera   staging: fsl-mc: ...
16
17
  
  static struct irq_chip its_msi_irq_chip = {
d64c28a31   Stuart Yoder   staging: fsl-mc: ...
18
  	.name = "ITS-fMSI",
3a288fd51   J. German Rivera   staging: fsl-mc: ...
19
20
21
22
23
24
25
26
27
28
29
30
  	.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;
a385dd7b3   Laurentiu Tudor   staging: fsl-mc: ...
31
  	if (!dev_is_fsl_mc(dev))
3a288fd51   J. German Rivera   staging: fsl-mc: ...
32
33
34
  		return -EINVAL;
  
  	mc_bus_dev = to_fsl_mc_device(dev);
a385dd7b3   Laurentiu Tudor   staging: fsl-mc: ...
35
  	if (!(mc_bus_dev->flags & FSL_MC_IS_DPRC))
3a288fd51   J. German Rivera   staging: fsl-mc: ...
36
37
38
39
40
41
42
43
44
45
  		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);
147c8f376   Marc Zyngier   irqchip/gic-v3-it...
46
47
48
  
  	/* Allocate at least 32 MSIs, and always as a power of 2 */
  	nvec = max_t(int, 32, roundup_pow_of_two(nvec));
3a288fd51   J. German Rivera   staging: fsl-mc: ...
49
50
  	return msi_info->ops->msi_prepare(msi_domain->parent, dev, nvec, info);
  }
76b94eb1e   Jess Frazelle   staging: set msi_...
51
  static struct msi_domain_ops its_fsl_mc_msi_ops __ro_after_init = {
3a288fd51   J. German Rivera   staging: fsl-mc: ...
52
53
54
55
56
57
58
59
60
61
62
63
64
  	.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",	},
  	{},
  };
a535929f4   Colin Ian King   staging: fsl-mc: ...
65
  static int __init its_fsl_mc_msi_init(void)
3a288fd51   J. German Rivera   staging: fsl-mc: ...
66
67
68
69
70
71
72
  {
  	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)) {
95a256259   Stephen Boyd   irqchip/gic-v3: I...
73
74
  		if (!of_device_is_available(np))
  			continue;
3a288fd51   J. German Rivera   staging: fsl-mc: ...
75
76
77
78
79
  		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)) {
3c18c44dc   Rob Herring   staging: fsl-mc: ...
80
81
  			pr_err("%pOF: unable to locate ITS domain
  ", np);
3a288fd51   J. German Rivera   staging: fsl-mc: ...
82
83
84
85
86
87
88
89
  			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) {
3c18c44dc   Rob Herring   staging: fsl-mc: ...
90
91
  			pr_err("%pOF: unable to create fsl-mc domain
  ", np);
3a288fd51   J. German Rivera   staging: fsl-mc: ...
92
93
  			continue;
  		}
3c18c44dc   Rob Herring   staging: fsl-mc: ...
94
95
  		pr_info("fsl-mc MSI: %pOF domain created
  ", np);
3a288fd51   J. German Rivera   staging: fsl-mc: ...
96
97
98
99
  	}
  
  	return 0;
  }
1d11d5566   Ioana Radulescu   staging: fsl-mc: ...
100
101
  
  early_initcall(its_fsl_mc_msi_init);