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/addressmap.h>
9 #include <soc/grf.h>
10 #include <soc/soc.h>
11 #include <soc/i2c.h>
12 #include <soc/clock.h>
13 #include <stddef.h>
14 #include <stdint.h>
15 
16 #define RETRY_COUNT 3
17 /* 100000us = 100ms */
18 #define I2C_TIMEOUT_US 100000
19 #define I2C_BUS_MAX 6
20 #define I2C_NOACK 2
21 #define I2C_TIMEOUT 3
22 
23 #define i2c_info(x...) do {if (0) printk(BIOS_DEBUG, x); } while (0)
24 
25 struct rk_i2c_regs {
35  u32 reserved0[(0x100 - 0x24) / 4];
36  u32 txdata[8];
37  u32 reserved1[(0x200 - 0x120) / 4];
38  u32 rxdata[8];
39 };
40 
41 static const uintptr_t i2c_bus[] = IC_BASES;
42 
43 /* Con register bits. */
44 #define I2C_ACT2NAK (1<<6)
45 #define I2C_NAK (1<<5)
46 #define I2C_STOP (1<<4)
47 #define I2C_START (1<<3)
48 #define I2C_MODE_TX (0<<1)
49 #define I2C_MODE_TRX (1<<1)
50 #define I2C_MODE_RX (2<<1)
51 #define I2C_EN (1<<0)
52 
53 #define I2C_8BIT (1<<24)
54 #define I2C_16BIT (3<<24)
55 #define I2C_24BIT (7<<24)
56 
57 /* Mtxcnt register bits. */
58 #define I2C_CNT(cnt) ((cnt) & 0x3F)
59 
60 #define I2C_NAKRCVI (1<<6)
61 #define I2C_STOPI (1<<5)
62 #define I2C_STARTI (1<<4)
63 #define I2C_MBRFI (1<<3)
64 #define I2C_MBTFI (1<<2)
65 #define I2C_BRFI (1<<1)
66 #define I2C_BTFI (1<<0)
67 #define I2C_CLEANI 0x7F
68 
69 static int i2c_send_start(struct rk_i2c_regs *reg_addr)
70 {
71  int res = 0;
72  int timeout = I2C_TIMEOUT_US;
73 
74  i2c_info("I2c Start::Send Start bit\n");
75  write32(&reg_addr->i2c_ipd, I2C_CLEANI);
76  write32(&reg_addr->i2c_con, I2C_EN | I2C_START);
77  while (timeout--) {
78  if (read32(&reg_addr->i2c_ipd) & I2C_STARTI)
79  break;
80  udelay(1);
81  }
82 
83  if (timeout <= 0) {
84  printk(BIOS_ERR, "I2C Start::Send Start Bit Timeout\n");
85  res = I2C_TIMEOUT;
86  }
87 
88  return res;
89 }
90 
91 static int i2c_send_stop(struct rk_i2c_regs *reg_addr)
92 {
93  int res = 0;
94  int timeout = I2C_TIMEOUT_US;
95 
96  i2c_info("I2c Stop::Send Stop bit\n");
97  write32(&reg_addr->i2c_ipd, I2C_CLEANI);
98  write32(&reg_addr->i2c_con, I2C_EN | I2C_STOP);
99  while (timeout--) {
100  if (read32(&reg_addr->i2c_ipd) & I2C_STOPI)
101  break;
102  udelay(1);
103  }
104  write32(&reg_addr->i2c_con, 0);
105  if (timeout <= 0) {
106  printk(BIOS_ERR, "I2C Stop::Send Stop Bit Timeout\n");
107  res = I2C_TIMEOUT;
108  }
109 
110  return res;
111 }
112 
113 static int i2c_read(struct rk_i2c_regs *reg_addr, struct i2c_msg segment)
114 {
115  int res = 0;
116  uint8_t *data = segment.buf;
117  unsigned int bytes_remaining = segment.len;
118  unsigned int con = 0;
119 
120  write32(&reg_addr->i2c_mrxaddr, I2C_8BIT | segment.slave << 1 | 1);
121  write32(&reg_addr->i2c_mrxraddr, 0);
122  con = I2C_MODE_TRX | I2C_EN | I2C_ACT2NAK;
123  while (bytes_remaining) {
124  int timeout = CONFIG_I2C_TRANSFER_TIMEOUT_US;
125  size_t size = MIN(bytes_remaining, 32);
126  bytes_remaining -= size;
127  if (!bytes_remaining)
128  con |= I2C_EN | I2C_NAK;
129 
130  i2c_info("I2C Read::%zu bytes\n", size);
131  write32(&reg_addr->i2c_ipd, I2C_CLEANI);
132  write32(&reg_addr->i2c_con, con);
133  write32(&reg_addr->i2c_mrxcnt, size);
134 
135  while (timeout--) {
136  if (read32(&reg_addr->i2c_ipd) & I2C_NAKRCVI) {
137  write32(&reg_addr->i2c_mrxcnt, 0);
138  write32(&reg_addr->i2c_con, 0);
139  return I2C_NOACK;
140  }
141  if (read32(&reg_addr->i2c_ipd) & I2C_MBRFI)
142  break;
143  udelay(1);
144  }
145  if (timeout <= 0) {
146  printk(BIOS_ERR, "I2C Read::Recv Data Timeout\n");
147  write32(&reg_addr->i2c_mrxcnt, 0);
148  write32(&reg_addr->i2c_con, 0);
149  return I2C_TIMEOUT;
150  }
151 
152  buffer_from_fifo32(data, size, &reg_addr->rxdata, 4, 4);
153  data += size;
154  con = I2C_MODE_RX | I2C_EN | I2C_ACT2NAK;
155  }
156  return res;
157 }
158 
159 static int i2c_write(struct rk_i2c_regs *reg_addr, struct i2c_msg segment)
160 {
161  int res = 0;
162  uint8_t *data = segment.buf;
163  int bytes_remaining = segment.len + 1;
164 
165  /* Prepend one byte for the slave address to the transfer. */
166  u32 prefix = segment.slave << 1;
167  int prefsz = 1;
168 
169  while (bytes_remaining) {
170  int timeout = CONFIG_I2C_TRANSFER_TIMEOUT_US;
171  size_t size = MIN(bytes_remaining, 32);
172  buffer_to_fifo32_prefix(data, prefix, prefsz, size,
173  &reg_addr->txdata, 4, 4);
174  data += size - prefsz;
175 
176  i2c_info("I2C Write::%zu bytes\n", size);
177  write32(&reg_addr->i2c_ipd, I2C_CLEANI);
178  write32(&reg_addr->i2c_con,
180  write32(&reg_addr->i2c_mtxcnt, size);
181 
182  while (timeout--) {
183  if (read32(&reg_addr->i2c_ipd) & I2C_NAKRCVI) {
184  write32(&reg_addr->i2c_mtxcnt, 0);
185  write32(&reg_addr->i2c_con, 0);
186  return I2C_NOACK;
187  }
188  if (read32(&reg_addr->i2c_ipd) & I2C_MBTFI)
189  break;
190  udelay(1);
191  }
192 
193  if (timeout <= 0) {
194  printk(BIOS_ERR, "I2C Write::Send Data Timeout\n");
195  write32(&reg_addr->i2c_mtxcnt, 0);
196  write32(&reg_addr->i2c_con, 0);
197  return I2C_TIMEOUT;
198  }
199 
200  bytes_remaining -= size;
201  prefsz = 0;
202  prefix = 0;
203  }
204  return res;
205 }
206 
207 static int i2c_do_xfer(void *reg_addr, struct i2c_msg segment)
208 {
209  int res = 0;
210 
211  if (i2c_send_start(reg_addr))
212  return I2C_TIMEOUT;
213  if (segment.flags & I2C_M_RD)
214  res = i2c_read(reg_addr, segment);
215  else
216  res = i2c_write(reg_addr, segment);
217  return i2c_send_stop(reg_addr) || res;
218 }
219 
220 int platform_i2c_transfer(unsigned int bus, struct i2c_msg *segments,
221  int seg_count)
222 {
223  int i;
224  int res = 0;
225  struct rk_i2c_regs *regs = (struct rk_i2c_regs *)(i2c_bus[bus]);
226  struct i2c_msg *seg = segments;
227 
228  for (i = 0; i < seg_count; i++, seg++) {
229  res = i2c_do_xfer(regs, *seg);
230  if (res)
231  break;
232  }
233  return res;
234 }
235 
236 void i2c_init(unsigned int bus, unsigned int hz)
237 {
238  unsigned int clk_div;
239  unsigned int divl;
240  unsigned int divh;
241  unsigned int i2c_src_clk;
242  unsigned int i2c_clk;
243  struct rk_i2c_regs *regs = (struct rk_i2c_regs *)(i2c_bus[bus]);
244 
245  i2c_src_clk = rkclk_i2c_clock_for_bus(bus);
246 
247  /* SCL Divisor = 8*(CLKDIVL + 1 + CLKDIVH + 1)
248  SCL = PCLK / SCLK Divisor */
249  clk_div = DIV_ROUND_UP(i2c_src_clk, hz * 8);
250  divh = clk_div * 3 / 7 - 1;
251  divl = clk_div - divh - 2;
252  i2c_clk = i2c_src_clk / (8 * (divl + 1 + divh + 1));
253  printk(BIOS_DEBUG, "I2C bus %u: %uHz (divh = %u, divl = %u)\n",
254  bus, i2c_clk, divh, divl);
255  assert((divh < 65536) && (divl < 65536) && hz - i2c_clk < 15*KHz);
256  write32(&regs->i2c_clkdiv, (divh << 16) | (divl << 0));
257 }
static void write32(void *addr, uint32_t val)
Definition: mmio.h:40
static uint32_t read32(const void *addr)
Definition: mmio.h:22
#define assert(statement)
Definition: assert.h:74
#define MIN(a, b)
Definition: helpers.h:37
#define KHz
Definition: helpers.h:79
#define DIV_ROUND_UP(x, y)
Definition: helpers.h:60
#define printk(level,...)
Definition: stdlib.h:16
void buffer_from_fifo32(void *buffer, size_t size, void *fifo, int fifo_stride, int fifo_width)
Definition: mmio.c:8
void buffer_to_fifo32_prefix(const void *buffer, u32 prefix, int prefsz, size_t size, void *fifo, int fifo_stride, int fifo_width)
Definition: mmio.c:24
#define I2C_M_RD
Definition: i2c.h:34
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#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
#define I2C_MODE_TRX
Definition: i2c.c:49
#define i2c_info(x...)
Definition: i2c.c:23
#define I2C_MODE_TX
Definition: i2c.c:48
#define I2C_MBTFI
Definition: i2c.c:64
#define I2C_EN
Definition: i2c.c:51
#define I2C_START
Definition: i2c.c:47
#define I2C_NAK
Definition: i2c.c:45
static int i2c_write(struct rk_i2c_regs *reg_addr, struct i2c_msg segment)
Definition: i2c.c:159
#define I2C_8BIT
Definition: i2c.c:53
#define I2C_CLEANI
Definition: i2c.c:67
#define I2C_NAKRCVI
Definition: i2c.c:60
static int i2c_send_start(struct rk_i2c_regs *reg_addr)
Definition: i2c.c:69
static int i2c_read(struct rk_i2c_regs *reg_addr, struct i2c_msg segment)
Definition: i2c.c:113
#define I2C_TIMEOUT_US
Definition: i2c.c:18
#define I2C_STARTI
Definition: i2c.c:62
#define I2C_MBRFI
Definition: i2c.c:63
#define I2C_MODE_RX
Definition: i2c.c:50
static int i2c_do_xfer(void *reg_addr, struct i2c_msg segment)
Definition: i2c.c:207
static int i2c_send_stop(struct rk_i2c_regs *reg_addr)
Definition: i2c.c:91
#define I2C_STOP
Definition: i2c.c:46
#define I2C_ACT2NAK
Definition: i2c.c:44
#define I2C_NOACK
Definition: i2c.c:20
#define I2C_STOPI
Definition: i2c.c:61
#define I2C_TIMEOUT
Definition: i2c.c:21
unsigned int rkclk_i2c_clock_for_bus(unsigned int bus)
Definition: clock.c:658
#define IC_BASES
Definition: addressmap.h:91
uint32_t u32
Definition: stdint.h:51
unsigned long uintptr_t
Definition: stdint.h:21
unsigned char uint8_t
Definition: stdint.h:8
Definition: device.h:76
Definition: i2c.c:65
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
u32 reserved0[(0x100 - 0x24)/4]
Definition: i2c.c:35
u32 i2c_mrxaddr
Definition: i2c.c:28
u32 i2c_ipd
Definition: i2c.c:33
u32 i2c_mtxcnt
Definition: i2c.c:30
u32 i2c_fcnt
Definition: i2c.c:34
u32 reserved1[(0x200 - 0x120)/4]
Definition: i2c.c:37
u32 i2c_clkdiv
Definition: i2c.c:27
u32 i2c_mrxraddr
Definition: i2c.c:29
u32 i2c_con
Definition: i2c.c:26
u32 rxdata[8]
Definition: i2c.c:38
u32 i2c_mrxcnt
Definition: i2c.c:31
u32 i2c_ien
Definition: i2c.c:32
u32 txdata[8]
Definition: i2c.c:36
void udelay(uint32_t us)
Definition: udelay.c:15