Blame view

drivers/tc/tc.c 5.25 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
2
   *	TURBOchannel bus services.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
   *
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
4
5
6
   *	Copyright (c) Harald Koerfgen, 1998
   *	Copyright (c) 2001, 2003, 2005, 2006  Maciej W. Rozycki
   *	Copyright (c) 2005  James Simmons
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
   *
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
8
9
10
   *	This file is subject to the terms and conditions of the GNU
   *	General Public License.  See the file "COPYING" in the main
   *	directory of this archive for more details.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
   */
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
12
13
  #include <linux/compiler.h>
  #include <linux/errno.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
  #include <linux/init.h>
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
15
  #include <linux/ioport.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
  #include <linux/kernel.h>
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
17
  #include <linux/list.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
  #include <linux/module.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
19
  #include <linux/slab.h>
a5fc9c0bb   Maciej W. Rozycki   Use physical addr...
20
  #include <linux/string.h>
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
21
  #include <linux/tc.h>
a5fc9c0bb   Maciej W. Rozycki   Use physical addr...
22
  #include <linux/types.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23

a5fc9c0bb   Maciej W. Rozycki   Use physical addr...
24
  #include <asm/io.h>
a5fc9c0bb   Maciej W. Rozycki   Use physical addr...
25

b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
26
27
28
  static struct tc_bus tc_bus = {
  	.name = "TURBOchannel",
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
  /*
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
31
   * Probing for TURBOchannel modules.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
   */
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
33
  static void __init tc_bus_add_devices(struct tc_bus *tbus)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
  {
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
35
36
37
38
39
40
41
  	resource_size_t slotsize = tbus->info.slot_size << 20;
  	resource_size_t extslotsize = tbus->ext_slot_size;
  	resource_size_t slotaddr;
  	resource_size_t extslotaddr;
  	resource_size_t devsize;
  	void __iomem *module;
  	struct tc_dev *tdev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
  	int i, slot, err;
a5fc9c0bb   Maciej W. Rozycki   Use physical addr...
43
  	u8 pattern[4];
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
44
  	long offset;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45

b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
46
47
48
49
  	for (slot = 0; slot < tbus->num_tcslots; slot++) {
  		slotaddr = tbus->slot_base + slot * slotsize;
  		extslotaddr = tbus->ext_slot_base + slot * extslotsize;
  		module = ioremap_nocache(slotaddr, slotsize);
a5fc9c0bb   Maciej W. Rozycki   Use physical addr...
50
  		BUG_ON(!module);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51

b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
52
  		offset = TC_OLDCARD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
54
  
  		err = 0;
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
55
56
57
58
59
60
  		err |= tc_preadb(pattern + 0, module + offset + TC_PATTERN0);
  		err |= tc_preadb(pattern + 1, module + offset + TC_PATTERN1);
  		err |= tc_preadb(pattern + 2, module + offset + TC_PATTERN2);
  		err |= tc_preadb(pattern + 3, module + offset + TC_PATTERN3);
  		if (err)
  			goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61
62
63
  
  		if (pattern[0] != 0x55 || pattern[1] != 0x00 ||
  		    pattern[2] != 0xaa || pattern[3] != 0xff) {
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
64
  			offset = TC_NEWCARD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
66
  
  			err = 0;
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
67
68
69
70
71
72
73
74
75
76
  			err |= tc_preadb(pattern + 0,
  					 module + offset + TC_PATTERN0);
  			err |= tc_preadb(pattern + 1,
  					 module + offset + TC_PATTERN1);
  			err |= tc_preadb(pattern + 2,
  					 module + offset + TC_PATTERN2);
  			err |= tc_preadb(pattern + 3,
  					 module + offset + TC_PATTERN3);
  			if (err)
  				goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
78
79
  		}
  
  		if (pattern[0] != 0x55 || pattern[1] != 0x00 ||
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
80
81
82
83
84
85
  		    pattern[2] != 0xaa || pattern[3] != 0xff)
  			goto out_err;
  
  		/* Found a board, allocate it an entry in the list */
  		tdev = kzalloc(sizeof(*tdev), GFP_KERNEL);
  		if (!tdev) {
e2afb7de6   Maciej W. Rozycki   TC: Error handlin...
86
87
  			pr_err("tc%x: unable to allocate tc_dev
  ", slot);
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
88
  			goto out_err;
a5fc9c0bb   Maciej W. Rozycki   Use physical addr...
89
  		}
df388556d   Kay Sievers   tc: struct device...
90
  		dev_set_name(&tdev->dev, "tc%x", slot);
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
91
92
93
94
  		tdev->bus = tbus;
  		tdev->dev.parent = &tbus->dev;
  		tdev->dev.bus = &tc_bus_type;
  		tdev->slot = slot;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95

a5fc9c0bb   Maciej W. Rozycki   Use physical addr...
96
  		for (i = 0; i < 8; i++) {
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
97
98
99
100
101
102
  			tdev->firmware[i] =
  				readb(module + offset + TC_FIRM_VER + 4 * i);
  			tdev->vendor[i] =
  				readb(module + offset + TC_VENDOR + 4 * i);
  			tdev->name[i] =
  				readb(module + offset + TC_MODULE + 4 * i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
  		}
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
104
105
106
  		tdev->firmware[8] = 0;
  		tdev->vendor[8] = 0;
  		tdev->name[8] = 0;
df388556d   Kay Sievers   tc: struct device...
107
108
  		pr_info("%s: %s %s %s
  ", dev_name(&tdev->dev), tdev->vendor,
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
109
110
111
112
113
114
115
116
117
118
119
  			tdev->name, tdev->firmware);
  
  		devsize = readb(module + offset + TC_SLOT_SIZE);
  		devsize <<= 22;
  		if (devsize <= slotsize) {
  			tdev->resource.start = slotaddr;
  			tdev->resource.end = slotaddr + devsize - 1;
  		} else if (devsize <= extslotsize) {
  			tdev->resource.start = extslotaddr;
  			tdev->resource.end = extslotaddr + devsize - 1;
  		} else {
e2afb7de6   Maciej W. Rozycki   TC: Error handlin...
120
121
122
123
124
  			pr_err("%s: Cannot provide slot space "
  			       "(%ldMiB required, up to %ldMiB supported)
  ",
  			       dev_name(&tdev->dev), (long)(devsize >> 20),
  			       (long)(max(slotsize, extslotsize) >> 20));
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
125
126
  			kfree(tdev);
  			goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127
  		}
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
128
129
130
131
  		tdev->resource.name = tdev->name;
  		tdev->resource.flags = IORESOURCE_MEM;
  
  		tc_device_get_irq(tdev);
a5fc9c0bb   Maciej W. Rozycki   Use physical addr...
132

5bb7889f4   Levente Kurusa   TC: Handle device...
133
134
135
136
  		if (device_register(&tdev->dev)) {
  			put_device(&tdev->dev);
  			goto out_err;
  		}
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
137
138
139
  		list_add_tail(&tdev->node, &tbus->devices);
  
  out_err:
a5fc9c0bb   Maciej W. Rozycki   Use physical addr...
140
  		iounmap(module);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
142
143
144
  	}
  }
  
  /*
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
145
   * The main entry.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
   */
778220f7c   Maciej W. Rozycki   Fix function type...
147
  static int __init tc_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
  {
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
149
150
  	/* Initialize the TURBOchannel bus */
  	if (tc_bus_get_info(&tc_bus))
e2afb7de6   Maciej W. Rozycki   TC: Error handlin...
151
  		goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152

b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
153
  	INIT_LIST_HEAD(&tc_bus.devices);
df388556d   Kay Sievers   tc: struct device...
154
  	dev_set_name(&tc_bus.dev, "tc");
e2afb7de6   Maciej W. Rozycki   TC: Error handlin...
155
156
  	if (device_register(&tc_bus.dev))
  		goto out_err_device;
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
157
158
159
160
161
162
163
164
165
166
167
168
169
  
  	if (tc_bus.info.slot_size) {
  		unsigned int tc_clock = tc_get_speed(&tc_bus) / 100000;
  
  		pr_info("tc: TURBOchannel rev. %d at %d.%d MHz "
  			"(with%s parity)
  ", tc_bus.info.revision,
  			tc_clock / 10, tc_clock % 10,
  			tc_bus.info.parity ? "" : "out");
  
  		tc_bus.resource[0].start = tc_bus.slot_base;
  		tc_bus.resource[0].end = tc_bus.slot_base +
  					 (tc_bus.info.slot_size << 20) *
56a47da1b   Maciej W. Rozycki   [TC] MIPS: TURBOc...
170
  					 tc_bus.num_tcslots - 1;
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
171
172
173
174
  		tc_bus.resource[0].name = tc_bus.name;
  		tc_bus.resource[0].flags = IORESOURCE_MEM;
  		if (request_resource(&iomem_resource,
  				     &tc_bus.resource[0]) < 0) {
e2afb7de6   Maciej W. Rozycki   TC: Error handlin...
175
176
177
  			pr_err("tc: Cannot reserve resource
  ");
  			goto out_err_device;
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
178
179
180
181
182
  		}
  		if (tc_bus.ext_slot_size) {
  			tc_bus.resource[1].start = tc_bus.ext_slot_base;
  			tc_bus.resource[1].end = tc_bus.ext_slot_base +
  						 tc_bus.ext_slot_size *
56a47da1b   Maciej W. Rozycki   [TC] MIPS: TURBOc...
183
  						 tc_bus.num_tcslots - 1;
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
184
185
186
187
  			tc_bus.resource[1].name = tc_bus.name;
  			tc_bus.resource[1].flags = IORESOURCE_MEM;
  			if (request_resource(&iomem_resource,
  					     &tc_bus.resource[1]) < 0) {
e2afb7de6   Maciej W. Rozycki   TC: Error handlin...
188
189
190
  				pr_err("tc: Cannot reserve resource
  ");
  				goto out_err_resource;
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
191
  			}
a5fc9c0bb   Maciej W. Rozycki   Use physical addr...
192
  		}
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
193
194
  
  		tc_bus_add_devices(&tc_bus);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
  	}
778220f7c   Maciej W. Rozycki   Fix function type...
196
197
  
  	return 0;
e2afb7de6   Maciej W. Rozycki   TC: Error handlin...
198
199
200
201
202
203
204
  
  out_err_resource:
  	release_resource(&tc_bus.resource[0]);
  out_err_device:
  	put_device(&tc_bus.dev);
  out_err:
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205
206
207
  }
  
  subsys_initcall(tc_init);