diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-07-18 13:53:16 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-07-18 13:53:16 -0400 |
commit | 9b610fda0df5d0f0b0c64242e37441ad1b384aac (patch) | |
tree | 0ea14b15f2e6546f37fe18d8ac3dc83077ec0e55 /arch/powerpc/sysdev/dcr.c | |
parent | b8f8c3cf0a4ac0632ec3f0e15e9dc0c29de917af (diff) | |
parent | 5b664cb235e97afbf34db9c4d77f08ebd725335e (diff) |
Merge branch 'linus' into timers/nohz
Diffstat (limited to 'arch/powerpc/sysdev/dcr.c')
-rw-r--r-- | arch/powerpc/sysdev/dcr.c | 156 |
1 files changed, 123 insertions, 33 deletions
diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c index 437e48d3ae33..a8ba9983dd5a 100644 --- a/arch/powerpc/sysdev/dcr.c +++ b/arch/powerpc/sysdev/dcr.c | |||
@@ -23,6 +23,107 @@ | |||
23 | #include <asm/prom.h> | 23 | #include <asm/prom.h> |
24 | #include <asm/dcr.h> | 24 | #include <asm/dcr.h> |
25 | 25 | ||
26 | #ifdef CONFIG_PPC_DCR_MMIO | ||
27 | static struct device_node *find_dcr_parent(struct device_node *node) | ||
28 | { | ||
29 | struct device_node *par, *tmp; | ||
30 | const u32 *p; | ||
31 | |||
32 | for (par = of_node_get(node); par;) { | ||
33 | if (of_get_property(par, "dcr-controller", NULL)) | ||
34 | break; | ||
35 | p = of_get_property(par, "dcr-parent", NULL); | ||
36 | tmp = par; | ||
37 | if (p == NULL) | ||
38 | par = of_get_parent(par); | ||
39 | else | ||
40 | par = of_find_node_by_phandle(*p); | ||
41 | of_node_put(tmp); | ||
42 | } | ||
43 | return par; | ||
44 | } | ||
45 | #endif | ||
46 | |||
47 | #if defined(CONFIG_PPC_DCR_NATIVE) && defined(CONFIG_PPC_DCR_MMIO) | ||
48 | |||
49 | bool dcr_map_ok_generic(dcr_host_t host) | ||
50 | { | ||
51 | if (host.type == DCR_HOST_NATIVE) | ||
52 | return dcr_map_ok_native(host.host.native); | ||
53 | else if (host.type == DCR_HOST_MMIO) | ||
54 | return dcr_map_ok_mmio(host.host.mmio); | ||
55 | else | ||
56 | return 0; | ||
57 | } | ||
58 | EXPORT_SYMBOL_GPL(dcr_map_ok_generic); | ||
59 | |||
60 | dcr_host_t dcr_map_generic(struct device_node *dev, | ||
61 | unsigned int dcr_n, | ||
62 | unsigned int dcr_c) | ||
63 | { | ||
64 | dcr_host_t host; | ||
65 | struct device_node *dp; | ||
66 | const char *prop; | ||
67 | |||
68 | host.type = DCR_HOST_INVALID; | ||
69 | |||
70 | dp = find_dcr_parent(dev); | ||
71 | if (dp == NULL) | ||
72 | return host; | ||
73 | |||
74 | prop = of_get_property(dp, "dcr-access-method", NULL); | ||
75 | |||
76 | pr_debug("dcr_map_generic(dcr-access-method = %s)\n", prop); | ||
77 | |||
78 | if (!strcmp(prop, "native")) { | ||
79 | host.type = DCR_HOST_NATIVE; | ||
80 | host.host.native = dcr_map_native(dev, dcr_n, dcr_c); | ||
81 | } else if (!strcmp(prop, "mmio")) { | ||
82 | host.type = DCR_HOST_MMIO; | ||
83 | host.host.mmio = dcr_map_mmio(dev, dcr_n, dcr_c); | ||
84 | } | ||
85 | |||
86 | of_node_put(dp); | ||
87 | return host; | ||
88 | } | ||
89 | EXPORT_SYMBOL_GPL(dcr_map_generic); | ||
90 | |||
91 | void dcr_unmap_generic(dcr_host_t host, unsigned int dcr_c) | ||
92 | { | ||
93 | if (host.type == DCR_HOST_NATIVE) | ||
94 | dcr_unmap_native(host.host.native, dcr_c); | ||
95 | else if (host.type == DCR_HOST_MMIO) | ||
96 | dcr_unmap_mmio(host.host.mmio, dcr_c); | ||
97 | else /* host.type == DCR_HOST_INVALID */ | ||
98 | WARN_ON(true); | ||
99 | } | ||
100 | EXPORT_SYMBOL_GPL(dcr_unmap_generic); | ||
101 | |||
102 | u32 dcr_read_generic(dcr_host_t host, unsigned int dcr_n) | ||
103 | { | ||
104 | if (host.type == DCR_HOST_NATIVE) | ||
105 | return dcr_read_native(host.host.native, dcr_n); | ||
106 | else if (host.type == DCR_HOST_MMIO) | ||
107 | return dcr_read_mmio(host.host.mmio, dcr_n); | ||
108 | else /* host.type == DCR_HOST_INVALID */ | ||
109 | WARN_ON(true); | ||
110 | return 0; | ||
111 | } | ||
112 | EXPORT_SYMBOL_GPL(dcr_read_generic); | ||
113 | |||
114 | void dcr_write_generic(dcr_host_t host, unsigned int dcr_n, u32 value) | ||
115 | { | ||
116 | if (host.type == DCR_HOST_NATIVE) | ||
117 | dcr_write_native(host.host.native, dcr_n, value); | ||
118 | else if (host.type == DCR_HOST_MMIO) | ||
119 | dcr_write_mmio(host.host.mmio, dcr_n, value); | ||
120 | else /* host.type == DCR_HOST_INVALID */ | ||
121 | WARN_ON(true); | ||
122 | } | ||
123 | EXPORT_SYMBOL_GPL(dcr_write_generic); | ||
124 | |||
125 | #endif /* defined(CONFIG_PPC_DCR_NATIVE) && defined(CONFIG_PPC_DCR_MMIO) */ | ||
126 | |||
26 | unsigned int dcr_resource_start(struct device_node *np, unsigned int index) | 127 | unsigned int dcr_resource_start(struct device_node *np, unsigned int index) |
27 | { | 128 | { |
28 | unsigned int ds; | 129 | unsigned int ds; |
@@ -47,26 +148,7 @@ unsigned int dcr_resource_len(struct device_node *np, unsigned int index) | |||
47 | } | 148 | } |
48 | EXPORT_SYMBOL_GPL(dcr_resource_len); | 149 | EXPORT_SYMBOL_GPL(dcr_resource_len); |
49 | 150 | ||
50 | #ifndef CONFIG_PPC_DCR_NATIVE | 151 | #ifdef CONFIG_PPC_DCR_MMIO |
51 | |||
52 | static 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 | 152 | ||
71 | u64 of_translate_dcr_address(struct device_node *dev, | 153 | u64 of_translate_dcr_address(struct device_node *dev, |
72 | unsigned int dcr_n, | 154 | unsigned int dcr_n, |
@@ -75,7 +157,7 @@ u64 of_translate_dcr_address(struct device_node *dev, | |||
75 | struct device_node *dp; | 157 | struct device_node *dp; |
76 | const u32 *p; | 158 | const u32 *p; |
77 | unsigned int stride; | 159 | unsigned int stride; |
78 | u64 ret; | 160 | u64 ret = OF_BAD_ADDR; |
79 | 161 | ||
80 | dp = find_dcr_parent(dev); | 162 | dp = find_dcr_parent(dev); |
81 | if (dp == NULL) | 163 | if (dp == NULL) |
@@ -90,7 +172,7 @@ u64 of_translate_dcr_address(struct device_node *dev, | |||
90 | if (p == NULL) | 172 | if (p == NULL) |
91 | p = of_get_property(dp, "dcr-mmio-space", NULL); | 173 | p = of_get_property(dp, "dcr-mmio-space", NULL); |
92 | if (p == NULL) | 174 | if (p == NULL) |
93 | return OF_BAD_ADDR; | 175 | goto done; |
94 | 176 | ||
95 | /* Maybe could do some better range checking here */ | 177 | /* Maybe could do some better range checking here */ |
96 | ret = of_translate_address(dp, p); | 178 | ret = of_translate_address(dp, p); |
@@ -98,21 +180,25 @@ u64 of_translate_dcr_address(struct device_node *dev, | |||
98 | ret += (u64)(stride) * (u64)dcr_n; | 180 | ret += (u64)(stride) * (u64)dcr_n; |
99 | if (out_stride) | 181 | if (out_stride) |
100 | *out_stride = stride; | 182 | *out_stride = stride; |
183 | |||
184 | done: | ||
185 | of_node_put(dp); | ||
101 | return ret; | 186 | return ret; |
102 | } | 187 | } |
103 | 188 | ||
104 | dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n, | 189 | dcr_host_mmio_t dcr_map_mmio(struct device_node *dev, |
105 | unsigned int dcr_c) | 190 | unsigned int dcr_n, |
191 | unsigned int dcr_c) | ||
106 | { | 192 | { |
107 | dcr_host_t ret = { .token = NULL, .stride = 0, .base = dcr_n }; | 193 | dcr_host_mmio_t ret = { .token = NULL, .stride = 0, .base = dcr_n }; |
108 | u64 addr; | 194 | u64 addr; |
109 | 195 | ||
110 | pr_debug("dcr_map(%s, 0x%x, 0x%x)\n", | 196 | pr_debug("dcr_map(%s, 0x%x, 0x%x)\n", |
111 | dev->full_name, dcr_n, dcr_c); | 197 | dev->full_name, dcr_n, dcr_c); |
112 | 198 | ||
113 | addr = of_translate_dcr_address(dev, dcr_n, &ret.stride); | 199 | addr = of_translate_dcr_address(dev, dcr_n, &ret.stride); |
114 | pr_debug("translates to addr: 0x%lx, stride: 0x%x\n", | 200 | pr_debug("translates to addr: 0x%llx, stride: 0x%x\n", |
115 | addr, ret.stride); | 201 | (unsigned long long) addr, ret.stride); |
116 | if (addr == OF_BAD_ADDR) | 202 | if (addr == OF_BAD_ADDR) |
117 | return ret; | 203 | return ret; |
118 | pr_debug("mapping 0x%x bytes\n", dcr_c * ret.stride); | 204 | pr_debug("mapping 0x%x bytes\n", dcr_c * ret.stride); |
@@ -124,11 +210,11 @@ dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n, | |||
124 | ret.token -= dcr_n * ret.stride; | 210 | ret.token -= dcr_n * ret.stride; |
125 | return ret; | 211 | return ret; |
126 | } | 212 | } |
127 | EXPORT_SYMBOL_GPL(dcr_map); | 213 | EXPORT_SYMBOL_GPL(dcr_map_mmio); |
128 | 214 | ||
129 | void dcr_unmap(dcr_host_t host, unsigned int dcr_c) | 215 | void dcr_unmap_mmio(dcr_host_mmio_t host, unsigned int dcr_c) |
130 | { | 216 | { |
131 | dcr_host_t h = host; | 217 | dcr_host_mmio_t h = host; |
132 | 218 | ||
133 | if (h.token == NULL) | 219 | if (h.token == NULL) |
134 | return; | 220 | return; |
@@ -136,7 +222,11 @@ void dcr_unmap(dcr_host_t host, unsigned int dcr_c) | |||
136 | iounmap(h.token); | 222 | iounmap(h.token); |
137 | h.token = NULL; | 223 | h.token = NULL; |
138 | } | 224 | } |
139 | EXPORT_SYMBOL_GPL(dcr_unmap); | 225 | EXPORT_SYMBOL_GPL(dcr_unmap_mmio); |
140 | #else /* defined(CONFIG_PPC_DCR_NATIVE) */ | 226 | |
227 | #endif /* defined(CONFIG_PPC_DCR_MMIO) */ | ||
228 | |||
229 | #ifdef CONFIG_PPC_DCR_NATIVE | ||
141 | DEFINE_SPINLOCK(dcr_ind_lock); | 230 | DEFINE_SPINLOCK(dcr_ind_lock); |
142 | #endif /* !defined(CONFIG_PPC_DCR_NATIVE) */ | 231 | #endif /* defined(CONFIG_PPC_DCR_NATIVE) */ |
232 | |||