Add a note about Rockbox not running on Sansas v2 (FS#8477 by Marc Guay).
[Rockbox.git] / firmware / drivers / sw_i2c.c
blobc1f6868226a2d3d85281681fa686fd643e9efc2c
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2006 by Miika Pekkarinen
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.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
19 #include "system.h"
20 #include "logf.h"
21 #include "inttypes.h"
23 #include "sw_i2c.h"
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
28 * by the rtc-ds1339c and later by the m:robe-100 code by Robert Kukla
31 /* cute little functions, atomic read-modify-write */
33 #ifdef MROBE_100
35 /* SCL is GPIOC, 4 */
36 #define SCL (GPIOC_INPUT_VAL & 0x00000010)
37 #define SCL_OUT_LO GPIOC_OUTPUT_VAL&=~0x00000010
38 #define SCL_LO GPIOC_OUTPUT_EN |= 0x00000010
39 #define SCL_HI GPIOC_OUTPUT_EN &=~0x00000010
41 /* SDA is GPIOC, 5 */
42 #define SDA (GPIOC_INPUT_VAL & 0x00000020)
43 #define SDA_OUT_LO GPIOC_OUTPUT_VAL&=~0x00000020
44 #define SDA_LO GPIOC_OUTPUT_EN |= 0x00000020
45 #define SDA_HI GPIOC_OUTPUT_EN &=~0x00000020
47 #define DELAY do { volatile int _x; for(_x=0;_x<22;_x++);} while(0)
49 #else
51 /* SCL is GPIO, 12 */
52 #define SCL ( 0x00001000 & GPIO_READ)
53 #define SCL_OUT_LO and_l(~0x00001000, &GPIO_OUT)
54 #define SCL_LO or_l( 0x00001000, &GPIO_ENABLE)
55 #define SCL_HI and_l(~0x00001000, &GPIO_ENABLE)
57 /* SDA is GPIO1, 13 */
58 #define SDA ( 0x00002000 & GPIO1_READ)
59 #define SDA_OUT_LO and_l(~0x00002000, &GPIO1_OUT)
60 #define SDA_LO or_l( 0x00002000, &GPIO1_ENABLE)
61 #define SDA_HI and_l(~0x00002000, &GPIO1_ENABLE)
63 /* delay loop to achieve 400kHz at 120MHz CPU frequency */
64 #define DELAY \
65 ({ \
66 int _x_; \
67 asm volatile ( \
68 "move.l #21, %[_x_] \r\n" \
69 "1: \r\n" \
70 "subq.l #1, %[_x_] \r\n" \
71 "bhi.b 1b \r\n" \
72 : [_x_]"=&d"(_x_) \
73 ); \
76 #endif
78 void sw_i2c_init(void)
80 #ifndef MROBE_100
81 or_l(0x00001000, &GPIO_FUNCTION);
82 or_l(0x00002000, &GPIO1_FUNCTION);
83 #endif
85 SDA_HI;
86 SCL_HI;
87 SDA_OUT_LO;
88 SCL_OUT_LO;
91 /* in: C=? D=?
92 * out: C=L D=L
94 static void sw_i2c_start(void)
96 SCL_LO;
97 DELAY;
98 SDA_HI;
99 DELAY;
100 SCL_HI;
101 DELAY;
102 SDA_LO;
103 DELAY;
104 SCL_LO;
107 /* in: C=L D=?
108 * out: C=H D=H
110 static void sw_i2c_stop(void)
112 SDA_LO;
113 DELAY;
114 SCL_HI;
115 DELAY;
116 SDA_HI;
119 /* in: C=L D=H
120 * out: C=L D=L
122 static void sw_i2c_ack(void)
124 SDA_LO;
125 DELAY;
127 SCL_HI;
128 DELAY;
129 SCL_LO;
132 /* in: C=L D=H
133 * out: C=L D=H
135 static void sw_i2c_nack(void)
137 SDA_HI; /* redundant */
138 DELAY;
140 SCL_HI;
141 DELAY;
142 SCL_LO;
145 /* in: C=L D=?
146 * out: C=L D=H
148 static bool sw_i2c_getack(void)
150 bool ret = true;
151 /* int count = 10; */
153 SDA_HI; /* sets to input */
154 DELAY;
155 SCL_HI;
156 DELAY;
158 /* while (SDA && count--) */
159 /* DELAY; */
161 if (SDA)
162 /* ack failed */
163 ret = false;
165 SCL_LO;
167 return ret;
170 /* in: C=L D=?
171 * out: C=L D=?
173 static void sw_i2c_outb(unsigned char byte)
175 int i;
177 /* clock out each bit, MSB first */
178 for ( i=0x80; i; i>>=1 )
180 if ( i & byte )
181 SDA_HI;
182 else
183 SDA_LO;
184 DELAY;
186 SCL_HI;
187 DELAY;
188 SCL_LO;
192 /* in: C=L D=?
193 * out: C=L D=H
195 static unsigned char sw_i2c_inb(void)
197 int i;
198 unsigned char byte = 0;
200 SDA_HI; /* sets to input */
202 /* clock in each bit, MSB first */
203 for ( i=0x80; i; i>>=1 )
205 DELAY;
206 do {
207 SCL_HI;
208 DELAY;
210 while(SCL==0); /* wait for any SCL clock stretching */
211 if ( SDA )
212 byte |= i;
213 SCL_LO;
216 return byte;
219 int sw_i2c_write(unsigned char chip, unsigned char location, unsigned char* buf, int count)
221 int i;
223 sw_i2c_start();
224 sw_i2c_outb((chip & 0xfe) | SW_I2C_WRITE);
225 if (!sw_i2c_getack())
227 sw_i2c_stop();
228 return -1;
231 #ifdef MROBE_100 /* does not use register addressing */
232 (void) location;
233 #else
234 sw_i2c_outb(location);
235 if (!sw_i2c_getack())
237 sw_i2c_stop();
238 return -2;
240 #endif
242 for (i=0; i<count; i++)
244 sw_i2c_outb(buf[i]);
245 if (!sw_i2c_getack())
247 sw_i2c_stop();
248 return -3;
252 sw_i2c_stop();
254 return 0;
257 int sw_i2c_read(unsigned char chip, unsigned char location, unsigned char* buf, int count)
259 int i;
261 #ifdef MROBE_100 /* does not use register addressing */
262 (void) location;
263 #else
264 sw_i2c_start();
265 sw_i2c_outb((chip & 0xfe) | SW_I2C_WRITE);
266 if (!sw_i2c_getack())
268 sw_i2c_stop();
269 return -1;
272 sw_i2c_outb(location);
273 if (!sw_i2c_getack())
275 sw_i2c_stop();
276 return -2;
278 #endif
280 sw_i2c_start();
281 sw_i2c_outb((chip & 0xfe) | SW_I2C_READ);
282 if (!sw_i2c_getack())
284 sw_i2c_stop();
285 return -3;
288 for (i=0; i<count-1; i++)
290 buf[i] = sw_i2c_inb();
291 sw_i2c_ack();
294 /* 1byte min */
295 buf[i] = sw_i2c_inb();
296 sw_i2c_nack();
298 sw_i2c_stop();
300 return 0;