Commit 86bdd70a09be7868df19983af27f3c18e96c610f
Committed by
Heiko Schocher
1 parent
d6a320d5bb
Exists in
master
and in
49 other branches
blackfin: rename bfin-twi_i2c driver to adi_i2c
The ADI twi peripheral is not binding to Blackfin processor only. Change to a generic name. Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
Showing 2 changed files with 393 additions and 0 deletions Side-by-side Diff
arch/blackfin/include/asm/twi.h
1 | +/* | |
2 | + * i2c.c - driver for Blackfin on-chip TWI/I2C | |
3 | + * | |
4 | + * Copyright (c) 2006-2010 Analog Devices Inc. | |
5 | + * | |
6 | + * Licensed under the GPL-2 or later. | |
7 | + */ | |
8 | + | |
9 | +#ifndef __ARCH_TWI_H | |
10 | +#define __ARCH_TWI_H | |
11 | + | |
12 | +#include <asm/blackfin.h> | |
13 | +#include <asm/mach-common/bits/twi.h> | |
14 | + | |
15 | +#endif |
drivers/i2c/adi_i2c.c
1 | +/* | |
2 | + * i2c.c - driver for Blackfin on-chip TWI/I2C | |
3 | + * | |
4 | + * Copyright (c) 2006-2010 Analog Devices Inc. | |
5 | + * | |
6 | + * Licensed under the GPL-2 or later. | |
7 | + */ | |
8 | + | |
9 | +#include <common.h> | |
10 | +#include <i2c.h> | |
11 | + | |
12 | +#include <asm/clock.h> | |
13 | +#include <asm/twi.h> | |
14 | + | |
15 | +/* Every register is 32bit aligned, but only 16bits in size */ | |
16 | +#define ureg(name) u16 name; u16 __pad_##name; | |
17 | +struct twi_regs { | |
18 | + ureg(clkdiv); | |
19 | + ureg(control); | |
20 | + ureg(slave_ctl); | |
21 | + ureg(slave_stat); | |
22 | + ureg(slave_addr); | |
23 | + ureg(master_ctl); | |
24 | + ureg(master_stat); | |
25 | + ureg(master_addr); | |
26 | + ureg(int_stat); | |
27 | + ureg(int_mask); | |
28 | + ureg(fifo_ctl); | |
29 | + ureg(fifo_stat); | |
30 | + char __pad[0x50]; | |
31 | + ureg(xmt_data8); | |
32 | + ureg(xmt_data16); | |
33 | + ureg(rcv_data8); | |
34 | + ureg(rcv_data16); | |
35 | +}; | |
36 | +#undef ureg | |
37 | + | |
38 | +/* U-Boot I2C framework allows only one active device at a time. */ | |
39 | +#ifdef TWI_CLKDIV | |
40 | +#define TWI0_CLKDIV TWI_CLKDIV | |
41 | +#endif | |
42 | +static volatile struct twi_regs *twi = (void *)TWI0_CLKDIV; | |
43 | + | |
44 | +#ifdef DEBUG | |
45 | +# define dmemset(s, c, n) memset(s, c, n) | |
46 | +#else | |
47 | +# define dmemset(s, c, n) | |
48 | +#endif | |
49 | +#define debugi(fmt, args...) \ | |
50 | + debug( \ | |
51 | + "MSTAT:0x%03x FSTAT:0x%x ISTAT:0x%02x\t%-20s:%-3i: " fmt "\n", \ | |
52 | + twi->master_stat, twi->fifo_stat, twi->int_stat, \ | |
53 | + __func__, __LINE__, ## args) | |
54 | + | |
55 | +#ifdef CONFIG_TWICLK_KHZ | |
56 | +# error do not define CONFIG_TWICLK_KHZ ... use CONFIG_SYS_I2C_SPEED | |
57 | +#endif | |
58 | + | |
59 | +/* | |
60 | + * The way speed is changed into duty often results in integer truncation | |
61 | + * with 50% duty, so we'll force rounding up to the next duty by adding 1 | |
62 | + * to the max. In practice this will get us a speed of something like | |
63 | + * 385 KHz. The other limit is easy to handle as it is only 8 bits. | |
64 | + */ | |
65 | +#define I2C_SPEED_MAX 400000 | |
66 | +#define I2C_SPEED_TO_DUTY(speed) (5000000 / (speed)) | |
67 | +#define I2C_DUTY_MAX (I2C_SPEED_TO_DUTY(I2C_SPEED_MAX) + 1) | |
68 | +#define I2C_DUTY_MIN 0xff /* 8 bit limited */ | |
69 | +#define SYS_I2C_DUTY I2C_SPEED_TO_DUTY(CONFIG_SYS_I2C_SPEED) | |
70 | +/* Note: duty is inverse of speed, so the comparisons below are correct */ | |
71 | +#if SYS_I2C_DUTY < I2C_DUTY_MAX || SYS_I2C_DUTY > I2C_DUTY_MIN | |
72 | +# error "The Blackfin I2C hardware can only operate 20KHz - 400KHz" | |
73 | +#endif | |
74 | + | |
75 | +/* All transfers are described by this data structure */ | |
76 | +struct i2c_msg { | |
77 | + u8 flags; | |
78 | +#define I2C_M_COMBO 0x4 | |
79 | +#define I2C_M_STOP 0x2 | |
80 | +#define I2C_M_READ 0x1 | |
81 | + int len; /* msg length */ | |
82 | + u8 *buf; /* pointer to msg data */ | |
83 | + int alen; /* addr length */ | |
84 | + u8 *abuf; /* addr buffer */ | |
85 | +}; | |
86 | + | |
87 | +/* Allow msec timeout per ~byte transfer */ | |
88 | +#define I2C_TIMEOUT 10 | |
89 | + | |
90 | +/** | |
91 | + * wait_for_completion - manage the actual i2c transfer | |
92 | + * @msg: the i2c msg | |
93 | + */ | |
94 | +static int wait_for_completion(struct i2c_msg *msg) | |
95 | +{ | |
96 | + uint16_t int_stat; | |
97 | + ulong timebase = get_timer(0); | |
98 | + | |
99 | + do { | |
100 | + int_stat = twi->int_stat; | |
101 | + | |
102 | + if (int_stat & XMTSERV) { | |
103 | + debugi("processing XMTSERV"); | |
104 | + twi->int_stat = XMTSERV; | |
105 | + SSYNC(); | |
106 | + if (msg->alen) { | |
107 | + twi->xmt_data8 = *(msg->abuf++); | |
108 | + --msg->alen; | |
109 | + } else if (!(msg->flags & I2C_M_COMBO) && msg->len) { | |
110 | + twi->xmt_data8 = *(msg->buf++); | |
111 | + --msg->len; | |
112 | + } else { | |
113 | + twi->master_ctl |= (msg->flags & I2C_M_COMBO) ? RSTART | MDIR : STOP; | |
114 | + SSYNC(); | |
115 | + } | |
116 | + } | |
117 | + if (int_stat & RCVSERV) { | |
118 | + debugi("processing RCVSERV"); | |
119 | + twi->int_stat = RCVSERV; | |
120 | + SSYNC(); | |
121 | + if (msg->len) { | |
122 | + *(msg->buf++) = twi->rcv_data8; | |
123 | + --msg->len; | |
124 | + } else if (msg->flags & I2C_M_STOP) { | |
125 | + twi->master_ctl |= STOP; | |
126 | + SSYNC(); | |
127 | + } | |
128 | + } | |
129 | + if (int_stat & MERR) { | |
130 | + debugi("processing MERR"); | |
131 | + twi->int_stat = MERR; | |
132 | + SSYNC(); | |
133 | + return msg->len; | |
134 | + } | |
135 | + if (int_stat & MCOMP) { | |
136 | + debugi("processing MCOMP"); | |
137 | + twi->int_stat = MCOMP; | |
138 | + SSYNC(); | |
139 | + if (msg->flags & I2C_M_COMBO && msg->len) { | |
140 | + twi->master_ctl = (twi->master_ctl & ~RSTART) | | |
141 | + (min(msg->len, 0xff) << 6) | MEN | MDIR; | |
142 | + SSYNC(); | |
143 | + } else | |
144 | + break; | |
145 | + } | |
146 | + | |
147 | + /* If we were able to do something, reset timeout */ | |
148 | + if (int_stat) | |
149 | + timebase = get_timer(0); | |
150 | + | |
151 | + } while (get_timer(timebase) < I2C_TIMEOUT); | |
152 | + | |
153 | + return msg->len; | |
154 | +} | |
155 | + | |
156 | +/** | |
157 | + * i2c_transfer - setup an i2c transfer | |
158 | + * @return: 0 if things worked, non-0 if things failed | |
159 | + * | |
160 | + * Here we just get the i2c stuff all prepped and ready, and then tail off | |
161 | + * into wait_for_completion() for all the bits to go. | |
162 | + */ | |
163 | +static int i2c_transfer(uchar chip, uint addr, int alen, uchar *buffer, int len, u8 flags) | |
164 | +{ | |
165 | + uchar addr_buffer[] = { | |
166 | + (addr >> 0), | |
167 | + (addr >> 8), | |
168 | + (addr >> 16), | |
169 | + }; | |
170 | + struct i2c_msg msg = { | |
171 | + .flags = flags | (len >= 0xff ? I2C_M_STOP : 0), | |
172 | + .buf = buffer, | |
173 | + .len = len, | |
174 | + .abuf = addr_buffer, | |
175 | + .alen = alen, | |
176 | + }; | |
177 | + int ret; | |
178 | + | |
179 | + dmemset(buffer, 0xff, len); | |
180 | + debugi("chip=0x%x addr=0x%02x alen=%i buf[0]=0x%02x len=%i flags=0x%02x[%s] ", | |
181 | + chip, addr, alen, buffer[0], len, flags, (flags & I2C_M_READ ? "rd" : "wr")); | |
182 | + | |
183 | + /* wait for things to settle */ | |
184 | + while (twi->master_stat & BUSBUSY) | |
185 | + if (ctrlc()) | |
186 | + return 1; | |
187 | + | |
188 | + /* Set Transmit device address */ | |
189 | + twi->master_addr = chip; | |
190 | + | |
191 | + /* Clear the FIFO before starting things */ | |
192 | + twi->fifo_ctl = XMTFLUSH | RCVFLUSH; | |
193 | + SSYNC(); | |
194 | + twi->fifo_ctl = 0; | |
195 | + SSYNC(); | |
196 | + | |
197 | + /* prime the pump */ | |
198 | + if (msg.alen) { | |
199 | + len = (msg.flags & I2C_M_COMBO) ? msg.alen : msg.alen + len; | |
200 | + debugi("first byte=0x%02x", *msg.abuf); | |
201 | + twi->xmt_data8 = *(msg.abuf++); | |
202 | + --msg.alen; | |
203 | + } else if (!(msg.flags & I2C_M_READ) && msg.len) { | |
204 | + debugi("first byte=0x%02x", *msg.buf); | |
205 | + twi->xmt_data8 = *(msg.buf++); | |
206 | + --msg.len; | |
207 | + } | |
208 | + | |
209 | + /* clear int stat */ | |
210 | + twi->master_stat = -1; | |
211 | + twi->int_stat = -1; | |
212 | + twi->int_mask = 0; | |
213 | + SSYNC(); | |
214 | + | |
215 | + /* Master enable */ | |
216 | + twi->master_ctl = | |
217 | + (twi->master_ctl & FAST) | | |
218 | + (min(len, 0xff) << 6) | MEN | | |
219 | + ((msg.flags & I2C_M_READ) ? MDIR : 0); | |
220 | + SSYNC(); | |
221 | + debugi("CTL=0x%04x", twi->master_ctl); | |
222 | + | |
223 | + /* process the rest */ | |
224 | + ret = wait_for_completion(&msg); | |
225 | + debugi("ret=%d", ret); | |
226 | + | |
227 | + if (ret) { | |
228 | + twi->master_ctl &= ~MEN; | |
229 | + twi->control &= ~TWI_ENA; | |
230 | + SSYNC(); | |
231 | + twi->control |= TWI_ENA; | |
232 | + SSYNC(); | |
233 | + } | |
234 | + | |
235 | + return ret; | |
236 | +} | |
237 | + | |
238 | +/** | |
239 | + * i2c_set_bus_speed - set i2c bus speed | |
240 | + * @speed: bus speed (in HZ) | |
241 | + */ | |
242 | +int i2c_set_bus_speed(unsigned int speed) | |
243 | +{ | |
244 | + u16 clkdiv = I2C_SPEED_TO_DUTY(speed); | |
245 | + | |
246 | + /* Set TWI interface clock */ | |
247 | + if (clkdiv < I2C_DUTY_MAX || clkdiv > I2C_DUTY_MIN) | |
248 | + return -1; | |
249 | + twi->clkdiv = (clkdiv << 8) | (clkdiv & 0xff); | |
250 | + | |
251 | + /* Don't turn it on */ | |
252 | + twi->master_ctl = (speed > 100000 ? FAST : 0); | |
253 | + | |
254 | + return 0; | |
255 | +} | |
256 | + | |
257 | +/** | |
258 | + * i2c_get_bus_speed - get i2c bus speed | |
259 | + * @speed: bus speed (in HZ) | |
260 | + */ | |
261 | +unsigned int i2c_get_bus_speed(void) | |
262 | +{ | |
263 | + /* 10 MHz / (2 * CLKDIV) -> 5 MHz / CLKDIV */ | |
264 | + return 5000000 / (twi->clkdiv & 0xff); | |
265 | +} | |
266 | + | |
267 | +/** | |
268 | + * i2c_init - initialize the i2c bus | |
269 | + * @speed: bus speed (in HZ) | |
270 | + * @slaveaddr: address of device in slave mode (0 - not slave) | |
271 | + * | |
272 | + * Slave mode isn't actually implemented. It'll stay that way until | |
273 | + * we get a real request for it. | |
274 | + */ | |
275 | +void i2c_init(int speed, int slaveaddr) | |
276 | +{ | |
277 | + uint8_t prescale = ((get_i2c_clk() / 1000 / 1000 + 5) / 10) & 0x7F; | |
278 | + | |
279 | + /* Set TWI internal clock as 10MHz */ | |
280 | + twi->control = prescale; | |
281 | + | |
282 | + /* Set TWI interface clock as specified */ | |
283 | + i2c_set_bus_speed(speed); | |
284 | + | |
285 | + /* Enable it */ | |
286 | + twi->control = TWI_ENA | prescale; | |
287 | + SSYNC(); | |
288 | + | |
289 | + debugi("CONTROL:0x%04x CLKDIV:0x%04x", twi->control, twi->clkdiv); | |
290 | + | |
291 | +#if CONFIG_SYS_I2C_SLAVE | |
292 | +# error I2C slave support not tested/supported | |
293 | + /* If they want us as a slave, do it */ | |
294 | + if (slaveaddr) { | |
295 | + twi->slave_addr = slaveaddr; | |
296 | + twi->slave_ctl = SEN; | |
297 | + } | |
298 | +#endif | |
299 | +} | |
300 | + | |
301 | +/** | |
302 | + * i2c_probe - test if a chip exists at a given i2c address | |
303 | + * @chip: i2c chip addr to search for | |
304 | + * @return: 0 if found, non-0 if not found | |
305 | + */ | |
306 | +int i2c_probe(uchar chip) | |
307 | +{ | |
308 | + u8 byte; | |
309 | + return i2c_read(chip, 0, 0, &byte, 1); | |
310 | +} | |
311 | + | |
312 | +/** | |
313 | + * i2c_read - read data from an i2c device | |
314 | + * @chip: i2c chip addr | |
315 | + * @addr: memory (register) address in the chip | |
316 | + * @alen: byte size of address | |
317 | + * @buffer: buffer to store data read from chip | |
318 | + * @len: how many bytes to read | |
319 | + * @return: 0 on success, non-0 on failure | |
320 | + */ | |
321 | +int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) | |
322 | +{ | |
323 | + return i2c_transfer(chip, addr, alen, buffer, len, (alen ? I2C_M_COMBO : I2C_M_READ)); | |
324 | +} | |
325 | + | |
326 | +/** | |
327 | + * i2c_write - write data to an i2c device | |
328 | + * @chip: i2c chip addr | |
329 | + * @addr: memory (register) address in the chip | |
330 | + * @alen: byte size of address | |
331 | + * @buffer: buffer holding data to write to chip | |
332 | + * @len: how many bytes to write | |
333 | + * @return: 0 on success, non-0 on failure | |
334 | + */ | |
335 | +int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) | |
336 | +{ | |
337 | + return i2c_transfer(chip, addr, alen, buffer, len, 0); | |
338 | +} | |
339 | + | |
340 | +/** | |
341 | + * i2c_set_bus_num - change active I2C bus | |
342 | + * @bus: bus index, zero based | |
343 | + * @returns: 0 on success, non-0 on failure | |
344 | + */ | |
345 | +int i2c_set_bus_num(unsigned int bus) | |
346 | +{ | |
347 | + switch (bus) { | |
348 | +#if CONFIG_SYS_MAX_I2C_BUS > 0 | |
349 | + case 0: twi = (void *)TWI0_CLKDIV; return 0; | |
350 | +#endif | |
351 | +#if CONFIG_SYS_MAX_I2C_BUS > 1 | |
352 | + case 1: twi = (void *)TWI1_CLKDIV; return 0; | |
353 | +#endif | |
354 | +#if CONFIG_SYS_MAX_I2C_BUS > 2 | |
355 | + case 2: twi = (void *)TWI2_CLKDIV; return 0; | |
356 | +#endif | |
357 | + default: return -1; | |
358 | + } | |
359 | +} | |
360 | + | |
361 | +/** | |
362 | + * i2c_get_bus_num - returns index of active I2C bus | |
363 | + */ | |
364 | +unsigned int i2c_get_bus_num(void) | |
365 | +{ | |
366 | + switch ((unsigned long)twi) { | |
367 | +#if CONFIG_SYS_MAX_I2C_BUS > 0 | |
368 | + case TWI0_CLKDIV: return 0; | |
369 | +#endif | |
370 | +#if CONFIG_SYS_MAX_I2C_BUS > 1 | |
371 | + case TWI1_CLKDIV: return 1; | |
372 | +#endif | |
373 | +#if CONFIG_SYS_MAX_I2C_BUS > 2 | |
374 | + case TWI2_CLKDIV: return 2; | |
375 | +#endif | |
376 | + default: return -1; | |
377 | + } | |
378 | +} |