0001
0002 #include <linux/string.h>
0003 #include <linux/kernel.h>
0004 #include <linux/of.h>
0005 #include <linux/export.h>
0006 #include <linux/mod_devicetable.h>
0007 #include <linux/errno.h>
0008 #include <linux/irq.h>
0009 #include <linux/of_platform.h>
0010 #include <linux/of_address.h>
0011 #include <linux/of_device.h>
0012 #include <linux/of_irq.h>
0013
0014 #include "of_device_common.h"
0015
0016 unsigned int irq_of_parse_and_map(struct device_node *node, int index)
0017 {
0018 struct platform_device *op = of_find_device_by_node(node);
0019
0020 if (!op || index >= op->archdata.num_irqs)
0021 return 0;
0022
0023 return op->archdata.irqs[index];
0024 }
0025 EXPORT_SYMBOL(irq_of_parse_and_map);
0026
0027 int of_address_to_resource(struct device_node *node, int index,
0028 struct resource *r)
0029 {
0030 struct platform_device *op = of_find_device_by_node(node);
0031
0032 if (!op || index >= op->num_resources)
0033 return -EINVAL;
0034
0035 memcpy(r, &op->archdata.resource[index], sizeof(*r));
0036 return 0;
0037 }
0038 EXPORT_SYMBOL_GPL(of_address_to_resource);
0039
0040 void __iomem *of_iomap(struct device_node *node, int index)
0041 {
0042 struct platform_device *op = of_find_device_by_node(node);
0043 struct resource *r;
0044
0045 if (!op || index >= op->num_resources)
0046 return NULL;
0047
0048 r = &op->archdata.resource[index];
0049
0050 return of_ioremap(r, 0, resource_size(r), (char *) r->name);
0051 }
0052 EXPORT_SYMBOL(of_iomap);
0053
0054
0055
0056
0057 void of_propagate_archdata(struct platform_device *bus)
0058 {
0059 struct dev_archdata *bus_sd = &bus->dev.archdata;
0060 struct device_node *bus_dp = bus->dev.of_node;
0061 struct device_node *dp;
0062
0063 for (dp = bus_dp->child; dp; dp = dp->sibling) {
0064 struct platform_device *op = of_find_device_by_node(dp);
0065
0066 op->dev.archdata.iommu = bus_sd->iommu;
0067 op->dev.archdata.stc = bus_sd->stc;
0068 op->dev.archdata.host_controller = bus_sd->host_controller;
0069 op->dev.archdata.numa_node = bus_sd->numa_node;
0070 op->dev.dma_ops = bus->dev.dma_ops;
0071
0072 if (dp->child)
0073 of_propagate_archdata(op);
0074 }
0075 }
0076
0077 static void get_cells(struct device_node *dp, int *addrc, int *sizec)
0078 {
0079 if (addrc)
0080 *addrc = of_n_addr_cells(dp);
0081 if (sizec)
0082 *sizec = of_n_size_cells(dp);
0083 }
0084
0085
0086
0087
0088
0089 void of_bus_default_count_cells(struct device_node *dev, int *addrc, int *sizec)
0090 {
0091 get_cells(dev, addrc, sizec);
0092 }
0093
0094
0095
0096
0097 int of_out_of_range(const u32 *addr, const u32 *base,
0098 const u32 *size, int na, int ns)
0099 {
0100 u64 a = of_read_addr(addr, na);
0101 u64 b = of_read_addr(base, na);
0102
0103 if (a < b)
0104 return 1;
0105
0106 b += of_read_addr(size, ns);
0107 if (a >= b)
0108 return 1;
0109
0110 return 0;
0111 }
0112
0113 int of_bus_default_map(u32 *addr, const u32 *range, int na, int ns, int pna)
0114 {
0115 u32 result[OF_MAX_ADDR_CELLS];
0116 int i;
0117
0118 if (ns > 2) {
0119 printk("of_device: Cannot handle size cells (%d) > 2.", ns);
0120 return -EINVAL;
0121 }
0122
0123 if (of_out_of_range(addr, range, range + na + pna, na, ns))
0124 return -EINVAL;
0125
0126
0127 memcpy(result, range + na, pna * 4);
0128
0129
0130 for (i = 0; i < na; i++)
0131 result[pna - 1 - i] +=
0132 (addr[na - 1 - i] -
0133 range[na - 1 - i]);
0134
0135 memcpy(addr, result, pna * 4);
0136
0137 return 0;
0138 }
0139
0140 unsigned long of_bus_default_get_flags(const u32 *addr, unsigned long flags)
0141 {
0142 if (flags)
0143 return flags;
0144 return IORESOURCE_MEM;
0145 }
0146
0147
0148
0149
0150
0151 int of_bus_sbus_match(struct device_node *np)
0152 {
0153 struct device_node *dp = np;
0154
0155 while (dp) {
0156 if (of_node_name_eq(dp, "sbus") ||
0157 of_node_name_eq(dp, "sbi"))
0158 return 1;
0159
0160
0161
0162
0163
0164
0165 if (of_find_property(dp, "ranges", NULL) != NULL)
0166 break;
0167
0168 dp = dp->parent;
0169 }
0170
0171 return 0;
0172 }
0173
0174 void of_bus_sbus_count_cells(struct device_node *child, int *addrc, int *sizec)
0175 {
0176 if (addrc)
0177 *addrc = 2;
0178 if (sizec)
0179 *sizec = 1;
0180 }