1 /*
2  * Copyright (c) 2013 Google Inc.
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 
9 #include <assert.h>
10 #include <lk/compiler.h>
11 #include <lk/debug.h>
12 #include <printf.h>
13 #include <lk/err.h>
14 
15 #include <dev/gpio.h>
16 #include <dev/gpio_i2c.h>
17 #include <kernel/mutex.h>
18 
19 #if (!(defined(GPIO_I2C_BUS_COUNT)) || (GPIO_I2C_BUS_COUNT <= 0))
20 #error ERROR: Must define GPIO_I2C_BUS_COUNT
21 #endif
22 
23 #if GPIO_I2C_PULLUPS
24 #define GPIO_I2C_INPUT (GPIO_INPUT | GPIO_PULLUP)
25 #else
26 #define GPIO_I2C_INPUT (GPIO_INPUT)
27 #endif  // GPIO_I2C_PULLUPS
28 
29 typedef struct gpio_i2c_state {
30     mutex_t                 lock;
31     const gpio_i2c_info_t  *info;
32 } gpio_i2c_state_t;
33 
34 static gpio_i2c_state_t gpio_i2c_states[GPIO_I2C_BUS_COUNT];
35 
36 /******************************************************************************
37  *
38  * Internal implementation.
39  *
40  ******************************************************************************/
send_start(const gpio_i2c_info_t * i)41 static inline void send_start(const gpio_i2c_info_t *i) {
42     gpio_config(i->sda, GPIO_OUTPUT);
43     spin_cycles(i->qcd);
44     gpio_config(i->scl, GPIO_OUTPUT);
45     spin_cycles(i->hcd);
46 }
47 
send_stop(const gpio_i2c_info_t * i)48 static inline void send_stop(const gpio_i2c_info_t *i) {
49     gpio_config(i->sda, GPIO_OUTPUT);
50     gpio_config(i->scl, GPIO_I2C_INPUT);
51     spin_cycles(i->qcd);
52     gpio_config(i->sda, GPIO_I2C_INPUT);
53 }
54 
send_restart(const gpio_i2c_info_t * i)55 static inline void send_restart(const gpio_i2c_info_t *i) {
56     gpio_config(i->scl, GPIO_I2C_INPUT);
57     spin_cycles(i->qcd);
58     send_start(i);
59 }
60 
send_nack(const gpio_i2c_info_t * i)61 static inline void send_nack(const gpio_i2c_info_t *i) {
62     spin_cycles(i->hcd);
63     gpio_config(i->scl, GPIO_I2C_INPUT);
64     spin_cycles(i->hcd);
65     gpio_config(i->scl, GPIO_OUTPUT);
66     gpio_config(i->sda, GPIO_I2C_INPUT);
67 }
68 
send_ack(const gpio_i2c_info_t * i)69 static inline void send_ack(const gpio_i2c_info_t *i) {
70     gpio_config(i->sda, GPIO_OUTPUT);
71     send_nack(i);
72 }
73 
send_byte(const gpio_i2c_info_t * i,uint32_t b)74 static inline bool send_byte(const gpio_i2c_info_t *i, uint32_t b) {
75     bool ret;
76 
77     for (size_t j = 0; j < 8; ++j) {
78         if (b & 0x80)
79             gpio_config(i->sda, GPIO_I2C_INPUT);
80         else
81             gpio_config(i->sda, GPIO_OUTPUT);
82         b <<= 1;
83         /* setup time for data (the time between when data becomes stable and
84          * clock becomes a stable high) is spec'ed to be 250ns for 100KHz i2c
85          * and 100nsec for 400KHz i2c.  If any micro running LK needs to spin
86          * here in order to hit that timing, they are welcome to add a spin
87          * right here.
88          */
89         spin_cycles(i->hcd);
90         gpio_config(i->scl, GPIO_I2C_INPUT);
91         spin_cycles(i->hcd);
92         gpio_config(i->scl, GPIO_OUTPUT);
93     }
94 
95     gpio_config(i->sda, GPIO_I2C_INPUT);
96     spin_cycles(i->hcd);
97     gpio_config(i->scl, GPIO_I2C_INPUT);
98     spin_cycles(i->hcd);
99     ret = (0 == gpio_get(i->sda));
100     gpio_config(i->scl, GPIO_OUTPUT);
101     spin_cycles(i->hcd);
102 
103     return ret;
104 }
105 
recv_byte(const gpio_i2c_info_t * i,uint8_t * b)106 static inline void recv_byte(const gpio_i2c_info_t *i, uint8_t *b) {
107     uint32_t tmp = 0;
108 
109     for (size_t j = 0; j < 7; ++j) {
110         gpio_config(i->scl, GPIO_I2C_INPUT);
111         spin_cycles(i->hcd);
112         if (gpio_get(i->sda))
113             tmp |= 1;
114         tmp <<= 1;
115         gpio_config(i->scl, GPIO_OUTPUT);
116         spin_cycles(i->hcd);
117     }
118 
119     gpio_config(i->scl, GPIO_I2C_INPUT);
120     spin_cycles(i->hcd);
121     if (gpio_get(i->sda))
122         tmp |= 1;
123     gpio_config(i->scl, GPIO_OUTPUT);
124 
125     *b = (uint8_t)tmp;
126 }
127 
gpio_i2c_tx_common(gpio_i2c_state_t * s,uint8_t address,const uint8_t * reg,const void * buf,size_t cnt)128 static status_t gpio_i2c_tx_common(gpio_i2c_state_t *s,
129                                    uint8_t address,
130                                    const uint8_t *reg,
131                                    const void *buf,
132                                    size_t cnt) {
133     const gpio_i2c_info_t *i = s->info;
134     status_t ret = ERR_I2C_NACK;
135 
136     DEBUG_ASSERT(buf || !cnt);
137 
138     mutex_acquire(&s->lock);
139     send_start(i);
140     if (!send_byte(i, address << 1))
141         goto finished;
142 
143     if ((NULL != reg) && !send_byte(i, *reg))
144         goto finished;
145 
146     for (size_t j = 0; j < cnt; ++j)
147         if (!send_byte(i, ((const uint8_t *)buf)[j]))
148             goto finished;
149 
150     ret = NO_ERROR;
151 
152 finished:
153     send_stop(i);
154     mutex_release(&s->lock);
155     return ret;
156 }
157 
gpio_i2c_rx_common(gpio_i2c_state_t * s,uint8_t address,const uint8_t * reg,void * buf,size_t cnt)158 static status_t gpio_i2c_rx_common(gpio_i2c_state_t *s,
159                                    uint8_t address,
160                                    const uint8_t *reg,
161                                    void *buf,
162                                    size_t cnt) {
163     const gpio_i2c_info_t *i = s->info;
164     status_t ret = ERR_I2C_NACK;
165 
166     DEBUG_ASSERT(buf && cnt);
167 
168     address <<= 1;
169 
170     mutex_acquire(&s->lock);
171     send_start(i);
172     if (!send_byte(i, address | (!reg ? 0x1 : 0x0)))
173         goto finished;
174 
175     if (NULL != reg) {
176         if (!send_byte(i, *reg))
177             goto finished;
178 
179         send_restart(i);
180 
181         if (!send_byte(i, address | 0x1))
182             goto finished;
183     }
184 
185     recv_byte(i, buf++);
186     for (size_t j = 0; j < (cnt - 1); ++j) {
187         send_ack(i);
188         recv_byte(i, buf++);
189     }
190     send_nack(i);
191     ret = NO_ERROR;
192 
193 finished:
194     send_stop(i);
195     mutex_release(&s->lock);
196     return ret;
197 }
198 
gpio_i2c_add_bus(uint32_t bus_id,const gpio_i2c_info_t * info)199 void gpio_i2c_add_bus(uint32_t bus_id, const gpio_i2c_info_t *info) {
200     gpio_i2c_state_t *s = gpio_i2c_states + bus_id;
201 
202     DEBUG_ASSERT(info);
203     DEBUG_ASSERT(bus_id < GPIO_I2C_BUS_COUNT);
204     DEBUG_ASSERT(!s->info);
205 
206     gpio_config(info->scl, GPIO_I2C_INPUT);
207     gpio_config(info->sda, GPIO_I2C_INPUT);
208     gpio_set(info->scl, 0);
209     gpio_set(info->sda, 0);
210 
211     mutex_init(&s->lock);
212     s->info = info;
213 }
214 
215 /******************************************************************************
216 *
217 *  LK facing API
218 *
219 * *****************************************************************************/
gpio_i2c_init_early(void)220 void gpio_i2c_init_early(void) { }
gpio_i2c_init(void)221 void gpio_i2c_init(void) { }
222 
gpio_i2c_transmit(int bus,uint8_t address,const void * buf,size_t cnt)223 status_t gpio_i2c_transmit(int bus, uint8_t address, const void *buf, size_t cnt) {
224     gpio_i2c_state_t *s = gpio_i2c_states + bus;
225     if (((unsigned)bus >= countof(gpio_i2c_states)) || !s->info)
226         return ERR_NOT_FOUND;
227 
228     return gpio_i2c_tx_common(s, address, NULL, buf, cnt);
229 }
230 
gpio_i2c_receive(int bus,uint8_t address,void * buf,size_t cnt)231 status_t gpio_i2c_receive(int bus, uint8_t address, void *buf, size_t cnt) {
232     gpio_i2c_state_t *s = gpio_i2c_states + bus;
233     if (((unsigned)bus >= countof(gpio_i2c_states)) || !s->info)
234         return ERR_NOT_FOUND;
235 
236     return gpio_i2c_rx_common(s, address, NULL, buf, cnt);
237 }
238 
gpio_i2c_write_reg_bytes(int bus,uint8_t address,uint8_t reg,const uint8_t * buf,size_t cnt)239 status_t gpio_i2c_write_reg_bytes(int bus, uint8_t address, uint8_t reg, const uint8_t *buf, size_t cnt) {
240     gpio_i2c_state_t *s = gpio_i2c_states + bus;
241     if (((unsigned)bus >= countof(gpio_i2c_states)) || !s->info)
242         return ERR_NOT_FOUND;
243 
244     return gpio_i2c_tx_common(s, address, &reg, buf, cnt);
245 }
246 
gpio_i2c_read_reg_bytes(int bus,uint8_t address,uint8_t reg,uint8_t * buf,size_t cnt)247 status_t gpio_i2c_read_reg_bytes(int bus, uint8_t address, uint8_t reg, uint8_t *buf, size_t cnt) {
248     gpio_i2c_state_t *s = gpio_i2c_states + bus;
249     if (((unsigned)bus >= countof(gpio_i2c_states)) || !s->info) {
250         return ERR_NOT_FOUND;
251     }
252 
253     return gpio_i2c_rx_common(s, address, &reg, buf, cnt);
254 }
255 
256 void i2c_init_early(void) __WEAK_ALIAS("gpio_i2c_init_early");
257 void i2c_init(void) __WEAK_ALIAS("gpio_i2c_init");
258 status_t i2c_transmit(int, uint8_t, const void *, size_t) __WEAK_ALIAS("gpio_i2c_transmit");
259 status_t i2c_receive(int, uint8_t, void *, size_t) __WEAK_ALIAS("gpio_i2c_receive");
260 status_t i2c_write_reg_bytes(int, uint8_t, uint8_t,
261                              const uint8_t *, size_t) __WEAK_ALIAS("gpio_i2c_write_reg_bytes");
262 status_t i2c_read_reg_bytes(int, uint8_t, uint8_t,
263                             uint8_t *, size_t) __WEAK_ALIAS("gpio_i2c_read_reg_bytes");
264