1 /*
2 * Copyright (c) 2013 Google Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24 #include <assert.h>
25 #include <compiler.h>
26 #include <debug.h>
27 #include <printf.h>
28 #include <err.h>
29
30 #include <dev/gpio.h>
31 #include <dev/gpio_i2c.h>
32 #include <kernel/mutex.h>
33
34 #if (!(defined(GPIO_I2C_BUS_COUNT)) || (GPIO_I2C_BUS_COUNT <= 0))
35 #error ERROR: Must define GPIO_I2C_BUS_COUNT
36 #endif
37
38 #if GPIO_I2C_PULLUPS
39 #define GPIO_I2C_INPUT (GPIO_INPUT | GPIO_PULLUP)
40 #else
41 #define GPIO_I2C_INPUT (GPIO_INPUT)
42 #endif // GPIO_I2C_PULLUPS
43
44 typedef struct gpio_i2c_state {
45 mutex_t lock;
46 const gpio_i2c_info_t *info;
47 } gpio_i2c_state_t;
48
49 static gpio_i2c_state_t gpio_i2c_states[GPIO_I2C_BUS_COUNT];
50
51 /******************************************************************************
52 *
53 * Internal implementation.
54 *
55 ******************************************************************************/
send_start(const gpio_i2c_info_t * i)56 static inline void send_start(const gpio_i2c_info_t *i)
57 {
58 gpio_config(i->sda, GPIO_OUTPUT);
59 spin_cycles(i->qcd);
60 gpio_config(i->scl, GPIO_OUTPUT);
61 spin_cycles(i->hcd);
62 }
63
send_stop(const gpio_i2c_info_t * i)64 static inline void send_stop(const gpio_i2c_info_t *i)
65 {
66 gpio_config(i->sda, GPIO_OUTPUT);
67 gpio_config(i->scl, GPIO_I2C_INPUT);
68 spin_cycles(i->qcd);
69 gpio_config(i->sda, GPIO_I2C_INPUT);
70 }
71
send_restart(const gpio_i2c_info_t * i)72 static inline void send_restart(const gpio_i2c_info_t *i)
73 {
74 gpio_config(i->scl, GPIO_I2C_INPUT);
75 spin_cycles(i->qcd);
76 send_start(i);
77 }
78
send_nack(const gpio_i2c_info_t * i)79 static inline void send_nack(const gpio_i2c_info_t *i)
80 {
81 spin_cycles(i->hcd);
82 gpio_config(i->scl, GPIO_I2C_INPUT);
83 spin_cycles(i->hcd);
84 gpio_config(i->scl, GPIO_OUTPUT);
85 gpio_config(i->sda, GPIO_I2C_INPUT);
86 }
87
send_ack(const gpio_i2c_info_t * i)88 static inline void send_ack(const gpio_i2c_info_t *i)
89 {
90 gpio_config(i->sda, GPIO_OUTPUT);
91 send_nack(i);
92 }
93
send_byte(const gpio_i2c_info_t * i,uint32_t b)94 static inline bool send_byte(const gpio_i2c_info_t *i, uint32_t b)
95 {
96 bool ret;
97
98 for (size_t j = 0; j < 8; ++j) {
99 if (b & 0x80)
100 gpio_config(i->sda, GPIO_I2C_INPUT);
101 else
102 gpio_config(i->sda, GPIO_OUTPUT);
103 b <<= 1;
104 /* setup time for data (the time between when data becomes stable and
105 * clock becomes a stable high) is spec'ed to be 250ns for 100KHz i2c
106 * and 100nsec for 400KHz i2c. If any micro running LK needs to spin
107 * here in order to hit that timing, they are welcome to add a spin
108 * right here.
109 */
110 spin_cycles(i->hcd);
111 gpio_config(i->scl, GPIO_I2C_INPUT);
112 spin_cycles(i->hcd);
113 gpio_config(i->scl, GPIO_OUTPUT);
114 }
115
116 gpio_config(i->sda, GPIO_I2C_INPUT);
117 spin_cycles(i->hcd);
118 gpio_config(i->scl, GPIO_I2C_INPUT);
119 spin_cycles(i->hcd);
120 ret = (0 == gpio_get(i->sda));
121 gpio_config(i->scl, GPIO_OUTPUT);
122 spin_cycles(i->hcd);
123
124 return ret;
125 }
126
recv_byte(const gpio_i2c_info_t * i,uint8_t * b)127 static inline void recv_byte(const gpio_i2c_info_t *i, uint8_t *b)
128 {
129 uint32_t tmp = 0;
130
131 for (size_t j = 0; j < 7; ++j) {
132 gpio_config(i->scl, GPIO_I2C_INPUT);
133 spin_cycles(i->hcd);
134 if (gpio_get(i->sda))
135 tmp |= 1;
136 tmp <<= 1;
137 gpio_config(i->scl, GPIO_OUTPUT);
138 spin_cycles(i->hcd);
139 }
140
141 gpio_config(i->scl, GPIO_I2C_INPUT);
142 spin_cycles(i->hcd);
143 if (gpio_get(i->sda))
144 tmp |= 1;
145 gpio_config(i->scl, GPIO_OUTPUT);
146
147 *b = (uint8_t)tmp;
148 }
149
gpio_i2c_tx_common(gpio_i2c_state_t * s,uint8_t address,const uint8_t * reg,const void * buf,size_t cnt)150 static status_t gpio_i2c_tx_common(gpio_i2c_state_t *s,
151 uint8_t address,
152 const uint8_t *reg,
153 const void *buf,
154 size_t cnt)
155 {
156 const gpio_i2c_info_t *i = s->info;
157 status_t ret = ERR_I2C_NACK;
158
159 DEBUG_ASSERT(buf || !cnt);
160
161 mutex_acquire(&s->lock);
162 send_start(i);
163 if (!send_byte(i, address << 1))
164 goto finished;
165
166 if ((NULL != reg) && !send_byte(i, *reg))
167 goto finished;
168
169 for (size_t j = 0; j < cnt; ++j)
170 if (!send_byte(i, ((const uint8_t *)buf)[j]))
171 goto finished;
172
173 ret = NO_ERROR;
174
175 finished:
176 send_stop(i);
177 mutex_release(&s->lock);
178 return ret;
179 }
180
gpio_i2c_rx_common(gpio_i2c_state_t * s,uint8_t address,const uint8_t * reg,void * buf,size_t cnt)181 static status_t gpio_i2c_rx_common(gpio_i2c_state_t *s,
182 uint8_t address,
183 const uint8_t *reg,
184 void *buf,
185 size_t cnt)
186 {
187 const gpio_i2c_info_t *i = s->info;
188 status_t ret = ERR_I2C_NACK;
189
190 DEBUG_ASSERT(buf && cnt);
191
192 address <<= 1;
193
194 mutex_acquire(&s->lock);
195 send_start(i);
196 if (!send_byte(i, address | (!reg ? 0x1 : 0x0)))
197 goto finished;
198
199 if (NULL != reg) {
200 if (!send_byte(i, *reg))
201 goto finished;
202
203 send_restart(i);
204
205 if (!send_byte(i, address | 0x1))
206 goto finished;
207 }
208
209 recv_byte(i, buf++);
210 for (size_t j = 0; j < (cnt - 1); ++j) {
211 send_ack(i);
212 recv_byte(i, buf++);
213 }
214 send_nack(i);
215 ret = NO_ERROR;
216
217 finished:
218 send_stop(i);
219 mutex_release(&s->lock);
220 return ret;
221 }
222
gpio_i2c_add_bus(uint32_t bus_id,const gpio_i2c_info_t * info)223 void gpio_i2c_add_bus(uint32_t bus_id, const gpio_i2c_info_t *info)
224 {
225 gpio_i2c_state_t *s = gpio_i2c_states + bus_id;
226
227 DEBUG_ASSERT(info);
228 DEBUG_ASSERT(bus_id < GPIO_I2C_BUS_COUNT);
229 DEBUG_ASSERT(!s->info);
230
231 gpio_config(info->scl, GPIO_I2C_INPUT);
232 gpio_config(info->sda, GPIO_I2C_INPUT);
233 gpio_set(info->scl, 0);
234 gpio_set(info->sda, 0);
235
236 mutex_init(&s->lock);
237 s->info = info;
238 }
239
240 /******************************************************************************
241 *
242 * LK facing API
243 *
244 * *****************************************************************************/
gpio_i2c_init_early(void)245 void gpio_i2c_init_early(void) { }
gpio_i2c_init(void)246 void gpio_i2c_init(void) { }
247
gpio_i2c_transmit(int bus,uint8_t address,const void * buf,size_t cnt)248 status_t gpio_i2c_transmit(int bus, uint8_t address, const void *buf, size_t cnt)
249 {
250 gpio_i2c_state_t *s = gpio_i2c_states + bus;
251 if (((unsigned)bus >= countof(gpio_i2c_states)) || !s->info)
252 return ERR_NOT_FOUND;
253
254 return gpio_i2c_tx_common(s, address, NULL, buf, cnt);
255 }
256
gpio_i2c_receive(int bus,uint8_t address,void * buf,size_t cnt)257 status_t gpio_i2c_receive(int bus, uint8_t address, void *buf, size_t cnt)
258 {
259 gpio_i2c_state_t *s = gpio_i2c_states + bus;
260 if (((unsigned)bus >= countof(gpio_i2c_states)) || !s->info)
261 return ERR_NOT_FOUND;
262
263 return gpio_i2c_rx_common(s, address, NULL, buf, cnt);
264 }
265
gpio_i2c_write_reg_bytes(int bus,uint8_t address,uint8_t reg,const uint8_t * buf,size_t cnt)266 status_t gpio_i2c_write_reg_bytes(int bus, uint8_t address, uint8_t reg, const uint8_t *buf, size_t cnt)
267 {
268 gpio_i2c_state_t *s = gpio_i2c_states + bus;
269 if (((unsigned)bus >= countof(gpio_i2c_states)) || !s->info)
270 return ERR_NOT_FOUND;
271
272 return gpio_i2c_tx_common(s, address, ®, buf, cnt);
273 }
274
gpio_i2c_read_reg_bytes(int bus,uint8_t address,uint8_t reg,uint8_t * buf,size_t cnt)275 status_t gpio_i2c_read_reg_bytes(int bus, uint8_t address, uint8_t reg, uint8_t *buf, size_t cnt)
276 {
277 gpio_i2c_state_t *s = gpio_i2c_states + bus;
278 if (((unsigned)bus >= countof(gpio_i2c_states)) || !s->info) {
279 return ERR_NOT_FOUND;
280 }
281
282 return gpio_i2c_rx_common(s, address, ®, buf, cnt);
283 }
284
285 void i2c_init_early(void) __WEAK_ALIAS("gpio_i2c_init_early");
286 void i2c_init(void) __WEAK_ALIAS("gpio_i2c_init");
287 status_t i2c_transmit(int, uint8_t, const void *, size_t) __WEAK_ALIAS("gpio_i2c_transmit");
288 status_t i2c_receive(int, uint8_t, void *, size_t) __WEAK_ALIAS("gpio_i2c_receive");
289 status_t i2c_write_reg_bytes(int, uint8_t, uint8_t,
290 const uint8_t *, size_t) __WEAK_ALIAS("gpio_i2c_write_reg_bytes");
291 status_t i2c_read_reg_bytes(int, uint8_t, uint8_t,
292 uint8_t *, size_t) __WEAK_ALIAS("gpio_i2c_read_reg_bytes");
293