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>
17 #include "mb862xxfb.h"
18 #include "mb862xx_reg.h"
20 static int mb862xx_i2c_wait_event(struct i2c_adapter
*adap
)
22 struct mb862xxfb_par
*par
= adap
->algo_data
;
27 reg
= inreg(i2c
, GC_I2C_BCR
);
28 if (reg
& (I2C_INT
| I2C_BER
))
32 return (reg
& I2C_BER
) ? 0 : 1;
35 static int mb862xx_i2c_do_address(struct i2c_adapter
*adap
, int addr
)
37 struct mb862xxfb_par
*par
= adap
->algo_data
;
39 outreg(i2c
, GC_I2C_DAR
, addr
);
40 outreg(i2c
, GC_I2C_CCR
, I2C_CLOCK_AND_ENABLE
);
41 outreg(i2c
, GC_I2C_BCR
, par
->i2c_rs
? I2C_REPEATED_START
: I2C_START
);
42 if (!mb862xx_i2c_wait_event(adap
))
44 par
->i2c_rs
= !(inreg(i2c
, GC_I2C_BSR
) & I2C_LRB
);
48 static int mb862xx_i2c_write_byte(struct i2c_adapter
*adap
, u8 byte
)
50 struct mb862xxfb_par
*par
= adap
->algo_data
;
52 outreg(i2c
, GC_I2C_DAR
, byte
);
53 outreg(i2c
, GC_I2C_BCR
, I2C_START
);
54 if (!mb862xx_i2c_wait_event(adap
))
56 return !(inreg(i2c
, GC_I2C_BSR
) & I2C_LRB
);
59 static int mb862xx_i2c_read_byte(struct i2c_adapter
*adap
, u8
*byte
, int last
)
61 struct mb862xxfb_par
*par
= adap
->algo_data
;
63 outreg(i2c
, GC_I2C_BCR
, I2C_START
| (last
? 0 : I2C_ACK
));
64 if (!mb862xx_i2c_wait_event(adap
))
66 *byte
= inreg(i2c
, GC_I2C_DAR
);
70 void mb862xx_i2c_stop(struct i2c_adapter
*adap
)
72 struct mb862xxfb_par
*par
= adap
->algo_data
;
74 outreg(i2c
, GC_I2C_BCR
, I2C_STOP
);
75 outreg(i2c
, GC_I2C_CCR
, I2C_DISABLE
);
79 static int mb862xx_i2c_read(struct i2c_adapter
*adap
, struct i2c_msg
*m
)
82 int last
= m
->len
- 1;
84 for (i
= 0; i
< m
->len
; i
++) {
85 if (!mb862xx_i2c_read_byte(adap
, &m
->buf
[i
], i
== last
)) {
93 static int mb862xx_i2c_write(struct i2c_adapter
*adap
, struct i2c_msg
*m
)
97 for (i
= 0; i
< m
->len
; i
++) {
98 if (!mb862xx_i2c_write_byte(adap
, m
->buf
[i
])) {
106 static int mb862xx_xfer(struct i2c_adapter
*adap
, struct i2c_msg
*msgs
,
109 struct mb862xxfb_par
*par
= adap
->algo_data
;
114 dev_dbg(par
->dev
, "%s: %d msgs\n", __func__
, num
);
116 for (i
= 0; i
< num
; i
++) {
119 dev_dbg(par
->dev
, "%s: null msgs\n", __func__
);
123 if (m
->flags
& I2C_M_RD
)
126 err
= mb862xx_i2c_do_address(adap
, addr
);
129 if (m
->flags
& I2C_M_RD
)
130 err
= mb862xx_i2c_read(adap
, m
);
132 err
= mb862xx_i2c_write(adap
, m
);
136 mb862xx_i2c_stop(adap
);
138 return (err
< 0) ? err
: i
;
141 static u32
mb862xx_func(struct i2c_adapter
*adap
)
143 return I2C_FUNC_SMBUS_BYTE_DATA
;
146 static const struct i2c_algorithm mb862xx_algo
= {
147 .master_xfer
= mb862xx_xfer
,
148 .functionality
= mb862xx_func
,
151 static struct i2c_adapter mb862xx_i2c_adapter
= {
152 .name
= "MB862xx I2C adapter",
153 .algo
= &mb862xx_algo
,
154 .owner
= THIS_MODULE
,
157 int mb862xx_i2c_init(struct mb862xxfb_par
*par
)
161 mb862xx_i2c_adapter
.algo_data
= par
;
162 par
->adap
= &mb862xx_i2c_adapter
;
164 ret
= i2c_add_adapter(par
->adap
);
166 dev_err(par
->dev
, "failed to add %s\n",
167 mb862xx_i2c_adapter
.name
);
172 void mb862xx_i2c_exit(struct mb862xxfb_par
*par
)
175 i2c_del_adapter(par
->adap
);