summaryrefslogtreecommitdiff
path: root/firmware/target/coldfire/iriver/h100/sw_i2c-h100.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/coldfire/iriver/h100/sw_i2c-h100.c')
-rw-r--r--firmware/target/coldfire/iriver/h100/sw_i2c-h100.c259
1 files changed, 259 insertions, 0 deletions
diff --git a/firmware/target/coldfire/iriver/h100/sw_i2c-h100.c b/firmware/target/coldfire/iriver/h100/sw_i2c-h100.c
new file mode 100644
index 0000000000..cb061875e0
--- /dev/null
+++ b/firmware/target/coldfire/iriver/h100/sw_i2c-h100.c
@@ -0,0 +1,259 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Miika Pekkarinen
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "system.h"
20#include "logf.h"
21#include "inttypes.h"
22
23#include "sw_i2c.h"
24
25/**
26 * I2C-functions are copied and ported from fmradio.c.
27 * later fixed, adapted and moved to a seperate file so they can be re-used by the rtc-ds1339c code by Robert Kukla
28 */
29
30/* cute little functions, atomic read-modify-write */
31
32/* SCL is GPIO, 12 */
33#define SCL ( 0x00001000 & GPIO_READ)
34#define SCL_OUT_LO and_l(~0x00001000, &GPIO_OUT)
35#define SCL_LO or_l( 0x00001000, &GPIO_ENABLE)
36#define SCL_HI and_l(~0x00001000, &GPIO_ENABLE)
37
38/* SDA is GPIO1, 13 */
39#define SDA ( 0x00002000 & GPIO1_READ)
40#define SDA_OUT_LO and_l(~0x00002000, &GPIO1_OUT)
41#define SDA_LO or_l( 0x00002000, &GPIO1_ENABLE)
42#define SDA_HI and_l(~0x00002000, &GPIO1_ENABLE)
43
44/* delay loop to achieve 400kHz at 120MHz CPU frequency */
45#define DELAY do { int _x; for(_x=0;_x<22;_x++);} while(0)
46
47void sw_i2c_init(void)
48{
49 or_l(0x00001000, &GPIO_FUNCTION);
50 or_l(0x00002000, &GPIO1_FUNCTION);
51 SDA_HI;
52 SCL_HI;
53 SDA_OUT_LO;
54 SCL_OUT_LO;
55}
56
57/* in: C=? D=?
58 * out: C=L D=L
59 */
60static void sw_i2c_start(void)
61{
62 SCL_LO;
63 DELAY;
64 SDA_HI;
65 DELAY;
66 SCL_HI;
67 DELAY;
68 SDA_LO;
69 DELAY;
70 SCL_LO;
71}
72
73/* in: C=L D=?
74 * out: C=H D=H
75 */
76static void sw_i2c_stop(void)
77{
78 SDA_LO;
79 DELAY;
80 SCL_HI;
81 DELAY;
82 SDA_HI;
83}
84
85/* in: C=L D=H
86 * out: C=L D=L
87 */
88static void sw_i2c_ack(void)
89{
90 SDA_LO;
91 DELAY;
92
93 SCL_HI;
94 DELAY;
95 SCL_LO;
96}
97
98/* in: C=L D=H
99 * out: C=L D=H
100 */
101static void sw_i2c_nack(void)
102{
103 SDA_HI; /* redundant */
104 DELAY;
105
106 SCL_HI;
107 DELAY;
108 SCL_LO;
109}
110
111/* in: C=L D=?
112 * out: C=L D=H
113 */
114static bool sw_i2c_getack(void)
115{
116 bool ret = true;
117/* int count = 10; */
118
119 SDA_HI; /* sets to input */
120 DELAY;
121 SCL_HI;
122 DELAY;
123
124/* while (SDA && count--) */
125/* DELAY; */
126
127 if (SDA)
128 /* ack failed */
129 ret = false;
130
131 SCL_LO;
132
133 return ret;
134}
135
136/* in: C=L D=?
137 * out: C=L D=?
138 */
139static void sw_i2c_outb(unsigned char byte)
140{
141 int i;
142
143 /* clock out each bit, MSB first */
144 for ( i=0x80; i; i>>=1 )
145 {
146 if ( i & byte )
147 SDA_HI;
148 else
149 SDA_LO;
150 DELAY;
151
152 SCL_HI;
153 DELAY;
154 SCL_LO;
155 }
156}
157
158/* in: C=L D=?
159 * out: C=L D=H
160 */
161static unsigned char sw_i2c_inb(void)
162{
163 int i;
164 unsigned char byte = 0;
165
166 SDA_HI; /* sets to input */
167
168 /* clock in each bit, MSB first */
169 for ( i=0x80; i; i>>=1 )
170 {
171 DELAY;
172 do {
173 SCL_HI;
174 DELAY;
175 }
176 while(SCL==0); /* wait for any SCL clock stretching */
177 if ( SDA )
178 byte |= i;
179 SCL_LO;
180 }
181
182 return byte;
183}
184
185int sw_i2c_write(unsigned char chip, unsigned char location, const unsigned char* buf, int count)
186{
187 int i;
188
189 sw_i2c_start();
190 sw_i2c_outb((chip & 0xfe) | SW_I2C_WRITE);
191 if (!sw_i2c_getack())
192 {
193 sw_i2c_stop();
194 return -1;
195 }
196
197 sw_i2c_outb(location);
198 if (!sw_i2c_getack())
199 {
200 sw_i2c_stop();
201 return -2;
202 }
203
204 for (i=0; i<count; i++)
205 {
206 sw_i2c_outb(buf[i]);
207 if (!sw_i2c_getack())
208 {
209 sw_i2c_stop();
210 return -3;
211 }
212 }
213
214 sw_i2c_stop();
215
216 return 0;
217}
218
219int sw_i2c_read(unsigned char chip, unsigned char location, unsigned char* buf, int count)
220{
221 int i;
222
223 sw_i2c_start();
224 sw_i2c_outb((chip & 0xfe) | SW_I2C_WRITE);
225 if (!sw_i2c_getack())
226 {
227 sw_i2c_stop();
228 return -1;
229 }
230
231 sw_i2c_outb(location);
232 if (!sw_i2c_getack())
233 {
234 sw_i2c_stop();
235 return -2;
236 }
237
238 sw_i2c_start();
239 sw_i2c_outb((chip & 0xfe) | SW_I2C_READ);
240 if (!sw_i2c_getack())
241 {
242 sw_i2c_stop();
243 return -3;
244 }
245
246 for (i=0; i<count-1; i++)
247 {
248 buf[i] = sw_i2c_inb();
249 sw_i2c_ack();
250 }
251
252 /* 1byte min */
253 buf[i] = sw_i2c_inb();
254 sw_i2c_nack();
255
256 sw_i2c_stop();
257
258 return 0;
259}