]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/i2c/fti2c010.c
i2c: add Faraday FTI2C010 I2C controller support
[karo-tx-uboot.git] / drivers / i2c / fti2c010.c
1 /*
2  * Faraday I2C Controller
3  *
4  * (C) Copyright 2010 Faraday Technology
5  * Dante Su <dantesu@faraday-tech.com>
6  *
7  * This file is released under the terms of GPL v2 and any later version.
8  * See the file COPYING in the root directory of the source tree for details.
9  */
10
11 #include <common.h>
12 #include <asm/io.h>
13 #include <i2c.h>
14
15 #include "fti2c010.h"
16
17 #ifndef CONFIG_HARD_I2C
18 #error "fti2c010: CONFIG_HARD_I2C is not defined"
19 #endif
20
21 #ifndef CONFIG_SYS_I2C_SPEED
22 #define CONFIG_SYS_I2C_SPEED    50000
23 #endif
24
25 #ifndef CONFIG_FTI2C010_FREQ
26 #define CONFIG_FTI2C010_FREQ    clk_get_rate("I2C")
27 #endif
28
29 /* command timeout */
30 #define CFG_CMD_TIMEOUT         10 /* ms */
31
32 /* 7-bit chip address + 1-bit read/write */
33 #define I2C_RD(chip)            ((((chip) << 1) & 0xff) | 1)
34 #define I2C_WR(chip)            (((chip) << 1) & 0xff)
35
36 struct fti2c010_chip {
37         void __iomem *regs;
38         uint bus;
39         uint speed;
40 };
41
42 static struct fti2c010_chip chip_list[] = {
43         {
44                 .bus  = 0,
45                 .regs = (void __iomem *)CONFIG_FTI2C010_BASE,
46         },
47 #ifdef CONFIG_I2C_MULTI_BUS
48 # ifdef CONFIG_FTI2C010_BASE1
49         {
50                 .bus  = 1,
51                 .regs = (void __iomem *)CONFIG_FTI2C010_BASE1,
52         },
53 # endif
54 # ifdef CONFIG_FTI2C010_BASE2
55         {
56                 .bus  = 2,
57                 .regs = (void __iomem *)CONFIG_FTI2C010_BASE2,
58         },
59 # endif
60 # ifdef CONFIG_FTI2C010_BASE3
61         {
62                 .bus  = 3,
63                 .regs = (void __iomem *)CONFIG_FTI2C010_BASE3,
64         },
65 # endif
66 #endif  /* #ifdef CONFIG_I2C_MULTI_BUS */
67 };
68
69 static struct fti2c010_chip *curr = chip_list;
70
71 static int fti2c010_wait(uint32_t mask)
72 {
73         int ret = -1;
74         uint32_t stat, ts;
75         struct fti2c010_regs *regs = curr->regs;
76
77         for (ts = get_timer(0); get_timer(ts) < CFG_CMD_TIMEOUT; ) {
78                 stat = readl(&regs->sr);
79                 if ((stat & mask) == mask) {
80                         ret = 0;
81                         break;
82                 }
83         }
84
85         return ret;
86 }
87
88 /*
89  * u-boot I2C API
90  */
91
92 /*
93  * Initialization, must be called once on start up, may be called
94  * repeatedly to change the speed and slave addresses.
95  */
96 void i2c_init(int speed, int slaveaddr)
97 {
98         if (speed || !curr->speed)
99                 i2c_set_bus_speed(speed);
100
101         /* if slave mode disabled */
102         if (!slaveaddr)
103                 return;
104
105         /*
106          * TODO:
107          * Implement slave mode, but is it really necessary?
108          */
109 }
110
111 /*
112  * Probe the given I2C chip address.  Returns 0 if a chip responded,
113  * not 0 on failure.
114  */
115 int i2c_probe(uchar chip)
116 {
117         int ret;
118         struct fti2c010_regs *regs = curr->regs;
119
120         i2c_init(0, 0);
121
122         /* 1. Select slave device (7bits Address + 1bit R/W) */
123         writel(I2C_WR(chip), &regs->dr);
124         writel(CR_ENABLE | CR_TBEN | CR_START, &regs->cr);
125         ret = fti2c010_wait(SR_DT);
126         if (ret)
127                 return ret;
128
129         /* 2. Select device register */
130         writel(0, &regs->dr);
131         writel(CR_ENABLE | CR_TBEN, &regs->cr);
132         ret = fti2c010_wait(SR_DT);
133
134         return ret;
135 }
136
137 /*
138  * Read/Write interface:
139  *   chip:    I2C chip address, range 0..127
140  *   addr:    Memory (register) address within the chip
141  *   alen:    Number of bytes to use for addr (typically 1, 2 for larger
142  *              memories, 0 for register type devices with only one
143  *              register)
144  *   buffer:  Where to read/write the data
145  *   len:     How many bytes to read/write
146  *
147  *   Returns: 0 on success, not 0 on failure
148  */
149 int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
150 {
151         int ret, pos;
152         uchar paddr[4];
153         struct fti2c010_regs *regs = curr->regs;
154
155         i2c_init(0, 0);
156
157         paddr[0] = (addr >> 0)  & 0xFF;
158         paddr[1] = (addr >> 8)  & 0xFF;
159         paddr[2] = (addr >> 16) & 0xFF;
160         paddr[3] = (addr >> 24) & 0xFF;
161
162         /*
163          * Phase A. Set register address
164          */
165
166         /* A.1 Select slave device (7bits Address + 1bit R/W) */
167         writel(I2C_WR(chip), &regs->dr);
168         writel(CR_ENABLE | CR_TBEN | CR_START, &regs->cr);
169         ret = fti2c010_wait(SR_DT);
170         if (ret)
171                 return ret;
172
173         /* A.2 Select device register */
174         for (pos = 0; pos < alen; ++pos) {
175                 uint32_t ctrl = CR_ENABLE | CR_TBEN;
176
177                 writel(paddr[pos], &regs->dr);
178                 writel(ctrl, &regs->cr);
179                 ret = fti2c010_wait(SR_DT);
180                 if (ret)
181                         return ret;
182         }
183
184         /*
185          * Phase B. Get register data
186          */
187
188         /* B.1 Select slave device (7bits Address + 1bit R/W) */
189         writel(I2C_RD(chip), &regs->dr);
190         writel(CR_ENABLE | CR_TBEN | CR_START, &regs->cr);
191         ret = fti2c010_wait(SR_DT);
192         if (ret)
193                 return ret;
194
195         /* B.2 Get register data */
196         for (pos = 0; pos < len; ++pos) {
197                 uint32_t ctrl = CR_ENABLE | CR_TBEN;
198                 uint32_t stat = SR_DR;
199
200                 if (pos == len - 1) {
201                         ctrl |= CR_NAK | CR_STOP;
202                         stat |= SR_ACK;
203                 }
204                 writel(ctrl, &regs->cr);
205                 ret = fti2c010_wait(stat);
206                 if (ret)
207                         break;
208                 buf[pos] = (uchar)(readl(&regs->dr) & 0xFF);
209         }
210
211         return ret;
212 }
213
214 /*
215  * Read/Write interface:
216  *   chip:    I2C chip address, range 0..127
217  *   addr:    Memory (register) address within the chip
218  *   alen:    Number of bytes to use for addr (typically 1, 2 for larger
219  *              memories, 0 for register type devices with only one
220  *              register)
221  *   buffer:  Where to read/write the data
222  *   len:     How many bytes to read/write
223  *
224  *   Returns: 0 on success, not 0 on failure
225  */
226 int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
227 {
228         int ret, pos;
229         uchar paddr[4];
230         struct fti2c010_regs *regs = curr->regs;
231
232         i2c_init(0, 0);
233
234         paddr[0] = (addr >> 0)  & 0xFF;
235         paddr[1] = (addr >> 8)  & 0xFF;
236         paddr[2] = (addr >> 16) & 0xFF;
237         paddr[3] = (addr >> 24) & 0xFF;
238
239         /*
240          * Phase A. Set register address
241          *
242          * A.1 Select slave device (7bits Address + 1bit R/W)
243          */
244         writel(I2C_WR(chip), &regs->dr);
245         writel(CR_ENABLE | CR_TBEN | CR_START, &regs->cr);
246         ret = fti2c010_wait(SR_DT);
247         if (ret)
248                 return ret;
249
250         /* A.2 Select device register */
251         for (pos = 0; pos < alen; ++pos) {
252                 uint32_t ctrl = CR_ENABLE | CR_TBEN;
253
254                 writel(paddr[pos], &regs->dr);
255                 writel(ctrl, &regs->cr);
256                 ret = fti2c010_wait(SR_DT);
257                 if (ret)
258                         return ret;
259         }
260
261         /*
262          * Phase B. Set register data
263          */
264         for (pos = 0; pos < len; ++pos) {
265                 uint32_t ctrl = CR_ENABLE | CR_TBEN;
266
267                 if (pos == len - 1)
268                         ctrl |= CR_STOP;
269                 writel(buf[pos], &regs->dr);
270                 writel(ctrl, &regs->cr);
271                 ret = fti2c010_wait(SR_DT);
272                 if (ret)
273                         break;
274         }
275
276         return ret;
277 }
278
279 /*
280  * Functions for setting the current I2C bus and its speed
281  */
282 #ifdef CONFIG_I2C_MULTI_BUS
283
284 /*
285  * i2c_set_bus_num:
286  *
287  *  Change the active I2C bus.  Subsequent read/write calls will
288  *  go to this one.
289  *
290  *    bus - bus index, zero based
291  *
292  *    Returns: 0 on success, not 0 on failure
293  */
294 int i2c_set_bus_num(uint bus)
295 {
296         if (bus >= ARRAY_SIZE(chip_list))
297                 return -1;
298         curr = chip_list + bus;
299         i2c_init(0, 0);
300         return 0;
301 }
302
303 /*
304  * i2c_get_bus_num:
305  *
306  *  Returns index of currently active I2C bus.  Zero-based.
307  */
308
309 uint i2c_get_bus_num(void)
310 {
311         return curr->bus;
312 }
313
314 #endif    /* #ifdef CONFIG_I2C_MULTI_BUS */
315
316 /*
317  * i2c_set_bus_speed:
318  *
319  *  Change the speed of the active I2C bus
320  *
321  *    speed - bus speed in Hz
322  *
323  *    Returns: 0 on success, not 0 on failure
324  */
325 int i2c_set_bus_speed(uint speed)
326 {
327         struct fti2c010_regs *regs = curr->regs;
328         uint clk = CONFIG_FTI2C010_FREQ;
329         uint gsr = 0, tsr = 32;
330         uint spd, div;
331
332         if (!speed)
333                 speed = CONFIG_SYS_I2C_SPEED;
334
335         for (div = 0; div < 0x3ffff; ++div) {
336                 /* SCLout = PCLK/(2*(COUNT + 2) + GSR) */
337                 spd = clk / (2 * (div + 2) + gsr);
338                 if (spd <= speed)
339                         break;
340         }
341
342         if (curr->speed == spd)
343                 return 0;
344
345         writel(CR_I2CRST, &regs->cr);
346         mdelay(100);
347         if (readl(&regs->cr) & CR_I2CRST) {
348                 printf("fti2c010: reset timeout\n");
349                 return -1;
350         }
351
352         curr->speed = spd;
353
354         writel(TGSR_GSR(gsr) | TGSR_TSR(tsr), &regs->tgsr);
355         writel(CDR_DIV(div), &regs->cdr);
356
357         return 0;
358 }
359
360 /*
361  * i2c_get_bus_speed:
362  *
363  *  Returns speed of currently active I2C bus in Hz
364  */
365
366 uint i2c_get_bus_speed(void)
367 {
368         return curr->speed;
369 }