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(®s->bus_clear_config);
26 bc |= I2C_BUS_CLEAR_CONFIG_BC_TERMINATE_IMMEDIATE;
27 write32(®s->bus_clear_config, bc);
28 // 4.1 Set MSTR_CONFIG_LOAD and wait for clear
29 write32(®s->config_load, I2C_CONFIG_LOAD_MSTR_CONFIG_LOAD_ENABLE);
30 for (i = 0; i < timeout_ms * 10 && (read32(®s->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(®s->bus_clear_config, bc | I2C_BUS_CLEAR_CONFIG_BC_ENABLE);
38 for (i = 0; i < timeout_ms * 10 && (read32(®s->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(®s->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(®s->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(®s->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(®s->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(®s->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(®s->cnfg, I2C_CNFG_PACKET_MODE_EN);
211 }
212