diff options
author | Marcoen Hirschberg <marcoen@gmail.com> | 2007-05-11 16:42:53 +0000 |
---|---|---|
committer | Marcoen Hirschberg <marcoen@gmail.com> | 2007-05-11 16:42:53 +0000 |
commit | 685001f0d41c84ed123b8946b45397bf4e8a097e (patch) | |
tree | 4d53be7e5b3126784d163fd266c8addcc56ba7c0 /firmware/target/arm/s3c2440/gigabeat-fx | |
parent | d92e09556fdec3fbd65e153c6f41c31cb1e04c42 (diff) | |
download | rockbox-685001f0d41c84ed123b8946b45397bf4e8a097e.tar.gz rockbox-685001f0d41c84ed123b8946b45397bf4e8a097e.zip |
revert the last changes because they prevent some Gigabeats from shutting down
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13372 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/s3c2440/gigabeat-fx')
-rw-r--r-- | firmware/target/arm/s3c2440/gigabeat-fx/sc606-meg-fx.c | 201 |
1 files changed, 111 insertions, 90 deletions
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/sc606-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/sc606-meg-fx.c index c207e310d9..e69eab432a 100644 --- a/firmware/target/arm/s3c2440/gigabeat-fx/sc606-meg-fx.c +++ b/firmware/target/arm/s3c2440/gigabeat-fx/sc606-meg-fx.c | |||
@@ -1,5 +1,6 @@ | |||
1 | #include "config.h" | 1 | #include "config.h" |
2 | #include "cpu.h" | 2 | #include "cpu.h" |
3 | #include <stdbool.h> | ||
3 | #include "kernel.h" | 4 | #include "kernel.h" |
4 | #include "system.h" | 5 | #include "system.h" |
5 | #include "logf.h" | 6 | #include "logf.h" |
@@ -8,132 +9,147 @@ | |||
8 | 9 | ||
9 | #define SLAVE_ADDRESS 0xCC | 10 | #define SLAVE_ADDRESS 0xCC |
10 | 11 | ||
11 | #define USE_ASM | 12 | #define SDA_LO (GPHDAT &= ~(1 << 9)) |
12 | 13 | #define SDA_HI (GPHDAT |= (1 << 9)) | |
13 | /* This I2C driver tristates the outputs instead of driving logic high's */ | 14 | #define SDA_INPUT (GPHCON &= ~(3 << 18)) |
15 | #define SDA_OUTPUT (GPHCON |= (1 << 18)) | ||
14 | #define SDA (GPHDAT & (1 << 9)) | 16 | #define SDA (GPHDAT & (1 << 9)) |
15 | #define SDA_LO_OUT (GPHCON |= (1 << 18));(GPHDAT &= ~(1 << 9)); | ||
16 | #define SDA_HI_IN (GPHCON &= ~(3 << 18)) | ||
17 | 17 | ||
18 | #define SCL_LO (GPHDAT &= ~(1 << 10)) | ||
19 | #define SCL_HI (GPHDAT |= (1 << 10)) | ||
20 | #define SCL_INPUT (GPHCON &= ~(3 << 20)) | ||
21 | #define SCL_OUTPUT (GPHCON |= (1 << 20)) | ||
18 | #define SCL (GPHDAT & (1 << 10)) | 22 | #define SCL (GPHDAT & (1 << 10)) |
19 | #define SCL_LO_OUT (GPHCON |= (1 << 20));(GPHDAT &= ~(1 << 10)); | 23 | |
20 | #define SCL_HI_IN (GPHCON &= ~(3 << 20));while(!SCL); | 24 | #define SCL_SDA_HI (GPHDAT |= (3 << 9)) |
21 | 25 | ||
22 | /* The SC606 can clock at 400KHz: | 26 | /* The SC606 can clock at 400KHz: */ |
23 | * Clock period high is 600nS and low is 1300nS | 27 | /* Clock period high is 600nS and low is 1300nS */ |
24 | * The high and low times are different enough to need different timings | 28 | /* The high and low times are different enough to need different timings */ |
25 | * cycles delayed = 2 + 4 * loops | 29 | /* cycles delayed = 30 + 7 * loops */ |
26 | * 100MHz = 10nS per cycle: LO:1300nS=130:33 HI:600nS=60:15 | 30 | /* 100MHz = 10nS per cycle: LO:1300nS=130:14 HI:600nS=60:9 */ |
27 | * 300MHz = 3.33nS per cycle: | 31 | /* 300MHz = 3.36nS per cycle: LO:1300nS=387:51 HI:600nS=179:21 */ |
28 | * LO:1300nS=394:99 | 32 | #define DELAY_LO do{int x;for(x=51;x;x--);} while (0) |
29 | * HI:600nS=182:21 | 33 | #define DELAY do{int x;for(x=35;x;x--);} while (0) |
30 | * MID(50/50):950(1900/2)ns=288:72 | 34 | #define DELAY_HI do{int x;for(x=21;x;x--);} while (0) |
31 | */ | 35 | |
32 | 36 | ||
33 | #ifdef USE_ASM | ||
34 | |||
35 | #define DELAY_LO 99 | ||
36 | #define DELAY_MID 72 | ||
37 | #define DELAY_HI 46 | ||
38 | /* This delay loop takes 4 cycles/loop to execute plus 2 for setup */ | ||
39 | #define DELAY(dly) \ | ||
40 | asm volatile( "mov r0,%0 \n" \ | ||
41 | "1: \n" \ | ||
42 | "subs r0,r0,#1 \n" \ | ||
43 | "bhi 1b \n" \ | ||
44 | : : "r"((dly)) : "r0" ); | ||
45 | |||
46 | #else | ||
47 | |||
48 | #define DELAY_LO 51 | ||
49 | #define DELAY_MID 35 | ||
50 | #define DELAY_HI 21 | ||
51 | #define DELAY(dly) do{int x;for(x=(dly);x;x--);} while (0) | ||
52 | |||
53 | #endif | ||
54 | 37 | ||
55 | static void sc606_i2c_start(void) | 38 | static void sc606_i2c_start(void) |
56 | { | 39 | { |
57 | SDA_HI_IN; | 40 | SCL_SDA_HI; |
58 | SCL_HI_IN; | 41 | DELAY; |
59 | DELAY(DELAY_MID); | 42 | SDA_LO; |
60 | SDA_LO_OUT; | 43 | DELAY; |
61 | DELAY(DELAY_MID); | 44 | SCL_LO; |
62 | SCL_LO_OUT; | 45 | } |
46 | |||
47 | static void sc606_i2c_restart(void) | ||
48 | { | ||
49 | SCL_SDA_HI; | ||
50 | DELAY; | ||
51 | SDA_LO; | ||
52 | DELAY; | ||
53 | SCL_LO; | ||
63 | } | 54 | } |
64 | 55 | ||
65 | static void sc606_i2c_stop(void) | 56 | static void sc606_i2c_stop(void) |
66 | { | 57 | { |
67 | SDA_LO_OUT; | 58 | SDA_LO; |
68 | SCL_HI_IN; | 59 | SCL_HI; |
69 | DELAY(DELAY_HI); | 60 | DELAY_HI; |
70 | SDA_HI_IN; | 61 | SDA_HI; |
71 | } | 62 | } |
72 | 63 | ||
73 | static void sc606_i2c_ack(void) | 64 | static void sc606_i2c_ack(void) |
74 | { | 65 | { |
75 | SDA_HI_IN; | ||
76 | SCL_HI_IN; | ||
77 | 66 | ||
78 | DELAY(DELAY_HI); | 67 | SDA_LO; |
79 | SCL_LO_OUT; | 68 | SCL_HI; |
69 | DELAY_HI; | ||
70 | SCL_LO; | ||
80 | } | 71 | } |
81 | 72 | ||
82 | static bool sc606_i2c_getack(void) | 73 | |
74 | |||
75 | static int sc606_i2c_getack(void) | ||
83 | { | 76 | { |
84 | bool ret; | 77 | int ret; |
78 | |||
79 | /* Don't need a delay since follows a data bit with a delay on the end */ | ||
80 | SDA_INPUT; /* And set to input */ | ||
81 | DELAY; | ||
82 | SCL_HI; | ||
85 | 83 | ||
86 | SDA_HI_IN; | 84 | ret = (SDA != 0); /* ack failed if SDA is not low */ |
87 | DELAY(DELAY_MID); | 85 | DELAY_HI; |
88 | SCL_HI_IN; | ||
89 | 86 | ||
90 | ret = !SDA; | 87 | SCL_LO; |
88 | DELAY_LO; | ||
91 | 89 | ||
92 | SCL_LO_OUT; | 90 | SDA_HI; |
93 | DELAY(DELAY_LO); | 91 | SDA_OUTPUT; |
92 | DELAY_LO; | ||
94 | 93 | ||
95 | return ret; | 94 | return ret; |
96 | } | 95 | } |
97 | 96 | ||
97 | |||
98 | |||
98 | static void sc606_i2c_outb(unsigned char byte) | 99 | static void sc606_i2c_outb(unsigned char byte) |
99 | { | 100 | { |
100 | int i; | 101 | int i; |
101 | 102 | ||
102 | /* clock out each bit, MSB first */ | 103 | /* clock out each bit, MSB first */ |
103 | for ( i=0x80; i; i>>=1 ) | 104 | for (i = 0x80; i; i >>= 1) |
104 | { | 105 | { |
105 | if ( i & byte ) | 106 | if (i & byte) |
106 | SDA_HI_IN; | 107 | { |
108 | SDA_HI; | ||
109 | } | ||
107 | else | 110 | else |
108 | SDA_LO_OUT; | 111 | { |
109 | DELAY(DELAY_MID); | 112 | SDA_LO; |
110 | SCL_HI_IN; | 113 | } |
111 | DELAY(DELAY_HI); | 114 | DELAY; |
112 | SCL_LO_OUT; | 115 | |
116 | SCL_HI; | ||
117 | DELAY_HI; | ||
118 | |||
119 | SCL_LO; | ||
120 | DELAY_LO; | ||
113 | } | 121 | } |
122 | |||
123 | SDA_HI; | ||
124 | |||
114 | } | 125 | } |
115 | 126 | ||
127 | |||
128 | |||
116 | static unsigned char sc606_i2c_inb(void) | 129 | static unsigned char sc606_i2c_inb(void) |
117 | { | 130 | { |
118 | int i; | 131 | int i; |
119 | unsigned char byte = 0; | 132 | unsigned char byte = 0; |
120 | 133 | ||
121 | /* clock in each bit, MSB first */ | 134 | SDA_INPUT; /* And set to input */ |
122 | SDA_HI_IN; | 135 | /* clock in each bit, MSB first */ |
123 | for ( i=0x80; i; i>>=1 ) | 136 | for (i = 0x80; i; i >>= 1) { |
124 | { | 137 | SCL_HI; |
125 | SCL_HI_IN; | 138 | |
126 | DELAY(DELAY_HI); | 139 | if (SDA) |
127 | if ( SDA ) | 140 | byte |= i; |
128 | byte |= i; | ||
129 | SCL_LO_OUT; | ||
130 | DELAY(DELAY_LO); | ||
131 | } | ||
132 | 141 | ||
133 | sc606_i2c_ack(); | 142 | SCL_LO; |
134 | return byte; | 143 | } |
144 | SDA_OUTPUT; | ||
145 | |||
146 | sc606_i2c_ack(); | ||
147 | |||
148 | return byte; | ||
135 | } | 149 | } |
136 | 150 | ||
151 | |||
152 | |||
137 | /* returns number of acks that were bad */ | 153 | /* returns number of acks that were bad */ |
138 | int sc606_write(unsigned char reg, unsigned char data) | 154 | int sc606_write(unsigned char reg, unsigned char data) |
139 | { | 155 | { |
@@ -147,7 +163,7 @@ int sc606_write(unsigned char reg, unsigned char data) | |||
147 | sc606_i2c_outb(reg); | 163 | sc606_i2c_outb(reg); |
148 | x += sc606_i2c_getack(); | 164 | x += sc606_i2c_getack(); |
149 | 165 | ||
150 | sc606_i2c_start(); | 166 | sc606_i2c_restart(); |
151 | 167 | ||
152 | sc606_i2c_outb(SLAVE_ADDRESS); | 168 | sc606_i2c_outb(SLAVE_ADDRESS); |
153 | x += sc606_i2c_getack(); | 169 | x += sc606_i2c_getack(); |
@@ -160,6 +176,8 @@ int sc606_write(unsigned char reg, unsigned char data) | |||
160 | return x; | 176 | return x; |
161 | } | 177 | } |
162 | 178 | ||
179 | |||
180 | |||
163 | int sc606_read(unsigned char reg, unsigned char* data) | 181 | int sc606_read(unsigned char reg, unsigned char* data) |
164 | { | 182 | { |
165 | int x; | 183 | int x; |
@@ -171,7 +189,7 @@ int sc606_read(unsigned char reg, unsigned char* data) | |||
171 | sc606_i2c_outb(reg); | 189 | sc606_i2c_outb(reg); |
172 | x += sc606_i2c_getack(); | 190 | x += sc606_i2c_getack(); |
173 | 191 | ||
174 | sc606_i2c_start(); | 192 | sc606_i2c_restart(); |
175 | sc606_i2c_outb(SLAVE_ADDRESS | 1); | 193 | sc606_i2c_outb(SLAVE_ADDRESS | 1); |
176 | x += sc606_i2c_getack(); | 194 | x += sc606_i2c_getack(); |
177 | 195 | ||
@@ -181,6 +199,8 @@ int sc606_read(unsigned char reg, unsigned char* data) | |||
181 | return x; | 199 | return x; |
182 | } | 200 | } |
183 | 201 | ||
202 | |||
203 | |||
184 | void sc606_init(void) | 204 | void sc606_init(void) |
185 | { | 205 | { |
186 | volatile int i; | 206 | volatile int i; |
@@ -194,11 +214,12 @@ void sc606_init(void) | |||
194 | 214 | ||
195 | /* About 400us - needs 350us */ | 215 | /* About 400us - needs 350us */ |
196 | for (i = 200; i; i--) | 216 | for (i = 200; i; i--) |
197 | DELAY(DELAY_LO); | 217 | { |
218 | DELAY_LO; | ||
219 | } | ||
198 | 220 | ||
199 | /* Set GPH9 (SDA) and GPH10 (SCL) to 1 */ | 221 | /* Set GPH9 (SDA) and GPH10 (SCL) to 1 */ |
200 | GPHUP &= ~(3<<9); | 222 | GPHUP &= ~(3<<9); |
201 | SCL_HI_IN; | 223 | GPHCON = (GPHCON & ~(0xF<<18)) | 5<<18; |
202 | SDA_HI_IN; | ||
203 | } | 224 | } |
204 | 225 | ||