root/lm-sensors/trunk/doc/design @ 14

Revision 14, 18.2 KB (checked in by frodo, 14 years ago)

update of doc/design; it now reflects the code again (which is nice
for a design document :-) ).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1This is a design for version 2 of our smbus and lm_sensors module. This
2document is Copyright (c) 1998 by Frodo Looijaard. You may freely copy and
3distribute it, as long as you recognize me as the author, and mark any
4changes you make as being your own, and distribute this notice with it.
5
6Document version 1.0, 19981101.
7                 1.1, 19981111.
8                 1.2, 19981118.
9                 1.3, 19981126.
10
11
12Object oriented approach
13========================
14
15The i2c module structs contain callback functions and data fields. In the
16i2c module, these structures are only referenced by pointers. This makes
17it easy to extend these structs to contain additional information or
18callback functions. For those familiar with object oriented languages,
19you can see the smbus and isa structures as an object extension of the i2c
20structures.
21
22To make this clearer, I will show in an example how this is done. Note
23that I have simplified some things here, so this example does not
24correspond to an actual struct found in one of the modules.
25
26In the i2c module, you can find a struct somewhat like this:
27
28struct i2c_adapter {
29  char name[32];
30  int (*detach_client) (struct i2c_client *);
31  struct i2c_adapter *next;
32}
33
34We have a plain data field (name), a call-back function which needs one
35parameter (a pointer to a i2c_client struct), and a data field which is
36a pointer to the next adapter.
37
38Now we want to extend this structure. We need another data field,
39containing a number of flags. We will call this new structure smbus_adapter.
40A few other things change too:
41
42struct smbus_adapter {
43  char name[32];
44  int (*detach_client) (struct smbus_client *);
45  struct smbus_adapter *next;
46  unsigned int flags;
47}
48
49So we copy all existing fields. The next field still points to the next
50adapter - but it is now of type smbus_adapter, not i2c_adapter. And the
51call-back function takes now a parameter of type pointer to smbus_client.
52And there is a new data field, called flags.
53
54Now examine this function definition:
55
56int fully_detach_i2c_client (struct i2c_client * client)
57{
58  res = 0;
59  struct i2c_adapter *current_adapter = first_adapter; /* a global var. */
60  while (current_adapter) {
61    res |= (current_adapter -> detach_client) (client);
62    current_adapter = current_adapter -> next;
63  }
64  return res;
65}
66
67This function detaches a client from all adapters. Nice. But now comes the
68Big Trick(tm): we can still use this function for smbus_adapters!
69
70int fully_detach_smbus_client (struct smbus_client * client)
71{
72  return fully_detach_i2c_client( (struct i2c_client *) client);
73}
74
75All we needed here was a simple typecast. Datapointers remain datapointers,
76so this can safely be done. And because we use call-back functions, the
77actual function called to detach a client from a single adapter might
78be the same, or different, depending on what function was put in
79client->detach_client!
80
81It gets even better. The i2c module stores internally all registered
82adapters. But it stores pointers to the i2c_adapter struct, not the
83structs themselves! So there is an array:
84
85#define I2C_ADAPTER_MAX 32
86struct i2c_adapter *adapters[I2C_ADAPTER_MAX];
87/* this is an array of pointers to structs, not vice versa! */
88
89So, an element of this array might in fact point to a smbus_adapter, instead
90of an i2c_adapter! If you know this for sure, you might use a typecast and
91access the additional fields. In the meantime, the i2c internal
92administration remains valid.
93
94We have to thank Simon Vogl and Gerd Knorr for the way they implemented
95their i2c module. Any other way would have made this approach impossible,
96and basing anything upon their module much more difficult.
97
98Limitations
99-----------
100
101Extending the adapter and algorithm structures in this way is quite safe.
102They are only allocated on places where the code knows that they are
103'special'. Extending the driver or client structures depending on a
104specific adapter/algorithm type is *very* *dangerous*. A driver/client
105module would need to be aware of every special adapter/algorithm in
106order to allocate itself! For the ISA bus, it has to be aware of this
107anyway, so it is safe to do; on other places, think twice first!
108
109
110Module overview
111===============
112
113All in all, lots of modules will be stacked on each other. Too bad, but
114that is the only way to cleanly implement everything. Note that in a
115specific situation, only a few modules may need to be loaded. isa.o,
116for example, does not depend on smbus.o (in the sense that you can load
117sensor.o without loading smbus.o). A specific bus driver, though, will
118depend on many of them.
119
120Generally:
121  isa.o depends on nothing (actually, on i2c.o, to keep the code small)
122  smbus.o depends on nothing (actually, on i2c.o, to keep the code small)
123  i2c.o depends on nothing.
124
125  A non-i2c SMBus bus driver depends only on smbus.o
126  A i2c bus driver depends only on i2c.o
127
128  A sensor chip driver depends either on isa.o or smbus.o, or both.
129  A SMBus chip driver depends only on smbus.o
130  A I2C chip driver depends only on i2c.o
131
132We may need a sensor.o module, to act as a central point for sensor
133modules. At this moment, it seems not really necessary, but this may
134change.
135
136We will need an enhanced i2c-dev.o module, to add SMBus access to I2C
137/dev entries.
138
139
140isa.o
141ISA bus handling.
142Encapsulates ISA bus access within the i2c structures.
143Unites I2C adapters and the ISA bus.
144Defines variables isa_algorithm and isa_adapter.
145
146smbus.o
147Main SMBus handling.
148Encapsulates SMBus access within the smbus structures.
149Unites I2C adapters and SMBus hosts (like the PIIX4).
150Emulates SMBus access on pure I2C adapters.
151Defines variable smbus_algorithm.
152
153  piix4.o
154  SMBus adapter driver for the PIIX4 SMBus host.
155  Defines variable piix4_adapter (based on smbus_algorithm).
156
157  FOO.o
158  Adapter driver for FOO SMBus host
159  Defines variable FOO_adapter (based on smbus_algorithm).
160
161i2c-core.o (From Simon Vogl)
162Main i2c handling.
163
164  ????.o
165  I2C adapter driver
166  Implementing a class of I2C busses
167
168
169A chip driver (typically defined in its own module) can be hooked on all
170these levels:
171  * If it is a sensor chip, it should be hooked to isa.o or smbus.o
172  * A pure ISA chip should be hooked to isa.o
173  * A pure SMBus chip should be hooked to smbus.o
174  * An I2C chip should be hooked to i2c.o
175It can be difficult to decide whether a specific chip should be hooked to
176smbus.o or i2c.o. A good deciding question is, 'could it be connected to
177a PIIX4?'
178
179
180Module i2c.o
181============
182
183This is Simon Vogl's i2c module (this one is different from the i2c module
184included in kernels around 1.2.120!).
185
186A driver
187--------
188
189struct i2c_driver {
190  char name[32];
191  int id;
192  unsigned int flags;
193  int (* attach_adapter) (struct i2c_adapter *);
194  int (* detach_client) (struct i2c_client *);
195  int (* command) (struct i2c_client *, unsigned int cmd, void *arg);
196  void (* inc_use) (struct i2c_client *);
197  void (* dec_use) (struct i2c_client *);
198}
199
200A driver tells us how we should handle a specific type of i2c chip. An
201instance of such a chip is called a 'client'. An example would be the LM75
202module: it would contain only one driver, which tells us how to handle the
203LM75; but each detected LM75 would be a separate client (which would be
204dynamically allocated).
205
206
207A description of the above struct:
208  name: The name of this driver
209  id: A unique driver identifier
210  flags: Flags to set certain kinds of behaviour. Most notably, DF_NOTIFY
211    will notify the driver when a new i2c bus is detected, so it can
212    try to detect chips on it.
213  attach_adapter: A call-back function which is called if a new adapter (bus)
214    is found. This allows us to do our detection stuff on the new adapter,
215    and register new clients.
216  detach_client: A call-back function which is called if a specific client
217    which uses this driver should be disallocated. If a specific sensor module
218    is removed, for instance, this function would be called for each registered
219    client.
220  command: A generic call-back function to communicate in a driver-dependent
221    way with a specific client. This should only be seldom needed.
222  inc_use: Can be called to add one to an internal 'use' counter. This can be
223    used to control when it is safe to remove this module, for example.
224
225
226A client
227--------
228
229struct i2c_client {
230  char name[32];
231  int id;
232  unsigned int flags;
233  unsigned char addr;
234  struct i2c_adapter *adapter;
235  struct i2c_driver *driver;
236  void *data;
237}
238
239A client is a specific sensor chip. Its operation is controlled by a driver
240(which describes a type of sensor chip), and it is connected to an adapter
241(a bus).
242
243A description of the above struct:
244  name: The name of this client
245  id: A unique client id
246  flags: Flags to set certain kinds of behaviour (not very important)
247  addr: The client address. 10-bit addresses are a bit of a kludge right now.
248  adapter: A pointer to the adapter this client is on.
249  driver: A pointer to the driver this client uses.
250  data: Additional, client-dependent data
251
252
253An algorithm
254------------
255
256struct i2c_algorithm {
257  char name[32];
258  unsigned int id;
259  int (* master_xfer) (struct i2c_adapter *adap, struct i2c_msg msgs[],
260                       int num);
261  int (* slave_send) (struct i2c_adapter *,char *, int);
262  int (* slave_recv) (struct i2c_adapter *,char *, int);
263  int (* algo_control) (struct i2c_adapter *, unsigned int, unsigned long);
264  int (* client_register) (struct i2c_client *);
265  int (* client_unregister) (struct i2c_client *);
266}
267
268An algorithm describes how a certain class of i2c busses can be accessed.
269
270A description of the above struct:
271  name: The name of this algorithm
272  id: A unique algorithm id
273  master_xfer: Transfer a bunch of messages through a specific i2c bus.
274  slave_send: Send a message as if we are a slave device
275  slave_recv: Receive a message as if we are a slave device
276  client_register: Register a new client
277  client_unregister: Unregister a client
278
279
280An adapter
281----------
282
283struct i2c_adapter {
284  char name[32];
285  unsigned int id;
286  struct i2c_algorithm *algo;
287  void *data;
288#ifdef SPINLOCK
289  spinlock_t lock;
290  unsigned long lockflags;
291#else
292  struct semaphore lock;
293#endif
294  unsigned int flags;
295  struct i2c_client *clients[I2C_CLIENT_MAX];
296  int client_count;
297  int timeout;
298  int retries;
299}
300
301An adapter is a specific i2c bus. How to access it is defined in the
302algorithm associated with it.
303
304A description of the above struct:
305  name: The name of this adapter
306  id: A unique adapter id
307  algo: The algorithm through which this bus must be accessed
308  data: Adapter specific data
309  lock, lockflags: To lock out simultaneous adapter access
310  flags: Modifiers for adapter operation
311  clients: All currently connected clients
312  client_count: The number of currently connected clients
313  timeout, retries: Internal variables (unimportant here).
314
315
316Access functions
317----------------
318
319All these functions are defined extern.
320
321int i2c_master_send(struct i2c_client *,const char *, int);
322int i2c_master_recv(struct i2c_client *,char *, int);
323int i2c_transfer(struct i2c_adapter *,struct i2c_msg [], int num);
324
325These function respectively send one message to a client, receive one message
326from a client, or transmit a bunch of messages. struct i2c_msg contains
327an i2c address to communicate with, and can both read from and write to this
328address.
329
330
331int i2c_slave_send(struct i2c_client *, char *, int);
332int i2c_slave_recv(struct i2c_client *, char *, int);
333
334Communicate with another master as if the normal master is a common slave
335device.
336
337
338Administration functions
339------------------------
340
341int i2c_add_algorithm(struct i2c_algorithm *);
342int i2c_del_algorithm(struct i2c_algorithm *);
343
344The i2c_{add,del}_algorithm functions must be called whenever a new module
345is inserted with this driver in it, by the module initialization function.
346
347
348int i2c_add_adapter(struct i2c_adapter *);
349int i2c_del_adapter(struct i2c_adapter *);
350
351The i2c_{add,del}_adapter functions must be called if you have detected
352a specific bus. It triggers driver->attach_adapter (add, for each driver
353present) or driver->detach_client (del, for each registered client on
354this adapter).
355
356
357int i2c_add_driver(struct i2c_driver *);
358int i2c_del_driver(struct i2c_driver *);
359
360The i2c_{add,del}_driver functions must be called whenever a new module is
361inserted with a chip driver in it, by the module initialization function.
362
363
364int i2c_attach_client(struct i2c_client *);
365int i2c_detach_client(struct i2c_client *);
366
367The i2c_{attach,detach}_client functions must be called if you have detected
368a single chip.
369
370
371Module smbus.o
372==============
373
374This module offers support for SMBus operation. An SMBus adapter can either
375accept SMBus commands (like the PIIX4), or be in fact an I2C driver. In
376the last case, all SMBus commands will be expressed through I2C primitives.
377This means that any I2C adapter driver will automatically be a SMBus
378driver.
379
380At this point, it should be noted that there can only be one System
381Management Bus in a given system (is this really true, by the way?). This
382means there must be some way of selecting which of the many possible adapters
383is in fact *the* SMBus. For now, I will ignore this problem. Later on,
384we can add a hook somewhere in the i2c module to help us decide this.
385
386This module consists in fact of three separate parts: first of all, it extends
387all i2c structs to accomodate the new smbus fields. Second, it defines a
388new algorithm (smbus_algorithm), that will be used by all non-i2c adapters.
389Finally, it implements a new access function that sends or receives SMBus
390commands; these are either translated into I2C commands or sent to the
391SMBus driver.
392
393
394A driver, client and algorithm
395------------------------------
396
397We will not need to extend i2c_driver, i2c_client or i2c_adapter. This means
398that struct smbus_driver is exactly the same as struct i2c_driver, and
399struct smbus_client is the same as struct i2c_client, and smbus_adapter is
400the same as struct i2c_adapter. We *will* define the smbus_* variants, and
401use them within this module, so it should be easy to extend them after all.
402
403Note that at this moment, 10 bit SMBus addresses seem to be only
404partially supported by the i2c module. We will ignore this issue for
405now.
406
407
408An adapter
409------------
410
411struct smbus_adapter {
412  char name[32];
413  unsigned int id;
414  struct smbus_algorithm *algo;
415  void *data;
416#ifdef SPINLOCK
417  spinlock_t lock;
418  unsigned long lockflags;
419#else
420  struct semaphore lock;
421#endif
422  unsigned int flags;
423  struct smbus_client *clients[I2C_CLIENT_MAX];
424  int client_count;
425  int timeout;
426  int retries;
427
428  /* Here ended i2c_adapter */
429  s32 (* smbus_access) (__u8 addr, char read_write,
430                        __u8 command, int size, union smbus_data * data);
431}
432
433A description of the above struct:
434  smbus_access: A function to access the SMBus. It is only used for non-i2c
435      smbus adapters.
436
437
438Access functions
439----------------
440
441All these functions are defined extern.
442
443The i2c access function should not be used within SMBus chip drivers, as
444they might not be defined (for the PIIX4, for example). Instead, use the
445following general access function, or one of the easier functions based
446on it:
447
448int smbus_access (struct i2c_adapter *, __u8 addr, char read_write,
449                  __u8 command, int size, union smbus_data * data);
450
451There are specific SMBus registration functions too, like the i2c ones.
452They are fully compatiable with each other; just substitute 'smbus' for
453'i2c' everywhere in the i2c description.
454
455int i2c_is_smbus_client(struct i2c_client *);
456int i2c_is_smbus_adapter(struct i2c_adapter *);
457
458Decide whether this client, or adapter, is (on) a non-I2C SMBus. Usually
459not needed, but it is nice anyway to be able to decide this.
460
461
462Module isa.o
463============
464
465This module implements a new algorithm and a specific adapter for the
466(single) ISA bus in your computer. This makes writing drivers for chips
467that can be both on ISA and SMBus much easier.
468
469Note that this module does *not* in any way depend on smbus.o (previous
470versions of this document still assumed it would be build upon it; this
471is no longer true).
472
473
474A driver, adapter or algorithm
475------------------------------
476
477We will not need to extend i2c_driver, i2c_adapter or i2c_algorithm. This
478means that struct isa_driver is exactly the same as struct i2c_driver,
479struct isa_adapter is the same as struct i2c_adapter and struct isa_algorithm
480is the same as struct isa_driver. We *will* define the isa_* variants, and
481use them within this module, so it should be easy to extend them after all.
482
483
484A client
485--------
486
487struct isa_client {
488  char name[32];
489  int id;
490  unsigned int flags;
491  unsigned char addr;
492  struct isa_adapter *adapter;
493  struct isa_driver *driver;
494  void *data;
495
496  unsigned int isa_addr;
497}
498
499A client is a specific sensor chip. Its operation is controlled by a driver
500(which describes a type of sensor chip), and it is connected to an adapter
501(a bus, the (single) ISA bus here).
502
503A description of the above struct:
504  isa_addr: ISA addresses do not fit in the i2c-compatible addr field, so
505    we needed a new field.
506
507
508Access functions
509----------------
510
511All these functions are defined extern.
512
513In case of the ISA bus, the master_xfer, slave_send and slave_recv hooks
514will be NULL, because these functions make no sense. It is regrettably
515not easy to create an access abstraction in which both ISA bus access
516and SMBus access are united. See below for examples how you can solve
517this problem.
518
519The most imporant additional access function:
520
521int i2c_is_isa_client(struct i2c_client *);
522int i2c_is_isa_adapter(struct i2c_adapter *);
523
524Decide whether this client, or adapter, is (on) the ISA bus. This is
525important, because it determines whether we can use the SMBus access
526routines.
527
528As an example, I will here implement our old LM78 access function:
529
530/* The SMBus locks itself, but ISA access must be locked explicitely!
531   We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks,
532   would slow down the LM78 access and should not be necessary.
533   There are some ugly typecasts here, but the good new is - they should
534   nowhere else be necessary! */
535int lm78_read_value(struct i2c_client *client, u8 reg)
536{
537  int res;
538  if (i2c_is_isa_client(client)) {
539    down((struct semaphore *) (client->data));
540    outb_p(reg,(((struct isa_client *) client)->isa_addr) +
541               LM78_ADDR_REG_OFFSET);
542    res = inb_p((((struct isa_client *) client)->isa_addr) +
543                LM78_DATA_REG_OFFSET);
544    up((struct semaphore *) (client->data));
545    return res;
546  } else
547    return smbus_read_byte_data(client->adapter,client->addr, reg);
548}
Note: See TracBrowser for help on using the browser.