blob: b3ac848a466d58553eed4c32a0393a3743cdaa2d [file] [log] [blame]
Jon Loeligerdebb7352006-04-26 17:58:56 -05001/*
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 *
Jon Loeligerc934f652006-05-31 13:55:35 -050010 * Modified for MPC86xx by Jeff Brown
Jon Loeligerdebb7352006-04-26 17:58:56 -050011 *
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
33#include <common.h>
34#include <command.h>
35#include <asm/io.h>
36
37#ifdef CONFIG_HARD_I2C
38#include <i2c.h>
39
40#define TIMEOUT (CFG_HZ/4)
41
42#define I2C_Addr ((u8 *)(CFG_CCSRBAR + 0x3100))
43
44#define I2CADR &I2C_Addr[0]
45#define I2CFDR &I2C_Addr[4]
46#define I2CCCR &I2C_Addr[8]
47#define I2CCSR &I2C_Addr[12]
48#define I2CCDR &I2C_Addr[16]
49#define I2CDFSRR &I2C_Addr[20]
50
51#define I2C_READ 1
52#define I2C_WRITE 0
53
54void
55i2c_init(int speed, int slaveadd)
56{
57 /* stop I2C controller */
58 writeb(0x0, I2CCCR);
59
60 /* set clock */
61 writeb(0x3f, I2CFDR);
62
63 /* set default filter */
64 writeb(0x10,I2CDFSRR);
65
66 /* write slave address */
67 writeb(slaveadd, I2CADR);
68
69 /* clear status register */
70 writeb(0x0, I2CCSR);
71
72 /* start I2C controller */
73 writeb(MPC86xx_I2CCR_MEN, I2CCCR);
74}
75
76static __inline__ int
Jon Loeliger5c9efb32006-04-27 10:15:16 -050077i2c_wait4bus(void)
Jon Loeligerdebb7352006-04-26 17:58:56 -050078{
79 ulong timeval = get_timer (0);
80
Jon Loeligerdebb7352006-04-26 17:58:56 -050081 while (readb(I2CCSR) & MPC86xx_I2CSR_MBB) {
Jon Loeliger5c9efb32006-04-27 10:15:16 -050082 if (get_timer(timeval) > TIMEOUT) {
Jon Loeligerdebb7352006-04-26 17:58:56 -050083 return -1;
84 }
85 }
86
Jon Loeliger5c9efb32006-04-27 10:15:16 -050087 return 0;
Jon Loeligerdebb7352006-04-26 17:58:56 -050088}
89
90static __inline__ int
Jon Loeliger5c9efb32006-04-27 10:15:16 -050091i2c_wait(int write)
Jon Loeligerdebb7352006-04-26 17:58:56 -050092{
93 u32 csr;
94 ulong timeval = get_timer (0);
95
96 do {
97 csr = readb(I2CCSR);
Jon Loeligerdebb7352006-04-26 17:58:56 -050098 if (!(csr & MPC86xx_I2CSR_MIF))
99 continue;
100
101 writeb(0x0, I2CCSR);
102
103 if (csr & MPC86xx_I2CSR_MAL) {
104 debug("i2c_wait: MAL\n");
105 return -1;
106 }
107
108 if (!(csr & MPC86xx_I2CSR_MCF)) {
109 debug("i2c_wait: unfinished\n");
110 return -1;
111 }
112
113 if (write == I2C_WRITE && (csr & MPC86xx_I2CSR_RXAK)) {
114 debug("i2c_wait: No RXACK\n");
115 return -1;
116 }
117
118 return 0;
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500119 } while (get_timer(timeval) < TIMEOUT);
Jon Loeligerdebb7352006-04-26 17:58:56 -0500120
121 debug("i2c_wait: timed out\n");
122 return -1;
123}
124
125static __inline__ int
126i2c_write_addr (u8 dev, u8 dir, int rsta)
127{
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500128 writeb(MPC86xx_I2CCR_MEN | MPC86xx_I2CCR_MSTA | MPC86xx_I2CCR_MTX
129 | (rsta ? MPC86xx_I2CCR_RSTA : 0),
Jon Loeligerdebb7352006-04-26 17:58:56 -0500130 I2CCCR);
131
132 writeb((dev << 1) | dir, I2CCDR);
133
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500134 if (i2c_wait(I2C_WRITE) < 0)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500135 return 0;
136
137 return 1;
138}
139
140static __inline__ int
141__i2c_write (u8 *data, int length)
142{
143 int i;
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500144
Jon Loeligerdebb7352006-04-26 17:58:56 -0500145 writeb(MPC86xx_I2CCR_MEN | MPC86xx_I2CCR_MSTA | MPC86xx_I2CCR_MTX,
146 I2CCCR);
147
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500148 for (i = 0; i < length; i++) {
Jon Loeligerdebb7352006-04-26 17:58:56 -0500149 writeb(data[i], I2CCDR);
150
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500151 if (i2c_wait(I2C_WRITE) < 0)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500152 break;
153 }
154
155 return i;
156}
157
158static __inline__ int
159__i2c_read (u8 *data, int length)
160{
161 int i;
162
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500163 writeb(MPC86xx_I2CCR_MEN | MPC86xx_I2CCR_MSTA
164 | ((length == 1) ? MPC86xx_I2CCR_TXAK : 0),
Jon Loeligerdebb7352006-04-26 17:58:56 -0500165 I2CCCR);
166
167 /* dummy read */
168 readb(I2CCDR);
Jon Loeligerdebb7352006-04-26 17:58:56 -0500169
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500170 for (i = 0; i < length; i++) {
171 if (i2c_wait(I2C_READ) < 0)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500172 break;
173
174 /* Generate ack on last next to last byte */
175 if (i == length - 2)
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500176 writeb(MPC86xx_I2CCR_MEN | MPC86xx_I2CCR_MSTA
177 | MPC86xx_I2CCR_TXAK,
Jon Loeligerdebb7352006-04-26 17:58:56 -0500178 I2CCCR);
179
180 /* Generate stop on last byte */
181 if (i == length - 1)
182 writeb(MPC86xx_I2CCR_MEN | MPC86xx_I2CCR_TXAK, I2CCCR);
183
Jon Loeligerdebb7352006-04-26 17:58:56 -0500184 data[i] = readb(I2CCDR);
Jon Loeligerdebb7352006-04-26 17:58:56 -0500185 }
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500186
Jon Loeligerdebb7352006-04-26 17:58:56 -0500187 return i;
188}
189
190int
191i2c_read (u8 dev, uint addr, int alen, u8 *data, int length)
192{
193 int i = 0;
194 u8 *a = (u8*)&addr;
195
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500196 if (i2c_wait4bus() < 0)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500197 goto exit;
198
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500199 if (i2c_write_addr(dev, I2C_WRITE, 0) == 0)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500200 goto exit;
201
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500202 if (__i2c_write(&a[4 - alen], alen) != alen)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500203 goto exit;
204
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500205 if (i2c_write_addr(dev, I2C_READ, 1) == 0)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500206 goto exit;
207
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500208 i = __i2c_read(data, length);
Jon Loeligerdebb7352006-04-26 17:58:56 -0500209
Jon Loeligerc934f652006-05-31 13:55:35 -0500210exit:
Jon Loeligerdebb7352006-04-26 17:58:56 -0500211 writeb(MPC86xx_I2CCR_MEN, I2CCCR);
212
213 return !(i == length);
214}
215
216int
217i2c_write (u8 dev, uint addr, int alen, u8 *data, int length)
218{
219 int i = 0;
220 u8 *a = (u8*)&addr;
221
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500222 if (i2c_wait4bus() < 0)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500223 goto exit;
224
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500225 if (i2c_write_addr(dev, I2C_WRITE, 0) == 0)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500226 goto exit;
227
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500228 if (__i2c_write(&a[4 - alen], alen) != alen)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500229 goto exit;
230
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500231 i = __i2c_write(data, length);
Jon Loeligerdebb7352006-04-26 17:58:56 -0500232
Jon Loeligerc934f652006-05-31 13:55:35 -0500233exit:
Jon Loeligerdebb7352006-04-26 17:58:56 -0500234 writeb(MPC86xx_I2CCR_MEN, I2CCCR);
235
236 return !(i == length);
237}
238
239int i2c_probe (uchar chip)
240{
241 int tmp;
242
243 /*
244 * Try to read the first location of the chip. The underlying
245 * driver doesn't appear to support sending just the chip address
246 * and looking for an <ACK> back.
247 */
248 udelay(10000);
249
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500250 return i2c_read(chip, 0, 1, (char *)&tmp, 1);
Jon Loeligerdebb7352006-04-26 17:58:56 -0500251}
252
253uchar i2c_reg_read (uchar i2c_addr, uchar reg)
254{
255 char buf[1];
256
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500257 i2c_read(i2c_addr, reg, 1, buf, 1);
Jon Loeligerdebb7352006-04-26 17:58:56 -0500258
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500259 return buf[0];
Jon Loeligerdebb7352006-04-26 17:58:56 -0500260}
261
262void i2c_reg_write (uchar i2c_addr, uchar reg, uchar val)
263{
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500264 i2c_write(i2c_addr, reg, 1, &val, 1);
Jon Loeligerdebb7352006-04-26 17:58:56 -0500265}
266
267#endif /* CONFIG_HARD_I2C */