diff options
Diffstat (limited to 'drivers/pcmcia/sa11xx_base.c')
-rw-r--r-- | drivers/pcmcia/sa11xx_base.c | 100 |
1 files changed, 64 insertions, 36 deletions
diff --git a/drivers/pcmcia/sa11xx_base.c b/drivers/pcmcia/sa11xx_base.c index e15d59f2d8a9..fa28d8911b00 100644 --- a/drivers/pcmcia/sa11xx_base.c +++ b/drivers/pcmcia/sa11xx_base.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/kernel.h> | 37 | #include <linux/kernel.h> |
38 | #include <linux/spinlock.h> | 38 | #include <linux/spinlock.h> |
39 | #include <linux/io.h> | 39 | #include <linux/io.h> |
40 | #include <linux/slab.h> | ||
40 | 41 | ||
41 | #include <mach/hardware.h> | 42 | #include <mach/hardware.h> |
42 | #include <asm/irq.h> | 43 | #include <asm/irq.h> |
@@ -171,12 +172,58 @@ static const char *skt_names[] = { | |||
171 | #define SKT_DEV_INFO_SIZE(n) \ | 172 | #define SKT_DEV_INFO_SIZE(n) \ |
172 | (sizeof(struct skt_dev_info) + (n)*sizeof(struct soc_pcmcia_socket)) | 173 | (sizeof(struct skt_dev_info) + (n)*sizeof(struct soc_pcmcia_socket)) |
173 | 174 | ||
175 | int sa11xx_drv_pcmcia_add_one(struct soc_pcmcia_socket *skt) | ||
176 | { | ||
177 | skt->res_skt.start = _PCMCIA(skt->nr); | ||
178 | skt->res_skt.end = _PCMCIA(skt->nr) + PCMCIASp - 1; | ||
179 | skt->res_skt.name = skt_names[skt->nr]; | ||
180 | skt->res_skt.flags = IORESOURCE_MEM; | ||
181 | |||
182 | skt->res_io.start = _PCMCIAIO(skt->nr); | ||
183 | skt->res_io.end = _PCMCIAIO(skt->nr) + PCMCIAIOSp - 1; | ||
184 | skt->res_io.name = "io"; | ||
185 | skt->res_io.flags = IORESOURCE_MEM | IORESOURCE_BUSY; | ||
186 | |||
187 | skt->res_mem.start = _PCMCIAMem(skt->nr); | ||
188 | skt->res_mem.end = _PCMCIAMem(skt->nr) + PCMCIAMemSp - 1; | ||
189 | skt->res_mem.name = "memory"; | ||
190 | skt->res_mem.flags = IORESOURCE_MEM; | ||
191 | |||
192 | skt->res_attr.start = _PCMCIAAttr(skt->nr); | ||
193 | skt->res_attr.end = _PCMCIAAttr(skt->nr) + PCMCIAAttrSp - 1; | ||
194 | skt->res_attr.name = "attribute"; | ||
195 | skt->res_attr.flags = IORESOURCE_MEM; | ||
196 | |||
197 | return soc_pcmcia_add_one(skt); | ||
198 | } | ||
199 | EXPORT_SYMBOL(sa11xx_drv_pcmcia_add_one); | ||
200 | |||
201 | void sa11xx_drv_pcmcia_ops(struct pcmcia_low_level *ops) | ||
202 | { | ||
203 | /* | ||
204 | * set default MECR calculation if the board specific | ||
205 | * code did not specify one... | ||
206 | */ | ||
207 | if (!ops->get_timing) | ||
208 | ops->get_timing = sa1100_pcmcia_default_mecr_timing; | ||
209 | |||
210 | /* Provide our SA11x0 specific timing routines. */ | ||
211 | ops->set_timing = sa1100_pcmcia_set_timing; | ||
212 | ops->show_timing = sa1100_pcmcia_show_timing; | ||
213 | #ifdef CONFIG_CPU_FREQ | ||
214 | ops->frequency_change = sa1100_pcmcia_frequency_change; | ||
215 | #endif | ||
216 | } | ||
217 | EXPORT_SYMBOL(sa11xx_drv_pcmcia_ops); | ||
218 | |||
174 | int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, | 219 | int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, |
175 | int first, int nr) | 220 | int first, int nr) |
176 | { | 221 | { |
177 | struct skt_dev_info *sinfo; | 222 | struct skt_dev_info *sinfo; |
178 | struct soc_pcmcia_socket *skt; | 223 | struct soc_pcmcia_socket *skt; |
179 | int i; | 224 | int i, ret = 0; |
225 | |||
226 | sa11xx_drv_pcmcia_ops(ops); | ||
180 | 227 | ||
181 | sinfo = kzalloc(SKT_DEV_INFO_SIZE(nr), GFP_KERNEL); | 228 | sinfo = kzalloc(SKT_DEV_INFO_SIZE(nr), GFP_KERNEL); |
182 | if (!sinfo) | 229 | if (!sinfo) |
@@ -188,45 +235,26 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, | |||
188 | for (i = 0; i < nr; i++) { | 235 | for (i = 0; i < nr; i++) { |
189 | skt = &sinfo->skt[i]; | 236 | skt = &sinfo->skt[i]; |
190 | 237 | ||
191 | skt->nr = first + i; | 238 | skt->nr = first + i; |
192 | skt->irq = NO_IRQ; | 239 | skt->ops = ops; |
193 | 240 | skt->socket.owner = ops->owner; | |
194 | skt->res_skt.start = _PCMCIA(skt->nr); | 241 | skt->socket.dev.parent = dev; |
195 | skt->res_skt.end = _PCMCIA(skt->nr) + PCMCIASp - 1; | 242 | skt->socket.pci_irq = NO_IRQ; |
196 | skt->res_skt.name = skt_names[skt->nr]; | ||
197 | skt->res_skt.flags = IORESOURCE_MEM; | ||
198 | |||
199 | skt->res_io.start = _PCMCIAIO(skt->nr); | ||
200 | skt->res_io.end = _PCMCIAIO(skt->nr) + PCMCIAIOSp - 1; | ||
201 | skt->res_io.name = "io"; | ||
202 | skt->res_io.flags = IORESOURCE_MEM | IORESOURCE_BUSY; | ||
203 | 243 | ||
204 | skt->res_mem.start = _PCMCIAMem(skt->nr); | 244 | ret = sa11xx_drv_pcmcia_add_one(skt); |
205 | skt->res_mem.end = _PCMCIAMem(skt->nr) + PCMCIAMemSp - 1; | 245 | if (ret) |
206 | skt->res_mem.name = "memory"; | 246 | break; |
207 | skt->res_mem.flags = IORESOURCE_MEM; | ||
208 | |||
209 | skt->res_attr.start = _PCMCIAAttr(skt->nr); | ||
210 | skt->res_attr.end = _PCMCIAAttr(skt->nr) + PCMCIAAttrSp - 1; | ||
211 | skt->res_attr.name = "attribute"; | ||
212 | skt->res_attr.flags = IORESOURCE_MEM; | ||
213 | } | 247 | } |
214 | 248 | ||
215 | /* | 249 | if (ret) { |
216 | * set default MECR calculation if the board specific | 250 | while (--i >= 0) |
217 | * code did not specify one... | 251 | soc_pcmcia_remove_one(&sinfo->skt[i]); |
218 | */ | 252 | kfree(sinfo); |
219 | if (!ops->get_timing) | 253 | } else { |
220 | ops->get_timing = sa1100_pcmcia_default_mecr_timing; | 254 | dev_set_drvdata(dev, sinfo); |
221 | 255 | } | |
222 | /* Provide our SA11x0 specific timing routines. */ | ||
223 | ops->set_timing = sa1100_pcmcia_set_timing; | ||
224 | ops->show_timing = sa1100_pcmcia_show_timing; | ||
225 | #ifdef CONFIG_CPU_FREQ | ||
226 | ops->frequency_change = sa1100_pcmcia_frequency_change; | ||
227 | #endif | ||
228 | 256 | ||
229 | return soc_common_drv_pcmcia_probe(dev, ops, sinfo); | 257 | return ret; |
230 | } | 258 | } |
231 | EXPORT_SYMBOL(sa11xx_drv_pcmcia_probe); | 259 | EXPORT_SYMBOL(sa11xx_drv_pcmcia_probe); |
232 | 260 | ||