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)
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>
17 #include <asm/uaccess.h>
18 #include <asm/envctrl.h>
20 #define ENVCTRL_MINOR 162
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
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
61 #define I2C_WRITE 0x00
66 __volatile__
unsigned char data
;
67 __volatile__
unsigned char csr
;
70 static struct pcf8584_reg
*i2c
;
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]))
89 PUT_DATA(__volatile__
unsigned char *data
, char *buffer
, int user
)
92 if (put_user(*data
, buffer
))
100 static __inline__
int
101 GET_DATA(__volatile__
unsigned char *data
, const char *buffer
, int user
)
104 if (get_user(*data
, buffer
))
113 i2c_read(unsigned char dev
, char *buffer
, int len
, int user
)
120 i2c
->data
= (dev
<< 1) | I2C_READ
;
122 while (!(i2c
->csr
& STATUS_BB
))
125 i2c
->csr
= CONTROL_PIN
| CONTROL_ES0
| CONTROL_STA
| CONTROL_ACK
;
129 while ((stat
= i2c
->csr
) & STATUS_PIN
)
132 if (stat
& STATUS_LRB
)
141 if (count
== (len
- 1))
145 error
= PUT_DATA(&i2c
->data
, buffer
++, user
);
152 i2c
->csr
= CONTROL_ES0
;
153 if (!error
&& (count
++ > 0))
154 error
= PUT_DATA(&i2c
->data
, buffer
++, user
);
159 while ((stat
= i2c
->csr
) & STATUS_PIN
)
163 i2c
->csr
= CONTROL_PIN
| CONTROL_ES0
| CONTROL_STO
| CONTROL_ACK
;
164 if (!error
&& (count
++ > 0))
165 error
= PUT_DATA(&i2c
->data
, buffer
++, user
);
175 i2c_write(unsigned char dev
, const char *buffer
, int len
, int user
)
180 while (!(i2c
->csr
& STATUS_BB
))
183 i2c
->data
= (dev
<< 1) | I2C_WRITE
;
184 i2c
->csr
= CONTROL_PIN
| CONTROL_ES0
| CONTROL_STA
| CONTROL_ACK
;
190 while ((stat
= i2c
->csr
) & STATUS_PIN
)
193 if (stat
& STATUS_LRB
)
200 error
= GET_DATA(&i2c
->data
, buffer
++, user
);
207 i2c
->csr
= CONTROL_PIN
| CONTROL_ES0
| CONTROL_STO
| CONTROL_ACK
;
211 __initfunc(static int i2c_scan_bus(void))
216 for (dev
= 1; dev
< 128; dev
++) {
217 if (i2c_read(dev
, 0, 0, 0) == 0) {
218 #ifdef DEBUG_BUS_SCAN
220 for (i
= 0; i
< NR_DEVMAP
; i
++)
221 if ((dev
& devmap
[i
].mask
) == devmap
[i
].addr
)
223 printk("envctrl: i2c device at %02x: %s\n", dev
,
224 i
< NR_DEVMAP
? devmap
[i
].name
: "unknown");
230 printk("%s: no devices found\n", __FUNCTION__
);
237 envctrl_llseek(struct file
*file
, loff_t offset
, int type
)
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);
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);
259 envctrl_ioctl(struct inode
*inode
, struct file
*file
,
260 unsigned int cmd
, unsigned long arg
)
267 if (get_user(addr
, (int *)arg
))
270 file
->private_data
= (void *)data
;
273 addr
= (unsigned long)file
->private_data
;
274 if (put_user(addr
, (int *)arg
))
284 envctrl_open(struct inode
*inode
, struct file
*file
)
286 file
->private_data
= 0;
292 envctrl_release(struct inode
*inode
, struct file
*file
)
298 static struct file_operations envctrl_fops
= {
311 static struct miscdevice envctrl_dev
= {
318 int init_module(void)
320 __initfunc(int envctrl_init(void))
324 struct linux_ebus
*ebus
;
325 struct linux_ebus_device
*edev
= 0;
328 for_each_ebus(ebus
) {
329 for_each_ebusdev(edev
, ebus
) {
330 if (!strcmp(edev
->prom_name
, "SUNW,envctrl"))
332 if (!strcmp(edev
->prom_name
, "SUNW,rasctrl"))
338 printk("%s: ebus device not found\n", __FUNCTION__
);
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
));
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
;
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();
367 release_region((unsigned long)i2c
, sizeof(*i2c
));
376 void cleanup_module(void)
378 misc_deregister(&envctrl_dev
);
379 release_region((unsigned long)i2c
, sizeof(*i2c
));