aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/sl811_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/sl811_cs.c')
-rw-r--r--drivers/usb/host/sl811_cs.c130
1 files changed, 53 insertions, 77 deletions
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index 5da63f53500..ca733b7caea 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -155,97 +155,72 @@ static void sl811_cs_release(struct pcmcia_device * link)
155 platform_device_unregister(&platform_dev); 155 platform_device_unregister(&platform_dev);
156} 156}
157 157
158static int sl811_cs_config_check(struct pcmcia_device *p_dev,
159 cistpl_cftable_entry_t *cfg,
160 cistpl_cftable_entry_t *dflt,
161 unsigned int vcc,
162 void *priv_data)
163{
164 if (cfg->index == 0)
165 return -ENODEV;
166
167 /* Use power settings for Vcc and Vpp if present */
168 /* Note that the CIS values need to be rescaled */
169 if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
170 if (cfg->vcc.param[CISTPL_POWER_VNOM]/10000 != vcc)
171 return -ENODEV;
172 } else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) {
173 if (dflt->vcc.param[CISTPL_POWER_VNOM]/10000 != vcc)
174 return -ENODEV;
175 }
176
177 if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
178 p_dev->conf.Vpp =
179 cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
180 else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
181 p_dev->conf.Vpp =
182 dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
183
184 /* we need an interrupt */
185 if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1)
186 p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
187
188 /* IO window settings */
189 p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
190 if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
191 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
192
193 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
194 p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
195 p_dev->io.BasePort1 = io->win[0].base;
196 p_dev->io.NumPorts1 = io->win[0].len;
197
198 return pcmcia_request_io(p_dev, &p_dev->io);
199 }
200 pcmcia_disable_device(p_dev);
201 return -ENODEV;
202}
203
204
158static int sl811_cs_config(struct pcmcia_device *link) 205static int sl811_cs_config(struct pcmcia_device *link)
159{ 206{
160 struct device *parent = &handle_to_dev(link); 207 struct device *parent = &handle_to_dev(link);
161 local_info_t *dev = link->priv; 208 local_info_t *dev = link->priv;
162 tuple_t tuple;
163 cisparse_t parse;
164 int last_fn, last_ret; 209 int last_fn, last_ret;
165 u_char buf[64];
166 config_info_t conf;
167 cistpl_cftable_entry_t dflt = { 0 };
168 210
169 DBG(0, "sl811_cs_config(0x%p)\n", link); 211 DBG(0, "sl811_cs_config(0x%p)\n", link);
170 212
171 /* Look up the current Vcc */ 213 if (pcmcia_loop_config(link, sl811_cs_config_check, NULL))
172 CS_CHECK(GetConfigurationInfo, 214 goto failed;
173 pcmcia_get_configuration_info(link, &conf));
174
175 tuple.Attributes = 0;
176 tuple.TupleData = buf;
177 tuple.TupleDataMax = sizeof(buf);
178 tuple.TupleOffset = 0;
179 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
180 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
181 while (1) {
182 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
183
184 if (pcmcia_get_tuple_data(link, &tuple) != 0
185 || pcmcia_parse_tuple(link, &tuple, &parse)
186 != 0)
187 goto next_entry;
188
189 if (cfg->flags & CISTPL_CFTABLE_DEFAULT) {
190 dflt = *cfg;
191 }
192
193 if (cfg->index == 0)
194 goto next_entry;
195
196 link->conf.ConfigIndex = cfg->index;
197
198 /* Use power settings for Vcc and Vpp if present */
199 /* Note that the CIS values need to be rescaled */
200 if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
201 if (cfg->vcc.param[CISTPL_POWER_VNOM]/10000
202 != conf.Vcc)
203 goto next_entry;
204 } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
205 if (dflt.vcc.param[CISTPL_POWER_VNOM]/10000
206 != conf.Vcc)
207 goto next_entry;
208 }
209
210 if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
211 link->conf.Vpp =
212 cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
213 else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
214 link->conf.Vpp =
215 dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
216
217 /* we need an interrupt */
218 if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
219 link->conf.Attributes |= CONF_ENABLE_IRQ;
220
221 /* IO window settings */
222 link->io.NumPorts1 = link->io.NumPorts2 = 0;
223 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
224 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
225
226 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
227 link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
228 link->io.BasePort1 = io->win[0].base;
229 link->io.NumPorts1 = io->win[0].len;
230
231 if (pcmcia_request_io(link, &link->io) != 0)
232 goto next_entry;
233 }
234 break;
235
236next_entry:
237 pcmcia_disable_device(link);
238 last_ret = pcmcia_get_next_tuple(link, &tuple);
239 }
240 215
241 /* require an IRQ and two registers */ 216 /* require an IRQ and two registers */
242 if (!link->io.NumPorts1 || link->io.NumPorts1 < 2) 217 if (!link->io.NumPorts1 || link->io.NumPorts1 < 2)
243 goto cs_failed; 218 goto failed;
244 if (link->conf.Attributes & CONF_ENABLE_IRQ) 219 if (link->conf.Attributes & CONF_ENABLE_IRQ)
245 CS_CHECK(RequestIRQ, 220 CS_CHECK(RequestIRQ,
246 pcmcia_request_irq(link, &link->irq)); 221 pcmcia_request_irq(link, &link->irq));
247 else 222 else
248 goto cs_failed; 223 goto failed;
249 224
250 CS_CHECK(RequestConfiguration, 225 CS_CHECK(RequestConfiguration,
251 pcmcia_request_configuration(link, &link->conf)); 226 pcmcia_request_configuration(link, &link->conf));
@@ -266,8 +241,9 @@ next_entry:
266 if (sl811_hc_init(parent, link->io.BasePort1, link->irq.AssignedIRQ) 241 if (sl811_hc_init(parent, link->io.BasePort1, link->irq.AssignedIRQ)
267 < 0) { 242 < 0) {
268cs_failed: 243cs_failed:
269 printk("sl811_cs_config failed\n");
270 cs_error(link, last_fn, last_ret); 244 cs_error(link, last_fn, last_ret);
245failed:
246 printk(KERN_WARNING "sl811_cs_config failed\n");
271 sl811_cs_release(link); 247 sl811_cs_release(link);
272 return -ENODEV; 248 return -ENODEV;
273 } 249 }