coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
i2c.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <device/mmio.h>
4 #include <assert.h>
5 #include <console/console.h>
6 #include <delay.h>
7 #include <device/i2c_simple.h>
8 #include <soc/clk.h>
9 #include <soc/i2c.h>
10 #include <soc/periph.h>
11 #include <timer.h>
12 
13 #define I2C_TIMEOUT_US (1000 * USECS_PER_MSEC)
14 
16 {
18  uint8_t _1[3];
20  uint8_t _2[3];
22  uint8_t _3[3];
24  uint8_t _4[3];
26  uint8_t _5[3];
27 };
28 
30  int bus_num;
31  struct i2c_regs *regs;
32  enum periph_id periph_id;
33 };
34 
35 enum {
36  I2cConIntPending = 0x1 << 4,
37  I2cConIntEn = 0x1 << 5,
38  I2cConAckGen = 0x1 << 7
39 };
40 
41 enum {
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,
49 
50  I2cStatModeMask = 0x3 << 6,
51  I2cStatSlaveRecv = 0x0 << 6,
52  I2cStatSlaveXmit = 0x1 << 6,
53  I2cStatMasterRecv = 0x2 << 6,
54  I2cStatMasterXmit = 0x3 << 6
55 };
56 
57 static struct s3c24x0_i2c_bus i2c_busses[] = {
58  {
59  .bus_num = 0,
60  .regs = (void *)0x12c60000,
62  },
63  {
64  .bus_num = 1,
65  .regs = (void *)0x12c70000,
67  },
68  {
69  .bus_num = 2,
70  .regs = (void *)0x12c80000,
72  },
73  {
74  .bus_num = 3,
75  .regs = (void *)0x12c90000,
77  },
78  {
79  .bus_num = 4,
80  .regs = (void *)0x12ca0000,
82  },
83  {
84  .bus_num = 5,
85  .regs = (void *)0x12cb0000,
87  },
88  {
89  .bus_num = 6,
90  .regs = (void *)0x12cc0000,
92  },
93  {
94  .bus_num = 7,
95  .regs = (void *)0x12cd0000,
97  },
98 };
99 
100 static int i2c_int_pending(struct i2c_regs *regs)
101 {
102  return read8(&regs->con) & I2cConIntPending;
103 }
104 
105 static void i2c_clear_int(struct i2c_regs *regs)
106 {
107  write8(&regs->con, read8(&regs->con) & ~I2cConIntPending);
108 }
109 
110 static void i2c_ack_enable(struct i2c_regs *regs)
111 {
112  write8(&regs->con, read8(&regs->con) | I2cConAckGen);
113 }
114 
115 static void i2c_ack_disable(struct i2c_regs *regs)
116 {
117  write8(&regs->con, read8(&regs->con) & ~I2cConAckGen);
118 }
119 
120 static int i2c_got_ack(struct i2c_regs *regs)
121 {
122  return !(read8(&regs->stat) & I2cStatAck);
123 }
124 
125 static int i2c_wait_for_idle(struct i2c_regs *regs, int timeout_us)
126 {
127  int timeout = DIV_ROUND_UP(timeout_us, 10);
128  while (timeout--) {
129  if (!(read8(&regs->stat) & I2cStatBusy))
130  return 0;
131  udelay(10);
132  }
133  printk(BIOS_ERR, "I2C timeout waiting for idle.\n");
134  return 1;
135 }
136 
137 static int i2c_wait_for_int(struct i2c_regs *regs, int timeout_us)
138 {
139  int timeout = DIV_ROUND_UP(timeout_us, 10);
140  while (timeout--) {
141  if (i2c_int_pending(regs))
142  return 0;
143  udelay(10);
144  }
145  printk(BIOS_ERR, "I2C timeout waiting for I2C interrupt.\n");
146  return 1;
147 }
148 
149 static int i2c_send_stop(struct i2c_regs *regs)
150 {
151  uint8_t mode = read8(&regs->stat) & (I2cStatModeMask);
152  write8(&regs->stat, mode | I2cStatEnable);
155 }
156 
157 static int i2c_send_start(struct i2c_regs *regs, int read, int chip)
158 {
159  write8(&regs->ds, chip << 1);
161  write8(&regs->stat, mode | I2cStatStartStop | I2cStatEnable);
163 
165  return 1;
166 
167  if (!i2c_got_ack(regs)) {
168  // Nobody home, but they may just be asleep.
169  return 1;
170  }
171 
172  return 0;
173 }
174 
175 static int i2c_xmit_buf(struct i2c_regs *regs, uint8_t *data, int len)
176 {
177  ASSERT(len);
178 
180 
181  int i;
182  for (i = 0; i < len; i++) {
183  write8(&regs->ds, data[i]);
184 
186  if (i2c_wait_for_int(regs, CONFIG_I2C_TRANSFER_TIMEOUT_US))
187  return 1;
188 
189  if (!i2c_got_ack(regs)) {
190  printk(BIOS_INFO, "I2c nacked.\n");
191  return 1;
192  }
193  }
194 
195  return 0;
196 }
197 
198 static int i2c_recv_buf(struct i2c_regs *regs, uint8_t *data, int len)
199 {
200  ASSERT(len);
201 
203 
204  int i;
205  for (i = 0; i < len; i++) {
206  if (i == len - 1)
208 
210  if (i2c_wait_for_int(regs, CONFIG_I2C_TRANSFER_TIMEOUT_US))
211  return 1;
212 
213  data[i] = read8(&regs->ds);
214  }
215 
216  return 0;
217 }
218 
219 int platform_i2c_transfer(unsigned int bus, struct i2c_msg *segments,
220  int seg_count)
221 {
222  struct s3c24x0_i2c_bus *i2c = &i2c_busses[bus];
223  struct i2c_regs *regs = i2c->regs;
224  int res = 0;
225 
227  return 1;
228 
230 
231  int i;
232  for (i = 0; i < seg_count; i++) {
233  struct i2c_msg *seg = &segments[i];
234 
235  res = i2c_send_start(regs, seg->flags & I2C_M_RD, seg->slave);
236  if (res)
237  break;
238  if (seg->flags & I2C_M_RD)
239  res = i2c_recv_buf(regs, seg->buf, seg->len);
240  else
241  res = i2c_xmit_buf(regs, seg->buf, seg->len);
242  if (res)
243  break;
244  }
245 
246  return i2c_send_stop(regs) || res;
247 }
248 
249 void i2c_init(unsigned int bus, int speed, int slaveadd)
250 {
251  struct s3c24x0_i2c_bus *i2c = &i2c_busses[bus];
252 
253  unsigned long freq, pres = 16, div;
254  unsigned long val;
255 
257  // Calculate prescaler and divisor values.
258  if ((freq / pres / (16 + 1)) > speed)
259  /* set prescaler to 512 */
260  pres = 512;
261 
262  div = 0;
263 
264  while ((freq / pres / (div + 1)) > speed)
265  div++;
266 
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);
270 
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).
276 }
static void write8(void *addr, uint8_t val)
Definition: mmio.h:30
static void write32(void *addr, uint32_t val)
Definition: mmio.h:40
static uint8_t read8(const void *addr)
Definition: mmio.h:12
#define ASSERT(x)
Definition: assert.h:44
#define DIV_ROUND_UP(x, y)
Definition: helpers.h:60
#define printk(level,...)
Definition: stdlib.h:16
periph_id
Definition: periph.h:13
@ PERIPH_ID_I2C5
Definition: periph.h:36
@ PERIPH_ID_I2C2
Definition: periph.h:33
@ PERIPH_ID_I2C3
Definition: periph.h:34
@ PERIPH_ID_I2C0
Definition: periph.h:31
@ PERIPH_ID_I2C4
Definition: periph.h:35
@ PERIPH_ID_I2C7
Definition: periph.h:38
@ PERIPH_ID_I2C1
Definition: periph.h:32
@ PERIPH_ID_I2C6
Definition: periph.h:37
static struct tpm_chip chip
Definition: tis.c:17
#define I2C_M_RD
Definition: i2c.h:34
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
int platform_i2c_transfer(unsigned int bus, struct i2c_msg *segment, int seg_count)
Definition: i2c.c:176
void i2c_init(unsigned int bus)
Definition: i2c.c:198
unsigned long clock_get_periph_rate(enum periph_id peripheral)
get the clk frequency of the required peripheral
Definition: clock.c:220
@ I2cStatBusy
Definition: i2c.c:48
@ I2cStatAddrZero
Definition: i2c.c:43
@ I2cStatMasterRecv
Definition: i2c.c:53
@ I2cStatModeMask
Definition: i2c.c:50
@ I2cStatStartStop
Definition: i2c.c:47
@ I2cStatSlaveXmit
Definition: i2c.c:52
@ I2cStatMasterXmit
Definition: i2c.c:54
@ I2cStatAck
Definition: i2c.c:42
@ I2cStatSlaveRecv
Definition: i2c.c:51
@ I2cStatEnable
Definition: i2c.c:46
@ I2cStatAddrSlave
Definition: i2c.c:44
@ I2cStatArb
Definition: i2c.c:45
static void i2c_ack_enable(struct i2c_regs *regs)
Definition: i2c.c:110
static int i2c_got_ack(struct i2c_regs *regs)
Definition: i2c.c:120
static void i2c_clear_int(struct i2c_regs *regs)
Definition: i2c.c:105
static int i2c_xmit_buf(struct i2c_regs *regs, uint8_t *data, int len)
Definition: i2c.c:175
static int i2c_int_pending(struct i2c_regs *regs)
Definition: i2c.c:100
static int i2c_send_stop(struct i2c_regs *regs)
Definition: i2c.c:149
static struct s3c24x0_i2c_bus i2c_busses[]
Definition: i2c.c:57
static int i2c_wait_for_idle(struct i2c_regs *regs, int timeout_us)
Definition: i2c.c:125
static int i2c_recv_buf(struct i2c_regs *regs, uint8_t *data, int len)
Definition: i2c.c:198
@ I2cConIntPending
Definition: i2c.c:36
@ I2cConAckGen
Definition: i2c.c:38
@ I2cConIntEn
Definition: i2c.c:37
#define I2C_TIMEOUT_US
Definition: i2c.c:13
static int i2c_send_start(struct i2c_regs *regs, int read, int chip)
Definition: i2c.c:157
static void i2c_ack_disable(struct i2c_regs *regs)
Definition: i2c.c:115
static int i2c_wait_for_int(struct i2c_regs *regs, int timeout_us)
Definition: i2c.c:137
unsigned char uint8_t
Definition: stdint.h:8
Definition: x86.c:23
Definition: device.h:76
Definition: dw_i2c.c:39
struct i2c_msg - an I2C transaction segment beginning with START @addr: Slave address,...
Definition: i2c.h:32
uint16_t len
Definition: i2c.h:39
uint16_t slave
Definition: i2c.h:38
uint16_t flags
Definition: i2c.h:33
uint8_t * buf
Definition: i2c.h:40
Definition: i2c.c:16
uint8_t lc
Definition: i2c.c:25
uint8_t add
Definition: i2c.c:21
uint8_t ds
Definition: i2c.c:23
uint8_t stat
Definition: i2c.c:19
uint8_t con
Definition: i2c.c:17
struct i2c_regs * regs
Definition: i2c.c:31
enum periph_id periph_id
Definition: i2c.c:32
int bus_num
Definition: i2c.c:30
u8 val
Definition: sys.c:300
void udelay(uint32_t us)
Definition: udelay.c:15