diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2006-06-24 01:12:39 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-06-24 02:16:17 -0400 |
commit | 9eccf1b3121f7e407d3159908f29252887194a16 (patch) | |
tree | da29cdcbe783e62dfffde79c77d0f0f846960272 | |
parent | 3d4253d9afabd6d42c33812a839ba67b8c9bbe49 (diff) |
[Documentation]: Update probing info in sbus_drivers.txt
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | Documentation/sparc/sbus_drivers.txt | 95 |
1 files changed, 65 insertions, 30 deletions
diff --git a/Documentation/sparc/sbus_drivers.txt b/Documentation/sparc/sbus_drivers.txt index 876195dc2aef..4b9351624f13 100644 --- a/Documentation/sparc/sbus_drivers.txt +++ b/Documentation/sparc/sbus_drivers.txt | |||
@@ -25,42 +25,84 @@ the bits necessary to run your device. The most commonly | |||
25 | used members of this structure, and their typical usage, | 25 | used members of this structure, and their typical usage, |
26 | will be detailed below. | 26 | will be detailed below. |
27 | 27 | ||
28 | Here is how probing is performed by an SBUS driver | 28 | Here is a piece of skeleton code for perofming a device |
29 | under Linux: | 29 | probe in an SBUS driverunder Linux: |
30 | 30 | ||
31 | static void init_one_mydevice(struct sbus_dev *sdev) | 31 | static int __devinit mydevice_probe_one(struct sbus_dev *sdev) |
32 | { | 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; | ||
33 | ... | 41 | ... |
34 | } | 42 | } |
35 | 43 | ||
36 | static int mydevice_match(struct sbus_dev *sdev) | 44 | static int __devinit mydevice_probe(struct of_device *dev, |
45 | const struct of_device_id *match) | ||
37 | { | 46 | { |
38 | if (some_criteria(sdev)) | 47 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); |
39 | return 1; | 48 | |
40 | return 0; | 49 | return mydevice_probe_one(sdev); |
41 | } | 50 | } |
42 | 51 | ||
43 | static void mydevice_probe(void) | 52 | static int __devexit mydevice_remove(struct of_device *dev) |
44 | { | 53 | { |
45 | struct sbus_bus *sbus; | 54 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); |
46 | struct sbus_dev *sdev; | 55 | struct mydevice *mp = dev_get_drvdata(&dev->dev); |
47 | 56 | ||
48 | for_each_sbus(sbus) { | 57 | return mydevice_remove_one(sdev, mp); |
49 | for_each_sbusdev(sdev, sbus) { | ||
50 | if (mydevice_match(sdev)) | ||
51 | init_one_mydevice(sdev); | ||
52 | } | ||
53 | } | ||
54 | } | 58 | } |
55 | 59 | ||
56 | All this does is walk through all SBUS devices in the | 60 | static struct of_device_id mydevice_match[] = { |
57 | system, checks each to see if it is of the type which | 61 | { |
58 | your driver is written for, and if so it calls the init | 62 | .name = "mydevice", |
59 | routine to attach the device and prepare to drive it. | 63 | }, |
64 | {}, | ||
65 | }; | ||
66 | |||
67 | MODULE_DEVICE_TABLE(of, mydevice_match); | ||
60 | 68 | ||
61 | "init_one_mydevice" might do things like allocate software | 69 | static struct of_platform_driver mydevice_driver = { |
62 | state structures, map in I/O registers, place the hardware | 70 | .name = "mydevice", |
63 | into an initialized state, etc. | 71 | .match_table = mydevice_match, |
72 | .probe = mydevice_probe, | ||
73 | .remove = __devexit_p(mydevice_remove), | ||
74 | }; | ||
75 | |||
76 | static int __init mydevice_init(void) | ||
77 | { | ||
78 | return of_register_driver(&mydevice_driver, &sbus_bus_type); | ||
79 | } | ||
80 | |||
81 | static void __exit mydevice_exit(void) | ||
82 | { | ||
83 | of_unregister_driver(&mydevice_driver); | ||
84 | } | ||
85 | |||
86 | module_init(mydevice_init); | ||
87 | module_exit(mydevice_exit); | ||
88 | |||
89 | The mydevice_match table is a series of entries which | ||
90 | describes what SBUS devices your driver is meant for. In the | ||
91 | simplest case you specify a string for the 'name' field. Every | ||
92 | SBUS device with a 'name' property matching your string will | ||
93 | be passed one-by-one to your .probe method. | ||
94 | |||
95 | You should store away your device private state structure | ||
96 | pointer in the drvdata area so that you can retrieve it later on | ||
97 | in your .remove method. | ||
98 | |||
99 | Any memory allocated, registers mapped, IRQs registered, | ||
100 | etc. must be undone by your .remove method so that all resources | ||
101 | of your device are relased by the time it returns. | ||
102 | |||
103 | You should _NOT_ use the for_each_sbus(), for_each_sbusdev(), | ||
104 | and for_all_sbusdev() interfaces. They are deprecated, will be | ||
105 | removed, and no new driver should reference them ever. | ||
64 | 106 | ||
65 | Mapping and Accessing I/O Registers | 107 | Mapping and Accessing I/O Registers |
66 | 108 | ||
@@ -263,10 +305,3 @@ discussed above and plus it handles both PCI and SBUS boards. | |||
263 | Lance driver abuses consistent mappings for data transfer. | 305 | Lance driver abuses consistent mappings for data transfer. |
264 | It is a nifty trick which we do not particularly recommend... | 306 | It is a nifty trick which we do not particularly recommend... |
265 | Just check it out and know that it's legal. | 307 | 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. | ||