diff options
Diffstat (limited to 'firmware/target/arm/s5l8702/i2c-s5l8702.c')
-rw-r--r-- | firmware/target/arm/s5l8702/i2c-s5l8702.c | 392 |
1 files changed, 196 insertions, 196 deletions
diff --git a/firmware/target/arm/s5l8702/i2c-s5l8702.c b/firmware/target/arm/s5l8702/i2c-s5l8702.c index 294e5b58ce..4d0e4188ab 100644 --- a/firmware/target/arm/s5l8702/i2c-s5l8702.c +++ b/firmware/target/arm/s5l8702/i2c-s5l8702.c | |||
@@ -1,196 +1,196 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * __________ __ ___. | 2 | * __________ __ ___. |
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
7 | * \/ \/ \/ \/ \/ | 7 | * \/ \/ \/ \/ \/ |
8 | * $Id: i2c-s5l8700.c 28589 2010-11-14 15:19:30Z theseven $ | 8 | * $Id: i2c-s5l8700.c 28589 2010-11-14 15:19:30Z theseven $ |
9 | * | 9 | * |
10 | * Copyright (C) 2009 by Bertrik Sikken | 10 | * Copyright (C) 2009 by Bertrik Sikken |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or | 12 | * This program is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU General Public License | 13 | * modify it under the terms of the GNU General Public License |
14 | * as published by the Free Software Foundation; either version 2 | 14 | * as published by the Free Software Foundation; either version 2 |
15 | * of the License, or (at your option) any later version. | 15 | * of the License, or (at your option) any later version. |
16 | * | 16 | * |
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | 17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
18 | * KIND, either express or implied. | 18 | * KIND, either express or implied. |
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | 21 | ||
22 | #include "config.h" | 22 | #include "config.h" |
23 | #include "system.h" | 23 | #include "system.h" |
24 | #include "kernel.h" | 24 | #include "kernel.h" |
25 | #include "i2c-s5l8702.h" | 25 | #include "i2c-s5l8702.h" |
26 | 26 | ||
27 | /* Driver for the s5l8700 built-in I2C controller in master mode | 27 | /* Driver for the s5l8700 built-in I2C controller in master mode |
28 | 28 | ||
29 | Both the i2c_read and i2c_write function take the following arguments: | 29 | Both the i2c_read and i2c_write function take the following arguments: |
30 | * slave, the address of the i2c slave device to read from / write to | 30 | * slave, the address of the i2c slave device to read from / write to |
31 | * address, optional sub-address in the i2c slave (unused if -1) | 31 | * address, optional sub-address in the i2c slave (unused if -1) |
32 | * len, number of bytes to be transfered | 32 | * len, number of bytes to be transfered |
33 | * data, pointer to data to be transfered | 33 | * data, pointer to data to be transfered |
34 | A return value < 0 indicates an error. | 34 | A return value < 0 indicates an error. |
35 | 35 | ||
36 | Note: | 36 | Note: |
37 | * blocks the calling thread for the entire duraton of the i2c transfer but | 37 | * blocks the calling thread for the entire duraton of the i2c transfer but |
38 | uses wakeup_wait/wakeup_signal to allow other threads to run. | 38 | uses wakeup_wait/wakeup_signal to allow other threads to run. |
39 | * ACK from slave is not checked, so functions never return an error | 39 | * ACK from slave is not checked, so functions never return an error |
40 | */ | 40 | */ |
41 | 41 | ||
42 | static struct mutex i2c_mtx[2]; | 42 | static struct mutex i2c_mtx[2]; |
43 | 43 | ||
44 | static void i2c_on(int bus) | 44 | static void i2c_on(int bus) |
45 | { | 45 | { |
46 | /* enable I2C clock */ | 46 | /* enable I2C clock */ |
47 | PWRCON(1) &= ~(1 << 4); | 47 | PWRCON(1) &= ~(1 << 4); |
48 | 48 | ||
49 | IICCON(bus) = (1 << 7) | /* ACK_GEN */ | 49 | IICCON(bus) = (1 << 7) | /* ACK_GEN */ |
50 | (0 << 6) | /* CLKSEL = PCLK/16 */ | 50 | (0 << 6) | /* CLKSEL = PCLK/16 */ |
51 | (1 << 5) | /* INT_EN */ | 51 | (1 << 5) | /* INT_EN */ |
52 | (1 << 4) | /* IRQ clear */ | 52 | (1 << 4) | /* IRQ clear */ |
53 | (7 << 0); /* CK_REG */ | 53 | (7 << 0); /* CK_REG */ |
54 | 54 | ||
55 | /* serial output on */ | 55 | /* serial output on */ |
56 | IICSTAT(bus) = (1 << 4); | 56 | IICSTAT(bus) = (1 << 4); |
57 | } | 57 | } |
58 | 58 | ||
59 | static void i2c_off(int bus) | 59 | static void i2c_off(int bus) |
60 | { | 60 | { |
61 | /* serial output off */ | 61 | /* serial output off */ |
62 | IICSTAT(bus) = 0; | 62 | IICSTAT(bus) = 0; |
63 | 63 | ||
64 | /* disable I2C clock */ | 64 | /* disable I2C clock */ |
65 | PWRCON(1) |= (1 << 4); | 65 | PWRCON(1) |= (1 << 4); |
66 | } | 66 | } |
67 | 67 | ||
68 | void i2c_init() | 68 | void i2c_init() |
69 | { | 69 | { |
70 | mutex_init(&i2c_mtx[0]); | 70 | mutex_init(&i2c_mtx[0]); |
71 | mutex_init(&i2c_mtx[1]); | 71 | mutex_init(&i2c_mtx[1]); |
72 | } | 72 | } |
73 | 73 | ||
74 | int i2c_write(int bus, unsigned char slave, int address, int len, const unsigned char *data) | 74 | int i2c_write(int bus, unsigned char slave, int address, int len, const unsigned char *data) |
75 | { | 75 | { |
76 | mutex_lock(&i2c_mtx[bus]); | 76 | mutex_lock(&i2c_mtx[bus]); |
77 | i2c_on(bus); | 77 | i2c_on(bus); |
78 | long timeout = current_tick + HZ / 50; | 78 | long timeout = current_tick + HZ / 50; |
79 | 79 | ||
80 | /* START */ | 80 | /* START */ |
81 | IICDS(bus) = slave & ~1; | 81 | IICDS(bus) = slave & ~1; |
82 | IICSTAT(bus) = 0xF0; | 82 | IICSTAT(bus) = 0xF0; |
83 | IICCON(bus) = 0xB3; | 83 | IICCON(bus) = 0xB3; |
84 | while ((IICCON(bus) & 0x10) == 0) | 84 | while ((IICCON(bus) & 0x10) == 0) |
85 | if (TIME_AFTER(current_tick, timeout)) | 85 | if (TIME_AFTER(current_tick, timeout)) |
86 | { | 86 | { |
87 | mutex_unlock(&i2c_mtx[bus]); | 87 | mutex_unlock(&i2c_mtx[bus]); |
88 | return 1; | 88 | return 1; |
89 | } | 89 | } |
90 | 90 | ||
91 | 91 | ||
92 | if (address >= 0) { | 92 | if (address >= 0) { |
93 | /* write address */ | 93 | /* write address */ |
94 | IICDS(bus) = address; | 94 | IICDS(bus) = address; |
95 | IICCON(bus) = 0xB3; | 95 | IICCON(bus) = 0xB3; |
96 | while ((IICCON(bus) & 0x10) == 0) | 96 | while ((IICCON(bus) & 0x10) == 0) |
97 | if (TIME_AFTER(current_tick, timeout)) | 97 | if (TIME_AFTER(current_tick, timeout)) |
98 | { | 98 | { |
99 | mutex_unlock(&i2c_mtx[bus]); | 99 | mutex_unlock(&i2c_mtx[bus]); |
100 | return 2; | 100 | return 2; |
101 | } | 101 | } |
102 | } | 102 | } |
103 | 103 | ||
104 | /* write data */ | 104 | /* write data */ |
105 | while (len--) { | 105 | while (len--) { |
106 | IICDS(bus) = *data++; | 106 | IICDS(bus) = *data++; |
107 | IICCON(bus) = 0xB3; | 107 | IICCON(bus) = 0xB3; |
108 | while ((IICCON(bus) & 0x10) == 0) | 108 | while ((IICCON(bus) & 0x10) == 0) |
109 | if (TIME_AFTER(current_tick, timeout)) | 109 | if (TIME_AFTER(current_tick, timeout)) |
110 | { | 110 | { |
111 | mutex_unlock(&i2c_mtx[bus]); | 111 | mutex_unlock(&i2c_mtx[bus]); |
112 | return 4; | 112 | return 4; |
113 | } | 113 | } |
114 | } | 114 | } |
115 | 115 | ||
116 | /* STOP */ | 116 | /* STOP */ |
117 | IICSTAT(bus) = 0xD0; | 117 | IICSTAT(bus) = 0xD0; |
118 | IICCON(bus) = 0xB3; | 118 | IICCON(bus) = 0xB3; |
119 | while ((IICSTAT(bus) & (1 << 5)) != 0) | 119 | while ((IICSTAT(bus) & (1 << 5)) != 0) |
120 | if (TIME_AFTER(current_tick, timeout)) | 120 | if (TIME_AFTER(current_tick, timeout)) |
121 | { | 121 | { |
122 | mutex_unlock(&i2c_mtx[bus]); | 122 | mutex_unlock(&i2c_mtx[bus]); |
123 | return 5; | 123 | return 5; |
124 | } | 124 | } |
125 | 125 | ||
126 | i2c_off(bus); | 126 | i2c_off(bus); |
127 | mutex_unlock(&i2c_mtx[bus]); | 127 | mutex_unlock(&i2c_mtx[bus]); |
128 | return 0; | 128 | return 0; |
129 | } | 129 | } |
130 | 130 | ||
131 | int i2c_read(int bus, unsigned char slave, int address, int len, unsigned char *data) | 131 | int i2c_read(int bus, unsigned char slave, int address, int len, unsigned char *data) |
132 | { | 132 | { |
133 | mutex_lock(&i2c_mtx[bus]); | 133 | mutex_lock(&i2c_mtx[bus]); |
134 | i2c_on(bus); | 134 | i2c_on(bus); |
135 | long timeout = current_tick + HZ / 50; | 135 | long timeout = current_tick + HZ / 50; |
136 | 136 | ||
137 | if (address >= 0) { | 137 | if (address >= 0) { |
138 | /* START */ | 138 | /* START */ |
139 | IICDS(bus) = slave & ~1; | 139 | IICDS(bus) = slave & ~1; |
140 | IICSTAT(bus) = 0xF0; | 140 | IICSTAT(bus) = 0xF0; |
141 | IICCON(bus) = 0xB3; | 141 | IICCON(bus) = 0xB3; |
142 | while ((IICCON(bus) & 0x10) == 0) | 142 | while ((IICCON(bus) & 0x10) == 0) |
143 | if (TIME_AFTER(current_tick, timeout)) | 143 | if (TIME_AFTER(current_tick, timeout)) |
144 | { | 144 | { |
145 | mutex_unlock(&i2c_mtx[bus]); | 145 | mutex_unlock(&i2c_mtx[bus]); |
146 | return 1; | 146 | return 1; |
147 | } | 147 | } |
148 | 148 | ||
149 | /* write address */ | 149 | /* write address */ |
150 | IICDS(bus) = address; | 150 | IICDS(bus) = address; |
151 | IICCON(bus) = 0xB3; | 151 | IICCON(bus) = 0xB3; |
152 | while ((IICCON(bus) & 0x10) == 0) | 152 | while ((IICCON(bus) & 0x10) == 0) |
153 | if (TIME_AFTER(current_tick, timeout)) | 153 | if (TIME_AFTER(current_tick, timeout)) |
154 | { | 154 | { |
155 | mutex_unlock(&i2c_mtx[bus]); | 155 | mutex_unlock(&i2c_mtx[bus]); |
156 | return 2; | 156 | return 2; |
157 | } | 157 | } |
158 | } | 158 | } |
159 | 159 | ||
160 | /* (repeated) START */ | 160 | /* (repeated) START */ |
161 | IICDS(bus) = slave | 1; | 161 | IICDS(bus) = slave | 1; |
162 | IICSTAT(bus) = 0xB0; | 162 | IICSTAT(bus) = 0xB0; |
163 | IICCON(bus) = 0xB3; | 163 | IICCON(bus) = 0xB3; |
164 | while ((IICCON(bus) & 0x10) == 0) | 164 | while ((IICCON(bus) & 0x10) == 0) |
165 | if (TIME_AFTER(current_tick, timeout)) | 165 | if (TIME_AFTER(current_tick, timeout)) |
166 | { | 166 | { |
167 | mutex_unlock(&i2c_mtx[bus]); | 167 | mutex_unlock(&i2c_mtx[bus]); |
168 | return 3; | 168 | return 3; |
169 | } | 169 | } |
170 | 170 | ||
171 | while (len--) { | 171 | while (len--) { |
172 | IICCON(bus) = (len == 0) ? 0x33 : 0xB3; /* NAK or ACK */ | 172 | IICCON(bus) = (len == 0) ? 0x33 : 0xB3; /* NAK or ACK */ |
173 | while ((IICCON(bus) & 0x10) == 0) | 173 | while ((IICCON(bus) & 0x10) == 0) |
174 | if (TIME_AFTER(current_tick, timeout)) | 174 | if (TIME_AFTER(current_tick, timeout)) |
175 | { | 175 | { |
176 | mutex_unlock(&i2c_mtx[bus]); | 176 | mutex_unlock(&i2c_mtx[bus]); |
177 | return 4; | 177 | return 4; |
178 | } | 178 | } |
179 | *data++ = IICDS(bus); | 179 | *data++ = IICDS(bus); |
180 | } | 180 | } |
181 | 181 | ||
182 | /* STOP */ | 182 | /* STOP */ |
183 | IICSTAT(bus) = 0x90; | 183 | IICSTAT(bus) = 0x90; |
184 | IICCON(bus) = 0xB3; | 184 | IICCON(bus) = 0xB3; |
185 | while ((IICSTAT(bus) & (1 << 5)) != 0) | 185 | while ((IICSTAT(bus) & (1 << 5)) != 0) |
186 | if (TIME_AFTER(current_tick, timeout)) | 186 | if (TIME_AFTER(current_tick, timeout)) |
187 | { | 187 | { |
188 | mutex_unlock(&i2c_mtx[bus]); | 188 | mutex_unlock(&i2c_mtx[bus]); |
189 | return 5; | 189 | return 5; |
190 | } | 190 | } |
191 | 191 | ||
192 | i2c_off(bus); | 192 | i2c_off(bus); |
193 | mutex_unlock(&i2c_mtx[bus]); | 193 | mutex_unlock(&i2c_mtx[bus]); |
194 | return 0; | 194 | return 0; |
195 | } | 195 | } |
196 | 196 | ||