diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /Documentation/sparc/sbus_drivers.txt |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'Documentation/sparc/sbus_drivers.txt')
-rw-r--r-- | Documentation/sparc/sbus_drivers.txt | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/Documentation/sparc/sbus_drivers.txt b/Documentation/sparc/sbus_drivers.txt new file mode 100644 index 000000000000..876195dc2aef --- /dev/null +++ b/Documentation/sparc/sbus_drivers.txt | |||
@@ -0,0 +1,272 @@ | |||
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 how probing is performed by an SBUS driver | ||
29 | under Linux: | ||
30 | |||
31 | static void init_one_mydevice(struct sbus_dev *sdev) | ||
32 | { | ||
33 | ... | ||
34 | } | ||
35 | |||
36 | static int mydevice_match(struct sbus_dev *sdev) | ||
37 | { | ||
38 | if (some_criteria(sdev)) | ||
39 | return 1; | ||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | static void mydevice_probe(void) | ||
44 | { | ||
45 | struct sbus_bus *sbus; | ||
46 | struct sbus_dev *sdev; | ||
47 | |||
48 | for_each_sbus(sbus) { | ||
49 | for_each_sbusdev(sdev, sbus) { | ||
50 | if (mydevice_match(sdev)) | ||
51 | init_one_mydevice(sdev); | ||
52 | } | ||
53 | } | ||
54 | } | ||
55 | |||
56 | All this does is walk through all SBUS devices in the | ||
57 | system, checks each to see if it is of the type which | ||
58 | your driver is written for, and if so it calls the init | ||
59 | routine to attach the device and prepare to drive it. | ||
60 | |||
61 | "init_one_mydevice" might do things like allocate software | ||
62 | state structures, map in I/O registers, place the hardware | ||
63 | into an initialized state, etc. | ||
64 | |||
65 | Mapping and Accessing I/O Registers | ||
66 | |||
67 | Each SBUS device structure contains an array of descriptors | ||
68 | which describe each register set. We abuse struct resource for that. | ||
69 | They each correspond to the "reg" properties provided by the OBP firmware. | ||
70 | |||
71 | Before you can access your device's registers you must map | ||
72 | them. And later if you wish to shutdown your driver (for module | ||
73 | unload or similar) you must unmap them. You must treat them as | ||
74 | a resource, which you allocate (map) before using and free up | ||
75 | (unmap) when you are done with it. | ||
76 | |||
77 | The mapping information is stored in an opaque value | ||
78 | typed as an "unsigned long". This is the type of the return value | ||
79 | of the mapping interface, and the arguments to the unmapping | ||
80 | interface. Let's say you want to map the first set of registers. | ||
81 | Perhaps part of your driver software state structure looks like: | ||
82 | |||
83 | struct mydevice { | ||
84 | unsigned long control_regs; | ||
85 | ... | ||
86 | struct sbus_dev *sdev; | ||
87 | ... | ||
88 | }; | ||
89 | |||
90 | At initialization time you then use the sbus_ioremap | ||
91 | interface to map in your registers, like so: | ||
92 | |||
93 | static void init_one_mydevice(struct sbus_dev *sdev) | ||
94 | { | ||
95 | struct mydevice *mp; | ||
96 | ... | ||
97 | |||
98 | mp->control_regs = sbus_ioremap(&sdev->resource[0], 0, | ||
99 | CONTROL_REGS_SIZE, "mydevice regs"); | ||
100 | if (!mp->control_regs) { | ||
101 | /* Failure, cleanup and return. */ | ||
102 | } | ||
103 | } | ||
104 | |||
105 | Second argument to sbus_ioremap is an offset for | ||
106 | cranky devices with broken OBP PROM. The sbus_ioremap uses only | ||
107 | a start address and flags from the resource structure. | ||
108 | Therefore it is possible to use the same resource to map | ||
109 | several sets of registers or even to fabricate a resource | ||
110 | structure if driver gets physical address from some private place. | ||
111 | This practice is discouraged though. Use whatever OBP PROM | ||
112 | provided to you. | ||
113 | |||
114 | And here is how you might unmap these registers later at | ||
115 | driver shutdown or module unload time, using the sbus_iounmap | ||
116 | interface: | ||
117 | |||
118 | static void mydevice_unmap_regs(struct mydevice *mp) | ||
119 | { | ||
120 | sbus_iounmap(mp->control_regs, CONTROL_REGS_SIZE); | ||
121 | } | ||
122 | |||
123 | Finally, to actually access your registers there are 6 | ||
124 | interface routines at your disposal. Accesses are byte (8 bit), | ||
125 | word (16 bit), or longword (32 bit) sized. Here they are: | ||
126 | |||
127 | u8 sbus_readb(unsigned long reg) /* read byte */ | ||
128 | u16 sbus_readw(unsigned long reg) /* read word */ | ||
129 | u32 sbus_readl(unsigned long reg) /* read longword */ | ||
130 | void sbus_writeb(u8 value, unsigned long reg) /* write byte */ | ||
131 | void sbus_writew(u16 value, unsigned long reg) /* write word */ | ||
132 | void sbus_writel(u32 value, unsigned long reg) /* write longword */ | ||
133 | |||
134 | So, let's say your device has a control register of some sort | ||
135 | at offset zero. The following might implement resetting your device: | ||
136 | |||
137 | #define CONTROL 0x00UL | ||
138 | |||
139 | #define CONTROL_RESET 0x00000001 /* Reset hardware */ | ||
140 | |||
141 | static void mydevice_reset(struct mydevice *mp) | ||
142 | { | ||
143 | sbus_writel(CONTROL_RESET, mp->regs + CONTROL); | ||
144 | } | ||
145 | |||
146 | Or perhaps there is a data port register at an offset of | ||
147 | 16 bytes which allows you to read bytes from a fifo in the device: | ||
148 | |||
149 | #define DATA 0x10UL | ||
150 | |||
151 | static u8 mydevice_get_byte(struct mydevice *mp) | ||
152 | { | ||
153 | return sbus_readb(mp->regs + DATA); | ||
154 | } | ||
155 | |||
156 | It's pretty straightforward, and clueful readers may have | ||
157 | noticed that these interfaces mimick the PCI interfaces of the | ||
158 | Linux kernel. This was not by accident. | ||
159 | |||
160 | WARNING: | ||
161 | |||
162 | DO NOT try to treat these opaque register mapping | ||
163 | values as a memory mapped pointer to some structure | ||
164 | which you can dereference. | ||
165 | |||
166 | It may be memory mapped, it may not be. In fact it | ||
167 | could be a physical address, or it could be the time | ||
168 | of day xor'd with 0xdeadbeef. :-) | ||
169 | |||
170 | Whatever it is, it's an implementation detail. The | ||
171 | interface was done this way to shield the driver | ||
172 | author from such complexities. | ||
173 | |||
174 | Doing DVMA | ||
175 | |||
176 | SBUS devices can perform DMA transactions in a way similar | ||
177 | to PCI but dissimilar to ISA, e.g. DMA masters supply address. | ||
178 | In contrast to PCI, however, that address (a bus address) is | ||
179 | translated by IOMMU before a memory access is performed and therefore | ||
180 | it is virtual. Sun calls this procedure DVMA. | ||
181 | |||
182 | Linux supports two styles of using SBUS DVMA: "consistent memory" | ||
183 | and "streaming DVMA". CPU view of consistent memory chunk is, well, | ||
184 | consistent with a view of a device. Think of it as an uncached memory. | ||
185 | Typically this way of doing DVMA is not very fast and drivers use it | ||
186 | mostly for control blocks or queues. On some CPUs we cannot flush or | ||
187 | invalidate individual pages or cache lines and doing explicit flushing | ||
188 | over ever little byte in every control block would be wasteful. | ||
189 | |||
190 | Streaming DVMA is a preferred way to transfer large amounts of data. | ||
191 | This process works in the following way: | ||
192 | 1. a CPU stops accessing a certain part of memory, | ||
193 | flushes its caches covering that memory; | ||
194 | 2. a device does DVMA accesses, then posts an interrupt; | ||
195 | 3. CPU invalidates its caches and starts to access the memory. | ||
196 | |||
197 | A single streaming DVMA operation can touch several discontiguous | ||
198 | regions of a virtual bus address space. This is called a scatter-gather | ||
199 | DVMA. | ||
200 | |||
201 | [TBD: Why do not we neither Solaris attempt to map disjoint pages | ||
202 | into a single virtual chunk with the help of IOMMU, so that non SG | ||
203 | DVMA masters would do SG? It'd be very helpful for RAID.] | ||
204 | |||
205 | In order to perform a consistent DVMA a driver does something | ||
206 | like the following: | ||
207 | |||
208 | char *mem; /* Address in the CPU space */ | ||
209 | u32 busa; /* Address in the SBus space */ | ||
210 | |||
211 | mem = (char *) sbus_alloc_consistent(sdev, MYMEMSIZE, &busa); | ||
212 | |||
213 | Then mem is used when CPU accesses this memory and u32 | ||
214 | is fed to the device so that it can do DVMA. This is typically | ||
215 | done with an sbus_writel() into some device register. | ||
216 | |||
217 | Do not forget to free the DVMA resources once you are done: | ||
218 | |||
219 | sbus_free_consistent(sdev, MYMEMSIZE, mem, busa); | ||
220 | |||
221 | Streaming DVMA is more interesting. First you allocate some | ||
222 | memory suitable for it or pin down some user pages. Then it all works | ||
223 | like this: | ||
224 | |||
225 | char *mem = argumen1; | ||
226 | unsigned int size = argument2; | ||
227 | u32 busa; /* Address in the SBus space */ | ||
228 | |||
229 | *mem = 1; /* CPU can access */ | ||
230 | busa = sbus_map_single(sdev, mem, size); | ||
231 | if (busa == 0) ....... | ||
232 | |||
233 | /* Tell the device to use busa here */ | ||
234 | /* CPU cannot access the memory without sbus_dma_sync_single() */ | ||
235 | |||
236 | sbus_unmap_single(sdev, busa, size); | ||
237 | if (*mem == 0) .... /* CPU can access again */ | ||
238 | |||
239 | It is possible to retain mappings and ask the device to | ||
240 | access data again and again without calling sbus_unmap_single. | ||
241 | However, CPU caches must be invalidated with sbus_dma_sync_single | ||
242 | before such access. | ||
243 | |||
244 | [TBD but what about writeback caches here... do we have any?] | ||
245 | |||
246 | There is an equivalent set of functions doing the same thing | ||
247 | only with several memory segments at once for devices capable of | ||
248 | scatter-gather transfers. Use the Source, Luke. | ||
249 | |||
250 | Examples | ||
251 | |||
252 | drivers/net/sunhme.c | ||
253 | This is a complicated driver which illustrates many concepts | ||
254 | discussed above and plus it handles both PCI and SBUS boards. | ||
255 | |||
256 | drivers/scsi/esp.c | ||
257 | Check it out for scatter-gather DVMA. | ||
258 | |||
259 | drivers/sbus/char/bpp.c | ||
260 | A non-DVMA device. | ||
261 | |||
262 | drivers/net/sunlance.c | ||
263 | Lance driver abuses consistent mappings for data transfer. | ||
264 | It is a nifty trick which we do not particularly recommend... | ||
265 | Just check it out and know that it's legal. | ||
266 | |||
267 | Bad examples, do NOT use | ||
268 | |||
269 | drivers/video/cgsix.c | ||
270 | This one uses result of sbus_ioremap as if it is an address. | ||
271 | This does NOT work on sparc64 and therefore is broken. We will | ||
272 | convert it at a later date. | ||