1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <device/mmio.h>
5 #include <console/console.h>
7 #include <device/i2c_simple.h>
10 #include <soc/periph.h>
13 #define I2C_TIMEOUT_US (1000 * USECS_PER_MSEC)
15 struct __packed i2c_regs
29 struct s3c24x0_i2c_bus
{
31 struct i2c_regs
*regs
;
32 enum periph_id periph_id
;
36 I2cConIntPending
= 0x1 << 4,
37 I2cConIntEn
= 0x1 << 5,
38 I2cConAckGen
= 0x1 << 7
42 I2cStatAck
= 0x1 << 0,
43 I2cStatAddrZero
= 0x1 << 1,
44 I2cStatAddrSlave
= 0x1 << 2,
45 I2cStatArb
= 0x1 << 3,
46 I2cStatEnable
= 0x1 << 4,
47 I2cStatStartStop
= 0x1 << 5,
48 I2cStatBusy
= 0x1 << 5,
50 I2cStatModeMask
= 0x3 << 6,
51 I2cStatSlaveRecv
= 0x0 << 6,
52 I2cStatSlaveXmit
= 0x1 << 6,
53 I2cStatMasterRecv
= 0x2 << 6,
54 I2cStatMasterXmit
= 0x3 << 6
57 static struct s3c24x0_i2c_bus i2c_busses
[] = {
60 .regs
= (void *)0x12c60000,
61 .periph_id
= PERIPH_ID_I2C0
,
65 .regs
= (void *)0x12c70000,
66 .periph_id
= PERIPH_ID_I2C1
,
70 .regs
= (void *)0x12c80000,
71 .periph_id
= PERIPH_ID_I2C2
,
75 .regs
= (void *)0x12c90000,
76 .periph_id
= PERIPH_ID_I2C3
,
80 .regs
= (void *)0x12ca0000,
81 .periph_id
= PERIPH_ID_I2C4
,
85 .regs
= (void *)0x12cb0000,
86 .periph_id
= PERIPH_ID_I2C5
,
90 .regs
= (void *)0x12cc0000,
91 .periph_id
= PERIPH_ID_I2C6
,
95 .regs
= (void *)0x12cd0000,
96 .periph_id
= PERIPH_ID_I2C7
,
100 static int i2c_int_pending(struct i2c_regs
*regs
)
102 return read8(®s
->con
) & I2cConIntPending
;
105 static void i2c_clear_int(struct i2c_regs
*regs
)
107 write8(®s
->con
, read8(®s
->con
) & ~I2cConIntPending
);
110 static void i2c_ack_enable(struct i2c_regs
*regs
)
112 write8(®s
->con
, read8(®s
->con
) | I2cConAckGen
);
115 static void i2c_ack_disable(struct i2c_regs
*regs
)
117 write8(®s
->con
, read8(®s
->con
) & ~I2cConAckGen
);
120 static int i2c_got_ack(struct i2c_regs
*regs
)
122 return !(read8(®s
->stat
) & I2cStatAck
);
125 static int i2c_wait_for_idle(struct i2c_regs
*regs
, int timeout_us
)
127 int timeout
= DIV_ROUND_UP(timeout_us
, 10);
129 if (!(read8(®s
->stat
) & I2cStatBusy
))
133 printk(BIOS_ERR
, "I2C timeout waiting for idle.\n");
137 static int i2c_wait_for_int(struct i2c_regs
*regs
, int timeout_us
)
139 int timeout
= DIV_ROUND_UP(timeout_us
, 10);
141 if (i2c_int_pending(regs
))
145 printk(BIOS_ERR
, "I2C timeout waiting for I2C interrupt.\n");
149 static int i2c_send_stop(struct i2c_regs
*regs
)
151 uint8_t mode
= read8(®s
->stat
) & (I2cStatModeMask
);
152 write8(®s
->stat
, mode
| I2cStatEnable
);
154 return i2c_wait_for_idle(regs
, I2C_TIMEOUT_US
);
157 static int i2c_send_start(struct i2c_regs
*regs
, int read
, int chip
)
159 write8(®s
->ds
, chip
<< 1);
160 uint8_t mode
= read
? I2cStatMasterRecv
: I2cStatMasterXmit
;
161 write8(®s
->stat
, mode
| I2cStatStartStop
| I2cStatEnable
);
164 if (i2c_wait_for_int(regs
, I2C_TIMEOUT_US
))
167 if (!i2c_got_ack(regs
)) {
168 // Nobody home, but they may just be asleep.
175 static int i2c_xmit_buf(struct i2c_regs
*regs
, uint8_t *data
, int len
)
179 i2c_ack_enable(regs
);
182 for (i
= 0; i
< len
; i
++) {
183 write8(®s
->ds
, data
[i
]);
186 if (i2c_wait_for_int(regs
, CONFIG_I2C_TRANSFER_TIMEOUT_US
))
189 if (!i2c_got_ack(regs
)) {
190 printk(BIOS_INFO
, "I2c nacked.\n");
198 static int i2c_recv_buf(struct i2c_regs
*regs
, uint8_t *data
, int len
)
202 i2c_ack_enable(regs
);
205 for (i
= 0; i
< len
; i
++) {
207 i2c_ack_disable(regs
);
210 if (i2c_wait_for_int(regs
, CONFIG_I2C_TRANSFER_TIMEOUT_US
))
213 data
[i
] = read8(®s
->ds
);
219 int platform_i2c_transfer(unsigned int bus
, struct i2c_msg
*segments
,
222 struct s3c24x0_i2c_bus
*i2c
= &i2c_busses
[bus
];
223 struct i2c_regs
*regs
= i2c
->regs
;
226 if (!regs
|| i2c_wait_for_idle(regs
, I2C_TIMEOUT_US
))
229 write8(®s
->stat
, I2cStatMasterXmit
| I2cStatEnable
);
232 for (i
= 0; i
< seg_count
; i
++) {
233 struct i2c_msg
*seg
= &segments
[i
];
235 res
= i2c_send_start(regs
, seg
->flags
& I2C_M_RD
, seg
->slave
);
238 if (seg
->flags
& I2C_M_RD
)
239 res
= i2c_recv_buf(regs
, seg
->buf
, seg
->len
);
241 res
= i2c_xmit_buf(regs
, seg
->buf
, seg
->len
);
246 return i2c_send_stop(regs
) || res
;
249 void i2c_init(unsigned int bus
, int speed
, int slaveadd
)
251 struct s3c24x0_i2c_bus
*i2c
= &i2c_busses
[bus
];
253 unsigned long freq
, pres
= 16, div
;
256 freq
= clock_get_periph_rate(i2c
->periph_id
);
257 // Calculate prescaler and divisor values.
258 if ((freq
/ pres
/ (16 + 1)) > speed
)
259 /* set prescaler to 512 */
264 while ((freq
/ pres
/ (div
+ 1)) > speed
)
267 // Set prescaler, divisor according to freq, also set ACKGEN, IRQ.
268 val
= (div
& 0x0f) | 0xa0 | ((pres
== 512) ? 0x40 : 0);
269 write32(&i2c
->regs
->con
, val
);
271 // Init to SLAVE RECEIVE mode and clear I2CADDn.
272 write32(&i2c
->regs
->stat
, 0);
273 write32(&i2c
->regs
->add
, slaveadd
);
274 // program Master Transmit (and implicit STOP).
275 write32(&i2c
->regs
->stat
, I2cStatMasterXmit
| I2cStatEnable
);