src/: Remove g_ prefixes and _g suffixes from variables
[coreboot.git] / src / soc / nvidia / tegra / i2c.c
blob3ca0e13fa43415cd0d6855f1f919951b4a28e294
1 /*
2 * This file is part of the coreboot project.
4 * Copyright 2013 Google Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #include <device/mmio.h>
17 #include <console/console.h>
18 #include <delay.h>
19 #include <device/i2c_simple.h>
20 #include <string.h>
21 #include <soc/addressmap.h>
22 #include <stdint.h>
24 #include "i2c.h"
26 static void do_bus_clear(int bus)
28 struct tegra_i2c_bus_info *info = &tegra_i2c_info[bus];
29 struct tegra_i2c_regs * const regs = info->base;
30 uint32_t bc;
31 int i, timeout_ms = 10;
33 // BUS CLEAR regs (from TRM):
34 // 1. Reset the I2C controller (already done)
35 // 2. Set the # of clock pulses required (using default of 9)
36 // 3. Select STOP condition (using default of 1 = STOP)
37 // 4. Set TERMINATE condition (1 = IMMEDIATE)
38 bc = read32(&regs->bus_clear_config);
39 bc |= I2C_BUS_CLEAR_CONFIG_BC_TERMINATE_IMMEDIATE;
40 write32(&regs->bus_clear_config, bc);
41 // 4.1 Set MSTR_CONFIG_LOAD and wait for clear
42 write32(&regs->config_load, I2C_CONFIG_LOAD_MSTR_CONFIG_LOAD_ENABLE);
43 for (i = 0; i < timeout_ms * 10 && (read32(&regs->config_load) &
44 I2C_CONFIG_LOAD_MSTR_CONFIG_LOAD_ENABLE); i++) {
45 printk(BIOS_DEBUG, "%s: wait for MSTR_CONFIG_LOAD to clear\n",
46 __func__);
47 udelay(100);
49 // 5. Set ENABLE to start the bus clear op
50 write32(&regs->bus_clear_config, bc | I2C_BUS_CLEAR_CONFIG_BC_ENABLE);
51 for (i = 0; i < timeout_ms * 10 && (read32(&regs->bus_clear_config) &
52 I2C_BUS_CLEAR_CONFIG_BC_ENABLE); i++) {
53 printk(BIOS_DEBUG, "%s: wait for bus clear completion\n",
54 __func__);
55 udelay(100);
59 static int tegra_i2c_send_recv(int bus, int read,
60 uint32_t *headers, int header_words,
61 uint8_t *data, int data_len)
63 struct tegra_i2c_bus_info *info = &tegra_i2c_info[bus];
64 struct tegra_i2c_regs * const regs = info->base;
66 while (data_len) {
67 uint32_t status = read32(&regs->fifo_status);
68 int tx_empty = status & I2C_FIFO_STATUS_TX_FIFO_EMPTY_CNT_MASK;
69 tx_empty >>= I2C_FIFO_STATUS_TX_FIFO_EMPTY_CNT_SHIFT;
70 int rx_full = status & I2C_FIFO_STATUS_RX_FIFO_FULL_CNT_MASK;
71 rx_full >>= I2C_FIFO_STATUS_RX_FIFO_FULL_CNT_SHIFT;
73 while (header_words && tx_empty) {
74 write32(&regs->tx_packet_fifo, *headers++);
75 header_words--;
76 tx_empty--;
79 if (!header_words) {
80 if (read) {
81 while (data_len && rx_full) {
82 uint32_t word = read32(&regs->rx_fifo);
83 int todo = MIN(data_len, sizeof(word));
85 memcpy(data, &word, todo);
86 data_len -= todo;
87 data += sizeof(word);
88 rx_full--;
90 } else {
91 while (data_len && tx_empty) {
92 uint32_t word;
93 int todo = MIN(data_len, sizeof(word));
95 memcpy(&word, data, todo);
96 write32(&regs->tx_packet_fifo, word);
97 data_len -= todo;
98 data += sizeof(word);
99 tx_empty--;
104 uint32_t transfer_status =
105 read32(&regs->packet_transfer_status);
107 if (transfer_status & I2C_PKT_STATUS_NOACK_ADDR) {
108 printk(BIOS_ERR,
109 "%s: The address was not acknowledged.\n",
110 __func__);
111 info->reset_func(info->reset_bit);
112 i2c_init(bus);
113 return -1;
114 } else if (transfer_status & I2C_PKT_STATUS_NOACK_DATA) {
115 printk(BIOS_ERR,
116 "%s: The data was not acknowledged.\n",
117 __func__);
118 info->reset_func(info->reset_bit);
119 i2c_init(bus);
120 return -1;
121 } else if (transfer_status & I2C_PKT_STATUS_ARB_LOST) {
122 printk(BIOS_ERR,
123 "%s: Lost arbitration.\n",
124 __func__);
125 info->reset_func(info->reset_bit);
127 /* Use Tegra bus clear registers to unlock SDA */
128 do_bus_clear(bus);
130 /* re-init i2c controller */
131 i2c_init(bus);
133 /* Return w/error, let caller decide what to do */
134 return -1;
138 return 0;
141 static int tegra_i2c_request(int bus, unsigned int chip, int cont, int restart,
142 int read, void *data, int data_len)
144 uint32_t headers[3];
146 if (restart && cont) {
147 printk(BIOS_ERR, "%s: Repeat start and continue xfer are "
148 "mutually exclusive.\n", __func__);
149 return -1;
152 headers[0] = (0 << IOHEADER_PROTHDRSZ_SHIFT) |
153 (1 << IOHEADER_PKTID_SHIFT) |
154 (bus << IOHEADER_CONTROLLER_ID_SHIFT) |
155 IOHEADER_PROTOCOL_I2C | IOHEADER_PKTTYPE_REQUEST;
157 headers[1] = (data_len - 1) << IOHEADER_PAYLOADSIZE_SHIFT;
159 uint32_t slave_addr = (chip << 1) | (read ? 1 : 0);
160 headers[2] = IOHEADER_I2C_REQ_ADDR_MODE_7BIT |
161 (slave_addr << IOHEADER_I2C_REQ_SLAVE_ADDR_SHIFT);
162 if (read)
163 headers[2] |= IOHEADER_I2C_REQ_READ;
164 if (restart)
165 headers[2] |= IOHEADER_I2C_REQ_REPEAT_START;
166 if (cont)
167 headers[2] |= IOHEADER_I2C_REQ_CONTINUE_XFER;
169 return tegra_i2c_send_recv(bus, read, headers, ARRAY_SIZE(headers),
170 data, data_len);
173 static int i2c_transfer_segment(unsigned int bus, unsigned int chip, int restart,
174 int read, void *buf, int len)
176 const uint32_t max_payload =
177 (IOHEADER_PAYLOADSIZE_MASK + 1) >> IOHEADER_PAYLOADSIZE_SHIFT;
179 while (len) {
180 int todo = MIN(len, max_payload);
181 int cont = (todo < len);
182 if (tegra_i2c_request(bus, chip, cont, restart,
183 read, buf, todo))
184 return -1;
185 len -= todo;
186 buf += todo;
188 return 0;
191 int platform_i2c_transfer(unsigned int bus, struct i2c_msg *segments, int count)
193 struct i2c_msg *seg = segments;
194 int i;
196 if (bus >= num_i2c_buses) {
197 printk(BIOS_ERR, "%s: ERROR: invalid I2C bus (%u)\n", __func__,
198 bus);
199 return -1;
202 for (i = 0; i < count; seg++, i++) {
203 if (i2c_transfer_segment(bus, seg->slave, i < count - 1,
204 seg->flags & I2C_M_RD,
205 seg->buf, seg->len))
206 return -1;
208 return 0;
211 void i2c_init(unsigned int bus)
213 struct tegra_i2c_regs *regs;
215 if (bus >= num_i2c_buses) {
216 printk(BIOS_ERR, "%s: ERROR: invalid I2C bus (%u)\n", __func__,
217 bus);
218 return;
221 regs = tegra_i2c_info[bus].base;
223 write32(&regs->cnfg, I2C_CNFG_PACKET_MODE_EN);