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