aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/Kconfig12
-rw-r--r--drivers/ata/Makefile1
-rw-r--r--drivers/ata/pata_of_platform.c114
-rw-r--r--drivers/ata/pata_platform.c144
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
608config PATA_PLATFORM 608config 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
617config 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
617config PATA_ICSIDE 627config 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
67obj-$(CONFIG_PATA_SCC) += pata_scc.o 67obj-$(CONFIG_PATA_SCC) += pata_scc.o
68obj-$(CONFIG_PATA_BF54X) += pata_bf54x.o 68obj-$(CONFIG_PATA_BF54X) += pata_bf54x.o
69obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o 69obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o
70obj-$(CONFIG_PATA_OF_PLATFORM) += pata_of_platform.o
70obj-$(CONFIG_PATA_ICSIDE) += pata_icside.o 71obj-$(CONFIG_PATA_ICSIDE) += pata_icside.o
71# Should be last but two libata driver 72# Should be last but two libata driver
72obj-$(CONFIG_PATA_ACPI) += pata_acpi.o 73obj-$(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
17static 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
81static int __devexit pata_of_platform_remove(struct of_device *ofdev)
82{
83 return __pata_platform_remove(&ofdev->dev);
84}
85
86static struct of_device_id pata_of_platform_match[] = {
87 { .compatible = "ata-generic", },
88 { .compatible = "electra-ide", },
89 {},
90};
91MODULE_DEVICE_TABLE(of, pata_of_platform_match);
92
93static 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
100static int __init pata_of_platform_init(void)
101{
102 return of_register_platform_driver(&pata_of_platform_driver);
103}
104module_init(pata_of_platform_init);
105
106static void __exit pata_of_platform_exit(void)
107{
108 of_unregister_platform_driver(&pata_of_platform_driver);
109}
110module_exit(pata_of_platform_exit);
111
112MODULE_DESCRIPTION("OF-platform PATA driver");
113MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
114MODULE_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
95static void pata_platform_setup_port(struct ata_ioports *ioaddr, 95static 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 */
138static int __devinit pata_platform_probe(struct platform_device *pdev) 138int __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}
216EXPORT_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 */
249static int __devexit pata_platform_remove(struct platform_device *pdev) 225int __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}
233EXPORT_SYMBOL_GPL(__pata_platform_remove);
234
235static 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
282static int __devexit pata_platform_remove(struct platform_device *pdev)
283{
284 return __pata_platform_remove(&pdev->dev);
285}
258 286
259static struct platform_driver pata_platform_driver = { 287static struct platform_driver pata_platform_driver = {
260 .probe = pata_platform_probe, 288 .probe = pata_platform_probe,