• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
18 static uintptr_t g_nxp_i2c_addr;
19 
i2c_init(uintptr_t nxp_i2c_addr)20 void 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 
wait_for_state(struct ls_i2c * ccsr_i2c,unsigned char state,unsigned char mask)32 static 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 
tx_byte(struct ls_i2c * ccsr_i2c,unsigned char c)60 static 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 
gen_stop(struct ls_i2c * ccsr_i2c)79 static 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 
i2c_write_addr(struct ls_i2c * ccsr_i2c,unsigned char chip,int addr,int alen)94 static 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 
read_data(struct ls_i2c * ccsr_i2c,unsigned char chip,unsigned char * buf,int len)144 static 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 
write_data(struct ls_i2c * ccsr_i2c,unsigned char chip,const unsigned char * buf,int len)182 static 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 
i2c_read(unsigned char chip,int addr,int alen,unsigned char * buf,int len)200 int 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 
i2c_write(unsigned char chip,int addr,int alen,const unsigned char * buf,int len)226 int 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 
i2c_probe_chip(unsigned char chip)240 int 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 }
258