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 <console/console.h>
5 #include <delay.h>
6 #include <device/i2c_simple.h>
7 #include <string.h>
8 #include <soc/addressmap.h>
9 #include <stdint.h>
10 
11 #include "i2c.h"
12 
13 static void do_bus_clear(int bus)
14 {
16  struct tegra_i2c_regs * const regs = info->base;
17  uint32_t bc;
18  int i, timeout_ms = 10;
19 
20  // BUS CLEAR regs (from TRM):
21  // 1. Reset the I2C controller (already done)
22  // 2. Set the # of clock pulses required (using default of 9)
23  // 3. Select STOP condition (using default of 1 = STOP)
24  // 4. Set TERMINATE condition (1 = IMMEDIATE)
25  bc = read32(&regs->bus_clear_config);
27  write32(&regs->bus_clear_config, bc);
28  // 4.1 Set MSTR_CONFIG_LOAD and wait for clear
30  for (i = 0; i < timeout_ms * 10 && (read32(&regs->config_load) &
32  printk(BIOS_DEBUG, "%s: wait for MSTR_CONFIG_LOAD to clear\n",
33  __func__);
34  udelay(100);
35  }
36  // 5. Set ENABLE to start the bus clear op
37  write32(&regs->bus_clear_config, bc | I2C_BUS_CLEAR_CONFIG_BC_ENABLE);
38  for (i = 0; i < timeout_ms * 10 && (read32(&regs->bus_clear_config) &
40  printk(BIOS_DEBUG, "%s: wait for bus clear completion\n",
41  __func__);
42  udelay(100);
43  }
44 }
45 
46 static int tegra_i2c_send_recv(int bus, int read,
47  uint32_t *headers, int header_words,
48  uint8_t *data, int data_len)
49 {
51  struct tegra_i2c_regs * const regs = info->base;
52 
53  while (data_len) {
54  uint32_t status = read32(&regs->fifo_status);
59 
60  while (header_words && tx_empty) {
61  write32(&regs->tx_packet_fifo, *headers++);
62  header_words--;
63  tx_empty--;
64  }
65 
66  if (!header_words) {
67  if (read) {
68  while (data_len && rx_full) {
69  uint32_t word = read32(&regs->rx_fifo);
70  int todo = MIN(data_len, sizeof(word));
71 
72  memcpy(data, &word, todo);
73  data_len -= todo;
74  data += sizeof(word);
75  rx_full--;
76  }
77  } else {
78  while (data_len && tx_empty) {
79  uint32_t word;
80  int todo = MIN(data_len, sizeof(word));
81 
82  memcpy(&word, data, todo);
83  write32(&regs->tx_packet_fifo, word);
84  data_len -= todo;
85  data += sizeof(word);
86  tx_empty--;
87  }
88  }
89  }
90 
91  uint32_t transfer_status =
92  read32(&regs->packet_transfer_status);
93 
94  if (transfer_status & I2C_PKT_STATUS_NOACK_ADDR) {
96  "%s: The address was not acknowledged.\n",
97  __func__);
98  info->reset_func(info->reset_bit);
99  i2c_init(bus);
100  return -1;
101  } else if (transfer_status & I2C_PKT_STATUS_NOACK_DATA) {
103  "%s: The data was not acknowledged.\n",
104  __func__);
105  info->reset_func(info->reset_bit);
106  i2c_init(bus);
107  return -1;
108  } else if (transfer_status & I2C_PKT_STATUS_ARB_LOST) {
110  "%s: Lost arbitration.\n",
111  __func__);
112  info->reset_func(info->reset_bit);
113 
114  /* Use Tegra bus clear registers to unlock SDA */
115  do_bus_clear(bus);
116 
117  /* re-init i2c controller */
118  i2c_init(bus);
119 
120  /* Return w/error, let caller decide what to do */
121  return -1;
122  }
123  }
124 
125  return 0;
126 }
127 
128 static int tegra_i2c_request(int bus, unsigned int chip, int cont, int restart,
129  int read, void *data, int data_len)
130 {
131  uint32_t headers[3];
132 
133  if (restart && cont) {
134  printk(BIOS_ERR, "%s: Repeat start and continue xfer are "
135  "mutually exclusive.\n", __func__);
136  return -1;
137  }
138 
139  headers[0] = (0 << IOHEADER_PROTHDRSZ_SHIFT) |
140  (1 << IOHEADER_PKTID_SHIFT) |
143 
144  headers[1] = (data_len - 1) << IOHEADER_PAYLOADSIZE_SHIFT;
145 
146  uint32_t slave_addr = (chip << 1) | (read ? 1 : 0);
148  (slave_addr << IOHEADER_I2C_REQ_SLAVE_ADDR_SHIFT);
149  if (read)
151  if (restart)
153  if (cont)
155 
157  data, data_len);
158 }
159 
160 static int i2c_transfer_segment(unsigned int bus, unsigned int chip, int restart,
161  int read, void *buf, int len)
162 {
163  const uint32_t max_payload =
165 
166  while (len) {
167  int todo = MIN(len, max_payload);
168  int cont = (todo < len);
169  if (tegra_i2c_request(bus, chip, cont, restart,
170  read, buf, todo))
171  return -1;
172  len -= todo;
173  buf += todo;
174  }
175  return 0;
176 }
177 
178 int platform_i2c_transfer(unsigned int bus, struct i2c_msg *segments, int count)
179 {
180  struct i2c_msg *seg = segments;
181  int i;
182 
183  if (bus >= num_i2c_buses) {
184  printk(BIOS_ERR, "%s: ERROR: invalid I2C bus (%u)\n", __func__,
185  bus);
186  return -1;
187  }
188 
189  for (i = 0; i < count; seg++, i++) {
190  if (i2c_transfer_segment(bus, seg->slave, i < count - 1,
191  seg->flags & I2C_M_RD,
192  seg->buf, seg->len))
193  return -1;
194  }
195  return 0;
196 }
197 
198 void i2c_init(unsigned int bus)
199 {
200  struct tegra_i2c_regs *regs;
201 
202  if (bus >= num_i2c_buses) {
203  printk(BIOS_ERR, "%s: ERROR: invalid I2C bus (%u)\n", __func__,
204  bus);
205  return;
206  }
207 
209 
211 }
static void write32(void *addr, uint32_t val)
Definition: mmio.h:40
static uint32_t read32(const void *addr)
Definition: mmio.h:22
void * memcpy(void *dest, const void *src, size_t n)
Definition: memcpy.c:7
#define ARRAY_SIZE(a)
Definition: helpers.h:12
#define MIN(a, b)
Definition: helpers.h:37
#define printk(level,...)
Definition: stdlib.h:16
static struct smmstore_params_info info
Definition: ramstage.c:12
static struct tpm_chip chip
Definition: tis.c:17
#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
static uint8_t * buf
Definition: uart.c:7
struct omap_image_headers headers
Definition: header.c:12
int platform_i2c_transfer(unsigned int bus, struct i2c_msg *segment, int seg_count)
Definition: i2c.c:176
struct tegra_i2c_bus_info tegra_i2c_info[]
Definition: i2c.c:7
const unsigned int num_i2c_buses
Definition: i2c.c:40
static int tegra_i2c_request(int bus, unsigned int chip, int cont, int restart, int read, void *data, int data_len)
Definition: i2c.c:128
static int tegra_i2c_send_recv(int bus, int read, uint32_t *headers, int header_words, uint8_t *data, int data_len)
Definition: i2c.c:46
void i2c_init(unsigned int bus)
Definition: i2c.c:198
static int i2c_transfer_segment(unsigned int bus, unsigned int chip, int restart, int read, void *buf, int len)
Definition: i2c.c:160
static void do_bus_clear(int bus)
Definition: i2c.c:13
@ I2C_PKT_STATUS_ARB_LOST
Definition: i2c.h:85
@ I2C_PKT_STATUS_NOACK_DATA
Definition: i2c.h:84
@ I2C_PKT_STATUS_NOACK_ADDR
Definition: i2c.h:83
@ IOHEADER_I2C_REQ_SLAVE_ADDR_SHIFT
Definition: i2c.h:54
@ IOHEADER_I2C_REQ_READ
Definition: i2c.h:43
@ IOHEADER_I2C_REQ_REPEAT_START
Definition: i2c.h:48
@ IOHEADER_I2C_REQ_CONTINUE_XFER
Definition: i2c.h:50
@ IOHEADER_I2C_REQ_ADDR_MODE_7BIT
Definition: i2c.h:45
@ I2C_FIFO_STATUS_TX_FIFO_EMPTY_CNT_MASK
Definition: i2c.h:91
@ I2C_FIFO_STATUS_RX_FIFO_FULL_CNT_MASK
Definition: i2c.h:94
@ I2C_FIFO_STATUS_RX_FIFO_FULL_CNT_SHIFT
Definition: i2c.h:93
@ I2C_FIFO_STATUS_TX_FIFO_EMPTY_CNT_SHIFT
Definition: i2c.h:90
@ I2C_BUS_CLEAR_CONFIG_BC_ENABLE
Definition: i2c.h:104
@ I2C_BUS_CLEAR_CONFIG_BC_TERMINATE_IMMEDIATE
Definition: i2c.h:103
@ I2C_CONFIG_LOAD_MSTR_CONFIG_LOAD_ENABLE
Definition: i2c.h:108
@ I2C_CNFG_PACKET_MODE_EN
Definition: i2c.h:64
@ IOHEADER_PKTID_SHIFT
Definition: i2c.h:16
@ IOHEADER_PAYLOADSIZE_MASK
Definition: i2c.h:32
@ IOHEADER_PROTOCOL_I2C
Definition: i2c.h:22
@ IOHEADER_PROTHDRSZ_SHIFT
Definition: i2c.h:14
@ IOHEADER_PKTTYPE_REQUEST
Definition: i2c.h:25
@ IOHEADER_PAYLOADSIZE_SHIFT
Definition: i2c.h:31
@ IOHEADER_CONTROLLER_ID_SHIFT
Definition: i2c.h:18
static unsigned int word
Definition: uart.c:88
unsigned int uint32_t
Definition: stdint.h:14
unsigned char uint8_t
Definition: stdint.h:8
Definition: device.h:76
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
void * base
Definition: i2c.h:112
uint32_t status
Definition: i2c.h:126
static struct am335x_pinmux_regs * regs
Definition: pinmux.c:7
void udelay(uint32_t us)
Definition: udelay.c:15
#define count