Commit fb49fa53 authored by Dominik Brodowski's avatar Dominik Brodowski

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: default avatarWolfram Sang <w.sang@pengutronix.de>
Signed-off-by: default avatarDominik Brodowski <linux@dominikbrodowski.net>
parent cdb13808
...@@ -316,15 +316,9 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on) ...@@ -316,15 +316,9 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on)
{ {
struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
struct pcmcia_device *link = dev->p_dev; struct pcmcia_device *link = dev->p_dev;
modconf_t mod;
int ret;
mod.Attributes = CONF_VPP1_CHANGE_VALID | CONF_VPP2_CHANGE_VALID;
mod.Vcc = 0;
mod.Vpp1 = mod.Vpp2 = on ? dev->vpp : 0;
DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp); DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp);
ret = pcmcia_modify_configuration(link, &mod); pcmcia_fixup_vpp(link, on ? dev->vpp : 0);
} }
......
...@@ -816,13 +816,10 @@ static int check_sig(struct pcmcia_device *link) ...@@ -816,13 +816,10 @@ static int check_sig(struct pcmcia_device *link)
} }
if (width) { if (width) {
modconf_t mod = {
.Attributes = CONF_IO_CHANGE_WIDTH,
};
printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n"); printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n");
smc91c92_suspend(link); smc91c92_suspend(link);
pcmcia_modify_configuration(link, &mod); pcmcia_fixup_iowidth(link);
smc91c92_resume(link); smc91c92_resume(link);
return check_sig(link); return check_sig(link);
} }
......
...@@ -226,92 +226,90 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, struct resource *res, ...@@ -226,92 +226,90 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, struct resource *res,
EXPORT_SYMBOL(pcmcia_map_mem_page); EXPORT_SYMBOL(pcmcia_map_mem_page);
/** pcmcia_modify_configuration /**
* pcmcia_fixup_iowidth() - reduce io width to 8bit
* *
* Modify a locked socket configuration * pcmcia_fixup_iowidth() allows a PCMCIA device driver to reduce the
* IO width to 8bit after having called pcmcia_request_configuration()
* previously.
*/ */
int pcmcia_modify_configuration(struct pcmcia_device *p_dev, int pcmcia_fixup_iowidth(struct pcmcia_device *p_dev)
modconf_t *mod)
{ {
struct pcmcia_socket *s; struct pcmcia_socket *s = p_dev->socket;
config_t *c; pccard_io_map io_off = { 0, 0, 0, 0, 1 };
int ret; pccard_io_map io_on;
int i, ret = 0;
s = p_dev->socket;
mutex_lock(&s->ops_mutex); mutex_lock(&s->ops_mutex);
c = p_dev->function_config;
if (!(s->state & SOCKET_PRESENT)) { dev_dbg(&p_dev->dev, "fixup iowidth to 8bit\n");
dev_dbg(&p_dev->dev, "No card present\n");
ret = -ENODEV; if (!(s->state & SOCKET_PRESENT) ||
goto unlock; !(p_dev->function_config->state & CONFIG_LOCKED)) {
} dev_dbg(&p_dev->dev, "No card? Config not locked?\n");
if (!(c->state & CONFIG_LOCKED)) {
dev_dbg(&p_dev->dev, "Configuration isnt't locked\n");
ret = -EACCES; ret = -EACCES;
goto unlock; goto unlock;
} }
if (mod->Attributes & (CONF_IRQ_CHANGE_VALID | CONF_VCC_CHANGE_VALID)) { io_on.speed = io_speed;
dev_dbg(&p_dev->dev, for (i = 0; i < MAX_IO_WIN; i++) {
"changing Vcc or IRQ is not allowed at this time\n"); if (!s->io[i].res)
ret = -EINVAL; continue;
goto unlock; io_off.map = i;
} io_on.map = i;
/* We only allow changing Vpp1 and Vpp2 to the same value */ io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8;
if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) && io_on.start = s->io[i].res->start;
(mod->Attributes & CONF_VPP2_CHANGE_VALID)) { io_on.stop = s->io[i].res->end;
if (mod->Vpp1 != mod->Vpp2) {
dev_dbg(&p_dev->dev, s->ops->set_io_map(s, &io_off);
"Vpp1 and Vpp2 must be the same\n"); mdelay(40);
ret = -EINVAL; s->ops->set_io_map(s, &io_on);
goto unlock;
}
s->socket.Vpp = mod->Vpp1;
if (s->ops->set_socket(s, &s->socket)) {
dev_printk(KERN_WARNING, &p_dev->dev,
"Unable to set VPP\n");
ret = -EIO;
goto unlock;
}
} else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
(mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
dev_dbg(&p_dev->dev,
"changing Vcc is not allowed at this time\n");
ret = -EINVAL;
goto unlock;
} }
unlock:
mutex_unlock(&s->ops_mutex);
if (mod->Attributes & CONF_IO_CHANGE_WIDTH) { return ret;
pccard_io_map io_off = { 0, 0, 0, 0, 1 }; }
pccard_io_map io_on; EXPORT_SYMBOL(pcmcia_fixup_iowidth);
int i;
io_on.speed = io_speed;
for (i = 0; i < MAX_IO_WIN; i++) {
if (!s->io[i].res)
continue;
io_off.map = i;
io_on.map = i;
io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8; /**
io_on.start = s->io[i].res->start; * pcmcia_fixup_vpp() - set Vpp to a new voltage level
io_on.stop = s->io[i].res->end; *
* pcmcia_fixup_vpp() allows a PCMCIA device driver to set Vpp to
* a new voltage level between calls to pcmcia_request_configuration()
* and pcmcia_disable_device().
*/
int pcmcia_fixup_vpp(struct pcmcia_device *p_dev, unsigned char new_vpp)
{
struct pcmcia_socket *s = p_dev->socket;
int ret = 0;
s->ops->set_io_map(s, &io_off); mutex_lock(&s->ops_mutex);
mdelay(40);
s->ops->set_io_map(s, &io_on); dev_dbg(&p_dev->dev, "fixup Vpp to %d\n", new_vpp);
}
if (!(s->state & SOCKET_PRESENT) ||
!(p_dev->function_config->state & CONFIG_LOCKED)) {
dev_dbg(&p_dev->dev, "No card? Config not locked?\n");
ret = -EACCES;
goto unlock;
} }
ret = 0;
s->socket.Vpp = new_vpp;
if (s->ops->set_socket(s, &s->socket)) {
dev_warn(&p_dev->dev, "Unable to set VPP\n");
ret = -EIO;
goto unlock;
}
unlock: unlock:
mutex_unlock(&s->ops_mutex); mutex_unlock(&s->ops_mutex);
return ret; return ret;
} /* modify_configuration */ }
EXPORT_SYMBOL(pcmcia_modify_configuration); EXPORT_SYMBOL(pcmcia_fixup_vpp);
int pcmcia_release_configuration(struct pcmcia_device *p_dev) int pcmcia_release_configuration(struct pcmcia_device *p_dev)
......
...@@ -19,19 +19,6 @@ ...@@ -19,19 +19,6 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#endif #endif
/* ModifyConfiguration */
typedef struct modconf_t {
u_int Attributes;
u_int Vcc, Vpp1, Vpp2;
} modconf_t;
/* Attributes for ModifyConfiguration */
#define CONF_IRQ_CHANGE_VALID 0x0100
#define CONF_VCC_CHANGE_VALID 0x0200
#define CONF_VPP1_CHANGE_VALID 0x0400
#define CONF_VPP2_CHANGE_VALID 0x0800
#define CONF_IO_CHANGE_WIDTH 0x1000
/* For RequestConfiguration */ /* For RequestConfiguration */
typedef struct config_req_t { typedef struct config_req_t {
u_int Attributes; u_int Attributes;
......
...@@ -212,7 +212,9 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res); ...@@ -212,7 +212,9 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res);
int pcmcia_map_mem_page(struct pcmcia_device *p_dev, struct resource *res, int pcmcia_map_mem_page(struct pcmcia_device *p_dev, struct resource *res,
unsigned int offset); unsigned int offset);
int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod); int pcmcia_fixup_vpp(struct pcmcia_device *p_dev, unsigned char new_vpp);
int pcmcia_fixup_iowidth(struct pcmcia_device *p_dev);
void pcmcia_disable_device(struct pcmcia_device *p_dev); void pcmcia_disable_device(struct pcmcia_device *p_dev);
/* IO ports */ /* IO ports */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment