2 * Coral-P(A)/Lime I2C adapter driver
4 * (C) 2011 DENX Software Engineering, Anatolij Gustschin <agust@denx.de>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
13 #include <linux/i2c.h>
15 #include <linux/delay.h>
16 #include <linux/export.h>
18 #include "mb862xxfb.h"
19 #include "mb862xx_reg.h"
21 static int mb862xx_i2c_wait_event(struct i2c_adapter
*adap
)
23 struct mb862xxfb_par
*par
= adap
->algo_data
;
28 reg
= inreg(i2c
, GC_I2C_BCR
);
29 if (reg
& (I2C_INT
| I2C_BER
))
33 return (reg
& I2C_BER
) ? 0 : 1;
36 static int mb862xx_i2c_do_address(struct i2c_adapter
*adap
, int addr
)
38 struct mb862xxfb_par
*par
= adap
->algo_data
;
40 outreg(i2c
, GC_I2C_DAR
, addr
);
41 outreg(i2c
, GC_I2C_CCR
, I2C_CLOCK_AND_ENABLE
);
42 outreg(i2c
, GC_I2C_BCR
, par
->i2c_rs
? I2C_REPEATED_START
: I2C_START
);
43 if (!mb862xx_i2c_wait_event(adap
))
45 par
->i2c_rs
= !(inreg(i2c
, GC_I2C_BSR
) & I2C_LRB
);
49 static int mb862xx_i2c_write_byte(struct i2c_adapter
*adap
, u8 byte
)
51 struct mb862xxfb_par
*par
= adap
->algo_data
;
53 outreg(i2c
, GC_I2C_DAR
, byte
);
54 outreg(i2c
, GC_I2C_BCR
, I2C_START
);
55 if (!mb862xx_i2c_wait_event(adap
))
57 return !(inreg(i2c
, GC_I2C_BSR
) & I2C_LRB
);
60 static int mb862xx_i2c_read_byte(struct i2c_adapter
*adap
, u8
*byte
, int last
)
62 struct mb862xxfb_par
*par
= adap
->algo_data
;
64 outreg(i2c
, GC_I2C_BCR
, I2C_START
| (last
? 0 : I2C_ACK
));
65 if (!mb862xx_i2c_wait_event(adap
))
67 *byte
= inreg(i2c
, GC_I2C_DAR
);
71 void mb862xx_i2c_stop(struct i2c_adapter
*adap
)
73 struct mb862xxfb_par
*par
= adap
->algo_data
;
75 outreg(i2c
, GC_I2C_BCR
, I2C_STOP
);
76 outreg(i2c
, GC_I2C_CCR
, I2C_DISABLE
);
80 static int mb862xx_i2c_read(struct i2c_adapter
*adap
, struct i2c_msg
*m
)
83 int last
= m
->len
- 1;
85 for (i
= 0; i
< m
->len
; i
++) {
86 if (!mb862xx_i2c_read_byte(adap
, &m
->buf
[i
], i
== last
)) {
94 static int mb862xx_i2c_write(struct i2c_adapter
*adap
, struct i2c_msg
*m
)
98 for (i
= 0; i
< m
->len
; i
++) {
99 if (!mb862xx_i2c_write_byte(adap
, m
->buf
[i
])) {
107 static int mb862xx_xfer(struct i2c_adapter
*adap
, struct i2c_msg
*msgs
,
110 struct mb862xxfb_par
*par
= adap
->algo_data
;
115 dev_dbg(par
->dev
, "%s: %d msgs\n", __func__
, num
);
117 for (i
= 0; i
< num
; i
++) {
120 dev_dbg(par
->dev
, "%s: null msgs\n", __func__
);
124 if (m
->flags
& I2C_M_RD
)
127 err
= mb862xx_i2c_do_address(adap
, addr
);
130 if (m
->flags
& I2C_M_RD
)
131 err
= mb862xx_i2c_read(adap
, m
);
133 err
= mb862xx_i2c_write(adap
, m
);
137 mb862xx_i2c_stop(adap
);
139 return (err
< 0) ? err
: i
;
142 static u32
mb862xx_func(struct i2c_adapter
*adap
)
144 return I2C_FUNC_SMBUS_BYTE_DATA
;
147 static const struct i2c_algorithm mb862xx_algo
= {
148 .master_xfer
= mb862xx_xfer
,
149 .functionality
= mb862xx_func
,
152 static struct i2c_adapter mb862xx_i2c_adapter
= {
153 .name
= "MB862xx I2C adapter",
154 .algo
= &mb862xx_algo
,
155 .owner
= THIS_MODULE
,
158 int mb862xx_i2c_init(struct mb862xxfb_par
*par
)
162 mb862xx_i2c_adapter
.algo_data
= par
;
163 par
->adap
= &mb862xx_i2c_adapter
;
165 ret
= i2c_add_adapter(par
->adap
);
167 dev_err(par
->dev
, "failed to add %s\n",
168 mb862xx_i2c_adapter
.name
);
173 void mb862xx_i2c_exit(struct mb862xxfb_par
*par
)
176 i2c_del_adapter(par
->adap
);