aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorStephen Neuendorffer <stephen.neuendorffer@xilinx.com>2008-05-06 14:29:17 -0400
committerJosh Boyer <jwboyer@linux.vnet.ibm.com>2008-05-29 08:06:56 -0400
commitb786af117b360843349cf66165c4efa0217ca2a7 (patch)
tree713c515b49003fe2b593703820169ffc326ed4bb /arch
parentacf464817d5e7be9fb67aec4027dbee0ac9be17a (diff)
[POWERPC] Refactor DCR code
Previously, DCR support was configured at compile time to either use MMIO or native dcr instructions. Although this works for most platforms, it fails on FPGA platforms: 1) Systems may include more than one DCR bus. 2) Systems may be native DCR capable and still use memory mapped DCR interface. This patch provides runtime support based on the device trees for the case where CONFIG_PPC_DCR_MMIO and CONFIG_PPC_DCR_NATIVE are both selected. Previously, this was a poorly defined configuration, which happened to provide NATIVE support. The runtime selection is made based on the dcr-controller having a 'dcr-access-method' attribute in the device tree. If only one of the above options is selected, then the code uses #defines to select only the used code in order to avoid introducing overhead in existing usage. Signed-off-by: Stephen Neuendorffer <stephen.neuendorffer@xilinx.com> Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/sysdev/dcr.c154
1 files changed, 121 insertions, 33 deletions
diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c
index 437e48d3ae33..5f39a79b0660 100644
--- a/arch/powerpc/sysdev/dcr.c
+++ b/arch/powerpc/sysdev/dcr.c
@@ -23,6 +23,105 @@
23#include <asm/prom.h> 23#include <asm/prom.h>
24#include <asm/dcr.h> 24#include <asm/dcr.h>
25 25
26static struct device_node *find_dcr_parent(struct device_node *node)
27{
28 struct device_node *par, *tmp;
29 const u32 *p;
30
31 for (par = of_node_get(node); par;) {
32 if (of_get_property(par, "dcr-controller", NULL))
33 break;
34 p = of_get_property(par, "dcr-parent", NULL);
35 tmp = par;
36 if (p == NULL)
37 par = of_get_parent(par);
38 else
39 par = of_find_node_by_phandle(*p);
40 of_node_put(tmp);
41 }
42 return par;
43}
44
45#if defined(CONFIG_PPC_DCR_NATIVE) && defined(CONFIG_PPC_DCR_MMIO)
46
47bool dcr_map_ok_generic(dcr_host_t host)
48{
49 if (host.type == DCR_HOST_NATIVE)
50 return dcr_map_ok_native(host.host.native);
51 else if (host.type == DCR_HOST_MMIO)
52 return dcr_map_ok_mmio(host.host.mmio);
53 else
54 return 0;
55}
56EXPORT_SYMBOL_GPL(dcr_map_ok_generic);
57
58dcr_host_t dcr_map_generic(struct device_node *dev,
59 unsigned int dcr_n,
60 unsigned int dcr_c)
61{
62 dcr_host_t host;
63 struct device_node *dp;
64 const char *prop;
65
66 host.type = DCR_HOST_INVALID;
67
68 dp = find_dcr_parent(dev);
69 if (dp == NULL)
70 return host;
71
72 prop = of_get_property(dp, "dcr-access-method", NULL);
73
74 pr_debug("dcr_map_generic(dcr-access-method = %s)\n", prop);
75
76 if (!strcmp(prop, "native")) {
77 host.type = DCR_HOST_NATIVE;
78 host.host.native = dcr_map_native(dev, dcr_n, dcr_c);
79 } else if (!strcmp(prop, "mmio")) {
80 host.type = DCR_HOST_MMIO;
81 host.host.mmio = dcr_map_mmio(dev, dcr_n, dcr_c);
82 }
83
84 of_node_put(dp);
85 return host;
86}
87EXPORT_SYMBOL_GPL(dcr_map_generic);
88
89void dcr_unmap_generic(dcr_host_t host, unsigned int dcr_c)
90{
91 if (host.type == DCR_HOST_NATIVE)
92 dcr_unmap_native(host.host.native, dcr_c);
93 else if (host.type == DCR_HOST_MMIO)
94 dcr_unmap_mmio(host.host.mmio, dcr_c);
95 else /* host.type == DCR_HOST_INVALID */
96 WARN_ON(true);
97}
98EXPORT_SYMBOL_GPL(dcr_unmap_generic);
99
100u32 dcr_read_generic(dcr_host_t host, unsigned int dcr_n)
101{
102 if (host.type == DCR_HOST_NATIVE)
103 return dcr_read_native(host.host.native, dcr_n);
104 else if (host.type == DCR_HOST_MMIO)
105 return dcr_read_mmio(host.host.mmio, dcr_n);
106 else /* host.type == DCR_HOST_INVALID */
107 WARN_ON(true);
108 return 0;
109}
110EXPORT_SYMBOL_GPL(dcr_read_generic);
111
112void dcr_write_generic(dcr_host_t host, unsigned int dcr_n, u32 value)
113{
114 if (host.type == DCR_HOST_NATIVE)
115 dcr_write_native(host.host.native, dcr_n, value);
116 else if (host.type == DCR_HOST_MMIO)
117 dcr_write_mmio(host.host.mmio, dcr_n, value);
118 else /* host.type == DCR_HOST_INVALID */
119 WARN_ON(true);
120}
121EXPORT_SYMBOL_GPL(dcr_write_generic);
122
123#endif /* defined(CONFIG_PPC_DCR_NATIVE) && defined(CONFIG_PPC_DCR_MMIO) */
124
26unsigned int dcr_resource_start(struct device_node *np, unsigned int index) 125unsigned int dcr_resource_start(struct device_node *np, unsigned int index)
27{ 126{
28 unsigned int ds; 127 unsigned int ds;
@@ -47,26 +146,7 @@ unsigned int dcr_resource_len(struct device_node *np, unsigned int index)
47} 146}
48EXPORT_SYMBOL_GPL(dcr_resource_len); 147EXPORT_SYMBOL_GPL(dcr_resource_len);
49 148
50#ifndef CONFIG_PPC_DCR_NATIVE 149#ifdef CONFIG_PPC_DCR_MMIO
51
52static struct device_node * find_dcr_parent(struct device_node * node)
53{
54 struct device_node *par, *tmp;
55 const u32 *p;
56
57 for (par = of_node_get(node); par;) {
58 if (of_get_property(par, "dcr-controller", NULL))
59 break;
60 p = of_get_property(par, "dcr-parent", NULL);
61 tmp = par;
62 if (p == NULL)
63 par = of_get_parent(par);
64 else
65 par = of_find_node_by_phandle(*p);
66 of_node_put(tmp);
67 }
68 return par;
69}
70 150
71u64 of_translate_dcr_address(struct device_node *dev, 151u64 of_translate_dcr_address(struct device_node *dev,
72 unsigned int dcr_n, 152 unsigned int dcr_n,
@@ -75,7 +155,7 @@ u64 of_translate_dcr_address(struct device_node *dev,
75 struct device_node *dp; 155 struct device_node *dp;
76 const u32 *p; 156 const u32 *p;
77 unsigned int stride; 157 unsigned int stride;
78 u64 ret; 158 u64 ret = OF_BAD_ADDR;
79 159
80 dp = find_dcr_parent(dev); 160 dp = find_dcr_parent(dev);
81 if (dp == NULL) 161 if (dp == NULL)
@@ -90,7 +170,7 @@ u64 of_translate_dcr_address(struct device_node *dev,
90 if (p == NULL) 170 if (p == NULL)
91 p = of_get_property(dp, "dcr-mmio-space", NULL); 171 p = of_get_property(dp, "dcr-mmio-space", NULL);
92 if (p == NULL) 172 if (p == NULL)
93 return OF_BAD_ADDR; 173 goto done;
94 174
95 /* Maybe could do some better range checking here */ 175 /* Maybe could do some better range checking here */
96 ret = of_translate_address(dp, p); 176 ret = of_translate_address(dp, p);
@@ -98,21 +178,25 @@ u64 of_translate_dcr_address(struct device_node *dev,
98 ret += (u64)(stride) * (u64)dcr_n; 178 ret += (u64)(stride) * (u64)dcr_n;
99 if (out_stride) 179 if (out_stride)
100 *out_stride = stride; 180 *out_stride = stride;
181
182 done:
183 of_node_put(dp);
101 return ret; 184 return ret;
102} 185}
103 186
104dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n, 187dcr_host_mmio_t dcr_map_mmio(struct device_node *dev,
105 unsigned int dcr_c) 188 unsigned int dcr_n,
189 unsigned int dcr_c)
106{ 190{
107 dcr_host_t ret = { .token = NULL, .stride = 0, .base = dcr_n }; 191 dcr_host_mmio_t ret = { .token = NULL, .stride = 0, .base = dcr_n };
108 u64 addr; 192 u64 addr;
109 193
110 pr_debug("dcr_map(%s, 0x%x, 0x%x)\n", 194 pr_debug("dcr_map(%s, 0x%x, 0x%x)\n",
111 dev->full_name, dcr_n, dcr_c); 195 dev->full_name, dcr_n, dcr_c);
112 196
113 addr = of_translate_dcr_address(dev, dcr_n, &ret.stride); 197 addr = of_translate_dcr_address(dev, dcr_n, &ret.stride);
114 pr_debug("translates to addr: 0x%lx, stride: 0x%x\n", 198 pr_debug("translates to addr: 0x%llx, stride: 0x%x\n",
115 addr, ret.stride); 199 (unsigned long long) addr, ret.stride);
116 if (addr == OF_BAD_ADDR) 200 if (addr == OF_BAD_ADDR)
117 return ret; 201 return ret;
118 pr_debug("mapping 0x%x bytes\n", dcr_c * ret.stride); 202 pr_debug("mapping 0x%x bytes\n", dcr_c * ret.stride);
@@ -124,11 +208,11 @@ dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n,
124 ret.token -= dcr_n * ret.stride; 208 ret.token -= dcr_n * ret.stride;
125 return ret; 209 return ret;
126} 210}
127EXPORT_SYMBOL_GPL(dcr_map); 211EXPORT_SYMBOL_GPL(dcr_map_mmio);
128 212
129void dcr_unmap(dcr_host_t host, unsigned int dcr_c) 213void dcr_unmap_mmio(dcr_host_mmio_t host, unsigned int dcr_c)
130{ 214{
131 dcr_host_t h = host; 215 dcr_host_mmio_t h = host;
132 216
133 if (h.token == NULL) 217 if (h.token == NULL)
134 return; 218 return;
@@ -136,7 +220,11 @@ void dcr_unmap(dcr_host_t host, unsigned int dcr_c)
136 iounmap(h.token); 220 iounmap(h.token);
137 h.token = NULL; 221 h.token = NULL;
138} 222}
139EXPORT_SYMBOL_GPL(dcr_unmap); 223EXPORT_SYMBOL_GPL(dcr_unmap_mmio);
140#else /* defined(CONFIG_PPC_DCR_NATIVE) */ 224
225#endif /* defined(CONFIG_PPC_DCR_MMIO) */
226
227#ifdef CONFIG_PPC_DCR_NATIVE
141DEFINE_SPINLOCK(dcr_ind_lock); 228DEFINE_SPINLOCK(dcr_ind_lock);
142#endif /* !defined(CONFIG_PPC_DCR_NATIVE) */ 229#endif /* defined(CONFIG_PPC_DCR_NATIVE) */
230