diff options
Diffstat (limited to 'firmware/drivers/i2c-coldfire.c')
-rw-r--r-- | firmware/drivers/i2c-coldfire.c | 174 |
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 | |||
31 | static int i2c_write_byte(int device, unsigned char data); | ||
32 | static int i2c_gen_start(int device); | ||
33 | static void i2c_gen_stop(int device); | ||
34 | static volatile unsigned char *i2c_get_addr(int device); | ||
35 | |||
36 | /* Public functions */ | ||
37 | |||
38 | void 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 | |||
56 | void 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 | */ | ||
70 | int 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. */ | ||
98 | int 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 */ | ||
141 | int 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 | |||
161 | void 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 | |||
168 | volatile unsigned char *i2c_get_addr(int device) | ||
169 | { | ||
170 | if (device == 1) | ||
171 | return I2C_DEVICE_1; | ||
172 | |||
173 | return I2C_DEVICE_2; | ||
174 | } | ||