Linux 2.3.1pre3
[davej-history.git] / drivers / sbus / char / envctrl.c
blobfbc93415db049ef90b1c6d3317e8fd8da55a87a7
1 /* $Id: envctrl.c,v 1.9 1998/11/06 07:38:20 ecd Exp $
2 * envctrl.c: Temperature and Fan monitoring on Machines providing it.
4 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
5 */
7 #include <linux/config.h>
8 #include <linux/module.h>
9 #include <linux/sched.h>
10 #include <linux/errno.h>
11 #include <linux/delay.h>
12 #include <linux/ioport.h>
13 #include <linux/init.h>
14 #include <linux/miscdevice.h>
16 #include <asm/ebus.h>
17 #include <asm/uaccess.h>
18 #include <asm/envctrl.h>
20 #define ENVCTRL_MINOR 162
23 #undef DEBUG_BUS_SCAN
26 #define PCF8584_ADDRESS 0x55
28 #define CONTROL_PIN 0x80
29 #define CONTROL_ES0 0x40
30 #define CONTROL_ES1 0x20
31 #define CONTROL_ES2 0x10
32 #define CONTROL_ENI 0x08
33 #define CONTROL_STA 0x04
34 #define CONTROL_STO 0x02
35 #define CONTROL_ACK 0x01
37 #define STATUS_PIN 0x80
38 #define STATUS_STS 0x20
39 #define STATUS_BER 0x10
40 #define STATUS_LRB 0x08
41 #define STATUS_AD0 0x08
42 #define STATUS_AAB 0x04
43 #define STATUS_LAB 0x02
44 #define STATUS_BB 0x01
47 * CLK Mode Register.
49 #define BUS_CLK_90 0x00
50 #define BUS_CLK_45 0x01
51 #define BUS_CLK_11 0x02
52 #define BUS_CLK_1_5 0x03
54 #define CLK_3 0x00
55 #define CLK_4_43 0x10
56 #define CLK_6 0x14
57 #define CLK_8 0x18
58 #define CLK_12 0x1c
61 #define I2C_WRITE 0x00
62 #define I2C_READ 0x01
64 struct pcf8584_reg
66 __volatile__ unsigned char data;
67 __volatile__ unsigned char csr;
70 static struct pcf8584_reg *i2c;
73 #ifdef DEBUG_BUS_SCAN
74 struct i2c_addr_map {
75 unsigned char addr;
76 unsigned char mask;
77 char *name;
80 static struct i2c_addr_map devmap[] = {
81 { 0x38, 0x78, "PCF8574A" },
82 { 0x20, 0x78, "TDA8444" },
83 { 0x48, 0x78, "PCF8591" },
85 #define NR_DEVMAP (sizeof(devmap) / sizeof(devmap[0]))
86 #endif
88 static __inline__ int
89 PUT_DATA(__volatile__ unsigned char *data, char *buffer, int user)
91 if (user) {
92 if (put_user(*data, buffer))
93 return -EFAULT;
94 } else {
95 *buffer = *data;
97 return 0;
100 static __inline__ int
101 GET_DATA(__volatile__ unsigned char *data, const char *buffer, int user)
103 if (user) {
104 if (get_user(*data, buffer))
105 return -EFAULT;
106 } else {
107 *data = *buffer;
109 return 0;
112 static int
113 i2c_read(unsigned char dev, char *buffer, int len, int user)
115 unsigned char dummy;
116 unsigned char stat;
117 int error = -ENODEV;
118 int count = 0;
120 i2c->data = (dev << 1) | I2C_READ;
122 while (!(i2c->csr & STATUS_BB))
123 udelay(1);
125 i2c->csr = CONTROL_PIN | CONTROL_ES0 | CONTROL_STA | CONTROL_ACK;
127 do {
128 udelay(1);
129 while ((stat = i2c->csr) & STATUS_PIN)
130 udelay(1);
132 if (stat & STATUS_LRB)
133 goto stop;
135 error = 0;
136 if (len == 0) {
137 count--;
138 break;
141 if (count == (len - 1))
142 break;
144 if (count++ > 0) {
145 error = PUT_DATA(&i2c->data, buffer++, user);
146 if (error)
147 break;
148 } else
149 dummy = i2c->data;
150 } while (1);
152 i2c->csr = CONTROL_ES0;
153 if (!error && (count++ > 0))
154 error = PUT_DATA(&i2c->data, buffer++, user);
155 else
156 dummy = i2c->data;
158 udelay(1);
159 while ((stat = i2c->csr) & STATUS_PIN)
160 udelay(1);
162 stop:
163 i2c->csr = CONTROL_PIN | CONTROL_ES0 | CONTROL_STO | CONTROL_ACK;
164 if (!error && (count++ > 0))
165 error = PUT_DATA(&i2c->data, buffer++, user);
166 else
167 dummy = i2c->data;
169 if (error)
170 return error;
171 return count - 1;
174 static int
175 i2c_write(unsigned char dev, const char *buffer, int len, int user)
177 int error = -ENODEV;
178 int count = 0;
180 while (!(i2c->csr & STATUS_BB))
181 udelay(1);
183 i2c->data = (dev << 1) | I2C_WRITE;
184 i2c->csr = CONTROL_PIN | CONTROL_ES0 | CONTROL_STA | CONTROL_ACK;
186 do {
187 unsigned char stat;
189 udelay(1);
190 while ((stat = i2c->csr) & STATUS_PIN)
191 udelay(1);
193 if (stat & STATUS_LRB)
194 break;
196 error = count;
197 if (count == len)
198 break;
200 error = GET_DATA(&i2c->data, buffer++, user);
201 if (error)
202 break;
204 count++;
205 } while (1);
207 i2c->csr = CONTROL_PIN | CONTROL_ES0 | CONTROL_STO | CONTROL_ACK;
208 return error;
211 __initfunc(static int i2c_scan_bus(void))
213 unsigned char dev;
214 int count = 0;
216 for (dev = 1; dev < 128; dev++) {
217 if (i2c_read(dev, 0, 0, 0) == 0) {
218 #ifdef DEBUG_BUS_SCAN
219 int i;
220 for (i = 0; i < NR_DEVMAP; i++)
221 if ((dev & devmap[i].mask) == devmap[i].addr)
222 break;
223 printk("envctrl: i2c device at %02x: %s\n", dev,
224 i < NR_DEVMAP ? devmap[i].name : "unknown");
225 #endif
226 count++;
229 if (!count) {
230 printk("%s: no devices found\n", __FUNCTION__);
231 return -ENODEV;
233 return 0;
236 static loff_t
237 envctrl_llseek(struct file *file, loff_t offset, int type)
239 return -ESPIPE;
242 static ssize_t
243 envctrl_read(struct file *file, char *buf, size_t count, loff_t *ppos)
245 unsigned long addr = (unsigned long)file->private_data;
247 return i2c_read(addr, buf, count, 1);
250 static ssize_t
251 envctrl_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
253 unsigned long addr = (unsigned long)file->private_data;
255 return i2c_write(addr, buf, count, 1);
258 static int
259 envctrl_ioctl(struct inode *inode, struct file *file,
260 unsigned int cmd, unsigned long arg)
262 unsigned long data;
263 int addr;
265 switch (cmd) {
266 case I2CIOCSADR:
267 if (get_user(addr, (int *)arg))
268 return -EFAULT;
269 data = addr & 0x7f;
270 file->private_data = (void *)data;
271 break;
272 case I2CIOCGADR:
273 addr = (unsigned long)file->private_data;
274 if (put_user(addr, (int *)arg))
275 return -EFAULT;
276 break;
277 default:
278 return -EINVAL;
280 return 0;
283 static int
284 envctrl_open(struct inode *inode, struct file *file)
286 file->private_data = 0;
287 MOD_INC_USE_COUNT;
288 return 0;
291 static int
292 envctrl_release(struct inode *inode, struct file *file)
294 MOD_DEC_USE_COUNT;
295 return 0;
298 static struct file_operations envctrl_fops = {
299 envctrl_llseek,
300 envctrl_read,
301 envctrl_write,
302 NULL, /* readdir */
303 NULL, /* poll */
304 envctrl_ioctl,
305 NULL, /* mmap */
306 envctrl_open,
307 NULL, /* flush */
308 envctrl_release
311 static struct miscdevice envctrl_dev = {
312 ENVCTRL_MINOR,
313 "envctrl",
314 &envctrl_fops
317 #ifdef MODULE
318 int init_module(void)
319 #else
320 __initfunc(int envctrl_init(void))
321 #endif
323 #ifdef CONFIG_PCI
324 struct linux_ebus *ebus;
325 struct linux_ebus_device *edev = 0;
326 int err;
328 for_each_ebus(ebus) {
329 for_each_ebusdev(edev, ebus) {
330 if (!strcmp(edev->prom_name, "SUNW,envctrl"))
331 goto ebus_done;
332 if (!strcmp(edev->prom_name, "SUNW,rasctrl"))
333 goto ebus_done;
336 ebus_done:
337 if (!edev) {
338 printk("%s: ebus device not found\n", __FUNCTION__);
339 return -ENODEV;
342 if (check_region(edev->base_address[0], sizeof(*i2c))) {
343 printk("%s: Can't get region %lx, %d\n",
344 __FUNCTION__, edev->base_address[0], (int)sizeof(*i2c));
345 return -ENODEV;
348 i2c = (struct pcf8584_reg *)edev->base_address[0];
350 request_region((unsigned long)i2c, sizeof(*i2c), "i2c");
352 i2c->csr = CONTROL_PIN;
353 i2c->data = PCF8584_ADDRESS;
354 i2c->csr = CONTROL_PIN | CONTROL_ES1;
355 i2c->data = CLK_4_43 | BUS_CLK_90;
356 i2c->csr = CONTROL_PIN | CONTROL_ES0 | CONTROL_ACK;
357 mdelay(10);
359 if (misc_register(&envctrl_dev)) {
360 printk("%s: unable to get misc minor %d\n",
361 __FUNCTION__, envctrl_dev.minor);
362 release_region((unsigned long)i2c, sizeof(*i2c));
365 err = i2c_scan_bus();
366 if (err)
367 release_region((unsigned long)i2c, sizeof(*i2c));
368 return err;
369 #else
370 return -ENODEV;
371 #endif
375 #ifdef MODULE
376 void cleanup_module(void)
378 misc_deregister(&envctrl_dev);
379 release_region((unsigned long)i2c, sizeof(*i2c));
381 #endif