Gigabeat S: Implement a genuine udelay function. Timer is gated to not run in WFI...
[kugel-rb.git] / firmware / target / arm / i2c-telechips.c
blobfb341c79055c8cdddb67a1cef356b984a0b4447b
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2008 by Rob Purchase
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include "config.h"
23 #include "system.h"
24 #include "i2c.h"
25 #include "i2c-target.h"
27 /* Delay loop based on CPU frequency (FREQ>>22 is 7..45 for 32MHz..192MHz) */
28 static inline void delay_loop(void)
30 unsigned long x;
31 for (x = (unsigned)(FREQ>>22); x; x--);
33 #define DELAY delay_loop()
35 static struct mutex i2c_mtx;
37 void i2c_init(void)
39 /* nothing to do */
42 void i2c_start(void)
44 SDA_OUTPUT;
46 SCL_HI;
47 SDA_HI;
48 DELAY;
50 SDA_LO;
51 DELAY;
52 SCL_LO;
53 DELAY;
56 void i2c_stop(void)
58 SDA_OUTPUT;
60 SDA_LO;
61 DELAY;
63 SCL_HI;
64 DELAY;
65 SDA_HI;
66 DELAY;
69 void i2c_outb(unsigned char byte)
71 int bit;
73 SDA_OUTPUT;
75 for (bit = 0; bit < 8; bit++)
77 if ((byte<<bit) & 0x80)
78 SDA_HI;
79 else
80 SDA_LO;
82 DELAY;
84 SCL_HI;
85 DELAY;
86 SCL_LO;
87 DELAY;
91 unsigned char i2c_inb(int ack)
93 int i;
94 unsigned char byte = 0;
96 SDA_INPUT;
98 /* clock in each bit, MSB first */
99 for ( i=0x80; i; i>>=1 )
101 SCL_HI;
102 DELAY;
104 if ( SDA ) byte |= i;
106 SCL_LO;
107 DELAY;
110 i2c_ack(ack);
111 return byte;
114 void i2c_ack(int bit)
116 SDA_OUTPUT;
118 if (bit)
119 SDA_HI;
120 else
121 SDA_LO;
123 SCL_HI;
124 DELAY;
125 SCL_LO;
126 DELAY;
129 int i2c_getack(void)
131 bool ack_bit;
133 SDA_INPUT;
135 SCL_HI;
136 DELAY;
138 ack_bit = SDA;
139 DELAY;
141 SCL_LO;
142 DELAY;
144 return ack_bit;
147 /* device = 8 bit slave address */
148 int i2c_write(int device, const unsigned char* buf, int count )
150 int i = 0;
151 mutex_lock(&i2c_mtx);
153 i2c_start();
154 i2c_outb(device & 0xfe);
156 while (!i2c_getack() && i < count)
158 i2c_outb(buf[i++]);
161 i2c_stop();
162 mutex_unlock(&i2c_mtx);
163 return 0;
167 /* device = 8 bit slave address */
168 int i2c_readmem(int device, int address, unsigned char* buf, int count )
170 int i = 0;
171 mutex_lock(&i2c_mtx);
173 i2c_start();
174 i2c_outb(device & 0xfe);
175 if (i2c_getack()) goto exit;
177 i2c_outb(address);
178 if (i2c_getack()) goto exit;
180 i2c_start();
181 i2c_outb(device | 1);
182 if (i2c_getack()) goto exit;
184 while (i < count)
186 buf[i] = i2c_inb(i == (count-1));
187 i++;
190 exit:
191 i2c_stop();
192 mutex_unlock(&i2c_mtx);
193 return 0;