2 * i2c-algo-sgi.c: i2c driver algorithms for SGI adapters.
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License version 2 as published by the Free Software Foundation.
7 * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/init.h>
13 #include <linux/errno.h>
14 #include <linux/delay.h>
16 #include <linux/i2c.h>
17 #include <linux/i2c-algo-sgi.h>
20 #define SGI_I2C_FORCE_IDLE (0 << 0)
21 #define SGI_I2C_NOT_IDLE (1 << 0)
22 #define SGI_I2C_WRITE (0 << 1)
23 #define SGI_I2C_READ (1 << 1)
24 #define SGI_I2C_RELEASE_BUS (0 << 2)
25 #define SGI_I2C_HOLD_BUS (1 << 2)
26 #define SGI_I2C_XFER_DONE (0 << 4)
27 #define SGI_I2C_XFER_BUSY (1 << 4)
28 #define SGI_I2C_ACK (0 << 5)
29 #define SGI_I2C_NACK (1 << 5)
30 #define SGI_I2C_BUS_OK (0 << 7)
31 #define SGI_I2C_BUS_ERR (1 << 7)
33 #define get_control() adap->getctrl(adap->data)
34 #define set_control(val) adap->setctrl(adap->data, val)
35 #define read_data() adap->rdata(adap->data)
36 #define write_data(val) adap->wdata(adap->data, val)
39 static int wait_xfer_done(struct i2c_algo_sgi_data
*adap
)
43 for (i
= 0; i
< adap
->xfer_timeout
; i
++) {
44 if ((get_control() & SGI_I2C_XFER_BUSY
) == 0)
52 static int wait_ack(struct i2c_algo_sgi_data
*adap
)
56 if (wait_xfer_done(adap
))
58 for (i
= 0; i
< adap
->ack_timeout
; i
++) {
59 if ((get_control() & SGI_I2C_NACK
) == 0)
67 static int force_idle(struct i2c_algo_sgi_data
*adap
)
71 set_control(SGI_I2C_FORCE_IDLE
);
72 for (i
= 0; i
< adap
->xfer_timeout
; i
++) {
73 if ((get_control() & SGI_I2C_NOT_IDLE
) == 0)
79 if (get_control() & SGI_I2C_BUS_ERR
)
84 static int do_address(struct i2c_algo_sgi_data
*adap
, unsigned int addr
,
88 set_control(SGI_I2C_NOT_IDLE
);
89 /* Check if bus is idle, eventually force it to do so */
90 if (get_control() & SGI_I2C_NOT_IDLE
)
93 /* Write out the i2c chip address and specify operation */
94 set_control(SGI_I2C_HOLD_BUS
| SGI_I2C_WRITE
| SGI_I2C_NOT_IDLE
);
103 static int i2c_read(struct i2c_algo_sgi_data
*adap
, unsigned char *buf
,
108 set_control(SGI_I2C_HOLD_BUS
| SGI_I2C_READ
| SGI_I2C_NOT_IDLE
);
109 for (i
= 0; i
< len
; i
++) {
110 if (wait_xfer_done(adap
))
112 buf
[i
] = read_data();
114 set_control(SGI_I2C_RELEASE_BUS
| SGI_I2C_FORCE_IDLE
);
120 static int i2c_write(struct i2c_algo_sgi_data
*adap
, unsigned char *buf
,
125 /* We are already in write state */
126 for (i
= 0; i
< len
; i
++) {
134 static int sgi_xfer(struct i2c_adapter
*i2c_adap
, struct i2c_msg
*msgs
,
137 struct i2c_algo_sgi_data
*adap
= i2c_adap
->algo_data
;
141 for (i
= 0; !err
&& i
< num
; i
++) {
143 err
= do_address(adap
, p
->addr
, p
->flags
& I2C_M_RD
);
146 if (p
->flags
& I2C_M_RD
)
147 err
= i2c_read(adap
, p
->buf
, p
->len
);
149 err
= i2c_write(adap
, p
->buf
, p
->len
);
155 static u32
sgi_func(struct i2c_adapter
*adap
)
157 return I2C_FUNC_SMBUS_EMUL
;
160 static struct i2c_algorithm sgi_algo
= {
161 .master_xfer
= sgi_xfer
,
162 .functionality
= sgi_func
,
166 * registering functions to load algorithms at runtime
168 int i2c_sgi_add_bus(struct i2c_adapter
*adap
)
170 adap
->id
|= I2C_ALGO_SGI
;
171 adap
->algo
= &sgi_algo
;
173 return i2c_add_adapter(adap
);
177 int i2c_sgi_del_bus(struct i2c_adapter
*adap
)
179 return i2c_del_adapter(adap
);
182 EXPORT_SYMBOL(i2c_sgi_add_bus
);
183 EXPORT_SYMBOL(i2c_sgi_del_bus
);
185 MODULE_AUTHOR("Ladislav Michl <ladis@linux-mips.org>");
186 MODULE_DESCRIPTION("I2C-Bus SGI algorithm");
187 MODULE_LICENSE("GPL");