cowond2: make sure the i2c delay loop code is actually generated by the eabi compiler.
[kugel-rb.git] / firmware / target / arm / i2c-telechips.c
blob35f4cd41c5310e86851a2701dcb006650c79cf9e
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--)
32 asm volatile("nop");
35 #define DELAY delay_loop()
37 static struct mutex i2c_mtx;
39 void i2c_init(void)
41 mutex_init(&i2c_mtx);
44 void i2c_start(void)
46 SDA_OUTPUT;
48 SCL_HI;
49 SDA_HI;
50 DELAY;
52 SDA_LO;
53 DELAY;
54 SCL_LO;
55 DELAY;
58 void i2c_stop(void)
60 SDA_OUTPUT;
62 SDA_LO;
63 DELAY;
65 SCL_HI;
66 DELAY;
67 SDA_HI;
68 DELAY;
71 void i2c_outb(unsigned char byte)
73 int bit;
75 SDA_OUTPUT;
77 for (bit = 0; bit < 8; bit++)
79 if ((byte<<bit) & 0x80)
80 SDA_HI;
81 else
82 SDA_LO;
84 DELAY;
86 SCL_HI;
87 DELAY;
88 SCL_LO;
89 DELAY;
93 unsigned char i2c_inb(int ack)
95 int i;
96 unsigned char byte = 0;
98 SDA_INPUT;
100 /* clock in each bit, MSB first */
101 for ( i=0x80; i; i>>=1 )
103 SCL_HI;
104 DELAY;
106 if ( SDA ) byte |= i;
108 SCL_LO;
109 DELAY;
112 i2c_ack(ack);
113 return byte;
116 void i2c_ack(int bit)
118 SDA_OUTPUT;
120 if (bit)
121 SDA_HI;
122 else
123 SDA_LO;
125 SCL_HI;
126 DELAY;
127 SCL_LO;
128 DELAY;
131 int i2c_getack(void)
133 bool ack_bit;
135 SDA_INPUT;
137 SCL_HI;
138 DELAY;
140 ack_bit = SDA;
141 DELAY;
143 SCL_LO;
144 DELAY;
146 return ack_bit;
149 /* device = 8 bit slave address */
150 int i2c_write(int device, const unsigned char* buf, int count )
152 int i = 0;
153 mutex_lock(&i2c_mtx);
155 i2c_start();
156 i2c_outb(device & 0xfe);
158 while (!i2c_getack() && i < count)
160 i2c_outb(buf[i++]);
163 i2c_stop();
164 mutex_unlock(&i2c_mtx);
165 return 0;
169 /* device = 8 bit slave address */
170 int i2c_readmem(int device, int address, unsigned char* buf, int count )
172 int i = 0;
173 mutex_lock(&i2c_mtx);
175 i2c_start();
176 i2c_outb(device & 0xfe);
177 if (i2c_getack()) goto exit;
179 i2c_outb(address);
180 if (i2c_getack()) goto exit;
182 i2c_start();
183 i2c_outb(device | 1);
184 if (i2c_getack()) goto exit;
186 while (i < count)
188 buf[i] = i2c_inb(i == (count-1));
189 i++;
192 exit:
193 i2c_stop();
194 mutex_unlock(&i2c_mtx);
195 return 0;