1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2023-07-27   Chushicheng    the first version
9  */
10 
11 #include "drv_i2c.h"
12 #include "pico/binary_info.h"
13 #include "hardware/gpio.h"
14 #include "hardware/i2c.h"
15 
16 #ifdef BSP_USING_I2C
17 #define DBG_TAG              "drv.i2c"
18 #define DBG_LVL               DBG_INFO
19 #include <rtdbg.h>
20 
21 struct pico_i2c_bus
22 {
23     struct rt_i2c_bus_device parent;
24     i2c_inst_t *handle;
25     rt_uint8_t i2c_sda_pin;
26     rt_uint8_t i2c_scl_pin;
27     rt_uint32_t baud;
28     char *device_name;
29 
30 };
31 
32 static struct pico_i2c_bus pico_i2c_obj[] =
33 {
34 #ifdef BSP_USING_I2C0
35     {
36         .handle = i2c0,
37         .i2c_sda_pin  = BSP_I2C0_SDA_PIN,
38         .i2c_scl_pin  = BSP_I2C0_SCL_PIN,
39         .baud = 400000U,
40         .device_name = "i2c0",
41     },
42 #endif
43 #ifdef BSP_USING_I2C1
44     {
45         .handle = i2c1,
46         .i2c_sda_pin  = BSP_I2C1_SDA_PIN,
47         .i2c_scl_pin  = BSP_I2C1_SCL_PIN,
48         .baud = 400000U,
49         .device_name = "i2c1",
50     },
51 #endif
52 };
53 
pico_i2c_xfer(struct rt_i2c_bus_device * bus,struct rt_i2c_msg msgs[],rt_uint32_t num)54 rt_ssize_t pico_i2c_xfer(struct rt_i2c_bus_device *bus,
55                              struct rt_i2c_msg msgs[],
56                              rt_uint32_t num)
57 {
58     struct rt_i2c_msg *msg;
59     rt_uint32_t i;
60     rt_err_t ret = -RT_ERROR;
61 
62     struct pico_i2c_bus *pico_i2c = (struct pico_i2c_bus *)bus;
63 
64     for (i = 0; i < num; i++)
65     {
66         msg = &msgs[i];
67 
68         if (msg->flags & RT_I2C_RD)
69         {
70             i2c_read_blocking(pico_i2c->handle, msg->addr, msg->buf, msg->len, false);
71         }
72         else
73         {
74             i2c_write_blocking(pico_i2c->handle, msg->addr, msg->buf, msg->len, false);
75         }
76     }
77 
78     return ret;
79 }
80 
81 static const struct rt_i2c_bus_device_ops i2c_ops =
82 {
83     .master_xfer      = pico_i2c_xfer,
84     .slave_xfer       = RT_NULL,
85     .i2c_bus_control  = RT_NULL
86 };
87 
rt_hw_i2c_init(void)88 int rt_hw_i2c_init(void)
89 {
90     int result = RT_EOK;
91 
92     for (rt_size_t i = 0; i < sizeof(pico_i2c_obj) / sizeof(struct pico_i2c_bus); i++)
93     {
94         i2c_init(pico_i2c_obj[i].handle, pico_i2c_obj[i].baud);
95         gpio_set_function(pico_i2c_obj[i].i2c_sda_pin, GPIO_FUNC_I2C);
96         gpio_set_function(pico_i2c_obj[i].i2c_scl_pin, GPIO_FUNC_I2C);
97         gpio_pull_up(pico_i2c_obj[i].i2c_sda_pin);
98         gpio_pull_up(pico_i2c_obj[i].i2c_scl_pin);
99         // Make the I2C pins available to picotool
100         bi_decl(bi_2pins_with_func(pico_i2c_obj[i].i2c_sda_pin, pico_i2c_obj[i].i2c_scl_pin, GPIO_FUNC_I2C));
101         pico_i2c_obj[i].parent.ops = &i2c_ops;
102 
103         /* register i2c device */
104         if (rt_i2c_bus_device_register(&pico_i2c_obj[i].parent, pico_i2c_obj[i].device_name) == RT_EOK)
105         {
106             LOG_D("%s init success", pico_i2c_obj[i].device_name);
107         }
108         else
109         {
110             LOG_E("%s register failed", pico_i2c_obj[i].device_name);
111             result = -RT_ERROR;
112         }
113     }
114 
115     return result;
116 }
117 INIT_BOARD_EXPORT(rt_hw_i2c_init);
118 
119 #endif /* BSP_USING_I2C */
120