OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [Documentation/] [sparc/] [sbus_drivers.txt] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
 
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  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.

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.