1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <ddk/binding.h>
6 #include <ddk/debug.h>
7 #include <ddk/device.h>
8 #include <ddk/mmio-buffer.h>
9 #include <ddk/platform-defs.h>
10 #include <ddk/protocol/i2cimpl.h>
11 #include <ddk/protocol/platform/bus.h>
12 #include <ddk/protocol/platform/device.h>
13 #include <ddk/protocol/platform-device-lib.h>
14 #include <hw/reg.h>
15 #include <lib/sync/completion.h>
16 #include <zircon/process.h>
17 #include <zircon/assert.h>
18 
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <threads.h>
24 
25 #include "dw-i2c-regs.h"
26 
27 typedef struct {
28     zx_handle_t                     irq_handle;
29     zx_handle_t                     event_handle;
30     mmio_buffer_t                   regs_iobuff;
31     zx_duration_t                   timeout;
32 
33     uint32_t                        tx_fifo_depth;
34     uint32_t                        rx_fifo_depth;
35 } i2c_dw_dev_t;
36 
37 typedef struct {
38     pdev_protocol_t pdev;
39     i2c_impl_protocol_t i2c;
40     zx_device_t* zxdev;
41     i2c_dw_dev_t* i2c_devs;
42     size_t i2c_dev_count;
43 } i2c_dw_t;
44 
45 static zx_status_t i2c_dw_read(i2c_dw_dev_t* dev, uint8_t *buff, uint32_t len, bool stop);
46 static zx_status_t i2c_dw_write(i2c_dw_dev_t* dev, const uint8_t *buff, uint32_t len, bool stop);
47 static zx_status_t i2c_dw_set_slave_addr(i2c_dw_dev_t* dev, uint16_t addr);
48 
i2c_dw_dumpstate(i2c_dw_dev_t * dev)49 zx_status_t i2c_dw_dumpstate(i2c_dw_dev_t* dev) {
50     zxlogf(INFO, "########################\n");
51     zxlogf(INFO, "%s\n", __FUNCTION__);
52     zxlogf(INFO, "########################\n");
53     zxlogf(INFO, "DW_I2C_ENABLE_STATUS = \t0x%x\n", I2C_DW_READ32(DW_I2C_ENABLE_STATUS));
54     zxlogf(INFO, "DW_I2C_ENABLE = \t0x%x\n", I2C_DW_READ32(DW_I2C_ENABLE));
55     zxlogf(INFO, "DW_I2C_CON = \t0x%x\n", I2C_DW_READ32(DW_I2C_CON));
56     zxlogf(INFO, "DW_I2C_TAR = \t0x%x\n", I2C_DW_READ32(DW_I2C_TAR));
57     zxlogf(INFO, "DW_I2C_HS_MADDR = \t0x%x\n", I2C_DW_READ32(DW_I2C_HS_MADDR));
58     zxlogf(INFO, "DW_I2C_SS_SCL_HCNT = \t0x%x\n", I2C_DW_READ32(DW_I2C_SS_SCL_HCNT));
59     zxlogf(INFO, "DW_I2C_SS_SCL_LCNT = \t0x%x\n", I2C_DW_READ32(DW_I2C_SS_SCL_LCNT));
60     zxlogf(INFO, "DW_I2C_FS_SCL_HCNT = \t0x%x\n", I2C_DW_READ32(DW_I2C_FS_SCL_HCNT));
61     zxlogf(INFO, "DW_I2C_FS_SCL_LCNT = \t0x%x\n", I2C_DW_READ32(DW_I2C_FS_SCL_LCNT));
62     zxlogf(INFO, "DW_I2C_INTR_MASK = \t0x%x\n", I2C_DW_READ32(DW_I2C_INTR_MASK));
63     zxlogf(INFO, "DW_I2C_RAW_INTR_STAT = \t0x%x\n", I2C_DW_READ32(DW_I2C_RAW_INTR_STAT));
64     zxlogf(INFO, "DW_I2C_RX_TL = \t0x%x\n", I2C_DW_READ32(DW_I2C_RX_TL));
65     zxlogf(INFO, "DW_I2C_TX_TL = \t0x%x\n", I2C_DW_READ32(DW_I2C_TX_TL));
66     zxlogf(INFO, "DW_I2C_STATUS = \t0x%x\n", I2C_DW_READ32(DW_I2C_STATUS));
67     zxlogf(INFO, "DW_I2C_TXFLR = \t0x%x\n", I2C_DW_READ32(DW_I2C_TXFLR));
68     zxlogf(INFO, "DW_I2C_RXFLR = \t0x%x\n", I2C_DW_READ32(DW_I2C_RXFLR));
69     zxlogf(INFO, "DW_I2C_COMP_PARAM_1 = \t0x%x\n", I2C_DW_READ32(DW_I2C_COMP_PARAM_1));
70     zxlogf(INFO, "DW_I2C_TX_ABRT_SOURCE = \t0x%x\n", I2C_DW_READ32(DW_I2C_TX_ABRT_SOURCE));
71     return ZX_OK;
72 }
73 
i2c_dw_enable_wait(i2c_dw_dev_t * dev,bool enable)74 static zx_status_t i2c_dw_enable_wait(i2c_dw_dev_t* dev, bool enable) {
75     int max_poll = 100;
76     int poll = 0;
77 
78     // set enable bit to 0
79     I2C_DW_SET_BITS32(DW_I2C_ENABLE, DW_I2C_ENABLE_ENABLE_START, DW_I2C_ENABLE_ENABLE_BITS, enable);
80 
81     do {
82         if (I2C_DW_GET_BITS32(DW_I2C_ENABLE_STATUS, DW_I2C_ENABLE_STATUS_EN_START,
83                                                     DW_I2C_ENABLE_STATUS_EN_BITS) == enable) {
84             // we are done. exit
85             return ZX_OK;
86         }
87         // sleep 10 times the signaling period for the highest i2c transfer speed (400K) ~25uS
88         usleep(25);
89     } while (poll++ < max_poll);
90 
91     zxlogf(ERROR, "%s: Could not %s I2C contoller! DW_I2C_ENABLE_STATUS = 0x%x\n",
92                                                             __FUNCTION__,
93                                                             enable? "enable" : "disable",
94                                                             I2C_DW_READ32(DW_I2C_ENABLE_STATUS));
95     i2c_dw_dumpstate(dev);
96 
97     return ZX_ERR_TIMED_OUT;
98 }
99 
i2c_dw_enable(i2c_dw_dev_t * dev)100 static zx_status_t i2c_dw_enable(i2c_dw_dev_t* dev) {
101     return i2c_dw_enable_wait(dev, I2C_ENABLE);
102     return ZX_OK;
103 }
104 
i2c_dw_clear_interrupts(i2c_dw_dev_t * dev)105 static void i2c_dw_clear_interrupts(i2c_dw_dev_t* dev) {
106     I2C_DW_READ32(DW_I2C_CLR_INTR); // reading this register will clear all the interrupts
107 }
108 
i2c_dw_disable_interrupts(i2c_dw_dev_t * dev)109 static void i2c_dw_disable_interrupts(i2c_dw_dev_t* dev) {
110     I2C_DW_WRITE32(DW_I2C_INTR_MASK, 0);
111 }
112 
i2c_dw_enable_interrupts(i2c_dw_dev_t * dev,uint32_t flag)113 static void i2c_dw_enable_interrupts(i2c_dw_dev_t* dev, uint32_t flag) {
114     I2C_DW_WRITE32(DW_I2C_INTR_MASK, flag);
115 }
116 
i2c_dw_disable(i2c_dw_dev_t * dev)117 static zx_status_t i2c_dw_disable(i2c_dw_dev_t* dev) {
118     return i2c_dw_enable_wait(dev, I2C_DISABLE);
119 }
120 
i2c_dw_wait_event(i2c_dw_dev_t * dev,uint32_t sig_mask)121 static zx_status_t i2c_dw_wait_event(i2c_dw_dev_t* dev, uint32_t sig_mask) {
122     uint32_t    observed;
123     zx_time_t   deadline = zx_deadline_after(dev->timeout);
124 
125     sig_mask |= I2C_ERROR_SIGNAL;
126 
127     zx_status_t status = zx_object_wait_one(dev->event_handle, sig_mask, deadline, &observed);
128 
129     if (status != ZX_OK) {
130         return status;
131     }
132 
133     zx_object_signal(dev->event_handle, observed, 0);
134 
135     if (observed & I2C_ERROR_SIGNAL) {
136         return ZX_ERR_TIMED_OUT;
137     }
138 
139     return ZX_OK;
140 }
141 
142 // Thread to handle interrupts
i2c_dw_irq_thread(void * arg)143 static int i2c_dw_irq_thread(void* arg) {
144     i2c_dw_dev_t* dev = (i2c_dw_dev_t*)arg;
145     zx_status_t status;
146 
147     while (1) {
148         status = zx_interrupt_wait(dev->irq_handle, NULL);
149         if (status != ZX_OK) {
150             zxlogf(ERROR, "%s: irq wait failed, retcode = %d\n", __FUNCTION__, status);
151             continue;
152         }
153 
154         uint32_t reg = I2C_DW_READ32(DW_I2C_RAW_INTR_STAT);
155         if (reg & DW_I2C_INTR_TX_ABRT) {
156             // some sort of error has occurred. figure it out
157             i2c_dw_dumpstate(dev);
158             zx_object_signal(dev->event_handle, 0, I2C_ERROR_SIGNAL);
159             zxlogf(ERROR, "i2c: error on bus\n");
160         } else {
161             zx_object_signal(dev->event_handle, 0, I2C_TXN_COMPLETE_SIGNAL);
162         }
163         i2c_dw_clear_interrupts(dev);
164         i2c_dw_disable_interrupts(dev);
165     }
166 
167     return ZX_OK;
168 }
169 
i2c_dw_transact(void * ctx,uint32_t bus_id,const i2c_impl_op_t * rws,size_t count)170 static zx_status_t i2c_dw_transact(void* ctx, uint32_t bus_id, const i2c_impl_op_t* rws,
171                                    size_t count) {
172     size_t i;
173     for (i = 0; i < count; ++i) {
174         if (rws[i].data_size > I2C_DW_MAX_TRANSFER) {
175             return ZX_ERR_OUT_OF_RANGE;
176         }
177     }
178 
179     i2c_dw_t* i2c = ctx;
180 
181     if (bus_id >= i2c->i2c_dev_count) {
182         return ZX_ERR_INVALID_ARGS;
183     }
184 
185     i2c_dw_dev_t* dev = &i2c->i2c_devs[bus_id];
186 
187     if (count == 0) {
188         return ZX_OK;
189     }
190     for (i = 1; i < count; ++i) {
191         if (rws[i].address != rws[0].address) {
192             return ZX_ERR_NOT_SUPPORTED;
193         }
194     }
195     i2c_dw_set_slave_addr(dev, rws[0].address);
196     i2c_dw_enable(dev);
197     i2c_dw_disable_interrupts(dev);
198     i2c_dw_clear_interrupts(dev);
199 
200     zx_status_t status = ZX_OK;
201     for (i = 0; i < count; ++i) {
202         if (rws[i].is_read) {
203             status = i2c_dw_read(dev, rws[i].data_buffer, rws[i].data_size, rws[i].stop);
204         } else {
205             status = i2c_dw_write(dev, rws[i].data_buffer, rws[i].data_size, rws[i].stop);
206         }
207         if (status != ZX_OK) {
208             return status; // TODO(andresoportus) release the bus
209         }
210     }
211 
212     i2c_dw_disable_interrupts(dev);
213     i2c_dw_clear_interrupts(dev);
214     i2c_dw_disable(dev);
215 
216     return status;
217 }
218 
i2c_dw_set_bitrate(void * ctx,uint32_t bus_id,uint32_t bitrate)219 static zx_status_t i2c_dw_set_bitrate(void* ctx, uint32_t bus_id, uint32_t bitrate) {
220     // TODO: Can't implement due to lack of HI3660 documentation
221     return ZX_ERR_NOT_SUPPORTED;
222 }
223 
i2c_dw_get_bus_count(void * ctx)224 static uint32_t i2c_dw_get_bus_count(void* ctx) {
225     i2c_dw_t* i2c = ctx;
226 
227     return i2c->i2c_dev_count;
228 }
229 
i2c_dw_get_max_transfer_size(void * ctx,uint32_t bus_id,size_t * out_size)230 static zx_status_t i2c_dw_get_max_transfer_size(void* ctx, uint32_t bus_id, size_t* out_size) {
231     *out_size = I2C_DW_MAX_TRANSFER;
232     return ZX_OK;
233 }
234 
i2c_dw_set_slave_addr(i2c_dw_dev_t * dev,uint16_t addr)235 static zx_status_t i2c_dw_set_slave_addr(i2c_dw_dev_t* dev, uint16_t addr) {
236     addr &= 0x7f; // support 7bit for now
237     uint32_t reg = I2C_DW_READ32(DW_I2C_TAR);
238     reg = I2C_DW_SET_MASK(reg, DW_I2C_TAR_TAR_START, DW_I2C_TAR_TAR_BITS, addr);
239     reg = I2C_DW_SET_MASK(reg, DW_I2C_TAR_10BIT_START, DW_I2C_TAR_10BIT_BITS, 0);
240     I2C_DW_WRITE32(DW_I2C_TAR, reg);
241     return ZX_OK;
242 }
243 
i2c_dw_read(i2c_dw_dev_t * dev,uint8_t * buff,uint32_t len,bool stop)244 static zx_status_t i2c_dw_read(i2c_dw_dev_t* dev, uint8_t *buff, uint32_t len, bool stop) {
245      uint32_t rx_limit;
246 
247     ZX_DEBUG_ASSERT(len <= I2C_DW_MAX_TRANSFER);
248     rx_limit = dev->rx_fifo_depth - I2C_DW_READ32(DW_I2C_RXFLR);
249     ZX_DEBUG_ASSERT(len <= rx_limit);
250 
251     // set threshold to the number of bytes we want to read - 1
252     I2C_DW_SET_BITS32(DW_I2C_RX_TL, DW_I2C_RX_TL_START, DW_I2C_RX_TL_BITS, len-1);
253 
254     while (len > 0) {
255         uint32_t cmd = 0;
256         // send STOP cmd if last byte and stop set
257         if (len == 1 && stop) {
258             cmd = I2C_DW_SET_MASK(cmd, DW_I2C_DATA_CMD_STOP_START, DW_I2C_DATA_CMD_STOP_BITS, 1);
259         }
260         I2C_DW_WRITE32(DW_I2C_DATA_CMD, cmd | (1 << DW_I2C_DATA_CMD_CMD_START));
261         len--;
262     }
263 
264     i2c_dw_enable_interrupts(dev, DW_I2C_INTR_READ_INTR_MASK);
265     zx_status_t status = i2c_dw_wait_event(dev, I2C_TXN_COMPLETE_SIGNAL);
266     if (status != ZX_OK) {
267         return status;
268     }
269 
270     uint32_t avail_read = I2C_DW_READ32(DW_I2C_RXFLR);
271     for (uint32_t i = 0; i < avail_read; i++) {
272         buff[i] = I2C_DW_GET_BITS32(DW_I2C_DATA_CMD, DW_I2C_DATA_CMD_DAT_START,
273                                                                         DW_I2C_DATA_CMD_DAT_BITS);
274     }
275 
276     return ZX_OK;
277 }
278 
i2c_dw_write(i2c_dw_dev_t * dev,const uint8_t * buff,uint32_t len,bool stop)279 static zx_status_t i2c_dw_write(i2c_dw_dev_t* dev, const uint8_t *buff, uint32_t len, bool stop) {
280     uint32_t tx_limit;
281 
282     ZX_DEBUG_ASSERT(len <= I2C_DW_MAX_TRANSFER);
283     tx_limit = dev->tx_fifo_depth - I2C_DW_READ32(DW_I2C_TXFLR);
284     ZX_DEBUG_ASSERT(len <= tx_limit);
285     while (len > 0) {
286         uint32_t cmd = 0;
287         // send STOP cmd if last byte and stop set
288         if (len == 1 && stop) {
289             cmd = I2C_DW_SET_MASK(cmd, DW_I2C_DATA_CMD_STOP_START, DW_I2C_DATA_CMD_STOP_BITS, 1);
290         }
291         I2C_DW_WRITE32(DW_I2C_DATA_CMD, cmd | *buff++);
292         len--;
293     }
294 
295     // at this point, we have to wait until all data has been transmitted.
296     i2c_dw_enable_interrupts(dev, DW_I2C_INTR_DEFAULT_INTR_MASK);
297     zx_status_t status = i2c_dw_wait_event(dev, I2C_TXN_COMPLETE_SIGNAL);
298     if (status != ZX_OK) {
299         return status;
300     }
301 
302     return ZX_OK;
303 }
304 
i2c_dw_host_init(i2c_dw_dev_t * dev)305 static zx_status_t i2c_dw_host_init(i2c_dw_dev_t* dev) {
306     uint32_t dw_comp_type;
307     uint32_t regval;
308 
309     // Make sure we are truly running on a DesignWire IP
310     dw_comp_type = I2C_DW_READ32(DW_I2C_COMP_TYPE);
311 
312     if (dw_comp_type != I2C_DW_COMP_TYPE_NUM) {
313         zxlogf(ERROR, "%s: Incompatible IP Block detected. Expected = 0x%x, Actual = 0x%x\n",
314             __FUNCTION__, I2C_DW_COMP_TYPE_NUM, dw_comp_type);
315 
316         return ZX_ERR_NOT_SUPPORTED;
317     }
318 
319     // read the various capabilities of the component
320     dev->tx_fifo_depth = I2C_DW_GET_BITS32(DW_I2C_COMP_PARAM_1,
321                                                         DW_I2C_COMP_PARAM_1_TXFIFOSZ_START,
322                                                         DW_I2C_COMP_PARAM_1_TXFIFOSZ_BITS);
323     dev->rx_fifo_depth = I2C_DW_GET_BITS32(DW_I2C_COMP_PARAM_1,
324                                                         DW_I2C_COMP_PARAM_1_RXFIFOSZ_START,
325                                                         DW_I2C_COMP_PARAM_1_RXFIFOSZ_BITS);
326 
327     /* I2C Block Initialization based on DW_apb_i2c_databook Section 7.3 */
328 
329     // Disable I2C Block
330     i2c_dw_disable(dev);
331 
332     // Configure the controller:
333     // - Slave Disable
334     regval = 0;
335     regval = I2C_DW_SET_MASK(regval, DW_I2C_CON_SLAVE_DIS_START,
336                                                         DW_I2C_CON_SLAVE_DIS_BITS,
337                                                         I2C_ENABLE);
338 
339     // - Enable restart mode
340     regval = I2C_DW_SET_MASK(regval, DW_I2C_CON_RESTART_EN_START,
341                                                         DW_I2C_CON_RESTART_EN_BITS,
342                                                         I2C_ENABLE);
343 
344     // - Set 7-bit address modeset
345     regval = I2C_DW_SET_MASK(regval, DW_I2C_CON_10BITADDRSLAVE_START,
346                                                         DW_I2C_CON_10BITADDRSLAVE_BITS,
347                                                         I2C_7BIT_ADDR);
348     regval = I2C_DW_SET_MASK(regval, DW_I2C_CON_10BITADDRMASTER_START,
349                                                         DW_I2C_CON_10BITADDRMASTER_BITS,
350                                                         I2C_7BIT_ADDR);
351 
352     // - Set speed to fast, master enable
353     regval = I2C_DW_SET_MASK(regval, DW_I2C_CON_SPEED_START,
354                                                         DW_I2C_CON_SPEED_BITS,
355                                                         I2C_FAST_MODE);
356 
357     // - Set master enable
358     regval = I2C_DW_SET_MASK(regval, DW_I2C_CON_MASTER_MODE_START,
359                                                         DW_I2C_CON_MASTER_MODE_BITS,
360                                                         I2C_ENABLE);
361 
362     // write final mask
363     I2C_DW_WRITE32(DW_I2C_CON, regval);
364 
365     // Write SS/FS LCNT and HCNT
366     // FIXME: for now I am using the magical numbers from android source
367     I2C_DW_SET_BITS32(DW_I2C_SS_SCL_HCNT, DW_I2C_SS_SCL_HCNT_START, DW_I2C_SS_SCL_HCNT_BITS, 0x87);
368     I2C_DW_SET_BITS32(DW_I2C_SS_SCL_LCNT, DW_I2C_SS_SCL_LCNT_START, DW_I2C_SS_SCL_LCNT_BITS, 0x9f);
369     I2C_DW_SET_BITS32(DW_I2C_FS_SCL_HCNT, DW_I2C_FS_SCL_HCNT_START, DW_I2C_FS_SCL_HCNT_BITS, 0x1a);
370     I2C_DW_SET_BITS32(DW_I2C_FS_SCL_LCNT, DW_I2C_FS_SCL_LCNT_START, DW_I2C_FS_SCL_LCNT_BITS, 0x32);
371 
372     // Setup TX FIFO Thresholds
373     I2C_DW_SET_BITS32(DW_I2C_TX_TL, DW_I2C_TX_TL_START, DW_I2C_TX_TL_BITS, 0);
374 
375     // disable interrupts
376     i2c_dw_disable_interrupts(dev);
377 
378     return ZX_OK;
379 }
380 
i2c_dw_init(i2c_dw_t * i2c,uint32_t index)381 static zx_status_t i2c_dw_init(i2c_dw_t* i2c, uint32_t index) {
382     zx_status_t status;
383 
384     i2c_dw_dev_t* device = &i2c->i2c_devs[index];
385 
386     device->timeout = ZX_SEC(10);
387 
388     status = pdev_map_mmio_buffer2(&i2c->pdev, index, ZX_CACHE_POLICY_UNCACHED_DEVICE,
389                                    &device->regs_iobuff);
390     if (status != ZX_OK) {
391         zxlogf(ERROR, "%s: pdev_map_mmio_buffer failed %d\n", __FUNCTION__, status);
392         goto init_fail;
393     }
394 
395     status = pdev_map_interrupt(&i2c->pdev, index, &device->irq_handle);
396     if (status != ZX_OK) {
397         goto init_fail;
398     }
399 
400     status = zx_event_create(0, &device->event_handle);
401     if (status != ZX_OK) {
402         goto init_fail;
403     }
404 
405     // initialize i2c host controller
406     status = i2c_dw_host_init(device);
407     if (status != ZX_OK) {
408         zxlogf(ERROR, "%s: failed to initialize i2c host controller %d", __FUNCTION__, status);
409         goto init_fail;
410     }
411 
412     thrd_t irq_thread;
413     thrd_create_with_name(&irq_thread, i2c_dw_irq_thread, device, "i2c_dw_irq_thread");
414 
415     return ZX_OK;
416 
417 init_fail:
418     if (device) {
419         mmio_buffer_release(&device->regs_iobuff);
420         if (device->event_handle != ZX_HANDLE_INVALID) {
421             zx_handle_close(device->event_handle);
422         }
423         if (device->irq_handle != ZX_HANDLE_INVALID) {
424             zx_handle_close(device->irq_handle);
425         }
426         free(device);
427     }
428     return status;
429 }
430 
431 static i2c_impl_protocol_ops_t i2c_ops = {
432     .get_bus_count = i2c_dw_get_bus_count,
433     .get_max_transfer_size = i2c_dw_get_max_transfer_size,
434     .set_bitrate = i2c_dw_set_bitrate,
435     .transact = i2c_dw_transact,
436 };
437 
438 static zx_protocol_device_t i2c_device_proto = {
439     .version = DEVICE_OPS_VERSION,
440 };
441 
dw_i2c_bind(void * ctx,zx_device_t * parent)442 static zx_status_t dw_i2c_bind(void* ctx, zx_device_t* parent) {
443  printf("dw_i2c_bind\n");
444     zx_status_t status;
445 
446     i2c_dw_t* i2c = calloc(1, sizeof(i2c_dw_t));
447     if (!i2c) {
448         return ZX_ERR_NO_MEMORY;
449     }
450 
451     if ((status = device_get_protocol(parent, ZX_PROTOCOL_PDEV, &i2c->pdev)) != ZX_OK) {
452         zxlogf(ERROR, "dw_i2c_bind: ZX_PROTOCOL_PDEV not available\n");
453         goto fail;
454     }
455 
456     pbus_protocol_t pbus;
457     if ((status = device_get_protocol(parent, ZX_PROTOCOL_PBUS, &pbus)) != ZX_OK) {
458         zxlogf(ERROR, "dw_i2c_bind: ZX_PROTOCOL_PBUS not available\n");
459         goto fail;
460     }
461 
462     pdev_device_info_t info;
463     status = pdev_get_device_info(&i2c->pdev, &info);
464     if (status != ZX_OK) {
465         zxlogf(ERROR, "dw_i2c_bind: pdev_get_device_info failed\n");
466         goto fail;
467     }
468 
469     if (info.mmio_count != info.irq_count) {
470         zxlogf(ERROR, "dw_i2c_bind: mmio_count %u does not matchirq_count %u\n",
471                info.mmio_count, info.irq_count);
472         status = ZX_ERR_INVALID_ARGS;
473         goto fail;
474     }
475 
476     i2c->i2c_devs = calloc(info.mmio_count, sizeof(i2c_dw_dev_t));
477     if (!i2c->i2c_devs) {
478         free(i2c);
479         return ZX_ERR_NO_MEMORY;
480     }
481     i2c->i2c_dev_count = info.mmio_count;
482 
483     for (uint32_t i = 0; i < i2c->i2c_dev_count; i++) {
484         zx_status_t status = i2c_dw_init(i2c, i);
485         if (status != ZX_OK) {
486             zxlogf(ERROR, "dw_i2c_bind: dw_i2c_dev_init failed: %d\n", status);
487             goto fail;
488         }
489     }
490 
491     device_add_args_t args = {
492         .version = DEVICE_ADD_ARGS_VERSION,
493         .name = "dw-i2c",
494         .ctx = i2c,
495         .ops = &i2c_device_proto,
496         .flags = DEVICE_ADD_NON_BINDABLE,
497     };
498 
499     status = device_add(parent, &args, &i2c->zxdev);
500     if (status != ZX_OK) {
501         zxlogf(ERROR, "dw_i2c_bind: device_add failed\n");
502         goto fail;
503     }
504 
505     i2c->i2c.ops = &i2c_ops;
506     i2c->i2c.ctx = i2c;
507     const platform_proxy_cb_t kCallback = {NULL, NULL};
508     pbus_register_protocol(&pbus, ZX_PROTOCOL_I2C_IMPL, &i2c->i2c, sizeof(i2c->i2c), &kCallback);
509 
510     return ZX_OK;
511 
512 fail:
513     return status;
514 }
515 
516 static zx_driver_ops_t dw_i2c_driver_ops = {
517     .version = DRIVER_OPS_VERSION,
518     .bind = dw_i2c_bind,
519 };
520 
521 ZIRCON_DRIVER_BEGIN(dw_i2c, dw_i2c_driver_ops, "zircon", "0.1", 4)
522     BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_PDEV),
523     BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_GENERIC),
524     BI_ABORT_IF(NE, BIND_PLATFORM_DEV_PID, PDEV_PID_GENERIC),
525     BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_DW_I2C),
526 ZIRCON_DRIVER_END(dw_i2c)
527