diff options
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/arm/gigabeat/meg-fx/sc606-meg-fx.c | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/firmware/target/arm/gigabeat/meg-fx/sc606-meg-fx.c b/firmware/target/arm/gigabeat/meg-fx/sc606-meg-fx.c new file mode 100644 index 0000000000..b4e55083e3 --- /dev/null +++ b/firmware/target/arm/gigabeat/meg-fx/sc606-meg-fx.c | |||
@@ -0,0 +1,182 @@ | |||
1 | #include "config.h" | ||
2 | #include "cpu.h" | ||
3 | #include <stdbool.h> | ||
4 | #include "kernel.h" | ||
5 | #include "system.h" | ||
6 | #include "hwcompat.h" | ||
7 | #include "logf.h" | ||
8 | #include "debug.h" | ||
9 | #include "string.h" | ||
10 | |||
11 | #define SLAVE_ADDRESS 0xCC | ||
12 | |||
13 | #define SDA_LO GPHDAT &= ~(1 << 9) | ||
14 | #define SDA_HI GPHDAT |= (1 << 9) | ||
15 | #define SDA_INPUT GPHCON &= ~(3 << 18) | ||
16 | #define SDA_OUTPUT GPHCON |= (1 << 18) | ||
17 | #define SDA GPHDAT & (1 << 9) | ||
18 | |||
19 | #define SCL_LO GPHDAT &= ~(1 << 10) | ||
20 | #define SCL_HI GPHDAT |= (1 << 10) | ||
21 | #define SCL_INPUT GPHCON &= ~(3 << 20) | ||
22 | #define SCL_OUTPUT GPHCON |= (1 << 20) | ||
23 | #define SCL GPHDAT & (1 << 10) | ||
24 | |||
25 | #define SCL_SDA_HI GPHDAT |= (3 << 9) | ||
26 | |||
27 | /* arbitrary delay loop */ | ||
28 | #define DELAY do { int _x; for(_x=0;_x<2000;_x++);} while (0) | ||
29 | |||
30 | void sc606_i2c_start(void) | ||
31 | { | ||
32 | SCL_SDA_HI; | ||
33 | DELAY; | ||
34 | SDA_LO; | ||
35 | DELAY; | ||
36 | SCL_LO; | ||
37 | } | ||
38 | |||
39 | void sc606_i2c_restart(void) | ||
40 | { | ||
41 | SCL_SDA_HI; | ||
42 | DELAY; | ||
43 | SDA_LO; | ||
44 | DELAY; | ||
45 | SCL_LO; | ||
46 | } | ||
47 | |||
48 | void sc606_i2c_stop(void) | ||
49 | { | ||
50 | SDA_LO; | ||
51 | DELAY; | ||
52 | SCL_HI; | ||
53 | DELAY; | ||
54 | SDA_HI; | ||
55 | DELAY; | ||
56 | } | ||
57 | |||
58 | void sc606_i2c_ack() | ||
59 | { | ||
60 | |||
61 | SDA_LO; | ||
62 | SCL_HI; | ||
63 | DELAY; | ||
64 | SCL_LO; | ||
65 | } | ||
66 | |||
67 | int sc606_i2c_getack(void) | ||
68 | { | ||
69 | int ret = 0; | ||
70 | |||
71 | /* Don't need a delay since this follows a data bit with a delay on the end */ | ||
72 | SDA_INPUT; /* And set to input */ | ||
73 | SCL_HI; | ||
74 | DELAY; | ||
75 | |||
76 | if (SDA) /* ack failed */ | ||
77 | ret = 1; | ||
78 | |||
79 | DELAY; | ||
80 | SCL_LO; | ||
81 | DELAY; | ||
82 | SDA_OUTPUT; | ||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | int sc606_i2c_outb(unsigned char byte) | ||
87 | { | ||
88 | int i; | ||
89 | |||
90 | /* clock out each bit, MSB first */ | ||
91 | for (i = 0x80; i; i >>= 1) { | ||
92 | |||
93 | if (i & byte) { | ||
94 | SDA_HI; | ||
95 | } else { | ||
96 | SDA_LO; | ||
97 | } | ||
98 | |||
99 | DELAY; | ||
100 | SCL_HI; | ||
101 | DELAY; | ||
102 | SCL_LO; | ||
103 | DELAY; | ||
104 | } | ||
105 | |||
106 | return sc606_i2c_getack(); | ||
107 | } | ||
108 | |||
109 | unsigned char sc606_i2c_inb() | ||
110 | { | ||
111 | int i; | ||
112 | unsigned char byte = 0; | ||
113 | |||
114 | SDA_INPUT; /* And set to input */ | ||
115 | /* clock in each bit, MSB first */ | ||
116 | for (i = 0x80; i; i >>= 1) { | ||
117 | SCL_HI; | ||
118 | |||
119 | if (SDA) | ||
120 | byte |= i; | ||
121 | |||
122 | SCL_LO; | ||
123 | } | ||
124 | SDA_OUTPUT; | ||
125 | |||
126 | sc606_i2c_ack(); | ||
127 | |||
128 | return byte; | ||
129 | } | ||
130 | |||
131 | int sc606_write(unsigned char reg, unsigned char data) | ||
132 | { | ||
133 | int x = 0; | ||
134 | |||
135 | sc606_i2c_start(); | ||
136 | x += sc606_i2c_outb(SLAVE_ADDRESS); | ||
137 | x += 0x10 * sc606_i2c_outb(reg); | ||
138 | sc606_i2c_start(); | ||
139 | /* sc606_i2c_restart(); */ | ||
140 | x += 0x100 * sc606_i2c_outb(SLAVE_ADDRESS); | ||
141 | x += 0x1000 *sc606_i2c_outb(data); | ||
142 | sc606_i2c_stop(); | ||
143 | |||
144 | return x; | ||
145 | } | ||
146 | |||
147 | int sc606_read(unsigned char reg, unsigned char* data) | ||
148 | { | ||
149 | int x = 0; | ||
150 | |||
151 | sc606_i2c_start(); | ||
152 | sc606_i2c_outb(SLAVE_ADDRESS); | ||
153 | sc606_i2c_outb(reg); | ||
154 | sc606_i2c_restart(); | ||
155 | sc606_i2c_outb(SLAVE_ADDRESS | 1); | ||
156 | *data = sc606_i2c_inb(); | ||
157 | sc606_i2c_stop(); | ||
158 | |||
159 | return x; | ||
160 | } | ||
161 | |||
162 | void sc606_init() | ||
163 | { | ||
164 | /* Set GPB2 (EN) to 1 */ | ||
165 | GPBCON = (GPBCON & ~(3<<4)) | 1<<4; | ||
166 | |||
167 | /* Turn enable line on */ | ||
168 | GPBDAT |= 1<<2; | ||
169 | /* OFF GPBDAT &= ~(1 << 2); */ | ||
170 | |||
171 | /* About 400us - needs 350us */ | ||
172 | DELAY; | ||
173 | DELAY; | ||
174 | DELAY; | ||
175 | DELAY; | ||
176 | DELAY; | ||
177 | |||
178 | /* Set GPH9 (SDA) and GPH10 (SCL) to 1 */ | ||
179 | GPHUP &= ~(3<<9); | ||
180 | GPHCON = (GPHCON & ~(0xF<<18)) | 5<<18; | ||
181 | } | ||
182 | |||