FS#11417 by Joe Balough: fix audio/tuner on philips hdd6330
[kugel-rb.git] / firmware / target / arm / i2c-telechips.c
blob511bbe8865c3386a9cf52d6afda59b9752b5c1b2
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 asm volatile (" mov %[freq], %[freq], asr#22 \n\t"
31 "1: subs %[freq], %[freq], #1 \n\t"
32 " bne 1b"
33 : : [freq] "r" (cpu_frequency) : "memory");
36 #define DELAY delay_loop()
38 static struct mutex i2c_mtx;
40 void i2c_init(void)
42 mutex_init(&i2c_mtx);
45 void i2c_start(void)
47 SDA_OUTPUT;
49 SCL_HI;
50 SDA_HI;
51 DELAY;
53 SDA_LO;
54 DELAY;
55 SCL_LO;
56 DELAY;
59 void i2c_stop(void)
61 SDA_OUTPUT;
63 SDA_LO;
64 DELAY;
66 SCL_HI;
67 DELAY;
68 SDA_HI;
69 DELAY;
72 void i2c_outb(unsigned char byte)
74 int bit;
76 SDA_OUTPUT;
78 for (bit = 0; bit < 8; bit++)
80 if ((byte<<bit) & 0x80)
81 SDA_HI;
82 else
83 SDA_LO;
85 DELAY;
87 SCL_HI;
88 DELAY;
89 SCL_LO;
90 DELAY;
94 unsigned char i2c_inb(int ack)
96 int i;
97 unsigned char byte = 0;
99 SDA_INPUT;
101 /* clock in each bit, MSB first */
102 for ( i=0x80; i; i>>=1 )
104 SCL_HI;
105 DELAY;
107 if ( SDA ) byte |= i;
109 SCL_LO;
110 DELAY;
113 i2c_ack(ack);
114 return byte;
117 void i2c_ack(int bit)
119 SDA_OUTPUT;
121 if (bit)
122 SDA_HI;
123 else
124 SDA_LO;
126 SCL_HI;
127 DELAY;
128 SCL_LO;
129 DELAY;
132 int i2c_getack(void)
134 bool ack_bit;
136 SDA_INPUT;
138 SCL_HI;
139 DELAY;
141 ack_bit = SDA;
142 DELAY;
144 SCL_LO;
145 DELAY;
147 return ack_bit;
150 /* device = 8 bit slave address */
151 int i2c_write(int device, const unsigned char* buf, int count )
153 int i = 0;
154 mutex_lock(&i2c_mtx);
156 i2c_start();
157 i2c_outb(device & 0xfe);
159 while (!i2c_getack() && i < count)
161 i2c_outb(buf[i++]);
164 i2c_stop();
165 mutex_unlock(&i2c_mtx);
166 return 0;
170 /* device = 8 bit slave address */
171 int i2c_readmem(int device, int address, unsigned char* buf, int count )
173 int i = 0;
174 mutex_lock(&i2c_mtx);
176 i2c_start();
177 i2c_outb(device & 0xfe);
178 if (i2c_getack()) goto exit;
180 i2c_outb(address);
181 if (i2c_getack()) goto exit;
183 i2c_start();
184 i2c_outb(device | 1);
185 if (i2c_getack()) goto exit;
187 while (i < count)
189 buf[i] = i2c_inb(i == (count-1));
190 i++;
193 exit:
194 i2c_stop();
195 mutex_unlock(&i2c_mtx);
196 return 0;