]> git.sur5r.net Git - u-boot/blob - drivers/fsl_i2c.c
[PATCH] nand: Fix patch merge problem
[u-boot] / drivers / fsl_i2c.c
1 /*
2  * Copyright 2006 Freescale Semiconductor, Inc.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * Version 2 as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
16  * MA 02111-1307 USA
17  */
18
19 #include <common.h>
20
21 #ifdef CONFIG_FSL_I2C
22 #ifdef CONFIG_HARD_I2C
23
24 #include <command.h>
25 #include <i2c.h>                /* Functional interface */
26
27 #include <asm/io.h>
28 #include <asm/fsl_i2c.h>        /* HW definitions */
29
30 #define I2C_TIMEOUT     (CFG_HZ / 4)
31 #define I2C             ((struct fsl_i2c *)(CFG_IMMR + CFG_I2C_OFFSET))
32
33
34 void
35 i2c_init(int speed, int slaveadd)
36 {
37         /* stop I2C controller */
38         writeb(0x0, &I2C->cr);
39
40         /* set clock */
41         writeb(0x3f, &I2C->fdr);
42
43         /* set default filter */
44         writeb(0x10, &I2C->dfsrr);
45
46         /* write slave address */
47         writeb(slaveadd, &I2C->adr);
48
49         /* clear status register */
50         writeb(0x0, &I2C->sr);
51
52         /* start I2C controller */
53         writeb(I2C_CR_MEN, &I2C->cr);
54 }
55
56 static __inline__ int
57 i2c_wait4bus(void)
58 {
59         ulong timeval = get_timer(0);
60
61         while (readb(&I2C->sr) & I2C_SR_MBB) {
62                 if (get_timer(timeval) > I2C_TIMEOUT) {
63                         return -1;
64                 }
65         }
66
67         return 0;
68 }
69
70 static __inline__ int
71 i2c_wait(int write)
72 {
73         u32 csr;
74         ulong timeval = get_timer(0);
75
76         do {
77                 csr = readb(&I2C->sr);
78                 if (!(csr & I2C_SR_MIF))
79                         continue;
80
81                 writeb(0x0, &I2C->sr);
82
83                 if (csr & I2C_SR_MAL) {
84                         debug("i2c_wait: MAL\n");
85                         return -1;
86                 }
87
88                 if (!(csr & I2C_SR_MCF))        {
89                         debug("i2c_wait: unfinished\n");
90                         return -1;
91                 }
92
93                 if (write == I2C_WRITE && (csr & I2C_SR_RXAK)) {
94                         debug("i2c_wait: No RXACK\n");
95                         return -1;
96                 }
97
98                 return 0;
99         } while (get_timer (timeval) < I2C_TIMEOUT);
100
101         debug("i2c_wait: timed out\n");
102         return -1;
103 }
104
105 static __inline__ int
106 i2c_write_addr (u8 dev, u8 dir, int rsta)
107 {
108         writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_MTX
109                | (rsta ? I2C_CR_RSTA : 0),
110                &I2C->cr);
111
112         writeb((dev << 1) | dir, &I2C->dr);
113
114         if (i2c_wait(I2C_WRITE) < 0)
115                 return 0;
116
117         return 1;
118 }
119
120 static __inline__ int
121 __i2c_write(u8 *data, int length)
122 {
123         int i;
124
125         writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_MTX,
126                &I2C->cr);
127
128         for (i = 0; i < length; i++) {
129                 writeb(data[i], &I2C->dr);
130
131                 if (i2c_wait(I2C_WRITE) < 0)
132                         break;
133         }
134
135         return i;
136 }
137
138 static __inline__ int
139 __i2c_read(u8 *data, int length)
140 {
141         int i;
142
143         writeb(I2C_CR_MEN | I2C_CR_MSTA | ((length == 1) ? I2C_CR_TXAK : 0),
144                &I2C->cr);
145
146         /* dummy read */
147         readb(&I2C->dr);
148
149         for (i = 0; i < length; i++) {
150                 if (i2c_wait(I2C_READ) < 0)
151                         break;
152
153                 /* Generate ack on last next to last byte */
154                 if (i == length - 2)
155                         writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_TXAK,
156                                &I2C->cr);
157
158                 /* Generate stop on last byte */
159                 if (i == length - 1)
160                         writeb(I2C_CR_MEN | I2C_CR_TXAK, &I2C->cr);
161
162                 data[i] = readb(&I2C->dr);
163         }
164
165         return i;
166 }
167
168 int
169 i2c_read(u8 dev, uint addr, int alen, u8 *data, int length)
170 {
171         int i = 0;
172         u8 *a = (u8*)&addr;
173
174         if (i2c_wait4bus() >= 0
175             && i2c_write_addr(dev, I2C_WRITE, 0) != 0
176             && __i2c_write(&a[4 - alen], alen) == alen
177             && i2c_write_addr(dev, I2C_READ, 1) != 0) {
178                 i = __i2c_read(data, length);
179         }
180
181         writeb(I2C_CR_MEN, &I2C->cr);
182
183         if (i == length)
184             return 0;
185
186         return -1;
187 }
188
189 int
190 i2c_write(u8 dev, uint addr, int alen, u8 *data, int length)
191 {
192         int i = 0;
193         u8 *a = (u8*)&addr;
194
195         if (i2c_wait4bus() >= 0
196             && i2c_write_addr(dev, I2C_WRITE, 0) != 0
197             && __i2c_write(&a[4 - alen], alen) == alen) {
198                 i = __i2c_write(data, length);
199         }
200
201         writeb(I2C_CR_MEN, &I2C->cr);
202
203         if (i == length)
204             return 0;
205
206         return -1;
207 }
208
209 int
210 i2c_probe(uchar chip)
211 {
212         int tmp;
213
214         /*
215          * Try to read the first location of the chip.  The underlying
216          * driver doesn't appear to support sending just the chip address
217          * and looking for an <ACK> back.
218          */
219         udelay(10000);
220
221         return i2c_read(chip, 0, 1, (uchar *)&tmp, 1);
222 }
223
224 uchar
225 i2c_reg_read(uchar i2c_addr, uchar reg)
226 {
227         uchar buf[1];
228
229         i2c_read(i2c_addr, reg, 1, buf, 1);
230
231         return buf[0];
232 }
233
234 void
235 i2c_reg_write(uchar i2c_addr, uchar reg, uchar val)
236 {
237         i2c_write(i2c_addr, reg, 1, &val, 1);
238 }
239
240 #endif /* CONFIG_HARD_I2C */
241 #endif /* CONFIG_FSL_I2C */