aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2010-07-30 07:13:46 -0400
committerDominik Brodowski <linux@dominikbrodowski.net>2010-09-29 11:20:24 -0400
commit00990e7ce0b0e596fe41d9c64d6933ea70084003 (patch)
tree189e0dd92860feba84231c66955749574cac5d6d /drivers/pcmcia
parent440eed43e2a95bb842488755683716814da10f2b (diff)
pcmcia: use autoconfiguration feature for ioports and iomem
When CONF_AUTO_SET_IO or CONF_AUTO_SET_IOMEM are set, the corresponding fields in struct pcmcia_device *p_dev->resource[0,1,2] are set accordinly. Drivers wishing to override certain settings may do so in the callback function, but they no longer need to parse the CIS entries stored in cistpl_cftable_entry_t themselves. CC: netdev@vger.kernel.org CC: linux-wireless@vger.kernel.org CC: linux-ide@vger.kernel.org CC: linux-usb@vger.kernel.org CC: laforge@gnumonks.org CC: linux-mtd@lists.infradead.org CC: linux-bluetooth@vger.kernel.org CC: alsa-devel@alsa-project.org CC: linux-serial@vger.kernel.org CC: Jiri Kosina <jkosina@suse.cz> CC: linux-scsi@vger.kernel.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_cis.c78
1 files changed, 67 insertions, 11 deletions
diff --git a/drivers/pcmcia/pcmcia_cis.c b/drivers/pcmcia/pcmcia_cis.c
index 160da0697335..e2c92415b892 100644
--- a/drivers/pcmcia/pcmcia_cis.c
+++ b/drivers/pcmcia/pcmcia_cis.c
@@ -6,7 +6,7 @@
6 * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. 6 * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
7 * 7 *
8 * Copyright (C) 1999 David A. Hinds 8 * Copyright (C) 1999 David A. Hinds
9 * Copyright (C) 2004-2009 Dominik Brodowski 9 * Copyright (C) 2004-2010 Dominik Brodowski
10 * 10 *
11 * This program is free software; you can redistribute it and/or modify 11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as 12 * it under the terms of the GNU General Public License version 2 as
@@ -125,13 +125,24 @@ next_entry:
125 return ret; 125 return ret;
126} 126}
127 127
128
129/**
130 * pcmcia_io_cfg_data_width() - convert cfgtable to data path width parameter
131 */
132static int pcmcia_io_cfg_data_width(unsigned int flags)
133{
134 if (!(flags & CISTPL_IO_8BIT))
135 return IO_DATA_PATH_WIDTH_16;
136 if (!(flags & CISTPL_IO_16BIT))
137 return IO_DATA_PATH_WIDTH_8;
138 return IO_DATA_PATH_WIDTH_AUTO;
139}
140
141
128struct pcmcia_cfg_mem { 142struct pcmcia_cfg_mem {
129 struct pcmcia_device *p_dev; 143 struct pcmcia_device *p_dev;
144 int (*conf_check) (struct pcmcia_device *p_dev, void *priv_data);
130 void *priv_data; 145 void *priv_data;
131 int (*conf_check) (struct pcmcia_device *p_dev,
132 cistpl_cftable_entry_t *cfg,
133 cistpl_cftable_entry_t *dflt,
134 void *priv_data);
135 cisparse_t parse; 146 cisparse_t parse;
136 cistpl_cftable_entry_t dflt; 147 cistpl_cftable_entry_t dflt;
137}; 148};
@@ -184,16 +195,63 @@ static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv)
184 if ((flags & CONF_AUTO_AUDIO) && (cfg->flags & CISTPL_CFTABLE_AUDIO)) 195 if ((flags & CONF_AUTO_AUDIO) && (cfg->flags & CISTPL_CFTABLE_AUDIO))
185 p_dev->config_flags |= CONF_ENABLE_SPKR; 196 p_dev->config_flags |= CONF_ENABLE_SPKR;
186 197
187 return cfg_mem->conf_check(cfg_mem->p_dev, cfg, &cfg_mem->dflt, 198
188 cfg_mem->priv_data); 199 /* IO window settings? */
200 if (flags & CONF_AUTO_SET_IO) {
201 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
202 int i = 0;
203
204 p_dev->resource[0]->start = p_dev->resource[0]->end = 0;
205 p_dev->resource[1]->start = p_dev->resource[1]->end = 0;
206 if (io->nwin == 0)
207 return -ENODEV;
208
209 p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
210 p_dev->resource[0]->flags |=
211 pcmcia_io_cfg_data_width(io->flags);
212 if (io->nwin > 1) {
213 /* For multifunction cards, by convention, we
214 * configure the network function with window 0,
215 * and serial with window 1 */
216 i = (io->win[1].len > io->win[0].len);
217 p_dev->resource[1]->flags = p_dev->resource[0]->flags;
218 p_dev->resource[1]->start = io->win[1-i].base;
219 p_dev->resource[1]->end = io->win[1-i].len;
220 }
221 p_dev->resource[0]->start = io->win[i].base;
222 p_dev->resource[0]->end = io->win[i].len;
223 p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
224 }
225
226 /* MEM window settings? */
227 if (flags & CONF_AUTO_SET_IOMEM) {
228 /* so far, we only set one memory window */
229 cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
230
231 p_dev->resource[2]->start = p_dev->resource[2]->end = 0;
232 if (mem->nwin == 0)
233 return -ENODEV;
234
235 p_dev->resource[2]->start = mem->win[0].host_addr;
236 p_dev->resource[2]->end = mem->win[0].len;
237 if (p_dev->resource[2]->end < 0x1000)
238 p_dev->resource[2]->end = 0x1000;
239 p_dev->card_addr = mem->win[0].card_addr;
240 }
241
242 dev_dbg(&p_dev->dev,
243 "checking configuration %x: %pr %pr %pr (%d lines)\n",
244 p_dev->config_index, p_dev->resource[0], p_dev->resource[1],
245 p_dev->resource[2], p_dev->io_lines);
246
247 return cfg_mem->conf_check(p_dev, cfg_mem->priv_data);
189} 248}
190 249
191/** 250/**
192 * pcmcia_loop_config() - loop over configuration options 251 * pcmcia_loop_config() - loop over configuration options
193 * @p_dev: the struct pcmcia_device which we need to loop for. 252 * @p_dev: the struct pcmcia_device which we need to loop for.
194 * @conf_check: function to call for each configuration option. 253 * @conf_check: function to call for each configuration option.
195 * It gets passed the struct pcmcia_device, the CIS data 254 * It gets passed the struct pcmcia_device and private data
196 * describing the configuration option, and private data
197 * being passed to pcmcia_loop_config() 255 * being passed to pcmcia_loop_config()
198 * @priv_data: private data to be passed to the conf_check function. 256 * @priv_data: private data to be passed to the conf_check function.
199 * 257 *
@@ -203,8 +261,6 @@ static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv)
203 */ 261 */
204int pcmcia_loop_config(struct pcmcia_device *p_dev, 262int pcmcia_loop_config(struct pcmcia_device *p_dev,
205 int (*conf_check) (struct pcmcia_device *p_dev, 263 int (*conf_check) (struct pcmcia_device *p_dev,
206 cistpl_cftable_entry_t *cfg,
207 cistpl_cftable_entry_t *dflt,
208 void *priv_data), 264 void *priv_data),
209 void *priv_data) 265 void *priv_data)
210{ 266{