diff options
Diffstat (limited to 'drivers/ide/arm/rapide.c')
-rw-r--r-- | drivers/ide/arm/rapide.c | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c new file mode 100644 index 000000000000..3058217767d6 --- /dev/null +++ b/drivers/ide/arm/rapide.c | |||
@@ -0,0 +1,125 @@ | |||
1 | /* | ||
2 | * linux/drivers/ide/arm/rapide.c | ||
3 | * | ||
4 | * Copyright (c) 1996-2002 Russell King. | ||
5 | */ | ||
6 | |||
7 | #include <linux/module.h> | ||
8 | #include <linux/slab.h> | ||
9 | #include <linux/blkdev.h> | ||
10 | #include <linux/errno.h> | ||
11 | #include <linux/ide.h> | ||
12 | #include <linux/init.h> | ||
13 | |||
14 | #include <asm/ecard.h> | ||
15 | |||
16 | /* | ||
17 | * Something like this really should be in generic code, but isn't. | ||
18 | */ | ||
19 | static ide_hwif_t * | ||
20 | rapide_locate_hwif(void __iomem *base, void __iomem *ctrl, unsigned int sz, int irq) | ||
21 | { | ||
22 | unsigned long port = (unsigned long)base; | ||
23 | ide_hwif_t *hwif; | ||
24 | int index, i; | ||
25 | |||
26 | for (index = 0; index < MAX_HWIFS; ++index) { | ||
27 | hwif = ide_hwifs + index; | ||
28 | if (hwif->io_ports[IDE_DATA_OFFSET] == port) | ||
29 | goto found; | ||
30 | } | ||
31 | |||
32 | for (index = 0; index < MAX_HWIFS; ++index) { | ||
33 | hwif = ide_hwifs + index; | ||
34 | if (hwif->io_ports[IDE_DATA_OFFSET] == 0) | ||
35 | goto found; | ||
36 | } | ||
37 | |||
38 | return NULL; | ||
39 | |||
40 | found: | ||
41 | for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { | ||
42 | hwif->hw.io_ports[i] = port; | ||
43 | hwif->io_ports[i] = port; | ||
44 | port += sz; | ||
45 | } | ||
46 | hwif->hw.io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl; | ||
47 | hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl; | ||
48 | hwif->hw.irq = hwif->irq = irq; | ||
49 | hwif->mmio = 2; | ||
50 | default_hwif_mmiops(hwif); | ||
51 | |||
52 | return hwif; | ||
53 | } | ||
54 | |||
55 | static int __devinit | ||
56 | rapide_probe(struct expansion_card *ec, const struct ecard_id *id) | ||
57 | { | ||
58 | ide_hwif_t *hwif; | ||
59 | void __iomem *base; | ||
60 | int ret; | ||
61 | |||
62 | ret = ecard_request_resources(ec); | ||
63 | if (ret) | ||
64 | goto out; | ||
65 | |||
66 | base = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC), | ||
67 | ecard_resource_len(ec, ECARD_RES_MEMC)); | ||
68 | if (!base) { | ||
69 | ret = -ENOMEM; | ||
70 | goto release; | ||
71 | } | ||
72 | |||
73 | hwif = rapide_locate_hwif(base, base + 0x818, 1 << 6, ec->irq); | ||
74 | if (hwif) { | ||
75 | hwif->hwif_data = base; | ||
76 | hwif->gendev.parent = &ec->dev; | ||
77 | hwif->noprobe = 0; | ||
78 | probe_hwif_init(hwif); | ||
79 | create_proc_ide_interfaces(); | ||
80 | ecard_set_drvdata(ec, hwif); | ||
81 | goto out; | ||
82 | } | ||
83 | |||
84 | iounmap(base); | ||
85 | release: | ||
86 | ecard_release_resources(ec); | ||
87 | out: | ||
88 | return ret; | ||
89 | } | ||
90 | |||
91 | static void __devexit rapide_remove(struct expansion_card *ec) | ||
92 | { | ||
93 | ide_hwif_t *hwif = ecard_get_drvdata(ec); | ||
94 | |||
95 | ecard_set_drvdata(ec, NULL); | ||
96 | |||
97 | /* there must be a better way */ | ||
98 | ide_unregister(hwif - ide_hwifs); | ||
99 | iounmap(hwif->hwif_data); | ||
100 | ecard_release_resources(ec); | ||
101 | } | ||
102 | |||
103 | static struct ecard_id rapide_ids[] = { | ||
104 | { MANU_YELLOWSTONE, PROD_YELLOWSTONE_RAPIDE32 }, | ||
105 | { 0xffff, 0xffff } | ||
106 | }; | ||
107 | |||
108 | static struct ecard_driver rapide_driver = { | ||
109 | .probe = rapide_probe, | ||
110 | .remove = __devexit_p(rapide_remove), | ||
111 | .id_table = rapide_ids, | ||
112 | .drv = { | ||
113 | .name = "rapide", | ||
114 | }, | ||
115 | }; | ||
116 | |||
117 | static int __init rapide_init(void) | ||
118 | { | ||
119 | return ecard_register_driver(&rapide_driver); | ||
120 | } | ||
121 | |||
122 | MODULE_LICENSE("GPL"); | ||
123 | MODULE_DESCRIPTION("Yellowstone RAPIDE driver"); | ||
124 | |||
125 | module_init(rapide_init); | ||