diff options
author | Dominik Brodowski <linux@dominikbrodowski.net> | 2010-07-30 07:13:46 -0400 |
---|---|---|
committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2010-09-29 11:20:24 -0400 |
commit | 00990e7ce0b0e596fe41d9c64d6933ea70084003 (patch) | |
tree | 189e0dd92860feba84231c66955749574cac5d6d /drivers/ata/pata_pcmcia.c | |
parent | 440eed43e2a95bb842488755683716814da10f2b (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/ata/pata_pcmcia.c')
-rw-r--r-- | drivers/ata/pata_pcmcia.c | 81 |
1 files changed, 26 insertions, 55 deletions
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index 954f43c512f1..88cb03c36963 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c | |||
@@ -167,45 +167,26 @@ static struct ata_port_operations pcmcia_8bit_port_ops = { | |||
167 | }; | 167 | }; |
168 | 168 | ||
169 | 169 | ||
170 | struct pcmcia_config_check { | 170 | static int pcmcia_check_one_config(struct pcmcia_device *pdev, void *priv_data) |
171 | unsigned long ctl_base; | ||
172 | int is_kme; | ||
173 | }; | ||
174 | |||
175 | static int pcmcia_check_one_config(struct pcmcia_device *pdev, | ||
176 | cistpl_cftable_entry_t *cfg, | ||
177 | cistpl_cftable_entry_t *dflt, | ||
178 | void *priv_data) | ||
179 | { | 171 | { |
180 | struct pcmcia_config_check *stk = priv_data; | 172 | int *is_kme = priv_data; |
181 | 173 | ||
182 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | 174 | if (!(pdev->resource[0]->flags & IO_DATA_PATH_WIDTH_8)) { |
183 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | 175 | pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
184 | pdev->io_lines = io->flags & CISTPL_IO_LINES_MASK; | 176 | pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; |
185 | pdev->resource[0]->start = io->win[0].base; | 177 | } |
186 | if (!(io->flags & CISTPL_IO_16BIT)) { | 178 | pdev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH; |
187 | pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; | 179 | pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; |
188 | pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | 180 | |
189 | } | 181 | if (pdev->resource[1]->end) { |
190 | if (io->nwin == 2) { | 182 | pdev->resource[0]->end = 8; |
191 | pdev->resource[0]->end = 8; | 183 | pdev->resource[1]->end = (*is_kme) ? 2 : 1; |
192 | pdev->resource[1]->start = io->win[1].base; | 184 | } else { |
193 | pdev->resource[1]->end = (stk->is_kme) ? 2 : 1; | 185 | if (pdev->resource[0]->end < 16) |
194 | if (pcmcia_request_io(pdev) != 0) | ||
195 | return -ENODEV; | ||
196 | stk->ctl_base = pdev->resource[1]->start; | ||
197 | } else if ((io->nwin == 1) && (io->win[0].len >= 16)) { | ||
198 | pdev->resource[0]->end = io->win[0].len; | ||
199 | pdev->resource[1]->end = 0; | ||
200 | if (pcmcia_request_io(pdev) != 0) | ||
201 | return -ENODEV; | ||
202 | stk->ctl_base = pdev->resource[0]->start + 0x0e; | ||
203 | } else | ||
204 | return -ENODEV; | 186 | return -ENODEV; |
205 | /* If we've got this far, we're done */ | ||
206 | return 0; | ||
207 | } | 187 | } |
208 | return -ENODEV; | 188 | |
189 | return pcmcia_request_io(pdev); | ||
209 | } | 190 | } |
210 | 191 | ||
211 | /** | 192 | /** |
@@ -220,7 +201,6 @@ static int pcmcia_init_one(struct pcmcia_device *pdev) | |||
220 | { | 201 | { |
221 | struct ata_host *host; | 202 | struct ata_host *host; |
222 | struct ata_port *ap; | 203 | struct ata_port *ap; |
223 | struct pcmcia_config_check *stk = NULL; | ||
224 | int is_kme = 0, ret = -ENOMEM, p; | 204 | int is_kme = 0, ret = -ENOMEM, p; |
225 | unsigned long io_base, ctl_base; | 205 | unsigned long io_base, ctl_base; |
226 | void __iomem *io_addr, *ctl_addr; | 206 | void __iomem *io_addr, *ctl_addr; |
@@ -228,10 +208,8 @@ static int pcmcia_init_one(struct pcmcia_device *pdev) | |||
228 | struct ata_port_operations *ops = &pcmcia_port_ops; | 208 | struct ata_port_operations *ops = &pcmcia_port_ops; |
229 | 209 | ||
230 | /* Set up attributes in order to probe card and get resources */ | 210 | /* Set up attributes in order to probe card and get resources */ |
231 | pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; | 211 | pdev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO | |
232 | pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; | 212 | CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC; |
233 | pdev->config_flags |= CONF_ENABLE_IRQ; | ||
234 | pdev->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC; | ||
235 | 213 | ||
236 | /* See if we have a manufacturer identifier. Use it to set is_kme for | 214 | /* See if we have a manufacturer identifier. Use it to set is_kme for |
237 | vendor quirks */ | 215 | vendor quirks */ |
@@ -239,21 +217,17 @@ static int pcmcia_init_one(struct pcmcia_device *pdev) | |||
239 | ((pdev->card_id == PRODID_KME_KXLC005_A) || | 217 | ((pdev->card_id == PRODID_KME_KXLC005_A) || |
240 | (pdev->card_id == PRODID_KME_KXLC005_B))); | 218 | (pdev->card_id == PRODID_KME_KXLC005_B))); |
241 | 219 | ||
242 | /* Allocate resoure probing structures */ | 220 | if (pcmcia_loop_config(pdev, pcmcia_check_one_config, &is_kme)) { |
243 | |||
244 | stk = kzalloc(sizeof(*stk), GFP_KERNEL); | ||
245 | if (!stk) | ||
246 | goto out1; | ||
247 | stk->is_kme = is_kme; | ||
248 | io_base = ctl_base = 0; | ||
249 | |||
250 | if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk)) { | ||
251 | pdev->config_flags &= ~CONF_AUTO_CHECK_VCC; | 221 | pdev->config_flags &= ~CONF_AUTO_CHECK_VCC; |
252 | if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk)) | 222 | if (pcmcia_loop_config(pdev, pcmcia_check_one_config, &is_kme)) |
253 | goto failed; /* No suitable config found */ | 223 | goto failed; /* No suitable config found */ |
254 | } | 224 | } |
255 | io_base = pdev->resource[0]->start; | 225 | io_base = pdev->resource[0]->start; |
256 | ctl_base = stk->ctl_base; | 226 | if (pdev->resource[1]->end) |
227 | ctl_base = pdev->resource[1]->start; | ||
228 | else | ||
229 | ctl_base = pdev->resource[0]->start + 0x0e; | ||
230 | |||
257 | if (!pdev->irq) | 231 | if (!pdev->irq) |
258 | goto failed; | 232 | goto failed; |
259 | 233 | ||
@@ -310,13 +284,10 @@ static int pcmcia_init_one(struct pcmcia_device *pdev) | |||
310 | goto failed; | 284 | goto failed; |
311 | 285 | ||
312 | pdev->priv = host; | 286 | pdev->priv = host; |
313 | kfree(stk); | ||
314 | return 0; | 287 | return 0; |
315 | 288 | ||
316 | failed: | 289 | failed: |
317 | kfree(stk); | ||
318 | pcmcia_disable_device(pdev); | 290 | pcmcia_disable_device(pdev); |
319 | out1: | ||
320 | return ret; | 291 | return ret; |
321 | } | 292 | } |
322 | 293 | ||