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