root/lm-sensors/trunk/src/smbus.c @ 13

Revision 13, 5.9 KB (checked in by frodo, 15 years ago)

Example lm_sensors-2 driver

Though it is called the LM78 driver, there is not too much LM78 specific
code in it; it can better be seen as an example code skeleton for other
drivers. Right now, it creats a file /proc/sensors-test, which contains
a list of busses it registered itself on. Stupid, but very useful for
testing purposes!

You need a 2.0 kernel for lm78.o to insert (or hack the /proc system
specific parts; see lm78.c of lm_sensors version 1 how to do this).
Other parts of lm_sensors-2 are not tested for 2.1 kernels either, but
I am certain it won't work in this case :-).

See the TODO list to get some idea what is left to do, choose something
and implement it. Or not :-). But please, send a note to the mailing
list when you start on something, to avoid duplicate work...

Other notable changes:

the smbus_access routines now use (the more logical) i2c_adapter
structure, instead of smbus_adapter.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    smbus.c - A Linux module for reading sensor data.
3    Copyright (c) 1998  Frodo Looijaard <frodol@dds.nl>
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18*/
19
20#include <linux/module.h>
21#include <linux/kernel.h>
22
23#include "i2c.h"
24#ifdef SPINLOCK
25#include <asm/spinlock.h>
26#else
27#include <asm/semaphore.h>
28#endif
29
30#include "version.h"
31#include "smbus.h"
32
33static s32 smbus_access_i2c (struct i2c_adapter * adapter, u8 addr,
34                             char read_write, u8 command, int size,
35                             union smbus_data * data);
36
37static int smbus_master_xfer (struct smbus_adapter *adap,
38                              struct i2c_msg msgs[], int num);
39static int smbus_slave_send (struct smbus_adapter *adap, char *data, int len);
40static int smbus_slave_recv (struct smbus_adapter *adap, char *data, int len);
41static int smbus_algo_control (struct smbus_adapter *adap, unsigned int cmd, 
42                               unsigned long arg);
43static int smbus_client_register (struct smbus_client *client);
44static int smbus_client_unregister (struct smbus_client *client);
45
46static int smbus_init(void);
47static int smbus_cleanup(void);
48
49#ifdef MODULE
50extern int init_module(void);
51extern int cleanup_module(void);
52#endif /* MODULE */
53
54/* This is the actual algorithm we define */
55struct smbus_algorithm smbus_algorithm = {
56  /* name */            "Non-I2C SMBus adapter",
57  /* id */              ALGO_SMBUS,
58  /* master_xfer */     &smbus_master_xfer,
59  /* slave_send */      &smbus_slave_send,
60  /* slave_rcv */       &smbus_slave_recv,
61  /* algo_control */    &smbus_algo_control,
62  /* client_register */ &smbus_client_register,
63  /* client_unregister*/&smbus_client_unregister
64};
65
66
67/* OK, so you want to access a bus using the SMBus protocols. Well, it either
68   is registered as a SMBus-only adapter (like the PIIX4), or we need to
69   simulate the SMBus commands using the i2c access routines.
70   We do all locking here, so you can ignore that in the adapter-specific
71   smbus_accesss routine. */
72s32 smbus_access (struct i2c_adapter * adapter, u8 addr, char read_write,
73                  u8 command, int size, union smbus_data * data)
74{
75  int res;
76#ifdef SPINLOCK
77  spin_lock_irqsave(&adapter->lock,adapter->lockflags);
78#else
79  down(&adapter->lock);
80#endif
81  if (adapter->id & ALGO_SMBUS) 
82    res = ((struct smbus_adapter *) adapter) -> 
83           smbus_access(addr,read_write,command,size,data);
84  else
85    res = smbus_access_i2c(adapter,addr,read_write,command,size,data);
86#ifdef SPINLOCK
87  spin_unlock_irqrestore(&adapter->lock,adapter->lockflags);
88#else
89  up(&adapter->lock);
90#endif
91  return res;
92}
93 
94/* Simulate a SMBus command using the i2c protocol
95   No checking of paramters is done!
96   For SMBUS_QUICK: Use addr, read_write
97   For SMBUS_BYTE: Use addr, read_write, command
98   ....  */
99s32 smbus_access_i2c(struct i2c_adapter * adapter, u8 addr, char read_write,
100                     u8 command, int size, union smbus_data * data)
101{
102  /* So we need to generate a series of msgs */
103  struct i2c_msg msg[2];
104  char msgbuf0[2];
105  char msgbuf1[32];
106  msg[0].addr = addr;
107  msg[0].flags = read_write;
108  msg[0].len = 0;
109  msg[0].buf = msgbuf0;
110  /* WHATEVER */
111}
112
113/* Algorithm master_xfer call-back implementation. Can't do that... */
114int smbus_master_xfer (struct smbus_adapter *adap, struct i2c_msg msgs[], 
115                       int num)
116{
117  printk("smbus_master_xfer called for adapter `%s' "
118         "(no i2c level access possible!)\n",
119         adap->name);
120  return 0;
121}
122
123/* Algorithm slave_send call-back implementation. Can't do that... */
124int smbus_slave_send (struct smbus_adapter *adap, char *data, int len)
125{
126  printk("smbus_slave_send called for adapter `%s' "
127         "(no i2c level access possible!)\n",
128         adap->name);
129  return 0;
130}
131
132/* Algorithm slave_recv call-back implementation. Can't do that... */
133int smbus_slave_recv (struct smbus_adapter *adap, char *data, int len)
134{
135  printk("smbus_slave_recv called for adapter `%s' "
136         "(no i2c level access possible!)\n",
137         adap->name);
138  return 0;
139}
140
141/* Here we can put additional calls to modify the workings of the algorithm.
142   But right now, there is no need for that. */
143int smbus_algo_control (struct smbus_adapter *adap, unsigned int cmd, 
144                         unsigned long arg)
145{
146  return 0;
147}
148
149/* Ehm... This is called when a client is registered to an adapter. We could
150   do all kinds of neat stuff here like, ehm - returning success? */
151int smbus_client_register (struct smbus_client *client)
152{
153  return 0;
154}
155 
156int smbus_client_unregister (struct smbus_client *client)
157{
158  return 0;
159}
160
161int smbus_init(void)
162{
163  int res;
164  printk("smbus.o version %s (%s)\n",LM_VERSION,LM_DATE);
165  if ((res = smbus_add_algorithm(&smbus_algorithm)))
166    printk("Module smbus.o not inserted!\n");
167  else
168    printk("smbus.o initialized\n");
169  return res;
170}
171
172int smbus_cleanup(void)
173{
174  int res;
175  if ((res = smbus_del_algorithm(&smbus_algorithm)))
176    printk("Module smbus.o could not be removed cleanly!\n");
177  return res;
178}
179
180/* OK, this will for now _only_ compile as a module, but this is neat for
181   later, if we want to compile it straight into the kernel */
182#ifdef MODULE
183
184MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
185MODULE_DESCRIPTION("System Management Bus (SMBus) access");
186
187int init_module(void)
188{
189  return smbus_init();
190}
191
192int cleanup_module(void)
193{
194  return smbus_cleanup();
195}
196
197#endif /* MODULE */
Note: See TracBrowser for help on using the browser.