diff options
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r-- | drivers/pcmcia/Kconfig | 5 | ||||
-rw-r--r-- | drivers/pcmcia/m8xx_pcmcia.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/rsrc_mgr.c | 102 |
3 files changed, 107 insertions, 2 deletions
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index ea00b1f3cb44..df93df64c9f3 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig | |||
@@ -182,7 +182,7 @@ config TCIC | |||
182 | config PCMCIA_M8XX | 182 | config PCMCIA_M8XX |
183 | tristate "MPC8xx PCMCIA support" | 183 | tristate "MPC8xx PCMCIA support" |
184 | depends on PCMCIA && PPC && 8xx | 184 | depends on PCMCIA && PPC && 8xx |
185 | select PCCARD_NONSTATIC | 185 | select PCCARD_IODYN |
186 | help | 186 | help |
187 | Say Y here to include support for PowerPC 8xx series PCMCIA | 187 | Say Y here to include support for PowerPC 8xx series PCMCIA |
188 | controller. | 188 | controller. |
@@ -266,6 +266,9 @@ config OMAP_CF | |||
266 | config PCCARD_NONSTATIC | 266 | config PCCARD_NONSTATIC |
267 | tristate | 267 | tristate |
268 | 268 | ||
269 | config PCCARD_IODYN | ||
270 | bool | ||
271 | |||
269 | endif # PCCARD | 272 | endif # PCCARD |
270 | 273 | ||
271 | endmenu | 274 | endmenu |
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c index a7f27c3dfc24..570e4e868b24 100644 --- a/drivers/pcmcia/m8xx_pcmcia.c +++ b/drivers/pcmcia/m8xx_pcmcia.c | |||
@@ -1232,7 +1232,7 @@ static int __init m8xx_init(void) | |||
1232 | socket[i].socket.io_offset = 0; | 1232 | socket[i].socket.io_offset = 0; |
1233 | socket[i].socket.pci_irq = i ? 7 : 9; | 1233 | socket[i].socket.pci_irq = i ? 7 : 9; |
1234 | socket[i].socket.ops = &m8xx_services; | 1234 | socket[i].socket.ops = &m8xx_services; |
1235 | socket[i].socket.resource_ops = &pccard_nonstatic_ops; | 1235 | socket[i].socket.resource_ops = &pccard_iodyn_ops; |
1236 | socket[i].socket.cb_dev = NULL; | 1236 | socket[i].socket.cb_dev = NULL; |
1237 | socket[i].socket.dev.dev = &m8xx_device.dev; | 1237 | socket[i].socket.dev.dev = &m8xx_device.dev; |
1238 | } | 1238 | } |
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index b02598a5a912..514609369836 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c | |||
@@ -166,3 +166,105 @@ struct pccard_resource_ops pccard_static_ops = { | |||
166 | .exit = NULL, | 166 | .exit = NULL, |
167 | }; | 167 | }; |
168 | EXPORT_SYMBOL(pccard_static_ops); | 168 | EXPORT_SYMBOL(pccard_static_ops); |
169 | |||
170 | |||
171 | #ifdef CONFIG_PCCARD_IODYN | ||
172 | |||
173 | static struct resource * | ||
174 | make_resource(unsigned long b, unsigned long n, int flags, char *name) | ||
175 | { | ||
176 | struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); | ||
177 | |||
178 | if (res) { | ||
179 | res->name = name; | ||
180 | res->start = b; | ||
181 | res->end = b + n - 1; | ||
182 | res->flags = flags; | ||
183 | } | ||
184 | return res; | ||
185 | } | ||
186 | |||
187 | struct pcmcia_align_data { | ||
188 | unsigned long mask; | ||
189 | unsigned long offset; | ||
190 | }; | ||
191 | |||
192 | static void pcmcia_align(void *align_data, struct resource *res, | ||
193 | unsigned long size, unsigned long align) | ||
194 | { | ||
195 | struct pcmcia_align_data *data = align_data; | ||
196 | unsigned long start; | ||
197 | |||
198 | start = (res->start & ~data->mask) + data->offset; | ||
199 | if (start < res->start) | ||
200 | start += data->mask + 1; | ||
201 | res->start = start; | ||
202 | |||
203 | #ifdef CONFIG_X86 | ||
204 | if (res->flags & IORESOURCE_IO) { | ||
205 | if (start & 0x300) { | ||
206 | start = (start + 0x3ff) & ~0x3ff; | ||
207 | res->start = start; | ||
208 | } | ||
209 | } | ||
210 | #endif | ||
211 | |||
212 | #ifdef CONFIG_M68K | ||
213 | if (res->flags & IORESOURCE_IO) { | ||
214 | if ((res->start + size - 1) >= 1024) | ||
215 | res->start = res->end; | ||
216 | } | ||
217 | #endif | ||
218 | } | ||
219 | |||
220 | |||
221 | static int iodyn_adjust_io_region(struct resource *res, unsigned long r_start, | ||
222 | unsigned long r_end, struct pcmcia_socket *s) | ||
223 | { | ||
224 | return adjust_resource(res, r_start, r_end - r_start + 1); | ||
225 | } | ||
226 | |||
227 | |||
228 | static struct resource *iodyn_find_io_region(unsigned long base, int num, | ||
229 | unsigned long align, struct pcmcia_socket *s) | ||
230 | { | ||
231 | struct resource *res = make_resource(0, num, IORESOURCE_IO, | ||
232 | s->dev.class_id); | ||
233 | struct pcmcia_align_data data; | ||
234 | unsigned long min = base; | ||
235 | int ret; | ||
236 | |||
237 | if (align == 0) | ||
238 | align = 0x10000; | ||
239 | |||
240 | data.mask = align - 1; | ||
241 | data.offset = base & data.mask; | ||
242 | |||
243 | #ifdef CONFIG_PCI | ||
244 | if (s->cb_dev) { | ||
245 | ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1, | ||
246 | min, 0, pcmcia_align, &data); | ||
247 | } else | ||
248 | #endif | ||
249 | ret = allocate_resource(&ioport_resource, res, num, min, ~0UL, | ||
250 | 1, pcmcia_align, &data); | ||
251 | |||
252 | if (ret != 0) { | ||
253 | kfree(res); | ||
254 | res = NULL; | ||
255 | } | ||
256 | return res; | ||
257 | } | ||
258 | |||
259 | struct pccard_resource_ops pccard_iodyn_ops = { | ||
260 | .validate_mem = NULL, | ||
261 | .adjust_io_region = iodyn_adjust_io_region, | ||
262 | .find_io = iodyn_find_io_region, | ||
263 | .find_mem = NULL, | ||
264 | .adjust_resource = NULL, | ||
265 | .init = static_init, | ||
266 | .exit = NULL, | ||
267 | }; | ||
268 | EXPORT_SYMBOL(pccard_iodyn_ops); | ||
269 | |||
270 | #endif /* CONFIG_PCCARD_IODYN */ | ||