1 // SPDX-License-Identifier: GPL-2.0-only
3 * Coral-P(A)/Lime I2C adapter driver
5 * (C) 2011 DENX Software Engineering, Anatolij Gustschin <agust@denx.de>
11 #include <linux/delay.h>
12 #include <linux/export.h>
14 #include "mb862xxfb.h"
15 #include "mb862xx_reg.h"
17 static int mb862xx_i2c_wait_event(struct i2c_adapter
*adap
)
19 struct mb862xxfb_par
*par
= adap
->algo_data
;
24 reg
= inreg(i2c
, GC_I2C_BCR
);
25 if (reg
& (I2C_INT
| I2C_BER
))
29 return (reg
& I2C_BER
) ? 0 : 1;
32 static int mb862xx_i2c_do_address(struct i2c_adapter
*adap
, int addr
)
34 struct mb862xxfb_par
*par
= adap
->algo_data
;
36 outreg(i2c
, GC_I2C_DAR
, addr
);
37 outreg(i2c
, GC_I2C_CCR
, I2C_CLOCK_AND_ENABLE
);
38 outreg(i2c
, GC_I2C_BCR
, par
->i2c_rs
? I2C_REPEATED_START
: I2C_START
);
39 if (!mb862xx_i2c_wait_event(adap
))
41 par
->i2c_rs
= !(inreg(i2c
, GC_I2C_BSR
) & I2C_LRB
);
45 static int mb862xx_i2c_write_byte(struct i2c_adapter
*adap
, u8 byte
)
47 struct mb862xxfb_par
*par
= adap
->algo_data
;
49 outreg(i2c
, GC_I2C_DAR
, byte
);
50 outreg(i2c
, GC_I2C_BCR
, I2C_START
);
51 if (!mb862xx_i2c_wait_event(adap
))
53 return !(inreg(i2c
, GC_I2C_BSR
) & I2C_LRB
);
56 static int mb862xx_i2c_read_byte(struct i2c_adapter
*adap
, u8
*byte
, int last
)
58 struct mb862xxfb_par
*par
= adap
->algo_data
;
60 outreg(i2c
, GC_I2C_BCR
, I2C_START
| (last
? 0 : I2C_ACK
));
61 if (!mb862xx_i2c_wait_event(adap
))
63 *byte
= inreg(i2c
, GC_I2C_DAR
);
67 static void mb862xx_i2c_stop(struct i2c_adapter
*adap
)
69 struct mb862xxfb_par
*par
= adap
->algo_data
;
71 outreg(i2c
, GC_I2C_BCR
, I2C_STOP
);
72 outreg(i2c
, GC_I2C_CCR
, I2C_DISABLE
);
76 static int mb862xx_i2c_read(struct i2c_adapter
*adap
, struct i2c_msg
*m
)
79 int last
= m
->len
- 1;
81 for (i
= 0; i
< m
->len
; i
++) {
82 if (!mb862xx_i2c_read_byte(adap
, &m
->buf
[i
], i
== last
)) {
90 static int mb862xx_i2c_write(struct i2c_adapter
*adap
, struct i2c_msg
*m
)
94 for (i
= 0; i
< m
->len
; i
++) {
95 if (!mb862xx_i2c_write_byte(adap
, m
->buf
[i
])) {
103 static int mb862xx_xfer(struct i2c_adapter
*adap
, struct i2c_msg
*msgs
,
106 struct mb862xxfb_par
*par
= adap
->algo_data
;
111 dev_dbg(par
->dev
, "%s: %d msgs\n", __func__
, num
);
113 for (i
= 0; i
< num
; i
++) {
116 dev_dbg(par
->dev
, "%s: null msgs\n", __func__
);
120 if (m
->flags
& I2C_M_RD
)
123 err
= mb862xx_i2c_do_address(adap
, addr
);
126 if (m
->flags
& I2C_M_RD
)
127 err
= mb862xx_i2c_read(adap
, m
);
129 err
= mb862xx_i2c_write(adap
, m
);
133 mb862xx_i2c_stop(adap
);
135 return (err
< 0) ? err
: i
;
138 static u32
mb862xx_func(struct i2c_adapter
*adap
)
140 return I2C_FUNC_SMBUS_BYTE_DATA
;
143 static const struct i2c_algorithm mb862xx_algo
= {
144 .master_xfer
= mb862xx_xfer
,
145 .functionality
= mb862xx_func
,
148 static struct i2c_adapter mb862xx_i2c_adapter
= {
149 .name
= "MB862xx I2C adapter",
150 .algo
= &mb862xx_algo
,
151 .owner
= THIS_MODULE
,
154 int mb862xx_i2c_init(struct mb862xxfb_par
*par
)
156 mb862xx_i2c_adapter
.algo_data
= par
;
157 par
->adap
= &mb862xx_i2c_adapter
;
159 return i2c_add_adapter(par
->adap
);
162 void mb862xx_i2c_exit(struct mb862xxfb_par
*par
)
165 i2c_del_adapter(par
->adap
);