diff options
author | Paul Mackerras <paulus@samba.org> | 2008-01-17 00:17:58 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2008-01-17 00:17:58 -0500 |
commit | 52920df4aa9dd25836b8ed4dc0b177ea14c09e53 (patch) | |
tree | 47b3fab4849f7faeaaf88e2ca8dcc911a0c39103 /drivers | |
parent | 0173d422aa32fa1e5141f1759202b955215c1da2 (diff) | |
parent | 9cd55be4d22376893d2818ce3c0e5706a3d74121 (diff) |
Merge branch 'for-2.6.25' of master.kernel.org:/pub/scm/linux/kernel/git/olof/pasemi into for-2.6.25
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/Kconfig | 12 | ||||
-rw-r--r-- | drivers/ata/Makefile | 1 | ||||
-rw-r--r-- | drivers/ata/pata_of_platform.c | 114 | ||||
-rw-r--r-- | drivers/ata/pata_platform.c | 144 |
4 files changed, 212 insertions, 59 deletions
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index ba63619ae5df..64b4964d57e7 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig | |||
@@ -607,13 +607,23 @@ config PATA_WINBOND_VLB | |||
607 | 607 | ||
608 | config PATA_PLATFORM | 608 | config PATA_PLATFORM |
609 | tristate "Generic platform device PATA support" | 609 | tristate "Generic platform device PATA support" |
610 | depends on EMBEDDED || ARCH_RPC | 610 | depends on EMBEDDED || ARCH_RPC || PPC |
611 | help | 611 | help |
612 | This option enables support for generic directly connected ATA | 612 | This option enables support for generic directly connected ATA |
613 | devices commonly found on embedded systems. | 613 | devices commonly found on embedded systems. |
614 | 614 | ||
615 | If unsure, say N. | 615 | If unsure, say N. |
616 | 616 | ||
617 | config PATA_OF_PLATFORM | ||
618 | tristate "OpenFirmware platform device PATA support" | ||
619 | depends on PATA_PLATFORM && PPC_OF | ||
620 | help | ||
621 | This option enables support for generic directly connected ATA | ||
622 | devices commonly found on embedded systems with OpenFirmware | ||
623 | bindings. | ||
624 | |||
625 | If unsure, say N. | ||
626 | |||
617 | config PATA_ICSIDE | 627 | config PATA_ICSIDE |
618 | tristate "Acorn ICS PATA support" | 628 | tristate "Acorn ICS PATA support" |
619 | depends on ARM && ARCH_ACORN | 629 | depends on ARM && ARCH_ACORN |
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index b13feb2c5dae..ebcee64dd5e2 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile | |||
@@ -67,6 +67,7 @@ obj-$(CONFIG_PATA_IXP4XX_CF) += pata_ixp4xx_cf.o | |||
67 | obj-$(CONFIG_PATA_SCC) += pata_scc.o | 67 | obj-$(CONFIG_PATA_SCC) += pata_scc.o |
68 | obj-$(CONFIG_PATA_BF54X) += pata_bf54x.o | 68 | obj-$(CONFIG_PATA_BF54X) += pata_bf54x.o |
69 | obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o | 69 | obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o |
70 | obj-$(CONFIG_PATA_OF_PLATFORM) += pata_of_platform.o | ||
70 | obj-$(CONFIG_PATA_ICSIDE) += pata_icside.o | 71 | obj-$(CONFIG_PATA_ICSIDE) += pata_icside.o |
71 | # Should be last but two libata driver | 72 | # Should be last but two libata driver |
72 | obj-$(CONFIG_PATA_ACPI) += pata_acpi.o | 73 | obj-$(CONFIG_PATA_ACPI) += pata_acpi.o |
diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c new file mode 100644 index 000000000000..938f48a807eb --- /dev/null +++ b/drivers/ata/pata_of_platform.c | |||
@@ -0,0 +1,114 @@ | |||
1 | /* | ||
2 | * OF-platform PATA driver | ||
3 | * | ||
4 | * Copyright (c) 2007 MontaVista Software, Inc. | ||
5 | * Anton Vorontsov <avorontsov@ru.mvista.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License (Version 2) as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/of_platform.h> | ||
15 | #include <linux/pata_platform.h> | ||
16 | |||
17 | static int __devinit pata_of_platform_probe(struct of_device *ofdev, | ||
18 | const struct of_device_id *match) | ||
19 | { | ||
20 | int ret; | ||
21 | struct device_node *dn = ofdev->node; | ||
22 | struct resource io_res; | ||
23 | struct resource ctl_res; | ||
24 | struct resource irq_res; | ||
25 | unsigned int reg_shift = 0; | ||
26 | int pio_mode = 0; | ||
27 | int pio_mask; | ||
28 | const u32 *prop; | ||
29 | |||
30 | ret = of_address_to_resource(dn, 0, &io_res); | ||
31 | if (ret) { | ||
32 | dev_err(&ofdev->dev, "can't get IO address from " | ||
33 | "device tree\n"); | ||
34 | return -EINVAL; | ||
35 | } | ||
36 | |||
37 | if (of_device_is_compatible(dn, "electra-ide")) { | ||
38 | /* Altstatus is really at offset 0x3f6 from the primary window | ||
39 | * on electra-ide. Adjust ctl_res and io_res accordingly. | ||
40 | */ | ||
41 | ctl_res = io_res; | ||
42 | ctl_res.start = ctl_res.start+0x3f6; | ||
43 | io_res.end = ctl_res.start-1; | ||
44 | } else { | ||
45 | ret = of_address_to_resource(dn, 1, &ctl_res); | ||
46 | if (ret) { | ||
47 | dev_err(&ofdev->dev, "can't get CTL address from " | ||
48 | "device tree\n"); | ||
49 | return -EINVAL; | ||
50 | } | ||
51 | } | ||
52 | |||
53 | ret = of_irq_to_resource(dn, 0, &irq_res); | ||
54 | if (ret == NO_IRQ) | ||
55 | irq_res.start = irq_res.end = -1; | ||
56 | else | ||
57 | irq_res.flags = 0; | ||
58 | |||
59 | prop = of_get_property(dn, "reg-shift", NULL); | ||
60 | if (prop) | ||
61 | reg_shift = *prop; | ||
62 | |||
63 | prop = of_get_property(dn, "pio-mode", NULL); | ||
64 | if (prop) { | ||
65 | pio_mode = *prop; | ||
66 | if (pio_mode > 6) { | ||
67 | dev_err(&ofdev->dev, "invalid pio-mode\n"); | ||
68 | return -EINVAL; | ||
69 | } | ||
70 | } else { | ||
71 | dev_info(&ofdev->dev, "pio-mode unspecified, assuming PIO0\n"); | ||
72 | } | ||
73 | |||
74 | pio_mask = 1 << pio_mode; | ||
75 | pio_mask |= (1 << pio_mode) - 1; | ||
76 | |||
77 | return __pata_platform_probe(&ofdev->dev, &io_res, &ctl_res, &irq_res, | ||
78 | reg_shift, pio_mask); | ||
79 | } | ||
80 | |||
81 | static int __devexit pata_of_platform_remove(struct of_device *ofdev) | ||
82 | { | ||
83 | return __pata_platform_remove(&ofdev->dev); | ||
84 | } | ||
85 | |||
86 | static struct of_device_id pata_of_platform_match[] = { | ||
87 | { .compatible = "ata-generic", }, | ||
88 | { .compatible = "electra-ide", }, | ||
89 | {}, | ||
90 | }; | ||
91 | MODULE_DEVICE_TABLE(of, pata_of_platform_match); | ||
92 | |||
93 | static struct of_platform_driver pata_of_platform_driver = { | ||
94 | .name = "pata_of_platform", | ||
95 | .match_table = pata_of_platform_match, | ||
96 | .probe = pata_of_platform_probe, | ||
97 | .remove = __devexit_p(pata_of_platform_remove), | ||
98 | }; | ||
99 | |||
100 | static int __init pata_of_platform_init(void) | ||
101 | { | ||
102 | return of_register_platform_driver(&pata_of_platform_driver); | ||
103 | } | ||
104 | module_init(pata_of_platform_init); | ||
105 | |||
106 | static void __exit pata_of_platform_exit(void) | ||
107 | { | ||
108 | of_unregister_platform_driver(&pata_of_platform_driver); | ||
109 | } | ||
110 | module_exit(pata_of_platform_exit); | ||
111 | |||
112 | MODULE_DESCRIPTION("OF-platform PATA driver"); | ||
113 | MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>"); | ||
114 | MODULE_LICENSE("GPL"); | ||
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, |