xref: /aosp_15_r20/external/coreboot/src/soc/nvidia/tegra/i2c.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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 
do_bus_clear(int bus)13 static void do_bus_clear(int bus)
14 {
15 	struct tegra_i2c_bus_info *info = &tegra_i2c_info[bus];
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);
26 	bc |= I2C_BUS_CLEAR_CONFIG_BC_TERMINATE_IMMEDIATE;
27 	write32(&regs->bus_clear_config, bc);
28 	// 4.1 Set MSTR_CONFIG_LOAD and wait for clear
29 	write32(&regs->config_load, I2C_CONFIG_LOAD_MSTR_CONFIG_LOAD_ENABLE);
30 	for (i = 0; i < timeout_ms * 10 && (read32(&regs->config_load) &
31 			I2C_CONFIG_LOAD_MSTR_CONFIG_LOAD_ENABLE); i++) {
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) &
39 			I2C_BUS_CLEAR_CONFIG_BC_ENABLE); i++) {
40 		printk(BIOS_DEBUG, "%s: wait for bus clear completion\n",
41 			__func__);
42 		udelay(100);
43 	}
44 }
45 
tegra_i2c_send_recv(int bus,int read,uint32_t * headers,int header_words,uint8_t * data,int data_len)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 {
50 	struct tegra_i2c_bus_info *info = &tegra_i2c_info[bus];
51 	struct tegra_i2c_regs * const regs = info->base;
52 
53 	while (data_len) {
54 		uint32_t status = read32(&regs->fifo_status);
55 		int tx_empty = status & I2C_FIFO_STATUS_TX_FIFO_EMPTY_CNT_MASK;
56 		tx_empty >>= I2C_FIFO_STATUS_TX_FIFO_EMPTY_CNT_SHIFT;
57 		int rx_full = status & I2C_FIFO_STATUS_RX_FIFO_FULL_CNT_MASK;
58 		rx_full >>= I2C_FIFO_STATUS_RX_FIFO_FULL_CNT_SHIFT;
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) {
95 			printk(BIOS_ERR,
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) {
102 			printk(BIOS_ERR,
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) {
109 			printk(BIOS_ERR,
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 
tegra_i2c_request(int bus,unsigned int chip,int cont,int restart,int read,void * data,int data_len)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) |
141 		     (bus << IOHEADER_CONTROLLER_ID_SHIFT) |
142 		     IOHEADER_PROTOCOL_I2C | IOHEADER_PKTTYPE_REQUEST;
143 
144 	headers[1] = (data_len - 1) << IOHEADER_PAYLOADSIZE_SHIFT;
145 
146 	uint32_t slave_addr = (chip << 1) | (read ? 1 : 0);
147 	headers[2] = IOHEADER_I2C_REQ_ADDR_MODE_7BIT |
148 		     (slave_addr << IOHEADER_I2C_REQ_SLAVE_ADDR_SHIFT);
149 	if (read)
150 		headers[2] |= IOHEADER_I2C_REQ_READ;
151 	if (restart)
152 		headers[2] |= IOHEADER_I2C_REQ_REPEAT_START;
153 	if (cont)
154 		headers[2] |= IOHEADER_I2C_REQ_CONTINUE_XFER;
155 
156 	return tegra_i2c_send_recv(bus, read, headers, ARRAY_SIZE(headers),
157 				   data, data_len);
158 }
159 
i2c_transfer_segment(unsigned int bus,unsigned int chip,int restart,int read,void * buf,int len)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 =
164 		(IOHEADER_PAYLOADSIZE_MASK + 1) >> IOHEADER_PAYLOADSIZE_SHIFT;
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 
platform_i2c_transfer(unsigned int bus,struct i2c_msg * segments,int count)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 
i2c_init(unsigned int bus)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 
208 	regs = tegra_i2c_info[bus].base;
209 
210 	write32(&regs->cnfg, I2C_CNFG_PACKET_MODE_EN);
211 }
212