root/lm-sensors/trunk/kernel/chips/matorb.c @ 1705

Revision 1705, 7.7 KB (checked in by kmalkki, 10 years ago)

(Kyösti) Cleanups

Copy sysctl enums to chip drivers from sensors.h for now,
as seen in drivers included in 2.5 tree. File no longer included
from kernel side.

Apply i2c-proc change in CVS tagged -km2.

Partial clean and sort of includes everywhere.

Add i2c-dev.h, as a partial copy from i2c.
Add to sensors.h from i2c-proc.h to compile things.
Remove i2c-isa.h.

Reflect header file changes to lib/ and prog/.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    matorb.c - Part of lm_sensors, Linux kernel modules for hardware
3             monitoring
4    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>
5    and Philip Edelbrock <phil@netroedge.com>
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*/
21
22
23#define DEBUG 1
24
25#include <linux/module.h>
26#include <linux/slab.h>
27#include <linux/i2c.h>
28#include <linux/i2c-proc.h>
29#include <linux/init.h>
30#include "version.h"
31
32MODULE_LICENSE("GPL");
33
34/* Addresses to scan */
35static unsigned short normal_i2c[] = { 0x2E, SENSORS_I2C_END };
36static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
37static unsigned int normal_isa[] = { SENSORS_ISA_END };
38static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
39
40/* Insmod parameters */
41SENSORS_INSMOD_1(matorb);
42
43/* Many MATORB constants specified below */
44
45
46/* Each client has this additional data */
47struct matorb_data {
48        int sysctl_id;
49
50        struct semaphore update_lock;
51        char valid;             /* !=0 if following fields are valid */
52        unsigned long last_updated;     /* In jiffies */
53
54};
55
56static int matorb_attach_adapter(struct i2c_adapter *adapter);
57static int matorb_detect(struct i2c_adapter *adapter, int address,
58                         unsigned short flags, int kind);
59static void matorb_init_client(struct i2c_client *client);
60static int matorb_detach_client(struct i2c_client *client);
61
62static int matorb_write_value(struct i2c_client *client, u8 reg,
63                              u16 value);
64static void matorb_disp(struct i2c_client *client, int operation,
65                        int ctl_name, int *nrels_mag, long *results);
66static void matorb_update_client(struct i2c_client *client);
67
68
69/* This is the driver that will be inserted */
70static struct i2c_driver matorb_driver = {
71        .owner          = THIS_MODULE,
72        .name           = "Matrix Orbital LCD driver",
73        .id             = I2C_DRIVERID_MATORB,
74        .flags          = I2C_DF_NOTIFY,
75        .attach_adapter = matorb_attach_adapter,
76        .detach_client  = matorb_detach_client,
77};
78
79/* -- SENSORS SYSCTL START -- */
80#define MATORB_SYSCTL_DISP 1000
81/* -- SENSORS SYSCTL END -- */
82
83/* These files are created for each detected MATORB. This is just a template;
84   though at first sight, you might think we could use a statically
85   allocated list, we need some way to get back to the parent - which
86   is done through one of the 'extra' fields which are initialized
87   when a new copy is allocated. */
88static ctl_table matorb_dir_table_template[] = {
89        {MATORB_SYSCTL_DISP, "disp", NULL, 0, 0644, NULL, &i2c_proc_real,
90         &i2c_sysctl_real, NULL, &matorb_disp},
91        {0}
92};
93
94static int matorb_id = 0;
95
96static int matorb_attach_adapter(struct i2c_adapter *adapter)
97{
98        return i2c_detect(adapter, &addr_data, matorb_detect);
99}
100
101/* This function is called by i2c_detect */
102int matorb_detect(struct i2c_adapter *adapter, int address,
103                  unsigned short flags, int kind)
104{
105        int i, cur;
106        struct i2c_client *new_client;
107        struct matorb_data *data;
108        int err = 0;
109        const char *type_name = "matorb";
110        const char *client_name = "matorb";
111
112        /* Make sure we aren't probing the ISA bus!! This is just a safety check
113           at this moment; i2c_detect really won't call us. */
114#ifdef DEBUG
115        if (i2c_is_isa_adapter(adapter)) {
116                printk
117                    ("matorb.o: matorb_detect called for an ISA bus adapter?!?\n");
118                return 0;
119        }
120#endif
121
122        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE |
123                                     I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
124                    goto ERROR0;
125
126
127        /* OK. For now, we presume we have a valid client. We now create the
128           client structure, even though we cannot fill it completely yet.
129           But it allows us to access matorb_{read,write}_value. */
130        if (!(new_client = kmalloc(sizeof(struct i2c_client) +
131                                   sizeof(struct matorb_data),
132                                   GFP_KERNEL))) {
133                err = -ENOMEM;
134                goto ERROR0;
135        }
136
137        data = (struct matorb_data *) (new_client + 1);
138        new_client->addr = address;
139        new_client->data = data;
140        new_client->adapter = adapter;
141        new_client->driver = &matorb_driver;
142        new_client->flags = 0;
143
144        /* Now, we do the remaining detection. It is lousy. */
145        cur = i2c_smbus_write_byte_data(new_client, 0x0FE, 0x58);       /* clear screen */
146
147        printk("matorb.o: debug detect 0x%X\n", cur);
148
149        /* Fill in the remaining client fields and put it into the global list */
150        strcpy(new_client->name, client_name);
151
152        new_client->id = matorb_id++;
153        data->valid = 0;
154        init_MUTEX(&data->update_lock);
155
156        /* Tell the I2C layer a new client has arrived */
157        if ((err = i2c_attach_client(new_client)))
158                goto ERROR3;
159
160        /* Register a new directory entry with module sensors */
161        if ((i = i2c_register_entry(new_client, type_name,
162                                        matorb_dir_table_template)) < 0) {
163                err = i;
164                goto ERROR4;
165        }
166        data->sysctl_id = i;
167
168        matorb_init_client(new_client);
169        return 0;
170
171/* OK, this is not exactly good programming practice, usually. But it is
172   very code-efficient in this case. */
173
174      ERROR4:
175        i2c_detach_client(new_client);
176      ERROR3:
177        kfree(new_client);
178      ERROR0:
179        return err;
180}
181
182static int matorb_detach_client(struct i2c_client *client)
183{
184        int err;
185
186        i2c_deregister_entry(((struct matorb_data *) (client->data))->
187                                 sysctl_id);
188
189        if ((err = i2c_detach_client(client))) {
190                printk
191                    ("matorb.o: Client deregistration failed, client not detached.\n");
192                return err;
193        }
194
195        kfree(client);
196
197        return 0;
198}
199
200
201#if 0
202/* All registers are word-sized, except for the configuration register.
203   MATORB uses a high-byte first convention, which is exactly opposite to
204   the usual practice. */
205static int matorb_read_value(struct i2c_client *client, u8 reg)
206{
207        return -1;              /* Doesn't support reads */
208}
209#endif
210
211/* All registers are word-sized, except for the configuration register.
212   MATORB uses a high-byte first convention, which is exactly opposite to
213   the usual practice. */
214static int matorb_write_value(struct i2c_client *client, u8 reg, u16 value)
215{
216        if (reg == 0) {
217                return i2c_smbus_write_byte(client, value);
218        } else {
219                return i2c_smbus_write_byte_data(client, reg, value);
220        }
221}
222
223static void matorb_init_client(struct i2c_client *client)
224{
225        /* Initialize the MATORB chip */
226}
227
228static void matorb_update_client(struct i2c_client *client)
229{
230        struct matorb_data *data = client->data;
231
232        down(&data->update_lock);
233
234        if ((jiffies - data->last_updated > HZ + HZ / 2) ||
235            (jiffies < data->last_updated) || !data->valid) {
236
237#ifdef DEBUG
238                printk("Starting matorb update\n");
239#endif
240
241/* nothing yet */
242                data->last_updated = jiffies;
243                data->valid = 1;
244        }
245
246        up(&data->update_lock);
247}
248
249
250void matorb_disp(struct i2c_client *client, int operation, int ctl_name,
251                 int *nrels_mag, long *results)
252{
253        int i;
254
255        if (operation == SENSORS_PROC_REAL_INFO)
256                *nrels_mag = 0;
257        else if (operation == SENSORS_PROC_REAL_READ) {
258                matorb_update_client(client);
259                results[0] = 0;
260                *nrels_mag = 3;
261        } else if (operation == SENSORS_PROC_REAL_WRITE) {
262                for (i = 1; i <= *nrels_mag; i++) {
263                        matorb_write_value(client, 0, results[i - 1]);
264                }
265        }
266}
267
268static int __init sm_matorb_init(void)
269{
270        printk("matorb.o version %s (%s)\n", LM_VERSION, LM_DATE);
271        return i2c_add_driver(&matorb_driver);
272}
273
274static void __exit sm_matorb_exit(void)
275{
276        i2c_del_driver(&matorb_driver);
277}
278
279
280
281MODULE_AUTHOR
282    ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
283MODULE_DESCRIPTION("MATORB driver");
284
285module_init(sm_matorb_init);
286module_exit(sm_matorb_exit);
Note: See TracBrowser for help on using the browser.