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