Import 2.1.118
[davej-history.git] / drivers / sbus / char / envctrl.c
blobaf8f6ce789603c1125ed229e4e892f112ad3f573
1 /* $Id: envctrl.c,v 1.7 1998/06/10 07:25:28 davem 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 = -1;
120 if (len == 0)
121 return 0;
123 i2c->data = (dev << 1) | I2C_READ;
125 while (!(i2c->csr & STATUS_BB))
126 udelay(1);
128 i2c->csr = CONTROL_PIN | CONTROL_ES0 | CONTROL_STA | CONTROL_ACK;
130 do {
131 udelay(1);
132 while ((stat = i2c->csr) & STATUS_PIN)
133 udelay(1);
135 if (stat & STATUS_LRB)
136 goto stop;
137 error = 0;
138 if (count == (len - 2))
139 goto final;
141 if (++count > 0) {
142 error = PUT_DATA(&i2c->data, buffer++, user);
143 if (error)
144 goto final;
145 } else
146 dummy = i2c->data;
147 } while (1);
149 final:
150 i2c->csr = CONTROL_ES0;
151 if (!error && (++count > 0))
152 error = PUT_DATA(&i2c->data, buffer++, user);
153 else
154 dummy = i2c->data;
156 udelay(1);
157 while ((stat = i2c->csr) & STATUS_PIN)
158 udelay(1);
160 stop:
161 i2c->csr = CONTROL_PIN | CONTROL_ES0 | CONTROL_STO | CONTROL_ACK;
162 if (!error && (++count > 0))
163 error = PUT_DATA(&i2c->data, buffer++, user);
164 else
165 dummy = i2c->data;
167 if (error)
168 return error;
169 return count;
172 static int
173 i2c_write(unsigned char dev, const char *buffer, int len, int user)
175 int error = -ENODEV;
176 int count = 0;
178 while (!(i2c->csr & STATUS_BB))
179 udelay(1);
181 i2c->data = (dev << 1) | I2C_WRITE;
182 i2c->csr = CONTROL_PIN | CONTROL_ES0 | CONTROL_STA | CONTROL_ACK;
184 do {
185 unsigned char stat;
187 udelay(1);
188 while ((stat = i2c->csr) & STATUS_PIN)
189 udelay(1);
191 if (stat & STATUS_LRB)
192 goto stop;
193 error = count;
194 if (count == len)
195 goto stop;
197 error = GET_DATA(&i2c->data, buffer++, user);
198 if (error)
199 goto stop;
201 count++;
202 } while (1);
204 stop:
205 i2c->csr = CONTROL_PIN | CONTROL_ES0 | CONTROL_STO | CONTROL_ACK;
206 return error;
209 __initfunc(static int i2c_scan_bus(void))
211 unsigned char dev;
212 int count = 0;
214 for (dev = 1; dev < 128; dev++) {
215 if (i2c_write(dev, 0, 0, 0) == 0) {
216 #ifdef DEBUG_BUS_SCAN
217 int i;
218 for (i = 0; i < NR_DEVMAP; i++)
219 if ((dev & devmap[i].mask) == devmap[i].addr)
220 break;
221 printk("envctrl: i2c device at %02x: %s\n", dev,
222 i < NR_DEVMAP ? devmap[i].name : "unknown");
223 #endif
224 count++;
227 return count ? 0 : -ENODEV;
230 static loff_t
231 envctrl_llseek(struct file *file, loff_t offset, int type)
233 return -ESPIPE;
236 static ssize_t
237 envctrl_read(struct file *file, char *buf, size_t count, loff_t *ppos)
239 unsigned long addr = (unsigned long)file->private_data;
241 return i2c_read(addr, buf, count, 1);
244 static ssize_t
245 envctrl_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
247 unsigned long addr = (unsigned long)file->private_data;
249 return i2c_write(addr, buf, count, 1);
252 static int
253 envctrl_ioctl(struct inode *inode, struct file *file,
254 unsigned int cmd, unsigned long arg)
256 unsigned long data;
257 int addr;
259 switch (cmd) {
260 case I2CIOCSADR:
261 if (get_user(addr, (int *)arg))
262 return -EFAULT;
263 data = addr & 0x7f;
264 file->private_data = (void *)data;
265 break;
266 case I2CIOCGADR:
267 addr = (unsigned long)file->private_data;
268 if (put_user(addr, (int *)arg))
269 return -EFAULT;
270 break;
271 default:
272 return -EINVAL;
274 return 0;
277 static int
278 envctrl_open(struct inode *inode, struct file *file)
280 file->private_data = 0;
281 MOD_INC_USE_COUNT;
282 return 0;
285 static int
286 envctrl_release(struct inode *inode, struct file *file)
288 MOD_DEC_USE_COUNT;
289 return 0;
292 static struct file_operations envctrl_fops = {
293 envctrl_llseek,
294 envctrl_read,
295 envctrl_write,
296 NULL, /* readdir */
297 NULL, /* poll */
298 envctrl_ioctl,
299 NULL, /* mmap */
300 envctrl_open,
301 NULL, /* flush */
302 envctrl_release
305 static struct miscdevice envctrl_dev = {
306 ENVCTRL_MINOR,
307 "envctrl",
308 &envctrl_fops
311 #ifdef MODULE
312 int init_module(void)
313 #else
314 __initfunc(int envctrl_init(void))
315 #endif
317 #ifdef CONFIG_PCI
318 struct linux_ebus *ebus;
319 struct linux_ebus_device *edev = 0;
321 for_each_ebus(ebus) {
322 for_each_ebusdev(edev, ebus) {
323 if (!strcmp(edev->prom_name, "SUNW,envctrl"))
324 goto ebus_done;
325 if (!strcmp(edev->prom_name, "SUNW,rasctrl"))
326 goto ebus_done;
329 ebus_done:
330 if (!edev)
331 return -ENODEV;
333 if (check_region(edev->base_address[0], sizeof(*i2c))) {
334 printk("%s: Can't get region %lx, %d\n",
335 __FUNCTION__, edev->base_address[0], (int)sizeof(*i2c));
336 return -ENODEV;
339 i2c = (struct pcf8584_reg *)edev->base_address[0];
341 request_region((unsigned long)i2c, sizeof(*i2c), "i2c");
343 i2c->csr = CONTROL_PIN;
344 i2c->data = PCF8584_ADDRESS;
345 i2c->csr = CONTROL_PIN | CONTROL_ES1;
346 i2c->data = CLK_4_43 | BUS_CLK_90;
347 i2c->csr = CONTROL_PIN | CONTROL_ES0 | CONTROL_ACK;
348 mdelay(10);
350 if (misc_register(&envctrl_dev)) {
351 printk("%s: unable to get misc minor %d\n",
352 __FUNCTION__, envctrl_dev.minor);
353 release_region((unsigned long)i2c, sizeof(*i2c));
356 return i2c_scan_bus();
357 #else
358 return -ENODEV;
359 #endif
363 #ifdef MODULE
364 void cleanup_module(void)
366 misc_deregister(&envctrl_dev);
367 release_region((unsigned long)i2c, sizeof(*i2c));
369 #endif