summaryrefslogtreecommitdiff
path: root/firmware/target/arm/s5l8702/i2c-s5l8702.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/s5l8702/i2c-s5l8702.c')
-rw-r--r--firmware/target/arm/s5l8702/i2c-s5l8702.c392
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
42static struct mutex i2c_mtx[2]; 42static struct mutex i2c_mtx[2];
43 43
44static void i2c_on(int bus) 44static 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
59static void i2c_off(int bus) 59static 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
68void i2c_init() 68void 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
74int i2c_write(int bus, unsigned char slave, int address, int len, const unsigned char *data) 74int 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
131int i2c_read(int bus, unsigned char slave, int address, int len, unsigned char *data) 131int 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