diff options
-rw-r--r-- | drivers/ata/pata_platform.c | 144 | ||||
-rw-r--r-- | include/linux/pata_platform.h | 9 |
2 files changed, 95 insertions, 58 deletions
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c index ac03a90a6168..224bb6c2030a 100644 --- a/drivers/ata/pata_platform.c +++ b/drivers/ata/pata_platform.c | |||
@@ -93,14 +93,9 @@ static struct ata_port_operations pata_platform_port_ops = { | |||
93 | }; | 93 | }; |
94 | 94 | ||
95 | static void pata_platform_setup_port(struct ata_ioports *ioaddr, | 95 | static void pata_platform_setup_port(struct ata_ioports *ioaddr, |
96 | struct pata_platform_info *info) | 96 | unsigned int shift) |
97 | { | 97 | { |
98 | unsigned int shift = 0; | ||
99 | |||
100 | /* Fixup the port shift for platforms that need it */ | 98 | /* Fixup the port shift for platforms that need it */ |
101 | if (info && info->ioport_shift) | ||
102 | shift = info->ioport_shift; | ||
103 | |||
104 | ioaddr->data_addr = ioaddr->cmd_addr + (ATA_REG_DATA << shift); | 99 | ioaddr->data_addr = ioaddr->cmd_addr + (ATA_REG_DATA << shift); |
105 | ioaddr->error_addr = ioaddr->cmd_addr + (ATA_REG_ERR << shift); | 100 | ioaddr->error_addr = ioaddr->cmd_addr + (ATA_REG_ERR << shift); |
106 | ioaddr->feature_addr = ioaddr->cmd_addr + (ATA_REG_FEATURE << shift); | 101 | ioaddr->feature_addr = ioaddr->cmd_addr + (ATA_REG_FEATURE << shift); |
@@ -114,8 +109,13 @@ static void pata_platform_setup_port(struct ata_ioports *ioaddr, | |||
114 | } | 109 | } |
115 | 110 | ||
116 | /** | 111 | /** |
117 | * pata_platform_probe - attach a platform interface | 112 | * __pata_platform_probe - attach a platform interface |
118 | * @pdev: platform device | 113 | * @dev: device |
114 | * @io_res: Resource representing I/O base | ||
115 | * @ctl_res: Resource representing CTL base | ||
116 | * @irq_res: Resource representing IRQ and its flags | ||
117 | * @ioport_shift: I/O port shift | ||
118 | * @__pio_mask: PIO mask | ||
119 | * | 119 | * |
120 | * Register a platform bus IDE interface. Such interfaces are PIO and we | 120 | * Register a platform bus IDE interface. Such interfaces are PIO and we |
121 | * assume do not support IRQ sharing. | 121 | * assume do not support IRQ sharing. |
@@ -135,42 +135,18 @@ static void pata_platform_setup_port(struct ata_ioports *ioaddr, | |||
135 | * | 135 | * |
136 | * If no IRQ resource is present, PIO polling mode is used instead. | 136 | * If no IRQ resource is present, PIO polling mode is used instead. |
137 | */ | 137 | */ |
138 | static int __devinit pata_platform_probe(struct platform_device *pdev) | 138 | int __devinit __pata_platform_probe(struct device *dev, |
139 | struct resource *io_res, | ||
140 | struct resource *ctl_res, | ||
141 | struct resource *irq_res, | ||
142 | unsigned int ioport_shift, | ||
143 | int __pio_mask) | ||
139 | { | 144 | { |
140 | struct resource *io_res, *ctl_res; | ||
141 | struct ata_host *host; | 145 | struct ata_host *host; |
142 | struct ata_port *ap; | 146 | struct ata_port *ap; |
143 | struct pata_platform_info *pp_info; | ||
144 | unsigned int mmio; | 147 | unsigned int mmio; |
145 | int irq; | 148 | int irq = 0; |
146 | 149 | int irq_flags = 0; | |
147 | /* | ||
148 | * Simple resource validation .. | ||
149 | */ | ||
150 | if ((pdev->num_resources != 3) && (pdev->num_resources != 2)) { | ||
151 | dev_err(&pdev->dev, "invalid number of resources\n"); | ||
152 | return -EINVAL; | ||
153 | } | ||
154 | |||
155 | /* | ||
156 | * Get the I/O base first | ||
157 | */ | ||
158 | io_res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
159 | if (io_res == NULL) { | ||
160 | io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
161 | if (unlikely(io_res == NULL)) | ||
162 | return -EINVAL; | ||
163 | } | ||
164 | |||
165 | /* | ||
166 | * Then the CTL base | ||
167 | */ | ||
168 | ctl_res = platform_get_resource(pdev, IORESOURCE_IO, 1); | ||
169 | if (ctl_res == NULL) { | ||
170 | ctl_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
171 | if (unlikely(ctl_res == NULL)) | ||
172 | return -EINVAL; | ||
173 | } | ||
174 | 150 | ||
175 | /* | 151 | /* |
176 | * Check for MMIO | 152 | * Check for MMIO |
@@ -181,20 +157,21 @@ static int __devinit pata_platform_probe(struct platform_device *pdev) | |||
181 | /* | 157 | /* |
182 | * And the IRQ | 158 | * And the IRQ |
183 | */ | 159 | */ |
184 | irq = platform_get_irq(pdev, 0); | 160 | if (irq_res && irq_res->start > 0) { |
185 | if (irq < 0) | 161 | irq = irq_res->start; |
186 | irq = 0; /* no irq */ | 162 | irq_flags = irq_res->flags; |
163 | } | ||
187 | 164 | ||
188 | /* | 165 | /* |
189 | * Now that that's out of the way, wire up the port.. | 166 | * Now that that's out of the way, wire up the port.. |
190 | */ | 167 | */ |
191 | host = ata_host_alloc(&pdev->dev, 1); | 168 | host = ata_host_alloc(dev, 1); |
192 | if (!host) | 169 | if (!host) |
193 | return -ENOMEM; | 170 | return -ENOMEM; |
194 | ap = host->ports[0]; | 171 | ap = host->ports[0]; |
195 | 172 | ||
196 | ap->ops = &pata_platform_port_ops; | 173 | ap->ops = &pata_platform_port_ops; |
197 | ap->pio_mask = pio_mask; | 174 | ap->pio_mask = __pio_mask; |
198 | ap->flags |= ATA_FLAG_SLAVE_POSS; | 175 | ap->flags |= ATA_FLAG_SLAVE_POSS; |
199 | 176 | ||
200 | /* | 177 | /* |
@@ -209,25 +186,24 @@ static int __devinit pata_platform_probe(struct platform_device *pdev) | |||
209 | * Handle the MMIO case | 186 | * Handle the MMIO case |
210 | */ | 187 | */ |
211 | if (mmio) { | 188 | if (mmio) { |
212 | ap->ioaddr.cmd_addr = devm_ioremap(&pdev->dev, io_res->start, | 189 | ap->ioaddr.cmd_addr = devm_ioremap(dev, io_res->start, |
213 | io_res->end - io_res->start + 1); | 190 | io_res->end - io_res->start + 1); |
214 | ap->ioaddr.ctl_addr = devm_ioremap(&pdev->dev, ctl_res->start, | 191 | ap->ioaddr.ctl_addr = devm_ioremap(dev, ctl_res->start, |
215 | ctl_res->end - ctl_res->start + 1); | 192 | ctl_res->end - ctl_res->start + 1); |
216 | } else { | 193 | } else { |
217 | ap->ioaddr.cmd_addr = devm_ioport_map(&pdev->dev, io_res->start, | 194 | ap->ioaddr.cmd_addr = devm_ioport_map(dev, io_res->start, |
218 | io_res->end - io_res->start + 1); | 195 | io_res->end - io_res->start + 1); |
219 | ap->ioaddr.ctl_addr = devm_ioport_map(&pdev->dev, ctl_res->start, | 196 | ap->ioaddr.ctl_addr = devm_ioport_map(dev, ctl_res->start, |
220 | ctl_res->end - ctl_res->start + 1); | 197 | ctl_res->end - ctl_res->start + 1); |
221 | } | 198 | } |
222 | if (!ap->ioaddr.cmd_addr || !ap->ioaddr.ctl_addr) { | 199 | if (!ap->ioaddr.cmd_addr || !ap->ioaddr.ctl_addr) { |
223 | dev_err(&pdev->dev, "failed to map IO/CTL base\n"); | 200 | dev_err(dev, "failed to map IO/CTL base\n"); |
224 | return -ENOMEM; | 201 | return -ENOMEM; |
225 | } | 202 | } |
226 | 203 | ||
227 | ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr; | 204 | ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr; |
228 | 205 | ||
229 | pp_info = pdev->dev.platform_data; | 206 | pata_platform_setup_port(&ap->ioaddr, ioport_shift); |
230 | pata_platform_setup_port(&ap->ioaddr, pp_info); | ||
231 | 207 | ||
232 | ata_port_desc(ap, "%s cmd 0x%llx ctl 0x%llx", mmio ? "mmio" : "ioport", | 208 | ata_port_desc(ap, "%s cmd 0x%llx ctl 0x%llx", mmio ? "mmio" : "ioport", |
233 | (unsigned long long)io_res->start, | 209 | (unsigned long long)io_res->start, |
@@ -235,26 +211,78 @@ static int __devinit pata_platform_probe(struct platform_device *pdev) | |||
235 | 211 | ||
236 | /* activate */ | 212 | /* activate */ |
237 | return ata_host_activate(host, irq, irq ? ata_interrupt : NULL, | 213 | return ata_host_activate(host, irq, irq ? ata_interrupt : NULL, |
238 | pp_info ? pp_info->irq_flags : 0, | 214 | irq_flags, &pata_platform_sht); |
239 | &pata_platform_sht); | ||
240 | } | 215 | } |
216 | EXPORT_SYMBOL_GPL(__pata_platform_probe); | ||
241 | 217 | ||
242 | /** | 218 | /** |
243 | * pata_platform_remove - unplug a platform interface | 219 | * __pata_platform_remove - unplug a platform interface |
244 | * @pdev: platform device | 220 | * @dev: device |
245 | * | 221 | * |
246 | * A platform bus ATA device has been unplugged. Perform the needed | 222 | * A platform bus ATA device has been unplugged. Perform the needed |
247 | * cleanup. Also called on module unload for any active devices. | 223 | * cleanup. Also called on module unload for any active devices. |
248 | */ | 224 | */ |
249 | static int __devexit pata_platform_remove(struct platform_device *pdev) | 225 | int __devexit __pata_platform_remove(struct device *dev) |
250 | { | 226 | { |
251 | struct device *dev = &pdev->dev; | ||
252 | struct ata_host *host = dev_get_drvdata(dev); | 227 | struct ata_host *host = dev_get_drvdata(dev); |
253 | 228 | ||
254 | ata_host_detach(host); | 229 | ata_host_detach(host); |
255 | 230 | ||
256 | return 0; | 231 | return 0; |
257 | } | 232 | } |
233 | EXPORT_SYMBOL_GPL(__pata_platform_remove); | ||
234 | |||
235 | static int __devinit pata_platform_probe(struct platform_device *pdev) | ||
236 | { | ||
237 | struct resource *io_res; | ||
238 | struct resource *ctl_res; | ||
239 | struct resource *irq_res; | ||
240 | struct pata_platform_info *pp_info = pdev->dev.platform_data; | ||
241 | |||
242 | /* | ||
243 | * Simple resource validation .. | ||
244 | */ | ||
245 | if ((pdev->num_resources != 3) && (pdev->num_resources != 2)) { | ||
246 | dev_err(&pdev->dev, "invalid number of resources\n"); | ||
247 | return -EINVAL; | ||
248 | } | ||
249 | |||
250 | /* | ||
251 | * Get the I/O base first | ||
252 | */ | ||
253 | io_res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
254 | if (io_res == NULL) { | ||
255 | io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
256 | if (unlikely(io_res == NULL)) | ||
257 | return -EINVAL; | ||
258 | } | ||
259 | |||
260 | /* | ||
261 | * Then the CTL base | ||
262 | */ | ||
263 | ctl_res = platform_get_resource(pdev, IORESOURCE_IO, 1); | ||
264 | if (ctl_res == NULL) { | ||
265 | ctl_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
266 | if (unlikely(ctl_res == NULL)) | ||
267 | return -EINVAL; | ||
268 | } | ||
269 | |||
270 | /* | ||
271 | * And the IRQ | ||
272 | */ | ||
273 | irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
274 | if (irq_res) | ||
275 | irq_res->flags = pp_info ? pp_info->irq_flags : 0; | ||
276 | |||
277 | return __pata_platform_probe(&pdev->dev, io_res, ctl_res, irq_res, | ||
278 | pp_info ? pp_info->ioport_shift : 0, | ||
279 | pio_mask); | ||
280 | } | ||
281 | |||
282 | static int __devexit pata_platform_remove(struct platform_device *pdev) | ||
283 | { | ||
284 | return __pata_platform_remove(&pdev->dev); | ||
285 | } | ||
258 | 286 | ||
259 | static struct platform_driver pata_platform_driver = { | 287 | static struct platform_driver pata_platform_driver = { |
260 | .probe = pata_platform_probe, | 288 | .probe = pata_platform_probe, |
diff --git a/include/linux/pata_platform.h b/include/linux/pata_platform.h index 5799e8d50623..6a7a92db294c 100644 --- a/include/linux/pata_platform.h +++ b/include/linux/pata_platform.h | |||
@@ -15,4 +15,13 @@ struct pata_platform_info { | |||
15 | unsigned int irq_flags; | 15 | unsigned int irq_flags; |
16 | }; | 16 | }; |
17 | 17 | ||
18 | extern int __devinit __pata_platform_probe(struct device *dev, | ||
19 | struct resource *io_res, | ||
20 | struct resource *ctl_res, | ||
21 | struct resource *irq_res, | ||
22 | unsigned int ioport_shift, | ||
23 | int __pio_mask); | ||
24 | |||
25 | extern int __devexit __pata_platform_remove(struct device *dev); | ||
26 | |||
18 | #endif /* __LINUX_PATA_PLATFORM_H */ | 27 | #endif /* __LINUX_PATA_PLATFORM_H */ |