aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2005-12-07 06:32:20 -0500
committerDominik Brodowski <linux@dominikbrodowski.net>2006-01-05 18:27:43 -0500
commit3b27e9421a1433689704fe0a02e926d4ba971121 (patch)
treec3ca9e3e929da1c48ce5d8e9fa6d0257b5b900f5
parentefe3cd105f2a19e72ce9280bb22c7c80752e4314 (diff)
[PATCH] pcmcia: properly handle static mem, but dynamic io sockets
Some PCMCIA sockets have statically mapped memory windows, but dynamically mapped IO windows. Using the "nonstatic" socket library is inpractical for them, as they do neither need a resource database (as we can trust the kernel resource database on m68k and ppc) nor lots of other features of that library. Let them get a small "iodyn" socket library (105 lines of code) instead. Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
-rw-r--r--drivers/pcmcia/Kconfig5
-rw-r--r--drivers/pcmcia/m8xx_pcmcia.c2
-rw-r--r--drivers/pcmcia/rsrc_mgr.c102
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
182config PCMCIA_M8XX 182config 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
266config PCCARD_NONSTATIC 266config PCCARD_NONSTATIC
267 tristate 267 tristate
268 268
269config PCCARD_IODYN
270 bool
271
269endif # PCCARD 272endif # PCCARD
270 273
271endmenu 274endmenu
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};
168EXPORT_SYMBOL(pccard_static_ops); 168EXPORT_SYMBOL(pccard_static_ops);
169
170
171#ifdef CONFIG_PCCARD_IODYN
172
173static struct resource *
174make_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
187struct pcmcia_align_data {
188 unsigned long mask;
189 unsigned long offset;
190};
191
192static 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
221static 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
228static 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
259struct 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};
268EXPORT_SYMBOL(pccard_iodyn_ops);
269
270#endif /* CONFIG_PCCARD_IODYN */