summaryrefslogtreecommitdiff
path: root/firmware/drivers/i2c-coldfire.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers/i2c-coldfire.c')
-rw-r--r--firmware/drivers/i2c-coldfire.c174
1 files changed, 174 insertions, 0 deletions
diff --git a/firmware/drivers/i2c-coldfire.c b/firmware/drivers/i2c-coldfire.c
new file mode 100644
index 0000000000..5b4f4a1830
--- /dev/null
+++ b/firmware/drivers/i2c-coldfire.c
@@ -0,0 +1,174 @@
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-coldfire.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#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
41 /* Audio Codec */
42 MADR = 0x6c; /* iRiver firmware uses this addr */
43 MBDR = 0; /* iRiver firmware does this */
44 MBCR = IEN; /* Enable interface */
45
46#if 0
47 /* FM Tuner */
48 MADR2 = 0x6c;
49 MBDR2 = 0;
50 MBCR2 = IEN;
51#endif
52
53#endif
54}
55
56void i2c_close(void)
57{
58 MBCR = 0;
59 MBCR2 = 0;
60}
61
62/**
63 * Writes bytes to the selected device.
64 *
65 * Use device=1 for bus 1 at 0x40000280
66 * Use device=2 for bus 2 at 0x80000440
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 int rc;
74
75 rc = i2c_gen_start(device);
76 if (rc < 0)
77 {
78 DEBUGF("i2c: gen_start failed (d=%d)", device);
79 return rc*10 - 1;
80 }
81
82 for (i=0; i<count; i++)
83 {
84 rc = i2c_write_byte(device, buf[i]);
85 if (rc < 0)
86 {
87 DEBUGF("i2c: write failed at (d=%d,i=%d)", device, i);
88 return rc*10 - 2;
89 }
90 }
91
92 i2c_gen_stop(device);
93
94 return count;
95}
96
97/* Write a byte to the interface, returns 0 on success, -1 otherwise. */
98int i2c_write_byte(int device, unsigned char data)
99{
100 volatile unsigned char *regs = i2c_get_addr(device);
101
102 long count = 0;
103
104 regs[O_MBDR] = data; /* Write data byte */
105
106 /* Wait for bus busy */
107 while (!(regs[O_MBSR] & IBB) && count < MAX_LOOP)
108 {
109 yield();
110 count++;
111 }
112
113 if (count >= MAX_LOOP)
114 return -1;
115
116 count = 0;
117
118 /* Wait for interrupt flag */
119 while (!(regs[O_MBSR] & IFF) && count < MAX_LOOP)
120 {
121 yield();
122 count++;
123 }
124
125 if (count >= MAX_LOOP)
126 return -2;
127
128 regs[O_MBSR] &= ~IFF; /* Clear interrupt flag */
129
130 if (!(regs[O_MBSR] & ICF)) /* Check that transfer is complete */
131 return -3;
132
133 if (regs[O_MBSR] & RXAK) /* Check that the byte has been ACKed */
134 return -4;
135
136 return 0;
137}
138
139
140/* Returns 0 on success, -1 on failure */
141int i2c_gen_start(int device)
142{
143 volatile unsigned char *regs = i2c_get_addr(device);
144 long count = 0;
145
146 /* Wait for bus to become free */
147 while ((regs[O_MBSR] & IBB) && (count < MAX_LOOP))
148 {
149 yield();
150 count++;
151 }
152
153 if (count >= MAX_LOOP)
154 return -1;
155
156 regs[O_MBCR] |= MSTA | MTX; /* Generate START */
157
158 return 0;
159}
160
161void i2c_gen_stop(int device)
162{
163 volatile unsigned char *regs = i2c_get_addr(device);
164 regs[O_MBCR] &= ~MSTA; /* Clear MSTA to generate STOP */
165}
166
167
168volatile unsigned char *i2c_get_addr(int device)
169{
170 if (device == 1)
171 return I2C_DEVICE_1;
172
173 return I2C_DEVICE_2;
174}