blob: 92814091d695fa243ce65585161f017a59a0e77f [file] [log] [blame]
Pankaj Gupta0d2d3c22020-12-09 14:02:38 +05301/*
2 * Copyright 2016-2020 NXP
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#include <errno.h>
9#include <stdint.h>
10#include <stdio.h>
11#include <stdlib.h>
12
13#include <common/debug.h>
14#include <drivers/delay_timer.h>
15#include "i2c.h"
16#include <nxp_timer.h>
17
18static uintptr_t g_nxp_i2c_addr;
19
20void i2c_init(uintptr_t nxp_i2c_addr)
21{
22 struct ls_i2c *ccsr_i2c = (void *)nxp_i2c_addr;
23
24 g_nxp_i2c_addr = nxp_i2c_addr;
25 /* Presume workaround for erratum a009203 applied */
26 i2c_out(&ccsr_i2c->cr, I2C_CR_DIS);
27 i2c_out(&ccsr_i2c->fd, I2C_FD_CONSERV);
28 i2c_out(&ccsr_i2c->sr, I2C_SR_RST);
29 i2c_out(&ccsr_i2c->cr, I2C_CR_EN);
30}
31
32static int wait_for_state(struct ls_i2c *ccsr_i2c,
33 unsigned char state, unsigned char mask)
34{
35 unsigned char sr;
36 uint64_t start_time = get_timer_val(0);
37 uint64_t timer;
38
39 do {
40 sr = i2c_in(&ccsr_i2c->sr);
41 if (sr & I2C_SR_AL) {
42 i2c_out(&ccsr_i2c->sr, sr);
43 WARN("I2C arbitration lost\n");
44 return -EIO;
45 }
46 if ((sr & mask) == state) {
47 return (int)sr;
48 }
49
50 timer = get_timer_val(start_time);
51 if (timer > I2C_TIMEOUT)
52 break;
53 mdelay(1);
54 } while (1);
55 WARN("I2C: Timeout waiting for state 0x%x, sr = 0x%x\n", state, sr);
56
57 return -ETIMEDOUT;
58}
59
60static int tx_byte(struct ls_i2c *ccsr_i2c, unsigned char c)
61{
62 int ret;
63
64 i2c_out(&ccsr_i2c->sr, I2C_SR_IF);
65 i2c_out(&ccsr_i2c->dr, c);
66 ret = wait_for_state(ccsr_i2c, I2C_SR_IF, I2C_SR_IF);
67 if (ret < 0) {
68 WARN("%s: state error\n", __func__);
69 return ret;
70 }
71 if (ret & I2C_SR_RX_NAK) {
72 WARN("%s: nodev\n", __func__);
73 return -ENODEV;
74 }
75
76 return 0;
77}
78
79static int gen_stop(struct ls_i2c *ccsr_i2c)
80{
81 unsigned char cr;
82 int ret;
83
84 cr = i2c_in(&ccsr_i2c->cr);
85 cr &= ~(I2C_CR_MA | I2C_CR_TX);
86 i2c_out(&ccsr_i2c->cr, cr);
87 ret = wait_for_state(ccsr_i2c, I2C_SR_IDLE, I2C_SR_BB);
88 if (ret < 0) {
89 WARN("I2C: Generating stop failed.\n");
90 }
91 return ret;
92}
93
94static int i2c_write_addr(struct ls_i2c *ccsr_i2c, unsigned char chip,
95 int addr, int alen)
96{
97 int ret;
98 unsigned char cr;
99
100 if (alen != 1) {
101 WARN("I2C: Unsupported address len [%d]\n", alen);
102 return -EIO;
103 }
104
105 if (i2c_in(&ccsr_i2c->ad) == (chip << 1)) {
106 WARN("I2C: slave address same as self\n");
107 return -ENODEV;
108 }
109 i2c_out(&ccsr_i2c->sr, I2C_SR_IF);
110 ret = wait_for_state(ccsr_i2c, I2C_SR_IDLE, I2C_SR_BB);
111 if (ret < 0) {
112 return ret;
113 }
114
115 cr = i2c_in(&ccsr_i2c->cr);
116 cr |= I2C_CR_MA;
117 i2c_out(&ccsr_i2c->cr, cr);
118 ret = wait_for_state(ccsr_i2c, I2C_SR_BB, I2C_SR_BB);
119 if (ret < 0) {
120 return ret;
121 }
122
123 VERBOSE("Before writing chip %d\n", chip);
124 cr |= I2C_CR_TX | I2C_CR_TX_NAK;
125 i2c_out(&ccsr_i2c->cr, cr);
126 ret = tx_byte(ccsr_i2c, chip << 1);
127 if (ret < 0) {
128 gen_stop(ccsr_i2c);
129 return ret;
130 }
131
132 VERBOSE("Before writing addr\n");
133 while (alen--) {
134 ret = tx_byte(ccsr_i2c, (addr >> (alen << 3)) & 0xff);
135 if (ret < 0) {
136 gen_stop(ccsr_i2c);
137 return ret;
138 }
139 }
140
141 return 0;
142}
143
144static int read_data(struct ls_i2c *ccsr_i2c, unsigned char chip,
145 unsigned char *buf, int len)
146{
147 int i;
148 int ret;
149 unsigned char cr;
150
151 cr = i2c_in(&ccsr_i2c->cr);
152 cr &= ~(I2C_CR_TX | I2C_CR_TX_NAK);
153 if (len == 1) {
154 cr |= I2C_CR_TX_NAK;
155 }
156 i2c_out(&ccsr_i2c->cr, cr);
157 i2c_out(&ccsr_i2c->sr, I2C_SR_IF);
158 i2c_in(&ccsr_i2c->dr); /* dummy read */
159 for (i = 0; i < len; i++) {
160 ret = wait_for_state(ccsr_i2c, I2C_SR_IF, I2C_SR_IF);
161 if (ret < 0) {
162 gen_stop(ccsr_i2c);
163 return ret;
164 }
165 if (i == (len - 1)) {
166 gen_stop(ccsr_i2c);
167 } else if (i == (len - 2)) {
168 /* Updating the command to send
169 * No ACK.
170 */
171 cr = i2c_in(&ccsr_i2c->cr);
172 cr |= I2C_CR_TX_NAK;
173 i2c_out(&ccsr_i2c->cr, cr);
174 }
175 i2c_out(&ccsr_i2c->sr, I2C_SR_IF);
176 buf[i] = i2c_in(&ccsr_i2c->dr);
177 }
178
179 return 0;
180}
181
182static int write_data(struct ls_i2c *ccsr_i2c, unsigned char chip,
183 const unsigned char *buf, int len)
184{
185 int i;
186 int ret;
187
188 for (i = 0; i < len; i++) {
189 ret = tx_byte(ccsr_i2c, buf[i]);
190 if (ret < 0) {
191 break;
192 }
193 }
194 ret = gen_stop(ccsr_i2c);
195
196 return ret;
197}
198
199
200int i2c_read(unsigned char chip, int addr, int alen,
201 unsigned char *buf, int len)
202{
203 int ret;
204 unsigned char cr;
205 struct ls_i2c *ccsr_i2c = (void *)g_nxp_i2c_addr;
206
207 ret = i2c_write_addr(ccsr_i2c, chip, addr, alen);
208 if (ret < 0) {
209 gen_stop(ccsr_i2c);
210 return ret;
211 }
212
213 cr = i2c_in(&ccsr_i2c->cr);
214 cr |= I2C_CR_RSTA;
215 i2c_out(&ccsr_i2c->cr, cr);
216
217 ret = tx_byte(ccsr_i2c, (chip << 1) | 1);
218 if (ret < 0) {
219 gen_stop(ccsr_i2c);
220 return ret;
221 }
222
223 return read_data(ccsr_i2c, chip, buf, len);
224}
225
226int i2c_write(unsigned char chip, int addr, int alen,
227 const unsigned char *buf, int len)
228{
229 int ret;
230 struct ls_i2c *ccsr_i2c = (void *)g_nxp_i2c_addr;
231
232 ret = i2c_write_addr(ccsr_i2c, chip, addr, alen);
233 if (ret < 0) {
234 return ret;
235 }
236
237 return write_data(ccsr_i2c, chip, buf, len);
238}
239
240int i2c_probe_chip(unsigned char chip)
241{
242 int ret;
243 struct ls_i2c *ccsr_i2c = (void *)g_nxp_i2c_addr;
244
245 ret = i2c_write_addr(ccsr_i2c, chip, 0, 0);
246 if (ret < 0) {
247 WARN("write addr failed\n");
248 return ret;
249 }
250
251 ret = gen_stop(ccsr_i2c);
252 if (ret < 0) {
253 WARN("I2C: Probe not complete.\n");
254 }
255
256 return ret;
257}