Blame view

drivers/tc/tc.c 5.47 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
   *	Copyright (c) Harald Koerfgen, 1998
e7f6b41ad   Maciej W. Rozycki   TC: Set DMA masks...
5
   *	Copyright (c) 2001, 2003, 2005, 2006, 2018  Maciej W. Rozycki
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
6
   *	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
  #include <linux/compiler.h>
e7f6b41ad   Maciej W. Rozycki   TC: Set DMA masks...
13
  #include <linux/dma-mapping.h>
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
14
  #include <linux/errno.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
  #include <linux/init.h>
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
16
  #include <linux/ioport.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
  #include <linux/kernel.h>
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
18
  #include <linux/list.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
  #include <linux/module.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
20
  #include <linux/slab.h>
a5fc9c0bb   Maciej W. Rozycki   Use physical addr...
21
  #include <linux/string.h>
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
22
  #include <linux/tc.h>
a5fc9c0bb   Maciej W. Rozycki   Use physical addr...
23
  #include <linux/types.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
  /*
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
32
   * Probing for TURBOchannel modules.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
   */
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
34
  static void __init tc_bus_add_devices(struct tc_bus *tbus)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
  {
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
36
37
38
39
40
41
42
  	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
43
  	int i, slot, err;
a5fc9c0bb   Maciej W. Rozycki   Use physical addr...
44
  	u8 pattern[4];
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
45
  	long offset;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46

b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
47
48
49
50
  	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...
51
  		BUG_ON(!module);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52

b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
53
  		offset = TC_OLDCARD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
55
  
  		err = 0;
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
56
57
58
59
60
61
  		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
62
63
64
  
  		if (pattern[0] != 0x55 || pattern[1] != 0x00 ||
  		    pattern[2] != 0xaa || pattern[3] != 0xff) {
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
65
  			offset = TC_NEWCARD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
67
  
  			err = 0;
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
68
69
70
71
72
73
74
75
76
77
  			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
78
79
80
  		}
  
  		if (pattern[0] != 0x55 || pattern[1] != 0x00 ||
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
81
82
83
84
85
86
  		    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...
87
88
  			pr_err("tc%x: unable to allocate tc_dev
  ", slot);
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
89
  			goto out_err;
a5fc9c0bb   Maciej W. Rozycki   Use physical addr...
90
  		}
df388556d   Kay Sievers   tc: struct device...
91
  		dev_set_name(&tdev->dev, "tc%x", slot);
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
92
93
94
95
  		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
96

e7f6b41ad   Maciej W. Rozycki   TC: Set DMA masks...
97
98
99
100
  		/* TURBOchannel has 34-bit DMA addressing (16GiB space). */
  		tdev->dma_mask = DMA_BIT_MASK(34);
  		tdev->dev.dma_mask = &tdev->dma_mask;
  		tdev->dev.coherent_dma_mask = DMA_BIT_MASK(34);
a5fc9c0bb   Maciej W. Rozycki   Use physical addr...
101
  		for (i = 0; i < 8; i++) {
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
102
103
104
105
106
107
  			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
108
  		}
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
109
110
111
  		tdev->firmware[8] = 0;
  		tdev->vendor[8] = 0;
  		tdev->name[8] = 0;
df388556d   Kay Sievers   tc: struct device...
112
113
  		pr_info("%s: %s %s %s
  ", dev_name(&tdev->dev), tdev->vendor,
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
114
115
116
117
118
119
120
121
122
123
124
  			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...
125
126
127
128
129
  			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...
130
131
  			kfree(tdev);
  			goto out_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
  		}
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
133
134
135
136
  		tdev->resource.name = tdev->name;
  		tdev->resource.flags = IORESOURCE_MEM;
  
  		tc_device_get_irq(tdev);
a5fc9c0bb   Maciej W. Rozycki   Use physical addr...
137

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

b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
158
  	INIT_LIST_HEAD(&tc_bus.devices);
df388556d   Kay Sievers   tc: struct device...
159
  	dev_set_name(&tc_bus.dev, "tc");
e2afb7de6   Maciej W. Rozycki   TC: Error handlin...
160
161
  	if (device_register(&tc_bus.dev))
  		goto out_err_device;
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
162
163
164
165
166
167
168
169
170
171
172
173
174
  
  	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...
175
  					 tc_bus.num_tcslots - 1;
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
176
177
178
179
  		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...
180
181
182
  			pr_err("tc: Cannot reserve resource
  ");
  			goto out_err_device;
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
183
184
185
186
187
  		}
  		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...
188
  						 tc_bus.num_tcslots - 1;
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
189
190
191
192
  			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...
193
194
195
  				pr_err("tc: Cannot reserve resource
  ");
  				goto out_err_resource;
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
196
  			}
a5fc9c0bb   Maciej W. Rozycki   Use physical addr...
197
  		}
b454cc663   Maciej W. Rozycki   [TC] MIPS: TURBOc...
198
199
  
  		tc_bus_add_devices(&tc_bus);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
  	}
778220f7c   Maciej W. Rozycki   Fix function type...
201
202
  
  	return 0;
e2afb7de6   Maciej W. Rozycki   TC: Error handlin...
203
204
205
206
207
208
209
  
  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
210
211
212
  }
  
  subsys_initcall(tc_init);