diff options
| author | Dominik Brodowski <linux@dominikbrodowski.net> | 2010-07-29 08:06:42 -0400 |
|---|---|---|
| committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2010-09-29 11:20:21 -0400 |
| commit | fb49fa533f9d211994c33efb752ffa5b30033729 (patch) | |
| tree | 675d26cf01c23d9623f274971a065b0dedb10f3a | |
| parent | cdb138080b78146d1cdadba9f5dadbeb97445b91 (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.c | 8 | ||||
| -rw-r--r-- | drivers/net/pcmcia/smc91c92_cs.c | 5 | ||||
| -rw-r--r-- | drivers/pcmcia/pcmcia_resource.c | 128 | ||||
| -rw-r--r-- | include/pcmcia/cs.h | 13 | ||||
| -rw-r--r-- | include/pcmcia/ds.h | 4 |
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, | |||
| 226 | EXPORT_SYMBOL(pcmcia_map_mem_page); | 226 | EXPORT_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 | */ |
| 233 | int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | 236 | int 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 | } |
| 269 | unlock: | ||
| 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; | 274 | EXPORT_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 | */ | ||
| 284 | int 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 | |||
| 309 | unlock: | 307 | unlock: |
| 310 | mutex_unlock(&s->ops_mutex); | 308 | mutex_unlock(&s->ops_mutex); |
| 311 | 309 | ||
| 312 | return ret; | 310 | return ret; |
| 313 | } /* modify_configuration */ | 311 | } |
| 314 | EXPORT_SYMBOL(pcmcia_modify_configuration); | 312 | EXPORT_SYMBOL(pcmcia_fixup_vpp); |
| 315 | 313 | ||
| 316 | 314 | ||
| 317 | int pcmcia_release_configuration(struct pcmcia_device *p_dev) | 315 | int 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 */ | ||
| 23 | typedef 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 */ |
| 36 | typedef struct config_req_t { | 23 | typedef 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); | |||
| 212 | int pcmcia_map_mem_page(struct pcmcia_device *p_dev, struct resource *res, | 212 | int pcmcia_map_mem_page(struct pcmcia_device *p_dev, struct resource *res, |
| 213 | unsigned int offset); | 213 | unsigned int offset); |
| 214 | 214 | ||
| 215 | int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod); | 215 | int pcmcia_fixup_vpp(struct pcmcia_device *p_dev, unsigned char new_vpp); |
| 216 | int pcmcia_fixup_iowidth(struct pcmcia_device *p_dev); | ||
| 217 | |||
| 216 | void pcmcia_disable_device(struct pcmcia_device *p_dev); | 218 | void pcmcia_disable_device(struct pcmcia_device *p_dev); |
| 217 | 219 | ||
| 218 | /* IO ports */ | 220 | /* IO ports */ |
