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