]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/mpc83xx/i2c.c
mpc83xx: Changed to unified mpx83xx names and added common 83xx changes
[karo-tx-uboot.git] / cpu / mpc83xx / i2c.c
1 /*
2  * (C) Copyright 2006 Freescale Semiconductor, Inc.
3  *
4  * (C) Copyright 2003,Motorola Inc.
5  * Xianghua Xiao <x.xiao@motorola.com>
6  * Adapted for Motorola 85xx chip.
7  *
8  * (C) Copyright 2003
9  * Gleb Natapov <gnatapov@mrv.com>
10  * Some bits are taken from linux driver writen by adrian@humboldt.co.uk
11  *
12  * Hardware I2C driver for MPC107 PCI bridge.
13  *
14  * See file CREDITS for list of people who contributed to this
15  * project.
16  *
17  * This program is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU General Public License as
19  * published by the Free Software Foundation; either version 2 of
20  * the License, or (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
30  * MA 02111-1307 USA
31  *
32  * Change log:
33  *
34  * 20050101: Eran Liberty (liberty@freescale.com)
35  *           Initial file creating (porting from 85XX & 8260)
36  * 20060601: Dave Liu (daveliu@freescale.com)
37  *           Unified variable names for mpc83xx
38  */
39
40 #include <common.h>
41 #include <command.h>
42 #include <asm/io.h>
43
44 #ifdef CONFIG_HARD_I2C
45 #include <i2c.h>
46 #include <asm/i2c.h>
47
48 #if defined(CONFIG_MPC8349EMDS) || defined(CONFIG_TQM834X)
49 i2c_t * mpc83xx_i2c = (i2c_t*)(CFG_IMMRBAR + CFG_I2C_OFFSET);
50 #endif
51
52 void
53 i2c_init(int speed, int slaveadd)
54 {
55         /* stop I2C controller */
56         writeb(0x00 , &I2C->cr);
57
58         /* set clock */
59         writeb(speed, &I2C->fdr);
60
61         /* set default filter */
62         writeb(0x10,&I2C->dfsrr);
63
64         /* write slave address */
65         writeb(slaveadd, &I2C->adr);
66
67         /* clear status register */
68         writeb(0x00, &I2C->sr);
69
70         /* start I2C controller */
71         writeb(I2C_CR_MEN, &I2C->cr);
72 }
73
74 static __inline__ int
75 i2c_wait4bus (void)
76 {
77         ulong timeval = get_timer (0);
78         while (readb(&I2C->sr) & I2C_SR_MBB) {
79                 if (get_timer (timeval) > I2C_TIMEOUT) {
80                         return -1;
81                 }
82         }
83         return 0;
84 }
85
86 static __inline__ int
87 i2c_wait (int write)
88 {
89         u32 csr;
90         ulong timeval = get_timer(0);
91         do {
92                 csr = readb(&I2C->sr);
93
94                 if (!(csr & I2C_SR_MIF))
95                         continue;
96
97                 writeb(0x0, &I2C->sr);
98
99                 if (csr & I2C_SR_MAL) {
100                         debug("i2c_wait: MAL\n");
101                         return -1;
102                 }
103
104                 if (!(csr & I2C_SR_MCF))        {
105                         debug("i2c_wait: unfinished\n");
106                         return -1;
107                 }
108
109                 if (write == I2C_WRITE && (csr & I2C_SR_RXAK)) {
110                         debug("i2c_wait: No RXACK\n");
111                         return -1;
112                 }
113
114                 return 0;
115         } while (get_timer (timeval) < I2C_TIMEOUT);
116
117         debug("i2c_wait: timed out\n");
118         return -1;
119 }
120
121 static __inline__ int
122 i2c_write_addr (u8 dev, u8 dir, int rsta)
123 {
124         writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_MTX |
125                (rsta?I2C_CR_RSTA:0),
126                &I2C->cr);
127
128         writeb((dev << 1) | dir, &I2C->dr);
129
130         if (i2c_wait (I2C_WRITE) < 0)
131                 return 0;
132         return 1;
133 }
134
135 static __inline__ int
136 __i2c_write (u8 *data, int length)
137 {
138         int i;
139
140         writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_MTX,
141                &I2C->cr);
142
143         for (i=0; i < length; i++) {
144                 writeb(data[i], &I2C->dr);
145
146                 if (i2c_wait (I2C_WRITE) < 0)
147                         break;
148         }
149         return i;
150 }
151
152 static __inline__ int
153 __i2c_read (u8 *data, int length)
154 {
155         int i;
156
157         writeb(I2C_CR_MEN | I2C_CR_MSTA |
158                ((length == 1) ? I2C_CR_TXAK : 0),
159                &I2C->cr);
160
161         /* dummy read */
162         readb(&I2C->dr);
163
164         for (i=0; i < length; i++) {
165                 if (i2c_wait (I2C_READ) < 0)
166                         break;
167
168                 /* Generate ack on last next to last byte */
169                 if (i == length - 2)
170                         writeb(I2C_CR_MEN | I2C_CR_MSTA |
171                                I2C_CR_TXAK,
172                                &I2C->cr);
173
174                 /* Generate stop on last byte */
175                 if (i == length - 1)
176                         writeb(I2C_CR_MEN | I2C_CR_TXAK, &I2C->cr);
177
178                 data[i] = readb(&I2C->dr);
179         }
180         return i;
181 }
182
183 int
184 i2c_read (u8 dev, uint addr, int alen, u8 *data, int length)
185 {
186         int i = 0;
187         u8 *a = (u8*)&addr;
188
189         if (i2c_wait4bus () < 0)
190                 goto exit;
191
192         if (i2c_write_addr (dev, I2C_WRITE, 0) == 0)
193                 goto exit;
194
195         if (__i2c_write (&a[4 - alen], alen) != alen)
196                 goto exit;
197
198         if (i2c_write_addr (dev, I2C_READ, 1) == 0)
199                 goto exit;
200
201         i = __i2c_read (data, length);
202
203  exit:
204         writeb(I2C_CR_MEN, &I2C->cr);
205         return !(i == length);
206 }
207
208 int
209 i2c_write (u8 dev, uint addr, int alen, u8 *data, int length)
210 {
211         int i = 0;
212         u8 *a = (u8*)&addr;
213
214         if (i2c_wait4bus () < 0)
215                 goto exit;
216
217         if (i2c_write_addr (dev, I2C_WRITE, 0) == 0)
218                 goto exit;
219
220         if (__i2c_write (&a[4 - alen], alen) != alen)
221                 goto exit;
222
223         i = __i2c_write (data, length);
224
225  exit:
226         writeb(I2C_CR_MEN, &I2C->cr);
227         return !(i == length);
228 }
229
230 int i2c_probe (uchar chip)
231 {
232         int tmp;
233
234         /*
235          * Try to read the first location of the chip.  The underlying
236          * driver doesn't appear to support sending just the chip address
237          * and looking for an <ACK> back.
238          */
239         udelay(10000);
240         return i2c_read (chip, 0, 1, (uchar *)&tmp, 1);
241 }
242
243 uchar i2c_reg_read (uchar i2c_addr, uchar reg)
244 {
245         uchar buf[1];
246
247         i2c_read (i2c_addr, reg, 1, buf, 1);
248
249         return (buf[0]);
250 }
251
252 void i2c_reg_write (uchar i2c_addr, uchar reg, uchar val)
253 {
254         i2c_write (i2c_addr, reg, 1, &val, 1);
255 }
256
257 #endif /* CONFIG_HARD_I2C */