Commit b454cc6636d254fbf6049b73e9560aee76fb04a3
Committed by
Ralf Baechle
1 parent
5986a2ec35
Exists in
master
and in
39 other branches
[TC] MIPS: TURBOchannel update to the driver model
This is a set of changes to convert support for the TURBOchannel bus to the driver model. It implements the usual set of calls similar to what other bus drivers have: tc_register_driver(), tc_unregister_driver(), etc. All the platform-specific bits have been removed and headers from asm-mips/dec/ have been merged into linux/tc.h, which should be included by drivers. Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Showing 8 changed files with 396 additions and 328 deletions Side-by-side Diff
MAINTAINERS
... | ... | @@ -3287,6 +3287,11 @@ |
3287 | 3287 | W: http://vtun.sourceforge.net/tun |
3288 | 3288 | S: Maintained |
3289 | 3289 | |
3290 | +TURBOCHANNEL SUBSYSTEM | |
3291 | +P: Maciej W. Rozycki | |
3292 | +M: macro@linux-mips.org | |
3293 | +S: Maintained | |
3294 | + | |
3290 | 3295 | U14-34F SCSI DRIVER |
3291 | 3296 | P: Dario Ballabio |
3292 | 3297 | M: ballabio_dario@emc.com |
drivers/tc/Makefile
drivers/tc/tc-driver.c
1 | +/* | |
2 | + * TURBOchannel driver services. | |
3 | + * | |
4 | + * Copyright (c) 2005 James Simmons | |
5 | + * Copyright (c) 2006 Maciej W. Rozycki | |
6 | + * | |
7 | + * Loosely based on drivers/dio/dio-driver.c and | |
8 | + * drivers/pci/pci-driver.c. | |
9 | + * | |
10 | + * This file is subject to the terms and conditions of the GNU | |
11 | + * General Public License. See the file "COPYING" in the main | |
12 | + * directory of this archive for more details. | |
13 | + */ | |
14 | + | |
15 | +#include <linux/init.h> | |
16 | +#include <linux/module.h> | |
17 | +#include <linux/tc.h> | |
18 | + | |
19 | +/** | |
20 | + * tc_register_driver - register a new TC driver | |
21 | + * @drv: the driver structure to register | |
22 | + * | |
23 | + * Adds the driver structure to the list of registered drivers | |
24 | + * Returns a negative value on error, otherwise 0. | |
25 | + * If no error occurred, the driver remains registered even if | |
26 | + * no device was claimed during registration. | |
27 | + */ | |
28 | +int tc_register_driver(struct tc_driver *tdrv) | |
29 | +{ | |
30 | + return driver_register(&tdrv->driver); | |
31 | +} | |
32 | +EXPORT_SYMBOL(tc_register_driver); | |
33 | + | |
34 | +/** | |
35 | + * tc_unregister_driver - unregister a TC driver | |
36 | + * @drv: the driver structure to unregister | |
37 | + * | |
38 | + * Deletes the driver structure from the list of registered TC drivers, | |
39 | + * gives it a chance to clean up by calling its remove() function for | |
40 | + * each device it was responsible for, and marks those devices as | |
41 | + * driverless. | |
42 | + */ | |
43 | +void tc_unregister_driver(struct tc_driver *tdrv) | |
44 | +{ | |
45 | + driver_unregister(&tdrv->driver); | |
46 | +} | |
47 | +EXPORT_SYMBOL(tc_unregister_driver); | |
48 | + | |
49 | +/** | |
50 | + * tc_match_device - tell if a TC device structure has a matching | |
51 | + * TC device ID structure | |
52 | + * @tdrv: the TC driver to earch for matching TC device ID strings | |
53 | + * @tdev: the TC device structure to match against | |
54 | + * | |
55 | + * Used by a driver to check whether a TC device present in the | |
56 | + * system is in its list of supported devices. Returns the matching | |
57 | + * tc_device_id structure or %NULL if there is no match. | |
58 | + */ | |
59 | +const struct tc_device_id *tc_match_device(struct tc_driver *tdrv, | |
60 | + struct tc_dev *tdev) | |
61 | +{ | |
62 | + const struct tc_device_id *id = tdrv->id_table; | |
63 | + | |
64 | + if (id) { | |
65 | + while (id->name[0] || id->vendor[0]) { | |
66 | + if (strcmp(tdev->name, id->name) == 0 && | |
67 | + strcmp(tdev->vendor, id->vendor) == 0) | |
68 | + return id; | |
69 | + id++; | |
70 | + } | |
71 | + } | |
72 | + return NULL; | |
73 | +} | |
74 | +EXPORT_SYMBOL(tc_match_device); | |
75 | + | |
76 | +/** | |
77 | + * tc_bus_match - Tell if a device structure has a matching | |
78 | + * TC device ID structure | |
79 | + * @dev: the device structure to match against | |
80 | + * @drv: the device driver to search for matching TC device ID strings | |
81 | + * | |
82 | + * Used by a driver to check whether a TC device present in the | |
83 | + * system is in its list of supported devices. Returns 1 if there | |
84 | + * is a match or 0 otherwise. | |
85 | + */ | |
86 | +static int tc_bus_match(struct device *dev, struct device_driver *drv) | |
87 | +{ | |
88 | + struct tc_dev *tdev = to_tc_dev(dev); | |
89 | + struct tc_driver *tdrv = to_tc_driver(drv); | |
90 | + const struct tc_device_id *id; | |
91 | + | |
92 | + id = tc_match_device(tdrv, tdev); | |
93 | + if (id) | |
94 | + return 1; | |
95 | + | |
96 | + return 0; | |
97 | +} | |
98 | + | |
99 | +struct bus_type tc_bus_type = { | |
100 | + .name = "tc", | |
101 | + .match = tc_bus_match, | |
102 | +}; | |
103 | +EXPORT_SYMBOL(tc_bus_type); | |
104 | + | |
105 | +static int __init tc_driver_init(void) | |
106 | +{ | |
107 | + return bus_register(&tc_bus_type); | |
108 | +} | |
109 | + | |
110 | +postcore_initcall(tc_driver_init); |
drivers/tc/tc.c
1 | 1 | /* |
2 | - * tc-init: We assume the TURBOchannel to be up and running so | |
3 | - * just probe for Modules and fill in the global data structure | |
4 | - * tc_bus. | |
2 | + * TURBOchannel bus services. | |
5 | 3 | * |
6 | - * This file is subject to the terms and conditions of the GNU General Public | |
7 | - * License. See the file "COPYING" in the main directory of this archive | |
8 | - * for more details. | |
4 | + * Copyright (c) Harald Koerfgen, 1998 | |
5 | + * Copyright (c) 2001, 2003, 2005, 2006 Maciej W. Rozycki | |
6 | + * Copyright (c) 2005 James Simmons | |
9 | 7 | * |
10 | - * Copyright (c) Harald Koerfgen, 1998 | |
11 | - * Copyright (c) 2001, 2003, 2005 Maciej W. Rozycki | |
8 | + * This file is subject to the terms and conditions of the GNU | |
9 | + * General Public License. See the file "COPYING" in the main | |
10 | + * directory of this archive for more details. | |
12 | 11 | */ |
12 | +#include <linux/compiler.h> | |
13 | +#include <linux/errno.h> | |
13 | 14 | #include <linux/init.h> |
15 | +#include <linux/ioport.h> | |
14 | 16 | #include <linux/kernel.h> |
17 | +#include <linux/list.h> | |
15 | 18 | #include <linux/module.h> |
16 | 19 | #include <linux/string.h> |
20 | +#include <linux/tc.h> | |
17 | 21 | #include <linux/types.h> |
18 | 22 | |
19 | -#include <asm/addrspace.h> | |
20 | -#include <asm/errno.h> | |
21 | 23 | #include <asm/io.h> |
22 | -#include <asm/paccess.h> | |
23 | 24 | |
24 | -#include <asm/dec/machtype.h> | |
25 | -#include <asm/dec/prom.h> | |
26 | -#include <asm/dec/tcinfo.h> | |
27 | -#include <asm/dec/tcmodule.h> | |
28 | -#include <asm/dec/interrupts.h> | |
25 | +static struct tc_bus tc_bus = { | |
26 | + .name = "TURBOchannel", | |
27 | +}; | |
29 | 28 | |
30 | -MODULE_LICENSE("GPL"); | |
31 | -slot_info tc_bus[MAX_SLOT]; | |
32 | -static int num_tcslots; | |
33 | -static tcinfo *info; | |
34 | - | |
35 | 29 | /* |
36 | - * Interface to the world. Read comment in include/asm-mips/tc.h. | |
30 | + * Probing for TURBOchannel modules. | |
37 | 31 | */ |
38 | - | |
39 | -int search_tc_card(const char *name) | |
32 | +static void __init tc_bus_add_devices(struct tc_bus *tbus) | |
40 | 33 | { |
41 | - int slot; | |
42 | - slot_info *sip; | |
43 | - | |
44 | - for (slot = 0; slot < num_tcslots; slot++) { | |
45 | - sip = &tc_bus[slot]; | |
46 | - if ((sip->flags & FREE) && | |
47 | - (strncmp(sip->name, name, strlen(name)) == 0)) { | |
48 | - return slot; | |
49 | - } | |
50 | - } | |
51 | - | |
52 | - return -ENODEV; | |
53 | -} | |
54 | - | |
55 | -void claim_tc_card(int slot) | |
56 | -{ | |
57 | - if (tc_bus[slot].flags & IN_USE) { | |
58 | - printk("claim_tc_card: attempting to claim a card already in use\n"); | |
59 | - return; | |
60 | - } | |
61 | - tc_bus[slot].flags &= ~FREE; | |
62 | - tc_bus[slot].flags |= IN_USE; | |
63 | -} | |
64 | - | |
65 | -void release_tc_card(int slot) | |
66 | -{ | |
67 | - if (tc_bus[slot].flags & FREE) { | |
68 | - printk("release_tc_card: " | |
69 | - "attempting to release a card already free\n"); | |
70 | - return; | |
71 | - } | |
72 | - tc_bus[slot].flags &= ~IN_USE; | |
73 | - tc_bus[slot].flags |= FREE; | |
74 | -} | |
75 | - | |
76 | -unsigned long get_tc_base_addr(int slot) | |
77 | -{ | |
78 | - return tc_bus[slot].base_addr; | |
79 | -} | |
80 | - | |
81 | -unsigned long get_tc_irq_nr(int slot) | |
82 | -{ | |
83 | - return tc_bus[slot].interrupt; | |
84 | -} | |
85 | - | |
86 | -unsigned long get_tc_speed(void) | |
87 | -{ | |
88 | - return 100000 * (10000 / (unsigned long)info->clk_period); | |
89 | -} | |
90 | - | |
91 | -/* | |
92 | - * Probing for TURBOchannel modules | |
93 | - */ | |
94 | -static void __init tc_probe(unsigned long startaddr, unsigned long size, | |
95 | - int slots) | |
96 | -{ | |
97 | - unsigned long slotaddr; | |
34 | + resource_size_t slotsize = tbus->info.slot_size << 20; | |
35 | + resource_size_t extslotsize = tbus->ext_slot_size; | |
36 | + resource_size_t slotaddr; | |
37 | + resource_size_t extslotaddr; | |
38 | + resource_size_t devsize; | |
39 | + void __iomem *module; | |
40 | + struct tc_dev *tdev; | |
98 | 41 | int i, slot, err; |
99 | - long offset; | |
100 | 42 | u8 pattern[4]; |
101 | - volatile u8 *module; | |
43 | + long offset; | |
102 | 44 | |
103 | - for (slot = 0; slot < slots; slot++) { | |
104 | - slotaddr = startaddr + slot * size; | |
105 | - module = ioremap_nocache(slotaddr, size); | |
45 | + for (slot = 0; slot < tbus->num_tcslots; slot++) { | |
46 | + slotaddr = tbus->slot_base + slot * slotsize; | |
47 | + extslotaddr = tbus->ext_slot_base + slot * extslotsize; | |
48 | + module = ioremap_nocache(slotaddr, slotsize); | |
106 | 49 | BUG_ON(!module); |
107 | 50 | |
108 | - offset = OLDCARD; | |
51 | + offset = TC_OLDCARD; | |
109 | 52 | |
110 | 53 | err = 0; |
111 | - err |= get_dbe(pattern[0], module + OLDCARD + TC_PATTERN0); | |
112 | - err |= get_dbe(pattern[1], module + OLDCARD + TC_PATTERN1); | |
113 | - err |= get_dbe(pattern[2], module + OLDCARD + TC_PATTERN2); | |
114 | - err |= get_dbe(pattern[3], module + OLDCARD + TC_PATTERN3); | |
115 | - if (err) { | |
116 | - iounmap(module); | |
117 | - continue; | |
118 | - } | |
54 | + err |= tc_preadb(pattern + 0, module + offset + TC_PATTERN0); | |
55 | + err |= tc_preadb(pattern + 1, module + offset + TC_PATTERN1); | |
56 | + err |= tc_preadb(pattern + 2, module + offset + TC_PATTERN2); | |
57 | + err |= tc_preadb(pattern + 3, module + offset + TC_PATTERN3); | |
58 | + if (err) | |
59 | + goto out_err; | |
119 | 60 | |
120 | 61 | if (pattern[0] != 0x55 || pattern[1] != 0x00 || |
121 | 62 | pattern[2] != 0xaa || pattern[3] != 0xff) { |
122 | - offset = NEWCARD; | |
63 | + offset = TC_NEWCARD; | |
123 | 64 | |
124 | 65 | err = 0; |
125 | - err |= get_dbe(pattern[0], module + TC_PATTERN0); | |
126 | - err |= get_dbe(pattern[1], module + TC_PATTERN1); | |
127 | - err |= get_dbe(pattern[2], module + TC_PATTERN2); | |
128 | - err |= get_dbe(pattern[3], module + TC_PATTERN3); | |
129 | - if (err) { | |
130 | - iounmap(module); | |
131 | - continue; | |
132 | - } | |
66 | + err |= tc_preadb(pattern + 0, | |
67 | + module + offset + TC_PATTERN0); | |
68 | + err |= tc_preadb(pattern + 1, | |
69 | + module + offset + TC_PATTERN1); | |
70 | + err |= tc_preadb(pattern + 2, | |
71 | + module + offset + TC_PATTERN2); | |
72 | + err |= tc_preadb(pattern + 3, | |
73 | + module + offset + TC_PATTERN3); | |
74 | + if (err) | |
75 | + goto out_err; | |
133 | 76 | } |
134 | 77 | |
135 | 78 | if (pattern[0] != 0x55 || pattern[1] != 0x00 || |
136 | - pattern[2] != 0xaa || pattern[3] != 0xff) { | |
137 | - iounmap(module); | |
138 | - continue; | |
79 | + pattern[2] != 0xaa || pattern[3] != 0xff) | |
80 | + goto out_err; | |
81 | + | |
82 | + /* Found a board, allocate it an entry in the list */ | |
83 | + tdev = kzalloc(sizeof(*tdev), GFP_KERNEL); | |
84 | + if (!tdev) { | |
85 | + printk(KERN_ERR "tc%x: unable to allocate tc_dev\n", | |
86 | + slot); | |
87 | + goto out_err; | |
139 | 88 | } |
89 | + sprintf(tdev->dev.bus_id, "tc%x", slot); | |
90 | + tdev->bus = tbus; | |
91 | + tdev->dev.parent = &tbus->dev; | |
92 | + tdev->dev.bus = &tc_bus_type; | |
93 | + tdev->slot = slot; | |
140 | 94 | |
141 | - tc_bus[slot].base_addr = slotaddr; | |
142 | 95 | for (i = 0; i < 8; i++) { |
143 | - tc_bus[slot].firmware[i] = | |
144 | - module[TC_FIRM_VER + offset + 4 * i]; | |
145 | - tc_bus[slot].vendor[i] = | |
146 | - module[TC_VENDOR + offset + 4 * i]; | |
147 | - tc_bus[slot].name[i] = | |
148 | - module[TC_MODULE + offset + 4 * i]; | |
96 | + tdev->firmware[i] = | |
97 | + readb(module + offset + TC_FIRM_VER + 4 * i); | |
98 | + tdev->vendor[i] = | |
99 | + readb(module + offset + TC_VENDOR + 4 * i); | |
100 | + tdev->name[i] = | |
101 | + readb(module + offset + TC_MODULE + 4 * i); | |
149 | 102 | } |
150 | - tc_bus[slot].firmware[8] = 0; | |
151 | - tc_bus[slot].vendor[8] = 0; | |
152 | - tc_bus[slot].name[8] = 0; | |
153 | - /* | |
154 | - * Looks unneccesary, but we may change | |
155 | - * TC? in the future | |
156 | - */ | |
157 | - switch (slot) { | |
158 | - case 0: | |
159 | - tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC0]; | |
160 | - break; | |
161 | - case 1: | |
162 | - tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC1]; | |
163 | - break; | |
164 | - case 2: | |
165 | - tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC2]; | |
166 | - break; | |
167 | - /* | |
168 | - * Yuck! DS5000/200 onboard devices | |
169 | - */ | |
170 | - case 5: | |
171 | - tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC5]; | |
172 | - break; | |
173 | - case 6: | |
174 | - tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC6]; | |
175 | - break; | |
176 | - default: | |
177 | - tc_bus[slot].interrupt = -1; | |
178 | - break; | |
103 | + tdev->firmware[8] = 0; | |
104 | + tdev->vendor[8] = 0; | |
105 | + tdev->name[8] = 0; | |
106 | + | |
107 | + pr_info("%s: %s %s %s\n", tdev->dev.bus_id, tdev->vendor, | |
108 | + tdev->name, tdev->firmware); | |
109 | + | |
110 | + devsize = readb(module + offset + TC_SLOT_SIZE); | |
111 | + devsize <<= 22; | |
112 | + if (devsize <= slotsize) { | |
113 | + tdev->resource.start = slotaddr; | |
114 | + tdev->resource.end = slotaddr + devsize - 1; | |
115 | + } else if (devsize <= extslotsize) { | |
116 | + tdev->resource.start = extslotaddr; | |
117 | + tdev->resource.end = extslotaddr + devsize - 1; | |
118 | + } else { | |
119 | + printk(KERN_ERR "%s: Cannot provide slot space " | |
120 | + "(%dMiB required, up to %dMiB supported)\n", | |
121 | + tdev->dev.bus_id, devsize >> 20, | |
122 | + max(slotsize, extslotsize) >> 20); | |
123 | + kfree(tdev); | |
124 | + goto out_err; | |
179 | 125 | } |
126 | + tdev->resource.name = tdev->name; | |
127 | + tdev->resource.flags = IORESOURCE_MEM; | |
180 | 128 | |
129 | + tc_device_get_irq(tdev); | |
130 | + | |
131 | + device_register(&tdev->dev); | |
132 | + list_add_tail(&tdev->node, &tbus->devices); | |
133 | + | |
134 | +out_err: | |
181 | 135 | iounmap(module); |
182 | 136 | } |
183 | 137 | } |
184 | 138 | |
185 | 139 | /* |
186 | - * the main entry | |
140 | + * The main entry. | |
187 | 141 | */ |
188 | 142 | static int __init tc_init(void) |
189 | 143 | { |
190 | - int tc_clock; | |
191 | - int i; | |
192 | - unsigned long slot0addr; | |
193 | - unsigned long slot_size; | |
194 | - | |
195 | - if (!TURBOCHANNEL) | |
144 | + /* Initialize the TURBOchannel bus */ | |
145 | + if (tc_bus_get_info(&tc_bus)) | |
196 | 146 | return 0; |
197 | 147 | |
198 | - for (i = 0; i < MAX_SLOT; i++) { | |
199 | - tc_bus[i].base_addr = 0; | |
200 | - tc_bus[i].name[0] = 0; | |
201 | - tc_bus[i].vendor[0] = 0; | |
202 | - tc_bus[i].firmware[0] = 0; | |
203 | - tc_bus[i].interrupt = -1; | |
204 | - tc_bus[i].flags = FREE; | |
205 | - } | |
148 | + INIT_LIST_HEAD(&tc_bus.devices); | |
149 | + strcpy(tc_bus.dev.bus_id, "tc"); | |
150 | + device_register(&tc_bus.dev); | |
206 | 151 | |
207 | - info = rex_gettcinfo(); | |
208 | - slot0addr = CPHYSADDR((long)rex_slot_address(0)); | |
152 | + if (tc_bus.info.slot_size) { | |
153 | + unsigned int tc_clock = tc_get_speed(&tc_bus) / 100000; | |
209 | 154 | |
210 | - switch (mips_machtype) { | |
211 | - case MACH_DS5000_200: | |
212 | - num_tcslots = 7; | |
213 | - break; | |
214 | - case MACH_DS5000_1XX: | |
215 | - case MACH_DS5000_2X0: | |
216 | - case MACH_DS5900: | |
217 | - num_tcslots = 3; | |
218 | - break; | |
219 | - case MACH_DS5000_XX: | |
220 | - default: | |
221 | - num_tcslots = 2; | |
222 | - break; | |
223 | - } | |
155 | + pr_info("tc: TURBOchannel rev. %d at %d.%d MHz " | |
156 | + "(with%s parity)\n", tc_bus.info.revision, | |
157 | + tc_clock / 10, tc_clock % 10, | |
158 | + tc_bus.info.parity ? "" : "out"); | |
224 | 159 | |
225 | - tc_clock = 10000 / info->clk_period; | |
226 | - | |
227 | - if (info->slot_size && slot0addr) { | |
228 | - pr_info("TURBOchannel rev. %d at %d.%d MHz (with%s parity)\n", | |
229 | - info->revision, tc_clock / 10, tc_clock % 10, | |
230 | - info->parity ? "" : "out"); | |
231 | - | |
232 | - slot_size = info->slot_size << 20; | |
233 | - | |
234 | - tc_probe(slot0addr, slot_size, num_tcslots); | |
235 | - | |
236 | - for (i = 0; i < num_tcslots; i++) { | |
237 | - if (!tc_bus[i].base_addr) | |
238 | - continue; | |
239 | - pr_info(" slot %d: %s %s %s\n", i, tc_bus[i].vendor, | |
240 | - tc_bus[i].name, tc_bus[i].firmware); | |
160 | + tc_bus.resource[0].start = tc_bus.slot_base; | |
161 | + tc_bus.resource[0].end = tc_bus.slot_base + | |
162 | + (tc_bus.info.slot_size << 20) * | |
163 | + tc_bus.num_tcslots; | |
164 | + tc_bus.resource[0].name = tc_bus.name; | |
165 | + tc_bus.resource[0].flags = IORESOURCE_MEM; | |
166 | + if (request_resource(&iomem_resource, | |
167 | + &tc_bus.resource[0]) < 0) { | |
168 | + printk(KERN_ERR "tc: Cannot reserve resource\n"); | |
169 | + return 0; | |
241 | 170 | } |
171 | + if (tc_bus.ext_slot_size) { | |
172 | + tc_bus.resource[1].start = tc_bus.ext_slot_base; | |
173 | + tc_bus.resource[1].end = tc_bus.ext_slot_base + | |
174 | + tc_bus.ext_slot_size * | |
175 | + tc_bus.num_tcslots; | |
176 | + tc_bus.resource[1].name = tc_bus.name; | |
177 | + tc_bus.resource[1].flags = IORESOURCE_MEM; | |
178 | + if (request_resource(&iomem_resource, | |
179 | + &tc_bus.resource[1]) < 0) { | |
180 | + printk(KERN_ERR | |
181 | + "tc: Cannot reserve resource\n"); | |
182 | + release_resource(&tc_bus.resource[0]); | |
183 | + return 0; | |
184 | + } | |
185 | + } | |
186 | + | |
187 | + tc_bus_add_devices(&tc_bus); | |
242 | 188 | } |
243 | 189 | |
244 | 190 | return 0; |
245 | 191 | } |
246 | 192 | |
247 | 193 | subsys_initcall(tc_init); |
248 | - | |
249 | -EXPORT_SYMBOL(search_tc_card); | |
250 | -EXPORT_SYMBOL(claim_tc_card); | |
251 | -EXPORT_SYMBOL(release_tc_card); | |
252 | -EXPORT_SYMBOL(get_tc_base_addr); | |
253 | -EXPORT_SYMBOL(get_tc_irq_nr); | |
254 | -EXPORT_SYMBOL(get_tc_speed); |
include/asm-mips/dec/tc.h
1 | -/* | |
2 | - * Interface to the TURBOchannel related routines | |
3 | - * | |
4 | - * This file is subject to the terms and conditions of the GNU General Public | |
5 | - * License. See the file "COPYING" in the main directory of this archive | |
6 | - * for more details. | |
7 | - * | |
8 | - * Copyright (c) 1998 Harald Koerfgen | |
9 | - */ | |
10 | -#ifndef __ASM_DEC_TC_H | |
11 | -#define __ASM_DEC_TC_H | |
12 | - | |
13 | -/* | |
14 | - * Search for a TURBOchannel Option Module | |
15 | - * with a certain name. Returns slot number | |
16 | - * of the first card not in use or -ENODEV | |
17 | - * if none found. | |
18 | - */ | |
19 | -extern int search_tc_card(const char *); | |
20 | -/* | |
21 | - * Marks the card in slot as used | |
22 | - */ | |
23 | -extern void claim_tc_card(int); | |
24 | -/* | |
25 | - * Marks the card in slot as free | |
26 | - */ | |
27 | -extern void release_tc_card(int); | |
28 | -/* | |
29 | - * Return base address of card in slot | |
30 | - */ | |
31 | -extern unsigned long get_tc_base_addr(int); | |
32 | -/* | |
33 | - * Return interrupt number of slot | |
34 | - */ | |
35 | -extern unsigned long get_tc_irq_nr(int); | |
36 | -/* | |
37 | - * Return TURBOchannel clock frequency in Hz | |
38 | - */ | |
39 | -extern unsigned long get_tc_speed(void); | |
40 | - | |
41 | -#endif /* __ASM_DEC_TC_H */ |
include/asm-mips/dec/tcinfo.h
1 | -/* | |
2 | - * Various TURBOchannel related stuff | |
3 | - * | |
4 | - * This file is subject to the terms and conditions of the GNU General Public | |
5 | - * License. See the file "COPYING" in the main directory of this archive | |
6 | - * for more details. | |
7 | - * | |
8 | - * Information obtained through the get_tcinfo prom call | |
9 | - * created from: | |
10 | - * | |
11 | - * TURBOchannel Firmware Specification | |
12 | - * | |
13 | - * EK-TCAAD-FS-004 | |
14 | - * from Digital Equipment Corporation | |
15 | - * | |
16 | - * Copyright (c) 1998 Harald Koerfgen | |
17 | - */ | |
18 | - | |
19 | -typedef struct { | |
20 | - int revision; | |
21 | - int clk_period; | |
22 | - int slot_size; | |
23 | - int io_timeout; | |
24 | - int dma_range; | |
25 | - int max_dma_burst; | |
26 | - int parity; | |
27 | - int reserved[4]; | |
28 | -} tcinfo; | |
29 | - | |
30 | -#define MAX_SLOT 7 | |
31 | - | |
32 | -typedef struct { | |
33 | - unsigned long base_addr; | |
34 | - unsigned char name[9]; | |
35 | - unsigned char vendor[9]; | |
36 | - unsigned char firmware[9]; | |
37 | - int interrupt; | |
38 | - int flags; | |
39 | -} slot_info; | |
40 | - | |
41 | -/* | |
42 | - * Values for flags | |
43 | - */ | |
44 | -#define FREE 1<<0 | |
45 | -#define IN_USE 1<<1 |
include/asm-mips/dec/tcmodule.h
1 | -/* | |
2 | - * This file is subject to the terms and conditions of the GNU General Public | |
3 | - * License. See the file "COPYING" in the main directory of this archive | |
4 | - * for more details. | |
5 | - * | |
6 | - * Offsets for the ROM header locations for | |
7 | - * TURBOchannel cards | |
8 | - * | |
9 | - * created from: | |
10 | - * | |
11 | - * TURBOchannel Firmware Specification | |
12 | - * | |
13 | - * EK-TCAAD-FS-004 | |
14 | - * from Digital Equipment Corporation | |
15 | - * | |
16 | - * Jan.1998 Harald Koerfgen | |
17 | - */ | |
18 | -#ifndef __ASM_DEC_TCMODULE_H | |
19 | -#define __ASM_DEC_TCMODULE_H | |
20 | - | |
21 | -#define OLDCARD 0x3c0000 | |
22 | -#define NEWCARD 0x000000 | |
23 | - | |
24 | -#define TC_ROM_WIDTH 0x3e0 | |
25 | -#define TC_ROM_STRIDE 0x3e4 | |
26 | -#define TC_ROM_SIZE 0x3e8 | |
27 | -#define TC_SLOT_SIZE 0x3ec | |
28 | -#define TC_PATTERN0 0x3f0 | |
29 | -#define TC_PATTERN1 0x3f4 | |
30 | -#define TC_PATTERN2 0x3f8 | |
31 | -#define TC_PATTERN3 0x3fc | |
32 | -#define TC_FIRM_VER 0x400 | |
33 | -#define TC_VENDOR 0x420 | |
34 | -#define TC_MODULE 0x440 | |
35 | -#define TC_FIRM_TYPE 0x460 | |
36 | -#define TC_FLAGS 0x470 | |
37 | -#define TC_ROM_OBJECTS 0x480 | |
38 | - | |
39 | -#endif /* __ASM_DEC_TCMODULE_H */ |
include/linux/tc.h
1 | +/* | |
2 | + * Interface to the TURBOchannel related routines. | |
3 | + * | |
4 | + * Copyright (c) 1998 Harald Koerfgen | |
5 | + * Copyright (c) 2005 James Simmons | |
6 | + * Copyright (c) 2006 Maciej W. Rozycki | |
7 | + * | |
8 | + * Based on: | |
9 | + * | |
10 | + * "TURBOchannel Firmware Specification", EK-TCAAD-FS-004 | |
11 | + * | |
12 | + * from Digital Equipment Corporation. | |
13 | + * | |
14 | + * This file is subject to the terms and conditions of the GNU | |
15 | + * General Public License. See the file "COPYING" in the main | |
16 | + * directory of this archive for more details. | |
17 | + */ | |
18 | +#ifndef _LINUX_TC_H | |
19 | +#define _LINUX_TC_H | |
20 | + | |
21 | +#include <linux/compiler.h> | |
22 | +#include <linux/device.h> | |
23 | +#include <linux/ioport.h> | |
24 | +#include <linux/types.h> | |
25 | + | |
26 | +/* | |
27 | + * Offsets for the ROM header locations for TURBOchannel cards. | |
28 | + */ | |
29 | +#define TC_OLDCARD 0x3c0000 | |
30 | +#define TC_NEWCARD 0x000000 | |
31 | + | |
32 | +#define TC_ROM_WIDTH 0x3e0 | |
33 | +#define TC_ROM_STRIDE 0x3e4 | |
34 | +#define TC_ROM_SIZE 0x3e8 | |
35 | +#define TC_SLOT_SIZE 0x3ec | |
36 | +#define TC_PATTERN0 0x3f0 | |
37 | +#define TC_PATTERN1 0x3f4 | |
38 | +#define TC_PATTERN2 0x3f8 | |
39 | +#define TC_PATTERN3 0x3fc | |
40 | +#define TC_FIRM_VER 0x400 | |
41 | +#define TC_VENDOR 0x420 | |
42 | +#define TC_MODULE 0x440 | |
43 | +#define TC_FIRM_TYPE 0x460 | |
44 | +#define TC_FLAGS 0x470 | |
45 | +#define TC_ROM_OBJECTS 0x480 | |
46 | + | |
47 | +/* | |
48 | + * Information obtained through the get_tcinfo() PROM call. | |
49 | + */ | |
50 | +struct tcinfo { | |
51 | + s32 revision; /* Hardware revision level. */ | |
52 | + s32 clk_period; /* Clock period in nanoseconds. */ | |
53 | + s32 slot_size; /* Slot size in megabytes. */ | |
54 | + s32 io_timeout; /* I/O timeout in cycles. */ | |
55 | + s32 dma_range; /* DMA address range in megabytes. */ | |
56 | + s32 max_dma_burst; /* Maximum DMA burst length. */ | |
57 | + s32 parity; /* System module supports TC parity. */ | |
58 | + s32 reserved[4]; | |
59 | +}; | |
60 | + | |
61 | +/* | |
62 | + * TURBOchannel bus. | |
63 | + */ | |
64 | +struct tc_bus { | |
65 | + struct list_head devices; /* List of devices on this bus. */ | |
66 | + struct resource resource[2]; /* Address space routed to this bus. */ | |
67 | + | |
68 | + struct device dev; | |
69 | + char name[13]; | |
70 | + resource_size_t slot_base; | |
71 | + resource_size_t ext_slot_base; | |
72 | + resource_size_t ext_slot_size; | |
73 | + int num_tcslots; | |
74 | + struct tcinfo info; | |
75 | +}; | |
76 | + | |
77 | +/* | |
78 | + * TURBOchannel device. | |
79 | + */ | |
80 | +struct tc_dev { | |
81 | + struct list_head node; /* Node in list of all TC devices. */ | |
82 | + struct tc_bus *bus; /* Bus this device is on. */ | |
83 | + struct tc_driver *driver; /* Which driver has allocated this | |
84 | + device. */ | |
85 | + struct device dev; /* Generic device interface. */ | |
86 | + struct resource resource; /* Address space of this device. */ | |
87 | + char vendor[9]; | |
88 | + char name[9]; | |
89 | + char firmware[9]; | |
90 | + int interrupt; | |
91 | + int slot; | |
92 | +}; | |
93 | + | |
94 | +#define to_tc_dev(n) container_of(n, struct tc_dev, dev) | |
95 | + | |
96 | +struct tc_device_id { | |
97 | + char vendor[9]; | |
98 | + char name[9]; | |
99 | +}; | |
100 | + | |
101 | +/* | |
102 | + * TURBOchannel driver. | |
103 | + */ | |
104 | +struct tc_driver { | |
105 | + struct list_head node; | |
106 | + const struct tc_device_id *id_table; | |
107 | + struct device_driver driver; | |
108 | +}; | |
109 | + | |
110 | +#define to_tc_driver(drv) container_of(drv, struct tc_driver, driver) | |
111 | + | |
112 | +/* | |
113 | + * Return TURBOchannel clock frequency in Hz. | |
114 | + */ | |
115 | +static inline unsigned long tc_get_speed(struct tc_bus *tbus) | |
116 | +{ | |
117 | + return 100000 * (10000 / (unsigned long)tbus->info.clk_period); | |
118 | +} | |
119 | + | |
120 | +#ifdef CONFIG_TC | |
121 | + | |
122 | +extern struct bus_type tc_bus_type; | |
123 | + | |
124 | +extern int tc_register_driver(struct tc_driver *tdrv); | |
125 | +extern void tc_unregister_driver(struct tc_driver *tdrv); | |
126 | + | |
127 | +#else /* !CONFIG_TC */ | |
128 | + | |
129 | +static inline int tc_register_driver(struct tc_driver *tdrv) { return 0; } | |
130 | +static inline void tc_unregister_driver(struct tc_driver *tdrv) { } | |
131 | + | |
132 | +#endif /* CONFIG_TC */ | |
133 | + | |
134 | +/* | |
135 | + * These have to be provided by the architecture. | |
136 | + */ | |
137 | +extern int tc_preadb(u8 *valp, void __iomem *addr); | |
138 | +extern int tc_bus_get_info(struct tc_bus *tbus); | |
139 | +extern void tc_device_get_irq(struct tc_dev *tdev); | |
140 | + | |
141 | +#endif /* _LINUX_TC_H */ |