xref: /rk3399_rockchip-uboot/drivers/i2c/adi_i2c.c (revision f2465934b46235287e07473fa4919035ba1a2b68)
1fea9b69aSScott Jiang /*
2fea9b69aSScott Jiang  * i2c.c - driver for ADI TWI/I2C
3fea9b69aSScott Jiang  *
4fea9b69aSScott Jiang  * Copyright (c) 2006-2014 Analog Devices Inc.
5fea9b69aSScott Jiang  *
6fea9b69aSScott Jiang  * Licensed under the GPL-2 or later.
7*28527096SSimon Glass  *
8*28527096SSimon Glass  * NOTE: This driver should be converted to driver model before June 2017.
9*28527096SSimon Glass  * Please see doc/driver-model/i2c-howto.txt for instructions.
10fea9b69aSScott Jiang  */
11fea9b69aSScott Jiang 
12fea9b69aSScott Jiang #include <common.h>
1324b852a7SSimon Glass #include <console.h>
14fea9b69aSScott Jiang #include <i2c.h>
15fea9b69aSScott Jiang 
16fea9b69aSScott Jiang #include <asm/clock.h>
17fea9b69aSScott Jiang #include <asm/twi.h>
18a6be70f7SScott Jiang #include <asm/io.h>
19fea9b69aSScott Jiang 
20c469703bSScott Jiang static struct twi_regs *i2c_get_base(struct i2c_adapter *adap);
21c469703bSScott Jiang 
22fea9b69aSScott Jiang /* Every register is 32bit aligned, but only 16bits in size */
23fea9b69aSScott Jiang #define ureg(name) u16 name; u16 __pad_##name;
24fea9b69aSScott Jiang struct twi_regs {
25fea9b69aSScott Jiang 	ureg(clkdiv);
26fea9b69aSScott Jiang 	ureg(control);
27fea9b69aSScott Jiang 	ureg(slave_ctl);
28fea9b69aSScott Jiang 	ureg(slave_stat);
29fea9b69aSScott Jiang 	ureg(slave_addr);
30fea9b69aSScott Jiang 	ureg(master_ctl);
31fea9b69aSScott Jiang 	ureg(master_stat);
32fea9b69aSScott Jiang 	ureg(master_addr);
33fea9b69aSScott Jiang 	ureg(int_stat);
34fea9b69aSScott Jiang 	ureg(int_mask);
35fea9b69aSScott Jiang 	ureg(fifo_ctl);
36fea9b69aSScott Jiang 	ureg(fifo_stat);
37fea9b69aSScott Jiang 	char __pad[0x50];
38fea9b69aSScott Jiang 	ureg(xmt_data8);
39fea9b69aSScott Jiang 	ureg(xmt_data16);
40fea9b69aSScott Jiang 	ureg(rcv_data8);
41fea9b69aSScott Jiang 	ureg(rcv_data16);
42fea9b69aSScott Jiang };
43fea9b69aSScott Jiang #undef ureg
44fea9b69aSScott Jiang 
45fea9b69aSScott Jiang #ifdef TWI_CLKDIV
46fea9b69aSScott Jiang #define TWI0_CLKDIV TWI_CLKDIV
47c469703bSScott Jiang # ifdef CONFIG_SYS_MAX_I2C_BUS
48c469703bSScott Jiang # undef CONFIG_SYS_MAX_I2C_BUS
49fea9b69aSScott Jiang # endif
50c469703bSScott Jiang #define CONFIG_SYS_MAX_I2C_BUS 1
51fea9b69aSScott Jiang #endif
52fea9b69aSScott Jiang 
53fea9b69aSScott Jiang /*
54fea9b69aSScott Jiang  * The way speed is changed into duty often results in integer truncation
55fea9b69aSScott Jiang  * with 50% duty, so we'll force rounding up to the next duty by adding 1
56fea9b69aSScott Jiang  * to the max.  In practice this will get us a speed of something like
57fea9b69aSScott Jiang  * 385 KHz.  The other limit is easy to handle as it is only 8 bits.
58fea9b69aSScott Jiang  */
59fea9b69aSScott Jiang #define I2C_SPEED_MAX             400000
60fea9b69aSScott Jiang #define I2C_SPEED_TO_DUTY(speed)  (5000000 / (speed))
61fea9b69aSScott Jiang #define I2C_DUTY_MAX              (I2C_SPEED_TO_DUTY(I2C_SPEED_MAX) + 1)
62fea9b69aSScott Jiang #define I2C_DUTY_MIN              0xff	/* 8 bit limited */
63fea9b69aSScott Jiang #define SYS_I2C_DUTY              I2C_SPEED_TO_DUTY(CONFIG_SYS_I2C_SPEED)
64fea9b69aSScott Jiang /* Note: duty is inverse of speed, so the comparisons below are correct */
65fea9b69aSScott Jiang #if SYS_I2C_DUTY < I2C_DUTY_MAX || SYS_I2C_DUTY > I2C_DUTY_MIN
66c469703bSScott Jiang # error "The I2C hardware can only operate 20KHz - 400KHz"
67fea9b69aSScott Jiang #endif
68fea9b69aSScott Jiang 
69fea9b69aSScott Jiang /* All transfers are described by this data structure */
70fffff726SSimon Glass struct adi_i2c_msg {
71fea9b69aSScott Jiang 	u8 flags;
72fea9b69aSScott Jiang #define I2C_M_COMBO		0x4
73fea9b69aSScott Jiang #define I2C_M_STOP		0x2
74fea9b69aSScott Jiang #define I2C_M_READ		0x1
75fea9b69aSScott Jiang 	int len;		/* msg length */
76fea9b69aSScott Jiang 	u8 *buf;		/* pointer to msg data */
77fea9b69aSScott Jiang 	int alen;		/* addr length */
78fea9b69aSScott Jiang 	u8 *abuf;		/* addr buffer */
79fea9b69aSScott Jiang };
80fea9b69aSScott Jiang 
81fea9b69aSScott Jiang /* Allow msec timeout per ~byte transfer */
82fea9b69aSScott Jiang #define I2C_TIMEOUT 10
83fea9b69aSScott Jiang 
84fea9b69aSScott Jiang /**
85fea9b69aSScott Jiang  * wait_for_completion - manage the actual i2c transfer
86fea9b69aSScott Jiang  *	@msg: the i2c msg
87fea9b69aSScott Jiang  */
wait_for_completion(struct twi_regs * twi,struct adi_i2c_msg * msg)88fffff726SSimon Glass static int wait_for_completion(struct twi_regs *twi, struct adi_i2c_msg *msg)
89fea9b69aSScott Jiang {
90a6be70f7SScott Jiang 	u16 int_stat, ctl;
91fea9b69aSScott Jiang 	ulong timebase = get_timer(0);
92fea9b69aSScott Jiang 
93fea9b69aSScott Jiang 	do {
94a6be70f7SScott Jiang 		int_stat = readw(&twi->int_stat);
95fea9b69aSScott Jiang 
96fea9b69aSScott Jiang 		if (int_stat & XMTSERV) {
97a6be70f7SScott Jiang 			writew(XMTSERV, &twi->int_stat);
98fea9b69aSScott Jiang 			if (msg->alen) {
99a6be70f7SScott Jiang 				writew(*(msg->abuf++), &twi->xmt_data8);
100fea9b69aSScott Jiang 				--msg->alen;
101fea9b69aSScott Jiang 			} else if (!(msg->flags & I2C_M_COMBO) && msg->len) {
102a6be70f7SScott Jiang 				writew(*(msg->buf++), &twi->xmt_data8);
103fea9b69aSScott Jiang 				--msg->len;
104fea9b69aSScott Jiang 			} else {
105a6be70f7SScott Jiang 				ctl = readw(&twi->master_ctl);
106a6be70f7SScott Jiang 				if (msg->flags & I2C_M_COMBO)
107a6be70f7SScott Jiang 					writew(ctl | RSTART | MDIR,
108a6be70f7SScott Jiang 							&twi->master_ctl);
109a6be70f7SScott Jiang 				else
110a6be70f7SScott Jiang 					writew(ctl | STOP, &twi->master_ctl);
111fea9b69aSScott Jiang 			}
112fea9b69aSScott Jiang 		}
113fea9b69aSScott Jiang 		if (int_stat & RCVSERV) {
114a6be70f7SScott Jiang 			writew(RCVSERV, &twi->int_stat);
115fea9b69aSScott Jiang 			if (msg->len) {
116a6be70f7SScott Jiang 				*(msg->buf++) = readw(&twi->rcv_data8);
117fea9b69aSScott Jiang 				--msg->len;
118fea9b69aSScott Jiang 			} else if (msg->flags & I2C_M_STOP) {
119a6be70f7SScott Jiang 				ctl = readw(&twi->master_ctl);
120a6be70f7SScott Jiang 				writew(ctl | STOP, &twi->master_ctl);
121fea9b69aSScott Jiang 			}
122fea9b69aSScott Jiang 		}
123fea9b69aSScott Jiang 		if (int_stat & MERR) {
124a6be70f7SScott Jiang 			writew(MERR, &twi->int_stat);
125fea9b69aSScott Jiang 			return msg->len;
126fea9b69aSScott Jiang 		}
127fea9b69aSScott Jiang 		if (int_stat & MCOMP) {
128a6be70f7SScott Jiang 			writew(MCOMP, &twi->int_stat);
129fea9b69aSScott Jiang 			if (msg->flags & I2C_M_COMBO && msg->len) {
130a6be70f7SScott Jiang 				ctl = readw(&twi->master_ctl);
131a6be70f7SScott Jiang 				ctl = (ctl & ~RSTART) |
132fea9b69aSScott Jiang 					(min(msg->len, 0xff) << 6) | MEN | MDIR;
133a6be70f7SScott Jiang 				writew(ctl, &twi->master_ctl);
134fea9b69aSScott Jiang 			} else
135fea9b69aSScott Jiang 				break;
136fea9b69aSScott Jiang 		}
137fea9b69aSScott Jiang 
138fea9b69aSScott Jiang 		/* If we were able to do something, reset timeout */
139fea9b69aSScott Jiang 		if (int_stat)
140fea9b69aSScott Jiang 			timebase = get_timer(0);
141fea9b69aSScott Jiang 
142fea9b69aSScott Jiang 	} while (get_timer(timebase) < I2C_TIMEOUT);
143fea9b69aSScott Jiang 
144fea9b69aSScott Jiang 	return msg->len;
145fea9b69aSScott Jiang }
146fea9b69aSScott Jiang 
i2c_transfer(struct i2c_adapter * adap,uint8_t chip,uint addr,int alen,uint8_t * buffer,int len,uint8_t flags)147c469703bSScott Jiang static int i2c_transfer(struct i2c_adapter *adap, uint8_t chip, uint addr,
148c469703bSScott Jiang 			int alen, uint8_t *buffer, int len, uint8_t flags)
149fea9b69aSScott Jiang {
150c469703bSScott Jiang 	struct twi_regs *twi = i2c_get_base(adap);
151a6be70f7SScott Jiang 	int ret;
152a6be70f7SScott Jiang 	u16 ctl;
153fea9b69aSScott Jiang 	uchar addr_buffer[] = {
154fea9b69aSScott Jiang 		(addr >>  0),
155fea9b69aSScott Jiang 		(addr >>  8),
156fea9b69aSScott Jiang 		(addr >> 16),
157fea9b69aSScott Jiang 	};
158fffff726SSimon Glass 	struct adi_i2c_msg msg = {
159fea9b69aSScott Jiang 		.flags = flags | (len >= 0xff ? I2C_M_STOP : 0),
160fea9b69aSScott Jiang 		.buf   = buffer,
161fea9b69aSScott Jiang 		.len   = len,
162fea9b69aSScott Jiang 		.abuf  = addr_buffer,
163fea9b69aSScott Jiang 		.alen  = alen,
164fea9b69aSScott Jiang 	};
165fea9b69aSScott Jiang 
166fea9b69aSScott Jiang 	/* wait for things to settle */
167a6be70f7SScott Jiang 	while (readw(&twi->master_stat) & BUSBUSY)
168fea9b69aSScott Jiang 		if (ctrlc())
169fea9b69aSScott Jiang 			return 1;
170fea9b69aSScott Jiang 
171fea9b69aSScott Jiang 	/* Set Transmit device address */
172a6be70f7SScott Jiang 	writew(chip, &twi->master_addr);
173fea9b69aSScott Jiang 
174fea9b69aSScott Jiang 	/* Clear the FIFO before starting things */
175a6be70f7SScott Jiang 	writew(XMTFLUSH | RCVFLUSH, &twi->fifo_ctl);
176a6be70f7SScott Jiang 	writew(0, &twi->fifo_ctl);
177fea9b69aSScott Jiang 
178fea9b69aSScott Jiang 	/* prime the pump */
179fea9b69aSScott Jiang 	if (msg.alen) {
180fea9b69aSScott Jiang 		len = (msg.flags & I2C_M_COMBO) ? msg.alen : msg.alen + len;
181a6be70f7SScott Jiang 		writew(*(msg.abuf++), &twi->xmt_data8);
182fea9b69aSScott Jiang 		--msg.alen;
183fea9b69aSScott Jiang 	} else if (!(msg.flags & I2C_M_READ) && msg.len) {
184a6be70f7SScott Jiang 		writew(*(msg.buf++), &twi->xmt_data8);
185fea9b69aSScott Jiang 		--msg.len;
186fea9b69aSScott Jiang 	}
187fea9b69aSScott Jiang 
188fea9b69aSScott Jiang 	/* clear int stat */
189a6be70f7SScott Jiang 	writew(-1, &twi->master_stat);
190a6be70f7SScott Jiang 	writew(-1, &twi->int_stat);
191a6be70f7SScott Jiang 	writew(0, &twi->int_mask);
192fea9b69aSScott Jiang 
193fea9b69aSScott Jiang 	/* Master enable */
194a6be70f7SScott Jiang 	ctl = readw(&twi->master_ctl);
195a6be70f7SScott Jiang 	ctl = (ctl & FAST) | (min(len, 0xff) << 6) | MEN |
196fea9b69aSScott Jiang 		((msg.flags & I2C_M_READ) ? MDIR : 0);
197a6be70f7SScott Jiang 	writew(ctl, &twi->master_ctl);
198fea9b69aSScott Jiang 
199fea9b69aSScott Jiang 	/* process the rest */
200c469703bSScott Jiang 	ret = wait_for_completion(twi, &msg);
201fea9b69aSScott Jiang 
202fea9b69aSScott Jiang 	if (ret) {
203a6be70f7SScott Jiang 		ctl = readw(&twi->master_ctl) & ~MEN;
204a6be70f7SScott Jiang 		writew(ctl, &twi->master_ctl);
205a6be70f7SScott Jiang 		ctl = readw(&twi->control) & ~TWI_ENA;
206a6be70f7SScott Jiang 		writew(ctl, &twi->control);
207a6be70f7SScott Jiang 		ctl = readw(&twi->control) | TWI_ENA;
208a6be70f7SScott Jiang 		writew(ctl, &twi->control);
209fea9b69aSScott Jiang 	}
210fea9b69aSScott Jiang 
211fea9b69aSScott Jiang 	return ret;
212fea9b69aSScott Jiang }
213fea9b69aSScott Jiang 
adi_i2c_setspeed(struct i2c_adapter * adap,uint speed)214c469703bSScott Jiang static uint adi_i2c_setspeed(struct i2c_adapter *adap, uint speed)
215fea9b69aSScott Jiang {
216c469703bSScott Jiang 	struct twi_regs *twi = i2c_get_base(adap);
217fea9b69aSScott Jiang 	u16 clkdiv = I2C_SPEED_TO_DUTY(speed);
218fea9b69aSScott Jiang 
219fea9b69aSScott Jiang 	/* Set TWI interface clock */
220fea9b69aSScott Jiang 	if (clkdiv < I2C_DUTY_MAX || clkdiv > I2C_DUTY_MIN)
221fea9b69aSScott Jiang 		return -1;
222a6be70f7SScott Jiang 	clkdiv = (clkdiv << 8) | (clkdiv & 0xff);
223a6be70f7SScott Jiang 	writew(clkdiv, &twi->clkdiv);
224fea9b69aSScott Jiang 
225fea9b69aSScott Jiang 	/* Don't turn it on */
226a6be70f7SScott Jiang 	writew(speed > 100000 ? FAST : 0, &twi->master_ctl);
227fea9b69aSScott Jiang 
228fea9b69aSScott Jiang 	return 0;
229fea9b69aSScott Jiang }
230fea9b69aSScott Jiang 
adi_i2c_init(struct i2c_adapter * adap,int speed,int slaveaddr)231c469703bSScott Jiang static void adi_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
232fea9b69aSScott Jiang {
233c469703bSScott Jiang 	struct twi_regs *twi = i2c_get_base(adap);
234c469703bSScott Jiang 	u16 prescale = ((get_i2c_clk() / 1000 / 1000 + 5) / 10) & 0x7F;
235fea9b69aSScott Jiang 
236fea9b69aSScott Jiang 	/* Set TWI internal clock as 10MHz */
237a6be70f7SScott Jiang 	writew(prescale, &twi->control);
238fea9b69aSScott Jiang 
239fea9b69aSScott Jiang 	/* Set TWI interface clock as specified */
240fea9b69aSScott Jiang 	i2c_set_bus_speed(speed);
241fea9b69aSScott Jiang 
242fea9b69aSScott Jiang 	/* Enable it */
243a6be70f7SScott Jiang 	writew(TWI_ENA | prescale, &twi->control);
244fea9b69aSScott Jiang }
245fea9b69aSScott Jiang 
adi_i2c_read(struct i2c_adapter * adap,uint8_t chip,uint addr,int alen,uint8_t * buffer,int len)246c469703bSScott Jiang static int adi_i2c_read(struct i2c_adapter *adap, uint8_t chip,
247c469703bSScott Jiang 			uint addr, int alen, uint8_t *buffer, int len)
248c469703bSScott Jiang {
249c469703bSScott Jiang 	return i2c_transfer(adap, chip, addr, alen, buffer,
250c469703bSScott Jiang 			len, alen ? I2C_M_COMBO : I2C_M_READ);
251c469703bSScott Jiang }
252c469703bSScott Jiang 
adi_i2c_write(struct i2c_adapter * adap,uint8_t chip,uint addr,int alen,uint8_t * buffer,int len)253c469703bSScott Jiang static int adi_i2c_write(struct i2c_adapter *adap, uint8_t chip,
254c469703bSScott Jiang 			uint addr, int alen, uint8_t *buffer, int len)
255c469703bSScott Jiang {
256c469703bSScott Jiang 	return i2c_transfer(adap, chip, addr, alen, buffer, len, 0);
257c469703bSScott Jiang }
258c469703bSScott Jiang 
adi_i2c_probe(struct i2c_adapter * adap,uint8_t chip)259c469703bSScott Jiang static int adi_i2c_probe(struct i2c_adapter *adap, uint8_t chip)
260fea9b69aSScott Jiang {
261fea9b69aSScott Jiang 	u8 byte;
262c469703bSScott Jiang 	return adi_i2c_read(adap, chip, 0, 0, &byte, 1);
263fea9b69aSScott Jiang }
264fea9b69aSScott Jiang 
i2c_get_base(struct i2c_adapter * adap)265c469703bSScott Jiang static struct twi_regs *i2c_get_base(struct i2c_adapter *adap)
266fea9b69aSScott Jiang {
267c469703bSScott Jiang 	switch (adap->hwadapnr) {
268c469703bSScott Jiang #if CONFIG_SYS_MAX_I2C_BUS > 2
269c469703bSScott Jiang 	case 2:
270c469703bSScott Jiang 		return (struct twi_regs *)TWI2_CLKDIV;
271fea9b69aSScott Jiang #endif
272fea9b69aSScott Jiang #if CONFIG_SYS_MAX_I2C_BUS > 1
273a6be70f7SScott Jiang 	case 1:
274c469703bSScott Jiang 		return (struct twi_regs *)TWI1_CLKDIV;
275fea9b69aSScott Jiang #endif
276c469703bSScott Jiang 	case 0:
277c469703bSScott Jiang 		return (struct twi_regs *)TWI0_CLKDIV;
278c469703bSScott Jiang 
279c469703bSScott Jiang 	default:
280c469703bSScott Jiang 		printf("wrong hwadapnr: %d\n", adap->hwadapnr);
281fea9b69aSScott Jiang 	}
282fea9b69aSScott Jiang 
283c469703bSScott Jiang 	return NULL;
284c469703bSScott Jiang }
285c469703bSScott Jiang 
286c469703bSScott Jiang U_BOOT_I2C_ADAP_COMPLETE(adi_i2c0, adi_i2c_init, adi_i2c_probe,
287c469703bSScott Jiang 			 adi_i2c_read, adi_i2c_write,
288c469703bSScott Jiang 			 adi_i2c_setspeed,
289c469703bSScott Jiang 			 CONFIG_SYS_I2C_SPEED,
290c469703bSScott Jiang 			 0,
291c469703bSScott Jiang 			 0)
292c469703bSScott Jiang 
293fea9b69aSScott Jiang #if CONFIG_SYS_MAX_I2C_BUS > 1
294c469703bSScott Jiang U_BOOT_I2C_ADAP_COMPLETE(adi_i2c1, adi_i2c_init, adi_i2c_probe,
295c469703bSScott Jiang 			 adi_i2c_read, adi_i2c_write,
296c469703bSScott Jiang 			 adi_i2c_setspeed,
297c469703bSScott Jiang 			 CONFIG_SYS_I2C_SPEED,
298c469703bSScott Jiang 			 0,
299c469703bSScott Jiang 			 1)
300fea9b69aSScott Jiang #endif
301c469703bSScott Jiang 
302fea9b69aSScott Jiang #if CONFIG_SYS_MAX_I2C_BUS > 2
303c469703bSScott Jiang U_BOOT_I2C_ADAP_COMPLETE(adi_i2c2, adi_i2c_init, adi_i2c_probe,
304c469703bSScott Jiang 			 adi_i2c_read, adi_i2c_write,
305c469703bSScott Jiang 			 adi_i2c_setspeed,
306c469703bSScott Jiang 			 CONFIG_SYS_I2C_SPEED,
307c469703bSScott Jiang 			 0,
308c469703bSScott Jiang 			 2)
309fea9b69aSScott Jiang #endif
310