diff options
author | David S. Miller <davem@davemloft.net> | 2008-08-27 22:59:48 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-08-29 05:15:25 -0400 |
commit | 0c0db98b50ed1217c0dbf4051722034ba314d06e (patch) | |
tree | 7fb374211bafe47cbd513b06bb36990869f463ea /Documentation/sparc | |
parent | 7eb1aae555663118f8d81bb26dca896d9cd8166c (diff) |
sparc: Remove Documentation/sparc/sbus_drivers.txt
None of the text in this document is relevant any more.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'Documentation/sparc')
-rw-r--r-- | Documentation/sparc/sbus_drivers.txt | 309 |
1 files changed, 0 insertions, 309 deletions
diff --git a/Documentation/sparc/sbus_drivers.txt b/Documentation/sparc/sbus_drivers.txt deleted file mode 100644 index eb1e28ad8822..000000000000 --- a/Documentation/sparc/sbus_drivers.txt +++ /dev/null | |||
@@ -1,309 +0,0 @@ | |||
1 | |||
2 | Writing SBUS Drivers | ||
3 | |||
4 | David S. Miller (davem@redhat.com) | ||
5 | |||
6 | The SBUS driver interfaces of the Linux kernel have been | ||
7 | revamped completely for 2.4.x for several reasons. Foremost were | ||
8 | performance and complexity concerns. This document details these | ||
9 | new interfaces and how they are used to write an SBUS device driver. | ||
10 | |||
11 | SBUS drivers need to include <asm/sbus.h> to get access | ||
12 | to functions and structures described here. | ||
13 | |||
14 | Probing and Detection | ||
15 | |||
16 | Each SBUS device inside the machine is described by a | ||
17 | structure called "struct sbus_dev". Likewise, each SBUS bus | ||
18 | found in the system is described by a "struct sbus_bus". For | ||
19 | each SBUS bus, the devices underneath are hung in a tree-like | ||
20 | fashion off of the bus structure. | ||
21 | |||
22 | The SBUS device structure contains enough information | ||
23 | for you to implement your device probing algorithm and obtain | ||
24 | the bits necessary to run your device. The most commonly | ||
25 | used members of this structure, and their typical usage, | ||
26 | will be detailed below. | ||
27 | |||
28 | Here is a piece of skeleton code for performing a device | ||
29 | probe in an SBUS driver under Linux: | ||
30 | |||
31 | static int __devinit mydevice_probe_one(struct sbus_dev *sdev) | ||
32 | { | ||
33 | struct mysdevice *mp = kzalloc(sizeof(*mp), GFP_KERNEL); | ||
34 | |||
35 | if (!mp) | ||
36 | return -ENODEV; | ||
37 | |||
38 | ... | ||
39 | dev_set_drvdata(&sdev->ofdev.dev, mp); | ||
40 | return 0; | ||
41 | ... | ||
42 | } | ||
43 | |||
44 | static int __devinit mydevice_probe(struct of_device *dev, | ||
45 | const struct of_device_id *match) | ||
46 | { | ||
47 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); | ||
48 | |||
49 | return mydevice_probe_one(sdev); | ||
50 | } | ||
51 | |||
52 | static int __devexit mydevice_remove(struct of_device *dev) | ||
53 | { | ||
54 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); | ||
55 | struct mydevice *mp = dev_get_drvdata(&dev->dev); | ||
56 | |||
57 | return mydevice_remove_one(sdev, mp); | ||
58 | } | ||
59 | |||
60 | static struct of_device_id mydevice_match[] = { | ||
61 | { | ||
62 | .name = "mydevice", | ||
63 | }, | ||
64 | {}, | ||
65 | }; | ||
66 | |||
67 | MODULE_DEVICE_TABLE(of, mydevice_match); | ||
68 | |||
69 | static struct of_platform_driver mydevice_driver = { | ||
70 | .match_table = mydevice_match, | ||
71 | .probe = mydevice_probe, | ||
72 | .remove = __devexit_p(mydevice_remove), | ||
73 | .driver = { | ||
74 | .name = "mydevice", | ||
75 | }, | ||
76 | }; | ||
77 | |||
78 | static int __init mydevice_init(void) | ||
79 | { | ||
80 | return of_register_driver(&mydevice_driver, &sbus_bus_type); | ||
81 | } | ||
82 | |||
83 | static void __exit mydevice_exit(void) | ||
84 | { | ||
85 | of_unregister_driver(&mydevice_driver); | ||
86 | } | ||
87 | |||
88 | module_init(mydevice_init); | ||
89 | module_exit(mydevice_exit); | ||
90 | |||
91 | The mydevice_match table is a series of entries which | ||
92 | describes what SBUS devices your driver is meant for. In the | ||
93 | simplest case you specify a string for the 'name' field. Every | ||
94 | SBUS device with a 'name' property matching your string will | ||
95 | be passed one-by-one to your .probe method. | ||
96 | |||
97 | You should store away your device private state structure | ||
98 | pointer in the drvdata area so that you can retrieve it later on | ||
99 | in your .remove method. | ||
100 | |||
101 | Any memory allocated, registers mapped, IRQs registered, | ||
102 | etc. must be undone by your .remove method so that all resources | ||
103 | of your device are released by the time it returns. | ||
104 | |||
105 | You should _NOT_ use the for_each_sbus(), for_each_sbusdev(), | ||
106 | and for_all_sbusdev() interfaces. They are deprecated, will be | ||
107 | removed, and no new driver should reference them ever. | ||
108 | |||
109 | Mapping and Accessing I/O Registers | ||
110 | |||
111 | Each SBUS device structure contains an array of descriptors | ||
112 | which describe each register set. We abuse struct resource for that. | ||
113 | They each correspond to the "reg" properties provided by the OBP firmware. | ||
114 | |||
115 | Before you can access your device's registers you must map | ||
116 | them. And later if you wish to shutdown your driver (for module | ||
117 | unload or similar) you must unmap them. You must treat them as | ||
118 | a resource, which you allocate (map) before using and free up | ||
119 | (unmap) when you are done with it. | ||
120 | |||
121 | The mapping information is stored in an opaque value | ||
122 | typed as an "unsigned long". This is the type of the return value | ||
123 | of the mapping interface, and the arguments to the unmapping | ||
124 | interface. Let's say you want to map the first set of registers. | ||
125 | Perhaps part of your driver software state structure looks like: | ||
126 | |||
127 | struct mydevice { | ||
128 | unsigned long control_regs; | ||
129 | ... | ||
130 | struct sbus_dev *sdev; | ||
131 | ... | ||
132 | }; | ||
133 | |||
134 | At initialization time you then use the sbus_ioremap | ||
135 | interface to map in your registers, like so: | ||
136 | |||
137 | static void init_one_mydevice(struct sbus_dev *sdev) | ||
138 | { | ||
139 | struct mydevice *mp; | ||
140 | ... | ||
141 | |||
142 | mp->control_regs = sbus_ioremap(&sdev->resource[0], 0, | ||
143 | CONTROL_REGS_SIZE, "mydevice regs"); | ||
144 | if (!mp->control_regs) { | ||
145 | /* Failure, cleanup and return. */ | ||
146 | } | ||
147 | } | ||
148 | |||
149 | Second argument to sbus_ioremap is an offset for | ||
150 | cranky devices with broken OBP PROM. The sbus_ioremap uses only | ||
151 | a start address and flags from the resource structure. | ||
152 | Therefore it is possible to use the same resource to map | ||
153 | several sets of registers or even to fabricate a resource | ||
154 | structure if driver gets physical address from some private place. | ||
155 | This practice is discouraged though. Use whatever OBP PROM | ||
156 | provided to you. | ||
157 | |||
158 | And here is how you might unmap these registers later at | ||
159 | driver shutdown or module unload time, using the sbus_iounmap | ||
160 | interface: | ||
161 | |||
162 | static void mydevice_unmap_regs(struct mydevice *mp) | ||
163 | { | ||
164 | sbus_iounmap(mp->control_regs, CONTROL_REGS_SIZE); | ||
165 | } | ||
166 | |||
167 | Finally, to actually access your registers there are 6 | ||
168 | interface routines at your disposal. Accesses are byte (8 bit), | ||
169 | word (16 bit), or longword (32 bit) sized. Here they are: | ||
170 | |||
171 | u8 sbus_readb(unsigned long reg) /* read byte */ | ||
172 | u16 sbus_readw(unsigned long reg) /* read word */ | ||
173 | u32 sbus_readl(unsigned long reg) /* read longword */ | ||
174 | void sbus_writeb(u8 value, unsigned long reg) /* write byte */ | ||
175 | void sbus_writew(u16 value, unsigned long reg) /* write word */ | ||
176 | void sbus_writel(u32 value, unsigned long reg) /* write longword */ | ||
177 | |||
178 | So, let's say your device has a control register of some sort | ||
179 | at offset zero. The following might implement resetting your device: | ||
180 | |||
181 | #define CONTROL 0x00UL | ||
182 | |||
183 | #define CONTROL_RESET 0x00000001 /* Reset hardware */ | ||
184 | |||
185 | static void mydevice_reset(struct mydevice *mp) | ||
186 | { | ||
187 | sbus_writel(CONTROL_RESET, mp->regs + CONTROL); | ||
188 | } | ||
189 | |||
190 | Or perhaps there is a data port register at an offset of | ||
191 | 16 bytes which allows you to read bytes from a fifo in the device: | ||
192 | |||
193 | #define DATA 0x10UL | ||
194 | |||
195 | static u8 mydevice_get_byte(struct mydevice *mp) | ||
196 | { | ||
197 | return sbus_readb(mp->regs + DATA); | ||
198 | } | ||
199 | |||
200 | It's pretty straightforward, and clueful readers may have | ||
201 | noticed that these interfaces mimick the PCI interfaces of the | ||
202 | Linux kernel. This was not by accident. | ||
203 | |||
204 | WARNING: | ||
205 | |||
206 | DO NOT try to treat these opaque register mapping | ||
207 | values as a memory mapped pointer to some structure | ||
208 | which you can dereference. | ||
209 | |||
210 | It may be memory mapped, it may not be. In fact it | ||
211 | could be a physical address, or it could be the time | ||
212 | of day xor'd with 0xdeadbeef. :-) | ||
213 | |||
214 | Whatever it is, it's an implementation detail. The | ||
215 | interface was done this way to shield the driver | ||
216 | author from such complexities. | ||
217 | |||
218 | Doing DVMA | ||
219 | |||
220 | SBUS devices can perform DMA transactions in a way similar | ||
221 | to PCI but dissimilar to ISA, e.g. DMA masters supply address. | ||
222 | In contrast to PCI, however, that address (a bus address) is | ||
223 | translated by IOMMU before a memory access is performed and therefore | ||
224 | it is virtual. Sun calls this procedure DVMA. | ||
225 | |||
226 | Linux supports two styles of using SBUS DVMA: "consistent memory" | ||
227 | and "streaming DVMA". CPU view of consistent memory chunk is, well, | ||
228 | consistent with a view of a device. Think of it as an uncached memory. | ||
229 | Typically this way of doing DVMA is not very fast and drivers use it | ||
230 | mostly for control blocks or queues. On some CPUs we cannot flush or | ||
231 | invalidate individual pages or cache lines and doing explicit flushing | ||
232 | over ever little byte in every control block would be wasteful. | ||
233 | |||
234 | Streaming DVMA is a preferred way to transfer large amounts of data. | ||
235 | This process works in the following way: | ||
236 | 1. a CPU stops accessing a certain part of memory, | ||
237 | flushes its caches covering that memory; | ||
238 | 2. a device does DVMA accesses, then posts an interrupt; | ||
239 | 3. CPU invalidates its caches and starts to access the memory. | ||
240 | |||
241 | A single streaming DVMA operation can touch several discontiguous | ||
242 | regions of a virtual bus address space. This is called a scatter-gather | ||
243 | DVMA. | ||
244 | |||
245 | [TBD: Why do not we neither Solaris attempt to map disjoint pages | ||
246 | into a single virtual chunk with the help of IOMMU, so that non SG | ||
247 | DVMA masters would do SG? It'd be very helpful for RAID.] | ||
248 | |||
249 | In order to perform a consistent DVMA a driver does something | ||
250 | like the following: | ||
251 | |||
252 | char *mem; /* Address in the CPU space */ | ||
253 | u32 busa; /* Address in the SBus space */ | ||
254 | |||
255 | mem = (char *) sbus_alloc_consistent(sdev, MYMEMSIZE, &busa); | ||
256 | |||
257 | Then mem is used when CPU accesses this memory and u32 | ||
258 | is fed to the device so that it can do DVMA. This is typically | ||
259 | done with an sbus_writel() into some device register. | ||
260 | |||
261 | Do not forget to free the DVMA resources once you are done: | ||
262 | |||
263 | sbus_free_consistent(sdev, MYMEMSIZE, mem, busa); | ||
264 | |||
265 | Streaming DVMA is more interesting. First you allocate some | ||
266 | memory suitable for it or pin down some user pages. Then it all works | ||
267 | like this: | ||
268 | |||
269 | char *mem = argumen1; | ||
270 | unsigned int size = argument2; | ||
271 | u32 busa; /* Address in the SBus space */ | ||
272 | |||
273 | *mem = 1; /* CPU can access */ | ||
274 | busa = sbus_map_single(sdev, mem, size); | ||
275 | if (busa == 0) ....... | ||
276 | |||
277 | /* Tell the device to use busa here */ | ||
278 | /* CPU cannot access the memory without sbus_dma_sync_single() */ | ||
279 | |||
280 | sbus_unmap_single(sdev, busa, size); | ||
281 | if (*mem == 0) .... /* CPU can access again */ | ||
282 | |||
283 | It is possible to retain mappings and ask the device to | ||
284 | access data again and again without calling sbus_unmap_single. | ||
285 | However, CPU caches must be invalidated with sbus_dma_sync_single | ||
286 | before such access. | ||
287 | |||
288 | [TBD but what about writeback caches here... do we have any?] | ||
289 | |||
290 | There is an equivalent set of functions doing the same thing | ||
291 | only with several memory segments at once for devices capable of | ||
292 | scatter-gather transfers. Use the Source, Luke. | ||
293 | |||
294 | Examples | ||
295 | |||
296 | drivers/net/sunhme.c | ||
297 | This is a complicated driver which illustrates many concepts | ||
298 | discussed above and plus it handles both PCI and SBUS boards. | ||
299 | |||
300 | drivers/scsi/esp.c | ||
301 | Check it out for scatter-gather DVMA. | ||
302 | |||
303 | drivers/sbus/char/bpp.c | ||
304 | A non-DVMA device. | ||
305 | |||
306 | drivers/net/sunlance.c | ||
307 | Lance driver abuses consistent mappings for data transfer. | ||
308 | It is a nifty trick which we do not particularly recommend... | ||
309 | Just check it out and know that it's legal. | ||