PageRenderTime 25ms CodeModel.GetById 10ms app.highlight 11ms RepoModel.GetById 2ms app.codeStats 0ms

/board/evb64260/i2c.c

https://gitlab.com/veo-labs/u-boot
C | 310 lines | 236 code | 66 blank | 8 comment | 34 complexity | 659bcfb56da918253d4ad1af0777fdac MD5 | raw file
  1#include <common.h>
  2#include <mpc8xx.h>
  3#include <malloc.h>
  4#include <galileo/gt64260R.h>
  5#include <galileo/core.h>
  6
  7#define MAX_I2C_RETRYS	    10
  8#define I2C_DELAY	    1000  /* Should be at least the # of MHz of Tclk */
  9#undef	DEBUG_I2C
 10
 11#ifdef DEBUG_I2C
 12#define DP(x) x
 13#else
 14#define DP(x)
 15#endif
 16
 17/* Assuming that there is only one master on the bus (us) */
 18
 19static void
 20i2c_init(int speed, int slaveaddr)
 21{
 22	unsigned int n, m, freq, margin, power;
 23	unsigned int actualn = 0, actualm = 0;
 24	unsigned int control, status;
 25	unsigned int minmargin = 0xffffffff;
 26	unsigned int tclk = 125000000;
 27
 28	DP(puts("i2c_init\n"));
 29
 30	for (n = 0 ; n < 8 ; n++) {
 31		for (m = 0 ; m < 16 ; m++) {
 32			power = 2 << n; /* power = 2^(n+1) */
 33			freq = tclk / (10 * (m + 1) * power);
 34			if (speed > freq)
 35				margin = speed - freq;
 36			else
 37				margin = freq - speed;
 38			if (margin < minmargin) {
 39				minmargin   = margin;
 40				actualn	    = n;
 41				actualm	    = m;
 42			}
 43		}
 44	}
 45
 46	DP(puts("setup i2c bus\n"));
 47
 48	/* Setup bus */
 49
 50	GT_REG_WRITE(I2C_SOFT_RESET, 0);
 51
 52	DP(puts("udelay...\n"));
 53
 54	udelay(I2C_DELAY);
 55
 56	DP(puts("set baudrate\n"));
 57
 58	GT_REG_WRITE(I2C_STATUS_BAUDE_RATE, (actualm << 3) | actualn);
 59	GT_REG_WRITE(I2C_CONTROL, (0x1 << 2) | (0x1 << 6));
 60
 61	udelay(I2C_DELAY * 10);
 62
 63	DP(puts("read control, baudrate\n"));
 64
 65	GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
 66	GT_REG_READ(I2C_CONTROL, &control);
 67}
 68
 69static uchar
 70i2c_start(void)
 71{
 72	unsigned int control, status;
 73	int count = 0;
 74
 75	DP(puts("i2c_start\n"));
 76
 77	/* Set the start bit */
 78
 79	GT_REG_READ(I2C_CONTROL, &control);
 80	control |= (0x1 << 5);
 81	GT_REG_WRITE(I2C_CONTROL, control);
 82
 83	GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
 84
 85	count = 0;
 86	while ((status & 0xff) != 0x08) {
 87		udelay(I2C_DELAY);
 88		if (count > 20) {
 89			GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
 90			return status;
 91		}
 92		GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
 93		count++;
 94	}
 95
 96	return 0;
 97}
 98
 99static uchar
