diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/target/arm/gigabeat/meg-fx/sc606-meg-fx.c | 123 |
1 files changed, 80 insertions, 43 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 index 9e9fcb3547..654095c2f5 100644 --- a/firmware/target/arm/gigabeat/meg-fx/sc606-meg-fx.c +++ b/firmware/target/arm/gigabeat/meg-fx/sc606-meg-fx.c | |||
@@ -10,23 +10,28 @@ | |||
10 | 10 | ||
11 | #define SLAVE_ADDRESS 0xCC | 11 | #define SLAVE_ADDRESS 0xCC |
12 | 12 | ||
13 | #define SDA_LO GPHDAT &= ~(1 << 9) | 13 | #define SDA_LO (GPHDAT &= ~(1 << 9)) |
14 | #define SDA_HI GPHDAT |= (1 << 9) | 14 | #define SDA_HI (GPHDAT |= (1 << 9)) |
15 | #define SDA_INPUT GPHCON &= ~(3 << 18) | 15 | #define SDA_INPUT (GPHCON &= ~(3 << 18)) |
16 | #define SDA_OUTPUT GPHCON |= (1 << 18) | 16 | #define SDA_OUTPUT (GPHCON |= (1 << 18)) |
17 | #define SDA GPHDAT & (1 << 9) | 17 | #define SDA (GPHDAT & (1 << 9)) |
18 | 18 | ||
19 | #define SCL_LO GPHDAT &= ~(1 << 10) | 19 | #define SCL_LO (GPHDAT &= ~(1 << 10)) |
20 | #define SCL_HI GPHDAT |= (1 << 10) | 20 | #define SCL_HI (GPHDAT |= (1 << 10)) |
21 | #define SCL_INPUT GPHCON &= ~(3 << 20) | 21 | #define SCL_INPUT (GPHCON &= ~(3 << 20)) |
22 | #define SCL_OUTPUT GPHCON |= (1 << 20) | 22 | #define SCL_OUTPUT (GPHCON |= (1 << 20)) |
23 | #define SCL GPHDAT & (1 << 10) | 23 | #define SCL (GPHDAT & (1 << 10)) |
24 | 24 | ||
25 | #define SCL_SDA_HI GPHDAT |= (3 << 9) | 25 | #define SCL_SDA_HI (GPHDAT |= (3 << 9)) |
26 | 26 | ||
27 | /* The SC606 can clock at 400KHz: 2.5uS period -> 1.25uS half period */ | 27 | /* The SC606 can clock at 400KHz: 2.5uS period -> 1.25uS half period */ |
28 | /* At 300Mhz - if loop takes 10 cycles @ 3.3nS each -> 1.25uS / 30nS -> 40 */ | 28 | /* The high and low times are different enough to need different timings */ |
29 | #define DELAY do { volatile int _x; for(_x=0;_x<40;_x++);} while (0) | 29 | /* At 300Mhz - one loop takes about 10 cycles */ |
30 | #define DELAY_LO do { volatile int _x; for(_x=0;_x<20;_x++);} while (0) | ||
31 | #define DELAY do { volatile int _x; for(_x=0;_x<15;_x++);} while (0) | ||
32 | #define DELAY_HI do { volatile int _x; for(_x=0;_x<10;_x++);} while (0) | ||
33 | |||
34 | |||
30 | 35 | ||
31 | static void sc606_i2c_start(void) | 36 | static void sc606_i2c_start(void) |
32 | { | 37 | { |
@@ -49,11 +54,9 @@ static void sc606_i2c_restart(void) | |||
49 | static void sc606_i2c_stop(void) | 54 | static void sc606_i2c_stop(void) |
50 | { | 55 | { |
51 | SDA_LO; | 56 | SDA_LO; |
52 | DELAY; | ||
53 | SCL_HI; | 57 | SCL_HI; |
54 | DELAY; | 58 | DELAY_HI; |
55 | SDA_HI; | 59 | SDA_HI; |
56 | DELAY; | ||
57 | } | 60 | } |
58 | 61 | ||
59 | static void sc606_i2c_ack(void) | 62 | static void sc606_i2c_ack(void) |
@@ -61,52 +64,66 @@ static void sc606_i2c_ack(void) | |||
61 | 64 | ||
62 | SDA_LO; | 65 | SDA_LO; |
63 | SCL_HI; | 66 | SCL_HI; |
64 | DELAY; | 67 | DELAY_HI; |
65 | SCL_LO; | 68 | SCL_LO; |
66 | } | 69 | } |
67 | 70 | ||
71 | |||
72 | |||
68 | static int sc606_i2c_getack(void) | 73 | static int sc606_i2c_getack(void) |
69 | { | 74 | { |
70 | int ret = 0; | 75 | int ret; |
71 | 76 | ||
72 | /* Don't need a delay since follows a data bit with a delay on the end */ | 77 | /* Don't need a delay since follows a data bit with a delay on the end */ |
73 | SDA_INPUT; /* And set to input */ | 78 | SDA_INPUT; /* And set to input */ |
74 | SCL_HI; | ||
75 | DELAY; | 79 | DELAY; |
80 | SCL_HI; | ||
76 | 81 | ||
77 | if (SDA) /* ack failed */ | 82 | ret = (SDA != 0); /* ack failed if SDA is not low */ |
78 | ret = 1; | 83 | DELAY_HI; |
79 | 84 | ||
80 | DELAY; | ||
81 | SCL_LO; | 85 | SCL_LO; |
82 | DELAY; | 86 | DELAY_LO; |
87 | |||
88 | SDA_HI; | ||
83 | SDA_OUTPUT; | 89 | SDA_OUTPUT; |
90 | DELAY_LO; | ||
91 | |||
84 | return ret; | 92 | return ret; |
85 | } | 93 | } |
86 | 94 | ||
87 | static int sc606_i2c_outb(unsigned char byte) | 95 | |
96 | |||
97 | static void sc606_i2c_outb(unsigned char byte) | ||
88 | { | 98 | { |
89 | int i; | 99 | int i; |
90 | 100 | ||
91 | /* clock out each bit, MSB first */ | 101 | /* clock out each bit, MSB first */ |
92 | for (i = 0x80; i; i >>= 1) { | 102 | for (i = 0x80; i; i >>= 1) |
103 | { | ||
104 | if (i & byte) | ||
105 | { | ||
106 | SDA_HI; | ||
107 | } | ||
108 | else | ||
109 | { | ||
110 | SDA_LO; | ||
111 | } | ||
112 | DELAY; | ||
93 | 113 | ||
94 | if (i & byte) { | 114 | SCL_HI; |
95 | SDA_HI; | 115 | DELAY_HI; |
96 | } else { | ||
97 | SDA_LO; | ||
98 | } | ||
99 | 116 | ||
100 | DELAY; | 117 | SCL_LO; |
101 | SCL_HI; | 118 | DELAY_LO; |
102 | DELAY; | ||
103 | SCL_LO; | ||
104 | DELAY; | ||
105 | } | 119 | } |
106 | 120 | ||
107 | return sc606_i2c_getack(); | 121 | SDA_HI; |
122 | |||
108 | } | 123 | } |
109 | 124 | ||
125 | |||
126 | |||
110 | static unsigned char sc606_i2c_inb(void) | 127 | static unsigned char sc606_i2c_inb(void) |
111 | { | 128 | { |
112 | int i; | 129 | int i; |
@@ -131,37 +148,57 @@ static unsigned char sc606_i2c_inb(void) | |||
131 | 148 | ||
132 | 149 | ||
133 | 150 | ||
151 | /* returns number of acks that were bad */ | ||
134 | int sc606_write(unsigned char reg, unsigned char data) | 152 | int sc606_write(unsigned char reg, unsigned char data) |
135 | { | 153 | { |
136 | int x = 0; | 154 | int x = 0; |
137 | 155 | ||
138 | sc606_i2c_start(); | 156 | sc606_i2c_start(); |
139 | x += sc606_i2c_outb(SLAVE_ADDRESS); | 157 | |
140 | x += 0x10 * sc606_i2c_outb(reg); | 158 | sc606_i2c_outb(SLAVE_ADDRESS); |
141 | sc606_i2c_start(); | 159 | x = sc606_i2c_getack(); |
142 | /* sc606_i2c_restart(); */ | 160 | |
143 | x += 0x100 * sc606_i2c_outb(SLAVE_ADDRESS); | 161 | sc606_i2c_outb(reg); |
144 | x += 0x1000 *sc606_i2c_outb(data); | 162 | x += sc606_i2c_getack(); |
163 | |||
164 | sc606_i2c_restart(); | ||
165 | |||
166 | sc606_i2c_outb(SLAVE_ADDRESS); | ||
167 | x += sc606_i2c_getack(); | ||
168 | |||
169 | sc606_i2c_outb(data); | ||
170 | x += sc606_i2c_getack(); | ||
171 | |||
145 | sc606_i2c_stop(); | 172 | sc606_i2c_stop(); |
146 | 173 | ||
147 | return x; | 174 | return x; |
148 | } | 175 | } |
149 | 176 | ||
177 | |||
178 | |||
150 | int sc606_read(unsigned char reg, unsigned char* data) | 179 | int sc606_read(unsigned char reg, unsigned char* data) |
151 | { | 180 | { |
152 | int x = 0; | 181 | int x = 0; |
153 | 182 | ||
154 | sc606_i2c_start(); | 183 | sc606_i2c_start(); |
155 | sc606_i2c_outb(SLAVE_ADDRESS); | 184 | sc606_i2c_outb(SLAVE_ADDRESS); |
185 | x = sc606_i2c_getack(); | ||
186 | |||
156 | sc606_i2c_outb(reg); | 187 | sc606_i2c_outb(reg); |
188 | x += sc606_i2c_getack(); | ||
189 | |||
157 | sc606_i2c_restart(); | 190 | sc606_i2c_restart(); |
158 | sc606_i2c_outb(SLAVE_ADDRESS | 1); | 191 | sc606_i2c_outb(SLAVE_ADDRESS | 1); |
192 | x += sc606_i2c_getack(); | ||
193 | |||
159 | *data = sc606_i2c_inb(); | 194 | *data = sc606_i2c_inb(); |
160 | sc606_i2c_stop(); | 195 | sc606_i2c_stop(); |
161 | 196 | ||
162 | return x; | 197 | return x; |
163 | } | 198 | } |
164 | 199 | ||
200 | |||
201 | |||
165 | void sc606_init(void) | 202 | void sc606_init(void) |
166 | { | 203 | { |
167 | volatile int i; | 204 | volatile int i; |
@@ -176,7 +213,7 @@ void sc606_init(void) | |||
176 | /* About 400us - needs 350us */ | 213 | /* About 400us - needs 350us */ |
177 | for (i = 200; i; i--) | 214 | for (i = 200; i; i--) |
178 | { | 215 | { |
179 | DELAY; | 216 | DELAY_LO; |
180 | } | 217 | } |
181 | 218 | ||
182 | /* Set GPH9 (SDA) and GPH10 (SCL) to 1 */ | 219 | /* Set GPH9 (SDA) and GPH10 (SCL) to 1 */ |