blob: d99ecb92d496e32f36306368ecde02963377a63f [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 */
Jon Loeligerffff3ae2006-08-22 12:06:18 -050064 writeb(0x10, I2CDFSRR);
Jon Loeligerdebb7352006-04-26 17:58:56 -050065
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{
Jon Loeligerffff3ae2006-08-22 12:06:18 -050079 ulong timeval = get_timer(0);
Jon Loeligerdebb7352006-04-26 17:58:56 -050080
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;
Jon Loeligerffff3ae2006-08-22 12:06:18 -050094 ulong timeval = get_timer(0);
Jon Loeligerdebb7352006-04-26 17:58:56 -050095
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
Jon Loeligerffff3ae2006-08-22 12:06:18 -0500108 if (!(csr & MPC86xx_I2CSR_MCF)) {
Jon Loeligerdebb7352006-04-26 17:58:56 -0500109 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
Jon Loeligerffff3ae2006-08-22 12:06:18 -0500126i2c_write_addr(u8 dev, u8 dir, int rsta)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500127{
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
Jon Loeligerffff3ae2006-08-22 12:06:18 -0500141__i2c_write(u8 *data, int length)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500142{
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
Jon Loeligerffff3ae2006-08-22 12:06:18 -0500159__i2c_read(u8 *data, int length)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500160{
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
Jon Loeligerffff3ae2006-08-22 12:06:18 -0500177 | MPC86xx_I2CCR_TXAK, I2CCCR);
Jon Loeligerdebb7352006-04-26 17:58:56 -0500178
179 /* Generate stop on last byte */
180 if (i == length - 1)
181 writeb(MPC86xx_I2CCR_MEN | MPC86xx_I2CCR_TXAK, I2CCCR);
182
Jon Loeligerdebb7352006-04-26 17:58:56 -0500183 data[i] = readb(I2CCDR);
Jon Loeligerdebb7352006-04-26 17:58:56 -0500184 }
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500185
Jon Loeligerdebb7352006-04-26 17:58:56 -0500186 return i;
187}
188
189int
Jon Loeligerffff3ae2006-08-22 12:06:18 -0500190i2c_read(u8 dev, uint addr, int alen, u8 *data, int length)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500191{
192 int i = 0;
Jon Loeligerffff3ae2006-08-22 12:06:18 -0500193 u8 *a = (u8 *) &addr;
Jon Loeligerdebb7352006-04-26 17:58:56 -0500194
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500195 if (i2c_wait4bus() < 0)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500196 goto exit;
197
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500198 if (i2c_write_addr(dev, I2C_WRITE, 0) == 0)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500199 goto exit;
200
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500201 if (__i2c_write(&a[4 - alen], alen) != alen)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500202 goto exit;
203
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500204 if (i2c_write_addr(dev, I2C_READ, 1) == 0)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500205 goto exit;
206
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500207 i = __i2c_read(data, length);
Jon Loeligerdebb7352006-04-26 17:58:56 -0500208
Jon Loeligerc934f652006-05-31 13:55:35 -0500209exit:
Jon Loeligerdebb7352006-04-26 17:58:56 -0500210 writeb(MPC86xx_I2CCR_MEN, I2CCCR);
211
212 return !(i == length);
213}
214
215int
Jon Loeligerffff3ae2006-08-22 12:06:18 -0500216i2c_write(u8 dev, uint addr, int alen, u8 *data, int length)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500217{
218 int i = 0;
Jon Loeligerffff3ae2006-08-22 12:06:18 -0500219 u8 *a = (u8 *) &addr;
Jon Loeligerdebb7352006-04-26 17:58:56 -0500220
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500221 if (i2c_wait4bus() < 0)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500222 goto exit;
223
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500224 if (i2c_write_addr(dev, I2C_WRITE, 0) == 0)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500225 goto exit;
226
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500227 if (__i2c_write(&a[4 - alen], alen) != alen)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500228 goto exit;
229
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500230 i = __i2c_write(data, length);
Jon Loeligerdebb7352006-04-26 17:58:56 -0500231
Jon Loeligerc934f652006-05-31 13:55:35 -0500232exit:
Jon Loeligerdebb7352006-04-26 17:58:56 -0500233 writeb(MPC86xx_I2CCR_MEN, I2CCCR);
234
235 return !(i == length);
236}
237
Jon Loeligerffff3ae2006-08-22 12:06:18 -0500238int
239i2c_probe(uchar chip)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500240{
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
Jon Loeligerffff3ae2006-08-22 12:06:18 -0500253uchar
254i2c_reg_read(uchar i2c_addr, uchar reg)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500255{
256 char buf[1];
257
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500258 i2c_read(i2c_addr, reg, 1, buf, 1);
Jon Loeligerdebb7352006-04-26 17:58:56 -0500259
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500260 return buf[0];
Jon Loeligerdebb7352006-04-26 17:58:56 -0500261}
262
Jon Loeligerffff3ae2006-08-22 12:06:18 -0500263void
264i2c_reg_write(uchar i2c_addr, uchar reg, uchar val)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500265{
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500266 i2c_write(i2c_addr, reg, 1, &val, 1);
Jon Loeligerdebb7352006-04-26 17:58:56 -0500267}
268
269#endif /* CONFIG_HARD_I2C */