summaryrefslogtreecommitdiff
path: root/firmware/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers')
-rw-r--r--firmware/drivers/i2c-h100.c166
1 files changed, 166 insertions, 0 deletions
diff --git a/firmware/drivers/i2c-h100.c b/firmware/drivers/i2c-h100.c
new file mode 100644
index 0000000000..e2fbea2573
--- /dev/null
+++ b/firmware/drivers/i2c-h100.c
@@ -0,0 +1,166 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 by Andy Young
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
20#include "cpu.h"
21#include "kernel.h"
22#include "debug.h"
23#include "system.h"
24#include "i2c-h100.h"
25
26#define I2C_DEVICE_1 ((volatile unsigned char *)&MADR)
27#define I2C_DEVICE_2 ((volatile unsigned char *)&MADR2)
28
29/* Local functions definitions */
30
31static int i2c_write_byte(int device, unsigned char data);
32static int i2c_gen_start(int device);
33static void i2c_gen_stop(int device);
34static volatile unsigned char *i2c_get_addr(int device);
35
36/* Public functions */
37
38void i2c_init(void)
39{
40 /* Audio Codec */
41 MADR = 0x6c; /* iRiver firmware uses this addr */
42 MBDR = 0; /* iRiver firmware does this */
43 MBCR = IEN; /* Enable interface */
44
45#if 0
46 /* FM Tuner */
47 MADR2 = 0x6c;
48 MBDR2 = 0;
49 MBCR2 = IEN;
50#endif
51}
52
53void i2c_close(void)
54{
55 MBCR = 0;
56
57#if 0
58 MBCR2 = 0;
59#endif
60}
61
62/**
63 * Writes bytes to the selected device.
64 *
65 * Use device=1 for bus 1 at 0x40000280 (Audio Codec)
66 * Use device=2 for bus 2 at 0x80000440 (Tuner ?)
67 *
68 * Returns number of bytes successfully send or -1 if START failed
69 */
70int i2c_write(int device, unsigned char *buf, int count)
71{
72 int i;
73
74 if (i2c_gen_start(device) == -1)
75 {
76 DEBUGF("i2c: gen_start failed (d=%d)", device);
77 return -1;
78 }
79
80 for (i=0; i<count; i++)
81 {
82 if (i2c_write_byte(device, buf[i]) == -1)
83 {
84 DEBUGF("i2c: write failed at (d=%d,i=%d)", device, i);
85 return i-1;
86 }
87 }
88
89 i2c_gen_stop(device);
90
91 return count;
92}
93
94/* Write a byte to the interface, returns 0 on success, -1 otherwise. */
95int i2c_write_byte(int device, unsigned char data)
96{
97 volatile unsigned char *regs = i2c_get_addr(device);
98
99 long count = 0;
100
101 regs[O_MBDR] = data; /* Write data byte */
102
103 /* Wait for bus busy */
104 while (!(regs[O_MBSR] & IBB) && count < MAX_LOOP)
105 {
106 yield();
107 count++;
108 }
109
110 if (count >= MAX_LOOP)
111 return -1;
112
113 /* Wait for interrupt flag */
114 while (!(regs[O_MBSR] & IFF) && count < MAX_LOOP)
115 {
116 yield();
117 count++;
118 }
119
120 if (count >= MAX_LOOP)
121 return -1;
122
123 regs[O_MBSR] &= ~IFF; /* Clear interrupt flag */
124
125 if (!(regs[O_MBSR] & ICF)) /* Check that transfer is complete */
126 return -1;
127
128 if (regs[O_MBSR] & RXAK) /* Check that the byte has been ACKed */
129 return -1;
130
131 return 0;
132}
133
134
135/* Returns 0 on success, -1 on failure */
136int i2c_gen_start(int device)
137{
138 volatile unsigned char *regs = i2c_get_addr(device);
139 long count = 0;
140
141 /* Wait for bus to become free */
142 while ((regs[O_MBSR] & IBB) && (count < MAX_LOOP))
143 count++;
144
145 if (count >= MAX_LOOP)
146 return -1;
147
148 regs[O_MBCR] |= MSTA | MTX; /* Generate START */
149
150 return 0;
151}
152
153void i2c_gen_stop(int device)
154{
155 volatile unsigned char *regs = i2c_get_addr(device);
156 regs[O_MBCR] &= ~MSTA; /* Clear MSTA to generate STOP */
157}
158
159
160volatile unsigned char *i2c_get_addr(int device)
161{
162 if (device == 1)
163 return I2C_DEVICE_1;
164
165 return I2C_DEVICE_2;
166}