100i2c_select_device(uchar dev_addr, uchar read, int ten_bit)
101{
102	unsigned int status, data, bits = 7;
103	int count = 0;
104
105	DP(puts("i2c_select_device\n"));
106
107	/* Output slave address */
108
109	if (ten_bit)
110		bits = 10;
111
112	data = (dev_addr << 1);
113	/* set the read bit */
114	data |= read;
115	GT_REG_WRITE(I2C_DATA, data);
116	/* assert the address */
117	RESET_REG_BITS(I2C_CONTROL, BIT3);
118
119	udelay(I2C_DELAY);
120
121	GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
122	count = 0;
123	while (((status & 0xff) != 0x40) && ((status & 0xff) != 0x18)) {
124		udelay(I2C_DELAY);
125		if (count > 20) {
126			GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
127			return status;
128		}
129		GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
130		count++;
131	}
132
133	if (bits == 10) {
134		printf("10 bit I2C addressing not yet implemented\n");
135		return 0xff;
136	}
137
138	return 0;
139}
140
141static uchar
142i2c_get_data(uchar *return_data, int len) {
143
144	unsigned int data, status = 0;
145	int count = 0;
146
147	DP(puts("i2c_get_data\n"));
148
149	while (len) {
150
151		/* Get and return the data */
152
153		RESET_REG_BITS(I2C_CONTROL, (0x1 << 3));
154
155		udelay(I2C_DELAY * 5);
156
157		GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
158		count++;
159		while ((status & 0xff) != 0x50) {
160			udelay(I2C_DELAY);
161			if (count > 2) {
162				GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
163				return 0;
164			}
165			GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
166			count++;
167		}
168		GT_REG_READ(I2C_DATA, &data);
169		len--;
170		*return_data = (uchar)data;
171		return_data++;
172	}
173	RESET_REG_BITS(I2C_CONTROL, BIT2|BIT3);
174	while ((status & 0xff) != 0x58) {
175		udelay(I2C_DELAY);
176		if (count > 200) {
177			GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
178			return status;
179		}
180		GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
181		count++;
182	}
183	GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /* stop */
184
185	return 0;
186}
187
188static uchar
189i2c_write_data(unsigned int data, int len)
190{
191	unsigned int status;
192	int count = 0;
193
194	DP(puts("i2c_write_data\n"));
195
196	if (len > 4)
197		return -1;
198
199	while (len) {
200		/* Set and assert the data */
201
202		GT_REG_WRITE(I2C_DATA, (unsigned int)data);
203		RESET_REG_BITS(I2C_CONTROL, (0x1 << 3));
204
205		udelay(I2C_DELAY);
206
207		GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
208		count++;
209		while ((status & 0xff) != 0x28) {
210			udelay(I2C_DELAY);
211			if (count > 20) {
212				GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
213				return status;
214			}
215			GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
216			count++;
217		}
218		len--;
219	}
220	GT_REG_WRITE(I2C_CONTROL, (0x1 << 3) | (0x1 << 4));
221	GT_REG_WRITE(I2C_CONTROL, (0x1 << 4));
222
223	udelay(I2C_DELAY * 10);
224
225	return 0;
226}
227
228static uchar
229i2c_set_dev_offset(uchar dev_addr, unsigned int offset, int ten_bit)
230{
231	uchar status;
232
233	DP(puts("i2c_set_dev_offset\n"));
234
235	status = i2c_select_device(dev_addr, 0, ten_bit);
236	if (status) {
237#ifdef DEBUG_I2C
238		printf("Failed to select device setting offset: 0x%02x\n",
239		       status);
240#endif
241		return status;
242	}
243
244	status = i2c_write_data(offset, 1);
245	if (status) {
246#ifdef DEBUG_I2C
247		printf("Failed to write data: 0x%02x\n", status);
248#endif
249		return status;
250	}
251
252	return 0;
253}
254
255uchar
256i2c_read(uchar dev_addr, unsigned int offset, int len, uchar *data,
257	 int ten_bit)
258{
259	uchar status = 0;
260	unsigned int i2cfreq = 400000;
261
262	DP(puts("i2c_read\n"));
263
264	i2c_init(i2cfreq, 0);
265
266	status = i2c_start();
267
268	if (status) {
269#ifdef DEBUG_I2C
270		printf("Transaction start failed: 0x%02x\n", status);
271#endif
272		return status;
273	}
274
275	status = i2c_set_dev_offset(dev_addr, 0, 0);
276	if (status) {
277#ifdef DEBUG_I2C
278		printf("Failed to set offset: 0x%02x\n", status);
279#endif
280		return status;
281	}
282
283	i2c_init(i2cfreq, 0);
284
285	status = i2c_start();
286	if (status) {
287#ifdef DEBUG_I2C
288		printf("Transaction restart failed: 0x%02x\n", status);
289#endif
290		return status;
291	}
292
293	status = i2c_select_device(dev_addr, 1, ten_bit);
294	if (status) {
295#ifdef DEBUG_I2C
296		printf("Address not acknowledged: 0x%02x\n", status);
297#endif
298		return status;
299	}
300
301	status = i2c_get_data(data, len);
302	if (status) {
303#ifdef DEBUG_I2C
304		printf("Data not received: 0x%02x\n", status);
305#endif
306		return status;
307	}
308
309	return 0;
310}