summaryrefslogtreecommitdiff
path: root/firmware/target/arm/gigabeat
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/gigabeat')
-rw-r--r--firmware/target/arm/gigabeat/meg-fx/sc606-meg-fx.c123
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
31static void sc606_i2c_start(void) 36static void sc606_i2c_start(void)
32{ 37{
@@ -49,11 +54,9 @@ static void sc606_i2c_restart(void)
49static void sc606_i2c_stop(void) 54static 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
59static void sc606_i2c_ack(void) 62static 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
68static int sc606_i2c_getack(void) 73static 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
87static int sc606_i2c_outb(unsigned char byte) 95
96
97static 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
110static unsigned char sc606_i2c_inb(void) 127static 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 */
134int sc606_write(unsigned char reg, unsigned char data) 152int 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
150int sc606_read(unsigned char reg, unsigned char* data) 179int 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
165void sc606_init(void) 202void 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 */