1457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2c9f5b7e7SRobert Reif #include <linux/string.h>
3c9f5b7e7SRobert Reif #include <linux/kernel.h>
4066bcacaSPaul Gortmaker #include <linux/export.h>
5c9f5b7e7SRobert Reif #include <linux/mod_devicetable.h>
6c9f5b7e7SRobert Reif #include <linux/errno.h>
7c9f5b7e7SRobert Reif #include <linux/irq.h>
8*263291faSRob Herring #include <linux/of.h>
9c9f5b7e7SRobert Reif #include <linux/of_platform.h>
10985edb5bSSam Ravnborg #include <linux/of_address.h>
11985edb5bSSam Ravnborg #include <linux/of_irq.h>
12*263291faSRob Herring #include <linux/platform_device.h>
13c9f5b7e7SRobert Reif 
14c9f5b7e7SRobert Reif #include "of_device_common.h"
15c9f5b7e7SRobert Reif 
irq_of_parse_and_map(struct device_node * node,int index)16c9f5b7e7SRobert Reif unsigned int irq_of_parse_and_map(struct device_node *node, int index)
17c9f5b7e7SRobert Reif {
18cd4cd730SGrant Likely 	struct platform_device *op = of_find_device_by_node(node);
19c9f5b7e7SRobert Reif 
201636f8acSGrant Likely 	if (!op || index >= op->archdata.num_irqs)
21c9f5b7e7SRobert Reif 		return 0;
22c9f5b7e7SRobert Reif 
231636f8acSGrant Likely 	return op->archdata.irqs[index];
24c9f5b7e7SRobert Reif }
25c9f5b7e7SRobert Reif EXPORT_SYMBOL(irq_of_parse_and_map);
26c9f5b7e7SRobert Reif 
of_address_to_resource(struct device_node * node,int index,struct resource * r)27930952afSDavid S. Miller int of_address_to_resource(struct device_node *node, int index,
28930952afSDavid S. Miller 			   struct resource *r)
29930952afSDavid S. Miller {
30930952afSDavid S. Miller 	struct platform_device *op = of_find_device_by_node(node);
31930952afSDavid S. Miller 
32930952afSDavid S. Miller 	if (!op || index >= op->num_resources)
33930952afSDavid S. Miller 		return -EINVAL;
34930952afSDavid S. Miller 
35930952afSDavid S. Miller 	memcpy(r, &op->archdata.resource[index], sizeof(*r));
36930952afSDavid S. Miller 	return 0;
37930952afSDavid S. Miller }
38930952afSDavid S. Miller EXPORT_SYMBOL_GPL(of_address_to_resource);
39930952afSDavid S. Miller 
of_iomap(struct device_node * node,int index)409889376aSDavid S. Miller void __iomem *of_iomap(struct device_node *node, int index)
419889376aSDavid S. Miller {
429889376aSDavid S. Miller 	struct platform_device *op = of_find_device_by_node(node);
439889376aSDavid S. Miller 	struct resource *r;
449889376aSDavid S. Miller 
459889376aSDavid S. Miller 	if (!op || index >= op->num_resources)
469889376aSDavid S. Miller 		return NULL;
479889376aSDavid S. Miller 
489889376aSDavid S. Miller 	r = &op->archdata.resource[index];
499889376aSDavid S. Miller 
509889376aSDavid S. Miller 	return of_ioremap(r, 0, resource_size(r), (char *) r->name);
519889376aSDavid S. Miller }
529889376aSDavid S. Miller EXPORT_SYMBOL(of_iomap);
539889376aSDavid S. Miller 
54c9f5b7e7SRobert Reif /* Take the archdata values for IOMMU, STC, and HOSTDATA found in
55cd4cd730SGrant Likely  * BUS and propagate to all child platform_device objects.
56c9f5b7e7SRobert Reif  */
of_propagate_archdata(struct platform_device * bus)57cd4cd730SGrant Likely void of_propagate_archdata(struct platform_device *bus)
58c9f5b7e7SRobert Reif {
59c9f5b7e7SRobert Reif 	struct dev_archdata *bus_sd = &bus->dev.archdata;
6061c7a080SGrant Likely 	struct device_node *bus_dp = bus->dev.of_node;
61c9f5b7e7SRobert Reif 	struct device_node *dp;
62c9f5b7e7SRobert Reif 
63c9f5b7e7SRobert Reif 	for (dp = bus_dp->child; dp; dp = dp->sibling) {
64cd4cd730SGrant Likely 		struct platform_device *op = of_find_device_by_node(dp);
65c9f5b7e7SRobert Reif 
66c9f5b7e7SRobert Reif 		op->dev.archdata.iommu = bus_sd->iommu;
67c9f5b7e7SRobert Reif 		op->dev.archdata.stc = bus_sd->stc;
68c9f5b7e7SRobert Reif 		op->dev.archdata.host_controller = bus_sd->host_controller;
69c9f5b7e7SRobert Reif 		op->dev.archdata.numa_node = bus_sd->numa_node;
70255a69a9SChristoph Hellwig 		op->dev.dma_ops = bus->dev.dma_ops;
71c9f5b7e7SRobert Reif 
72c9f5b7e7SRobert Reif 		if (dp->child)
73c9f5b7e7SRobert Reif 			of_propagate_archdata(op);
74c9f5b7e7SRobert Reif 	}
75c9f5b7e7SRobert Reif }
76c9f5b7e7SRobert Reif 
get_cells(struct device_node * dp,int * addrc,int * sizec)77c9f5b7e7SRobert Reif static void get_cells(struct device_node *dp, int *addrc, int *sizec)
78c9f5b7e7SRobert Reif {
79c9f5b7e7SRobert Reif 	if (addrc)
80c9f5b7e7SRobert Reif 		*addrc = of_n_addr_cells(dp);
81c9f5b7e7SRobert Reif 	if (sizec)
82c9f5b7e7SRobert Reif 		*sizec = of_n_size_cells(dp);
83c9f5b7e7SRobert Reif }
84c9f5b7e7SRobert Reif 
85c9f5b7e7SRobert Reif /*
86c9f5b7e7SRobert Reif  * Default translator (generic bus)
87c9f5b7e7SRobert Reif  */
88c9f5b7e7SRobert Reif 
of_bus_default_count_cells(struct device_node * dev,int * addrc,int * sizec)89c9f5b7e7SRobert Reif void of_bus_default_count_cells(struct device_node *dev, int *addrc, int *sizec)
90c9f5b7e7SRobert Reif {
91c9f5b7e7SRobert Reif 	get_cells(dev, addrc, sizec);
92c9f5b7e7SRobert Reif }
93c9f5b7e7SRobert Reif 
94c9f5b7e7SRobert Reif /* Make sure the least significant 64-bits are in-range.  Even
95c9f5b7e7SRobert Reif  * for 3 or 4 cell values it is a good enough approximation.
96c9f5b7e7SRobert Reif  */
of_out_of_range(const u32 * addr,const u32 * base,const u32 * size,int na,int ns)97c9f5b7e7SRobert Reif int of_out_of_range(const u32 *addr, const u32 *base,
98c9f5b7e7SRobert Reif 		    const u32 *size, int na, int ns)
99c9f5b7e7SRobert Reif {
100c9f5b7e7SRobert Reif 	u64 a = of_read_addr(addr, na);
101c9f5b7e7SRobert Reif 	u64 b = of_read_addr(base, na);
102c9f5b7e7SRobert Reif 
103c9f5b7e7SRobert Reif 	if (a < b)
104c9f5b7e7SRobert Reif 		return 1;
105c9f5b7e7SRobert Reif 
106c9f5b7e7SRobert Reif 	b += of_read_addr(size, ns);
107c9f5b7e7SRobert Reif 	if (a >= b)
108c9f5b7e7SRobert Reif 		return 1;
109c9f5b7e7SRobert Reif 
110c9f5b7e7SRobert Reif 	return 0;
111c9f5b7e7SRobert Reif }
112c9f5b7e7SRobert Reif 
of_bus_default_map(u32 * addr,const u32 * range,int na,int ns,int pna)113c9f5b7e7SRobert Reif int of_bus_default_map(u32 *addr, const u32 *range, int na, int ns, int pna)
114c9f5b7e7SRobert Reif {
115c9f5b7e7SRobert Reif 	u32 result[OF_MAX_ADDR_CELLS];
116c9f5b7e7SRobert Reif 	int i;
117c9f5b7e7SRobert Reif 
118c9f5b7e7SRobert Reif 	if (ns > 2) {
119c9f5b7e7SRobert Reif 		printk("of_device: Cannot handle size cells (%d) > 2.", ns);
120c9f5b7e7SRobert Reif 		return -EINVAL;
121c9f5b7e7SRobert Reif 	}
122c9f5b7e7SRobert Reif 
123c9f5b7e7SRobert Reif 	if (of_out_of_range(addr, range, range + na + pna, na, ns))
124c9f5b7e7SRobert Reif 		return -EINVAL;
125c9f5b7e7SRobert Reif 
126c9f5b7e7SRobert Reif 	/* Start with the parent range base.  */
127c9f5b7e7SRobert Reif 	memcpy(result, range + na, pna * 4);
128c9f5b7e7SRobert Reif 
129c9f5b7e7SRobert Reif 	/* Add in the child address offset.  */
130c9f5b7e7SRobert Reif 	for (i = 0; i < na; i++)
131c9f5b7e7SRobert Reif 		result[pna - 1 - i] +=
132c9f5b7e7SRobert Reif 			(addr[na - 1 - i] -
133c9f5b7e7SRobert Reif 			 range[na - 1 - i]);
134c9f5b7e7SRobert Reif 
135c9f5b7e7SRobert Reif 	memcpy(addr, result, pna * 4);
136c9f5b7e7SRobert Reif 
137c9f5b7e7SRobert Reif 	return 0;
138c9f5b7e7SRobert Reif }
139c9f5b7e7SRobert Reif 
of_bus_default_get_flags(const u32 * addr,unsigned long flags)140c9f5b7e7SRobert Reif unsigned long of_bus_default_get_flags(const u32 *addr, unsigned long flags)
141c9f5b7e7SRobert Reif {
142c9f5b7e7SRobert Reif 	if (flags)
143c9f5b7e7SRobert Reif 		return flags;
144c9f5b7e7SRobert Reif 	return IORESOURCE_MEM;
145c9f5b7e7SRobert Reif }
146c9f5b7e7SRobert Reif 
147c9f5b7e7SRobert Reif /*
148c9f5b7e7SRobert Reif  * SBUS bus specific translator
149c9f5b7e7SRobert Reif  */
150c9f5b7e7SRobert Reif 
of_bus_sbus_match(struct device_node * np)151c9f5b7e7SRobert Reif int of_bus_sbus_match(struct device_node *np)
152c9f5b7e7SRobert Reif {
153c9f5b7e7SRobert Reif 	struct device_node *dp = np;
154c9f5b7e7SRobert Reif 
155c9f5b7e7SRobert Reif 	while (dp) {
15629c990dfSRob Herring 		if (of_node_name_eq(dp, "sbus") ||
15729c990dfSRob Herring 		    of_node_name_eq(dp, "sbi"))
158c9f5b7e7SRobert Reif 			return 1;
159c9f5b7e7SRobert Reif 
160c9f5b7e7SRobert Reif 		/* Have a look at use_1to1_mapping().  We're trying
161c9f5b7e7SRobert Reif 		 * to match SBUS if that's the top-level bus and we
162c9f5b7e7SRobert Reif 		 * don't have some intervening real bus that provides
163c9f5b7e7SRobert Reif 		 * ranges based translations.
164c9f5b7e7SRobert Reif 		 */
1656a71ca74SRob Herring 		if (of_property_present(dp, "ranges"))
166c9f5b7e7SRobert Reif 			break;
167c9f5b7e7SRobert Reif 
168c9f5b7e7SRobert Reif 		dp = dp->parent;
169c9f5b7e7SRobert Reif 	}
170c9f5b7e7SRobert Reif 
171c9f5b7e7SRobert Reif 	return 0;
172c9f5b7e7SRobert Reif }
173c9f5b7e7SRobert Reif 
of_bus_sbus_count_cells(struct device_node * child,int * addrc,int * sizec)174c9f5b7e7SRobert Reif void of_bus_sbus_count_cells(struct device_node *child, int *addrc, int *sizec)
175c9f5b7e7SRobert Reif {
176c9f5b7e7SRobert Reif 	if (addrc)
177c9f5b7e7SRobert Reif 		*addrc = 2;
178c9f5b7e7SRobert Reif 	if (sizec)
179c9f5b7e7SRobert Reif 		*sizec = 1;
180c9f5b7e7SRobert Reif }
181