blob: ae08d18832195b852452a4870818b8736e32af6f [file] [log] [blame]
wdenk42d1f032003-10-15 23:53:47 +00001/*
2 * (C) Copyright 2003,Motorola Inc.
3 * Xianghua Xiao <x.xiao@motorola.com>
4 * Adapted for Motorola 85xx chip.
5 *
6 * (C) Copyright 2003
7 * Gleb Natapov <gnatapov@mrv.com>
8 * Some bits are taken from linux driver writen by adrian@humboldt.co.uk
9 *
10 * Hardware I2C driver for MPC107 PCI bridge.
11 *
12 * See file CREDITS for list of people who contributed to this
13 * project.
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License as
17 * published by the Free Software Foundation; either version 2 of
18 * the License, or (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
28 * MA 02111-1307 USA
29 */
30
31#include <common.h>
32#include <command.h>
33
34#define DEBUG
35
36#if defined(DEBUG)
37#define DEB(x) x
38#else
39#define DEB(x)
40#endif
41
42#ifdef CONFIG_HARD_I2C
43#include <i2c.h>
44
45#define TIMEOUT (CFG_HZ/4)
46
47#define I2C_Addr ((unsigned *)(CFG_CCSRBAR + 0x3000))
48
49#define I2CADR &I2C_Addr[0]
50#define I2CFDR &I2C_Addr[1]
51#define I2CCCR &I2C_Addr[2]
52#define I2CCSR &I2C_Addr[3]
53#define I2CCDR &I2C_Addr[4]
54#define I2CDFSRR &I2C_Addr[5]
55
56#define I2C_READ 1
57#define I2C_WRITE 0
58
59/* taken from linux include/asm-ppc/io.h */
60inline unsigned in_le32(volatile unsigned *addr)
61{
62 unsigned ret;
63
64 __asm__ __volatile__("lwbrx %0,0,%1;\n"
65 "twi 0,%0,0;\n"
66 "isync" : "=r" (ret) :
67 "r" (addr), "m" (*addr));
68 return ret;
69}
70
71inline void out_le32(volatile unsigned *addr, int val)
72{
73 __asm__ __volatile__("stwbrx %1,0,%2; eieio" : "=m" (*addr) :
74 "r" (val), "r" (addr));
75}
76
77#define writel(val, addr) out_le32(addr, val)
78#define readl(addr) in_le32(addr)
79
80void
81i2c_init(int speed, int slaveadd)
82{
83 /* stop I2C controller */
84 writel (0x0, I2CCCR);
85 /* set clock */
86 writel (0x3f, I2CFDR);
87 /* set default filter */
88 writel (0x10,I2CDFSRR);
89 /* write slave address */
90 writel (slaveadd, I2CADR);
91 /* clear status register */
92 writel (0x0, I2CCSR);
93 /* start I2C controller */
94 writel (MPC85xx_I2CCR_MEN, I2CCCR);
95}
96
97static __inline__ int
98i2c_wait4bus (void)
99{
100 ulong timeval = get_timer (0);
101
102 while (readl (I2CCSR) & MPC85xx_I2CSR_MBB)
103 if (get_timer (timeval) > TIMEOUT)
104 return -1;
105
106 return 0;
107}
108
109static __inline__ int
110i2c_wait (int write)
111{
112 u32 csr;
113 ulong timeval = get_timer (0);
114
115 do
116 {
117 csr = readl (I2CCSR);
118
119 if (!(csr & MPC85xx_I2CSR_MIF))
120 continue;
121
122 writel (0x0, I2CCSR);
123
124 if (csr & MPC85xx_I2CSR_MAL)
125 {
126 DEB(printf ("i2c_wait: MAL\n"));
127 return -1;
128 }
129
130 if (!(csr & MPC85xx_I2CSR_MCF))
131 {
132 DEB(printf ("i2c_wait: unfinished\n"));
133 return -1;
134 }
135
136 if (write == I2C_WRITE && (csr & MPC85xx_I2CSR_RXAK))
137 {
138 DEB(printf ("i2c_wait: No RXACK\n"));
139 return -1;
140 }
141
142 return 0;
143 } while (get_timer (timeval) < TIMEOUT);
144
145 DEB(printf ("i2c_wait: timed out\n"));
146 return -1;
147}
148
149static __inline__ int
150i2c_write_addr (u8 dev, u8 dir, int rsta)
151{
152 writel (MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA | MPC85xx_I2CCR_MTX |
153 (rsta?MPC85xx_I2CCR_RSTA:0), I2CCCR);
154
155 writel ((dev << 1) | dir, I2CCDR);
156
157 if (i2c_wait (I2C_WRITE) < 0)
158 return 0;
159
160 return 1;
161}
162
163static __inline__ int
164__i2c_write (u8 *data, int length)
165{
166 int i;
167
168 writel (MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA | MPC85xx_I2CCR_MTX, I2CCCR);
169
170 for (i=0; i < length; i++)
171 {
172 writel (data[i], I2CCDR);
173
174 if (i2c_wait (I2C_WRITE) < 0)
175 break;
176 }
177
178 return i;
179}
180
181static __inline__ int
182__i2c_read (u8 *data, int length)
183{
184 int i;
185
186 writel (MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA |
187 ((length == 1) ? MPC85xx_I2CCR_TXAK : 0), I2CCCR);
188
189 /* dummy read */
190 readl (I2CCDR);
191
192 for (i=0; i < length; i++)
193 {
194 if (i2c_wait (I2C_READ) < 0)
195 break;
196
197 /* Generate ack on last next to last byte */
198 if (i == length - 2)
199 writel (MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA |
200 MPC85xx_I2CCR_TXAK, I2CCCR);
201
202 /* Generate stop on last byte */
203 if (i == length - 1)
204 writel (MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_TXAK, I2CCCR);
205
206 data[i] = readl (I2CCDR);
207 }
208
209 return i;
210}
211
212int
213i2c_read (u8 dev, uint addr, int alen, u8 *data, int length)
214{
215 int i = 0;
216 u8 *a = (u8*)&addr;
217
218 if (i2c_wait4bus () < 0)
219 goto exit;
220
221 if (i2c_write_addr (dev, I2C_WRITE, 0) == 0)
222 goto exit;
223
224 if (__i2c_write (&a[4 - alen], alen) != alen)
225 goto exit;
226
227 if (i2c_write_addr (dev, I2C_READ, 1) == 0)
228 goto exit;
229
230 i = __i2c_read (data, length);
231
232 exit:
233 writel (MPC85xx_I2CCR_MEN, I2CCCR);
234
235 return !(i == length);
236}
237
238int
239i2c_write (u8 dev, uint addr, int alen, u8 *data, int length)
240{
241 int i = 0;
242 u8 *a = (u8*)&addr;
243
244 if (i2c_wait4bus () < 0)
245 goto exit;
246
247 if (i2c_write_addr (dev, I2C_WRITE, 0) == 0)
248 goto exit;
249
250 if (__i2c_write (&a[4 - alen], alen) != alen)
251 goto exit;
252
253 i = __i2c_write (data, length);
254
255 exit:
256 writel (MPC85xx_I2CCR_MEN, I2CCCR);
257
258 return !(i == length);
259}
260
261int i2c_probe (uchar chip)
262{
263 int tmp;
264
265 /*
266 * Try to read the first location of the chip. The underlying
267 * driver doesn't appear to support sending just the chip address
268 * and looking for an <ACK> back.
269 */
270 udelay(10000);
271 return i2c_read (chip, 0, 1, (char *)&tmp, 1);
272}
273
274uchar i2c_reg_read (uchar i2c_addr, uchar reg)
275{
276 char buf[1];
277
278 i2c_read (i2c_addr, reg, 1, buf, 1);
279
280 return (buf[0]);
281}
282
283void i2c_reg_write (uchar i2c_addr, uchar reg, uchar val)
284{
285 i2c_write (i2c_addr, reg, 1, &val, 1);
286}
287
288#endif /* CONFIG_HARD_I2C */