]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/pcippc2/i2c.c
Initial revision
[karo-tx-uboot.git] / board / pcippc2 / i2c.c
1 /*
2  * (C) Copyright 2002
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #include <config.h>
25 #include <common.h>
26 #include <asm/io.h>
27
28 #include "hardware.h"
29 #include "i2c.h"
30
31 static void             i2c_start       (void);
32 static void             i2c_stop        (void);
33 static int              i2c_write       (u8             data);
34 static void             i2c_read        (u8 *           data);
35
36 static inline void      i2c_port_start  (void);
37 static inline void      i2c_clock       (unsigned int   val);
38 static inline void      i2c_data        (unsigned int   val);
39 static inline unsigned int
40                         i2c_in          (void);
41 static inline void      i2c_write_bit   (unsigned int   val);
42 static inline unsigned int
43                         i2c_read_bit    (void);
44
45 static inline void      i2c_udelay      (unsigned int   time);
46
47 int i2c_read_byte (
48   u8 *                  data,
49   u8                    dev,
50   u8                    offset)
51 {
52   int                   err = 0;
53
54   i2c_start();
55
56   err = ! i2c_write(dev);
57
58   if (! err)
59   {
60     err = ! i2c_write(offset);
61   }
62
63   if (! err)
64   {
65     i2c_start();
66   }
67
68   if (! err)
69   {
70     err = ! i2c_write(dev | 0x01);
71   }
72
73   if (! err)
74   {
75     i2c_read(data);
76   }
77
78   i2c_stop();
79
80   return ! err;
81 }
82
83 static inline void i2c_udelay (
84   unsigned int          time)
85 {
86   int                   v;
87
88   asm volatile("mtdec %0" : : "r" (time * ((CFG_BUS_CLK / 4) / 1000000)));
89
90   do
91   {
92     asm volatile("isync; mfdec %0" : "=r" (v));
93   } while (v >= 0);
94 }
95
96   /* Low-level hardware access
97    */
98
99 #define BIT_GPDATA              0x80000000
100 #define BIT_GPCLK               0x40000000
101
102 static inline void i2c_port_start (void)
103 {
104   out32(REG(CPC0, GPDIR), in32(REG(CPC0, GPDIR)) & ~(BIT_GPCLK | BIT_GPDATA));
105   out32(REG(CPC0, GPOUT), in32(REG(CPC0, GPOUT)) & ~(BIT_GPCLK | BIT_GPDATA));
106   iobarrier_rw();
107
108   i2c_udelay(1);
109 }
110
111 static inline void i2c_clock (
112   unsigned int          val)
113 {
114   if (val)
115   {
116     out32(REG(CPC0, GPDIR), in32(REG(CPC0, GPDIR)) & ~BIT_GPCLK);
117   }
118   else
119   {
120     out32(REG(CPC0, GPDIR), in32(REG(CPC0, GPDIR)) | BIT_GPCLK);
121   }
122
123   iobarrier_rw();
124
125   i2c_udelay(1);
126 }
127
128 static inline void i2c_data (
129   unsigned int          val)
130 {
131   if (val)
132   {
133     out32(REG(CPC0, GPDIR), in32(REG(CPC0, GPDIR)) & ~BIT_GPDATA);
134   }
135   else
136   {
137     out32(REG(CPC0, GPDIR), in32(REG(CPC0, GPDIR)) | BIT_GPDATA);
138   }
139
140   iobarrier_rw();
141
142   i2c_udelay(1);
143 }
144
145 static inline unsigned int i2c_in (void)
146 {
147   unsigned int          val = ((in32(REG(CPC0, GPIN)) & BIT_GPDATA) != 0)?1:0;
148
149   iobarrier_rw();
150
151   return val;
152 }
153
154
155   /* Protocol implementation
156    */
157
158 static inline void i2c_write_bit (
159   unsigned int          val)
160 {
161   i2c_data(val);
162   i2c_udelay(10);
163   i2c_clock(1);
164   i2c_udelay(10);
165   i2c_clock(0);
166   i2c_udelay(10);
167 }
168
169 static inline unsigned int i2c_read_bit (void)
170 {
171   unsigned int          val;
172
173   i2c_data(1);
174   i2c_udelay(10);
175
176   i2c_clock(1);
177   i2c_udelay(10);
178
179   val = i2c_in();
180
181   i2c_clock(0);
182   i2c_udelay(10);
183
184   return val;
185 }
186
187 unsigned int i2c_reset (void)
188 {
189   unsigned int          val;
190   int i;
191
192   i2c_port_start();
193
194   i=0;
195   do {
196     i2c_udelay(10);
197     i2c_clock(0);
198     i2c_udelay(10);
199     i2c_clock(1);
200     i2c_udelay(10);
201     val = i2c_in();
202     i++;
203   }  while ((i<9)&&(val==0));
204   return (val);
205 }
206
207
208 static void i2c_start (void)
209 {
210   i2c_data(1);
211   i2c_clock(1);
212   i2c_udelay(10);
213   i2c_data(0);
214   i2c_udelay(10);
215   i2c_clock(0);
216   i2c_udelay(10);
217 }
218
219 static void i2c_stop (void)
220 {
221   i2c_data(0);
222   i2c_udelay(10);
223   i2c_clock(1);
224   i2c_udelay(10);
225   i2c_data(1);
226   i2c_udelay(10);
227 }
228
229 static int i2c_write (
230   u8                    data)
231 {
232   unsigned int          i;
233
234   for (i = 0; i < 8; i++)
235   {
236     i2c_write_bit(data >> 7);
237     data <<= 1;
238   }
239
240   return i2c_read_bit() == 0;
241 }
242
243 static void i2c_read (
244   u8 *                  data)
245 {
246   unsigned int          i;
247   u8                    val = 0;
248
249   for (i = 0; i < 8; i++)
250   {
251     val <<= 1;
252     val |= i2c_read_bit();
253   }
254
255   *data = val;
256   i2c_write_bit(1); /* NoAck */
257 }