aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2010-07-29 08:06:42 -0400
committerDominik Brodowski <linux@dominikbrodowski.net>2010-09-29 11:20:21 -0400
commitfb49fa533f9d211994c33efb752ffa5b30033729 (patch)
tree675d26cf01c23d9623f274971a065b0dedb10f3a
parentcdb138080b78146d1cdadba9f5dadbeb97445b91 (diff)
pcmcia: split up modify_configuration() into two fixup functions
pcmcia_modify_configuration() was only used by two drivers to fix up one issue each: setting the Vpp to a different value, and reducing the IO width to 8 bit. Introduce two explicitly named functions handling these things, and remove one further typedef. CC: netdev@vger.kernel.org CC: linux-mtd@lists.infradead.org Tested-by: Wolfram Sang <w.sang@pengutronix.de> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
-rw-r--r--drivers/mtd/maps/pcmciamtd.c8
-rw-r--r--drivers/net/pcmcia/smc91c92_cs.c5
-rw-r--r--drivers/pcmcia/pcmcia_resource.c128
-rw-r--r--include/pcmcia/cs.h13
-rw-r--r--include/pcmcia/ds.h4
5 files changed, 68 insertions, 90 deletions
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index fb3c5380aa84..31ce404baa3c 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -316,15 +316,9 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on)
316{ 316{
317 struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; 317 struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
318 struct pcmcia_device *link = dev->p_dev; 318 struct pcmcia_device *link = dev->p_dev;
319 modconf_t mod;
320 int ret;
321
322 mod.Attributes = CONF_VPP1_CHANGE_VALID | CONF_VPP2_CHANGE_VALID;
323 mod.Vcc = 0;
324 mod.Vpp1 = mod.Vpp2 = on ? dev->vpp : 0;
325 319
326 DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp); 320 DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp);
327 ret = pcmcia_modify_configuration(link, &mod); 321 pcmcia_fixup_vpp(link, on ? dev->vpp : 0);
328} 322}
329 323
330 324
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index acc680739c89..395e586d7c0a 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -816,13 +816,10 @@ static int check_sig(struct pcmcia_device *link)
816 } 816 }
817 817
818 if (width) { 818 if (width) {
819 modconf_t mod = {
820 .Attributes = CONF_IO_CHANGE_WIDTH,
821 };
822 printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n"); 819 printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n");
823 820
824 smc91c92_suspend(link); 821 smc91c92_suspend(link);
825 pcmcia_modify_configuration(link, &mod); 822 pcmcia_fixup_iowidth(link);
826 smc91c92_resume(link); 823 smc91c92_resume(link);
827 return check_sig(link); 824 return check_sig(link);
828 } 825 }
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index bf16a1cf7399..14b1a951e1b6 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -226,92 +226,90 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, struct resource *res,
226EXPORT_SYMBOL(pcmcia_map_mem_page); 226EXPORT_SYMBOL(pcmcia_map_mem_page);
227 227
228 228
229/** pcmcia_modify_configuration 229/**
230 * pcmcia_fixup_iowidth() - reduce io width to 8bit
230 * 231 *
231 * Modify a locked socket configuration 232 * pcmcia_fixup_iowidth() allows a PCMCIA device driver to reduce the
233 * IO width to 8bit after having called pcmcia_request_configuration()
234 * previously.
232 */ 235 */
233int pcmcia_modify_configuration(struct pcmcia_device *p_dev, 236int pcmcia_fixup_iowidth(struct pcmcia_device *p_dev)
234 modconf_t *mod)
235{ 237{
236 struct pcmcia_socket *s; 238 struct pcmcia_socket *s = p_dev->socket;
237 config_t *c; 239 pccard_io_map io_off = { 0, 0, 0, 0, 1 };
238 int ret; 240 pccard_io_map io_on;
239 241 int i, ret = 0;
240 s = p_dev->socket;
241 242
242 mutex_lock(&s->ops_mutex); 243 mutex_lock(&s->ops_mutex);
243 c = p_dev->function_config;
244 244
245 if (!(s->state & SOCKET_PRESENT)) { 245 dev_dbg(&p_dev->dev, "fixup iowidth to 8bit\n");
246 dev_dbg(&p_dev->dev, "No card present\n"); 246
247 ret = -ENODEV; 247 if (!(s->state & SOCKET_PRESENT) ||
248 goto unlock; 248 !(p_dev->function_config->state & CONFIG_LOCKED)) {
249 } 249 dev_dbg(&p_dev->dev, "No card? Config not locked?\n");
250 if (!(c->state & CONFIG_LOCKED)) {
251 dev_dbg(&p_dev->dev, "Configuration isnt't locked\n");
252 ret = -EACCES; 250 ret = -EACCES;
253 goto unlock; 251 goto unlock;
254 } 252 }
255 253
256 if (mod->Attributes & (CONF_IRQ_CHANGE_VALID | CONF_VCC_CHANGE_VALID)) { 254 io_on.speed = io_speed;
257 dev_dbg(&p_dev->dev, 255 for (i = 0; i < MAX_IO_WIN; i++) {
258 "changing Vcc or IRQ is not allowed at this time\n"); 256 if (!s->io[i].res)
259 ret = -EINVAL; 257 continue;
260 goto unlock; 258 io_off.map = i;
261 } 259 io_on.map = i;
262 260
263 /* We only allow changing Vpp1 and Vpp2 to the same value */ 261 io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8;
264 if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) && 262 io_on.start = s->io[i].res->start;
265 (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { 263 io_on.stop = s->io[i].res->end;
266 if (mod->Vpp1 != mod->Vpp2) { 264
267 dev_dbg(&p_dev->dev, 265 s->ops->set_io_map(s, &io_off);
268 "Vpp1 and Vpp2 must be the same\n"); 266 mdelay(40);
269 ret = -EINVAL; 267 s->ops->set_io_map(s, &io_on);
270 goto unlock;
271 }
272 s->socket.Vpp = mod->Vpp1;
273 if (s->ops->set_socket(s, &s->socket)) {
274 dev_printk(KERN_WARNING, &p_dev->dev,
275 "Unable to set VPP\n");
276 ret = -EIO;
277 goto unlock;
278 }
279 } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
280 (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
281 dev_dbg(&p_dev->dev,
282 "changing Vcc is not allowed at this time\n");
283 ret = -EINVAL;
284 goto unlock;
285 } 268 }
269unlock:
270 mutex_unlock(&s->ops_mutex);
286 271
287 if (mod->Attributes & CONF_IO_CHANGE_WIDTH) { 272 return ret;
288 pccard_io_map io_off = { 0, 0, 0, 0, 1 }; 273}
289 pccard_io_map io_on; 274EXPORT_SYMBOL(pcmcia_fixup_iowidth);
290 int i;
291 275
292 io_on.speed = io_speed;
293 for (i = 0; i < MAX_IO_WIN; i++) {
294 if (!s->io[i].res)
295 continue;
296 io_off.map = i;
297 io_on.map = i;
298 276
299 io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8; 277/**
300 io_on.start = s->io[i].res->start; 278 * pcmcia_fixup_vpp() - set Vpp to a new voltage level
301 io_on.stop = s->io[i].res->end; 279 *
280 * pcmcia_fixup_vpp() allows a PCMCIA device driver to set Vpp to
281 * a new voltage level between calls to pcmcia_request_configuration()
282 * and pcmcia_disable_device().
283 */
284int pcmcia_fixup_vpp(struct pcmcia_device *p_dev, unsigned char new_vpp)
285{
286 struct pcmcia_socket *s = p_dev->socket;
287 int ret = 0;
302 288
303 s->ops->set_io_map(s, &io_off); 289 mutex_lock(&s->ops_mutex);
304 mdelay(40); 290
305 s->ops->set_io_map(s, &io_on); 291 dev_dbg(&p_dev->dev, "fixup Vpp to %d\n", new_vpp);
306 } 292
293 if (!(s->state & SOCKET_PRESENT) ||
294 !(p_dev->function_config->state & CONFIG_LOCKED)) {
295 dev_dbg(&p_dev->dev, "No card? Config not locked?\n");
296 ret = -EACCES;
297 goto unlock;
307 } 298 }
308 ret = 0; 299
300 s->socket.Vpp = new_vpp;
301 if (s->ops->set_socket(s, &s->socket)) {
302 dev_warn(&p_dev->dev, "Unable to set VPP\n");
303 ret = -EIO;
304 goto unlock;
305 }
306
309unlock: 307unlock:
310 mutex_unlock(&s->ops_mutex); 308 mutex_unlock(&s->ops_mutex);
311 309
312 return ret; 310 return ret;
313} /* modify_configuration */ 311}
314EXPORT_SYMBOL(pcmcia_modify_configuration); 312EXPORT_SYMBOL(pcmcia_fixup_vpp);
315 313
316 314
317int pcmcia_release_configuration(struct pcmcia_device *p_dev) 315int pcmcia_release_configuration(struct pcmcia_device *p_dev)
diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h
index 63cb9bbe390e..e13d0cd3f8f7 100644
--- a/include/pcmcia/cs.h
+++ b/include/pcmcia/cs.h
@@ -19,19 +19,6 @@
19#include <linux/interrupt.h> 19#include <linux/interrupt.h>
20#endif 20#endif
21 21
22/* ModifyConfiguration */
23typedef struct modconf_t {
24 u_int Attributes;
25 u_int Vcc, Vpp1, Vpp2;
26} modconf_t;
27
28/* Attributes for ModifyConfiguration */
29#define CONF_IRQ_CHANGE_VALID 0x0100
30#define CONF_VCC_CHANGE_VALID 0x0200
31#define CONF_VPP1_CHANGE_VALID 0x0400
32#define CONF_VPP2_CHANGE_VALID 0x0800
33#define CONF_IO_CHANGE_WIDTH 0x1000
34
35/* For RequestConfiguration */ 22/* For RequestConfiguration */
36typedef struct config_req_t { 23typedef struct config_req_t {
37 u_int Attributes; 24 u_int Attributes;
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index 6f7cb38d8850..8e307b93f47b 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -212,7 +212,9 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res);
212int pcmcia_map_mem_page(struct pcmcia_device *p_dev, struct resource *res, 212int pcmcia_map_mem_page(struct pcmcia_device *p_dev, struct resource *res,
213 unsigned int offset); 213 unsigned int offset);
214 214
215int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod); 215int pcmcia_fixup_vpp(struct pcmcia_device *p_dev, unsigned char new_vpp);
216int pcmcia_fixup_iowidth(struct pcmcia_device *p_dev);
217
216void pcmcia_disable_device(struct pcmcia_device *p_dev); 218void pcmcia_disable_device(struct pcmcia_device *p_dev);
217 219
218/* IO ports */ 220/* IO ports */