aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia
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 /drivers/pcmcia
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>
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r--drivers/pcmcia/pcmcia_resource.c128
1 files changed, 63 insertions, 65 deletions
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)