1 /*
2  * Copyright (c) 2006-2025, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2020-11-15     xckhmf       First Verison
9  * 2021-11-27     chenyingchun fix _master_xfer bug
10  * 2023-01-28     Andrew       add Nrf5340 support
11  */
12 
13 #include <rtdevice.h>
14 #include <nrfx_twi_twim.h>
15 #include <nrfx_twim.h>
16 #include <drv_i2c.h>
17 
18 
19 #if defined(BSP_USING_I2C0) || defined(BSP_USING_I2C1) || defined(BSP_USING_I2C2) || defined(BSP_USING_I2C3)
20 typedef struct
21 {
22     nrf_twim_frequency_t freq;
23     uint32_t scl_pin;
24     uint32_t sda_pin;
25     nrfx_twim_t twi_instance;
26 }drv_i2c_cfg_t;
27 
28 #ifdef BSP_USING_I2C0
29 static drv_i2c_cfg_t drv_i2c_0 =
30 {
31     .freq = NRF_TWIM_FREQ_400K,
32     .scl_pin = BSP_I2C0_SCL_PIN,
33     .sda_pin = BSP_I2C0_SDA_PIN,
34     .twi_instance = NRFX_TWIM_INSTANCE(0)
35 };
36 static struct rt_i2c_bus_device i2c0_bus;
37 #endif
38 #ifdef BSP_USING_I2C1
39 static drv_i2c_cfg_t drv_i2c_1 =
40 {
41     .freq = NRF_TWIM_FREQ_400K,
42     .scl_pin = BSP_I2C1_SCL_PIN,
43     .sda_pin = BSP_I2C1_SDA_PIN,
44     .twi_instance = NRFX_TWIM_INSTANCE(1)
45 };
46 static struct rt_i2c_bus_device i2c1_bus;
47 #endif
48 #ifdef BSP_USING_I2C2
49 static drv_i2c_cfg_t drv_i2c_2 =
50 {
51     .freq = NRF_TWIM_FREQ_400K,
52     .scl_pin = BSP_I2C2_SCL_PIN,
53     .sda_pin = BSP_I2C2_SDA_PIN,
54     .twi_instance = NRFX_TWIM_INSTANCE(2)
55 };
56 static struct rt_i2c_bus_device i2c_bus;
57 #endif
58 #ifdef BSP_USING_I2C3
59 static drv_i2c_cfg_t drv_i2c_3 =
60 {
61     .freq = NRF_TWIM_FREQ_400K,
62     .scl_pin = BSP_I2C3_SCL_PIN,
63     .sda_pin = BSP_I2C3_SDA_PIN,
64     .twi_instance = NRFX_TWIM_INSTANCE(3)
65 };
66 static struct rt_i2c_bus_device i2c3_bus;
67 #endif
68 
69 
twi_master_init(struct rt_i2c_bus_device * bus)70 static int twi_master_init(struct rt_i2c_bus_device *bus)
71 {
72     nrfx_err_t rtn;
73     nrfx_twim_config_t config = NRFX_TWIM_DEFAULT_CONFIG(0,0);
74     drv_i2c_cfg_t *p_cfg = bus->priv;
75     nrfx_twim_t const * p_instance = &p_cfg->twi_instance;
76 
77     config.frequency = p_cfg->freq;
78     config.scl = p_cfg->scl_pin;
79     config.sda = p_cfg->sda_pin;
80 
81     nrfx_twi_twim_bus_recover(config.scl,config.sda);
82 
83     rtn = nrfx_twim_init(p_instance,&config,NULL,NULL);
84     if (rtn != NRFX_SUCCESS)
85     {
86         return rtn;
87     }
88     nrfx_twim_enable(p_instance);
89     return 0;
90 }
91 
_master_xfer(struct rt_i2c_bus_device * bus,struct rt_i2c_msg msgs[],rt_uint32_t num)92 static rt_ssize_t _master_xfer(struct rt_i2c_bus_device *bus,
93                               struct rt_i2c_msg msgs[],
94                               rt_uint32_t num)
95 {
96     struct rt_i2c_msg *msg;
97     nrfx_twim_t const *p_instance = &((drv_i2c_cfg_t *)bus->priv)->twi_instance;
98     nrfx_err_t ret = NRFX_ERROR_INTERNAL;
99     uint32_t no_stop_flag = 0;
100     rt_int32_t i = 0;
101 
102     for (i = 0; i < num; i++)
103     {
104         msg = &msgs[i];
105         nrfx_twim_xfer_desc_t xfer = NRFX_TWIM_XFER_DESC_TX(msg->addr, msg->buf, msg->len);
106 
107         if (msg->flags & RT_I2C_RD)
108         {
109             xfer.type = NRFX_TWIM_XFER_RX;
110         }
111         else
112         {
113             xfer.type = NRFX_TWIM_XFER_TX;
114             if (msg->flags & RT_I2C_NO_READ_ACK)
115             {
116                 no_stop_flag = NRFX_TWIM_FLAG_TX_NO_STOP;
117             }
118         }
119 
120         ret = nrfx_twim_xfer(p_instance, &xfer, no_stop_flag);
121         if (ret != NRFX_SUCCESS)
122         {
123             goto out;
124         }
125     }
126 
127 out:
128     return i;
129 }
130 
131 
132 static const struct rt_i2c_bus_device_ops _i2c_ops =
133 {
134      _master_xfer,
135      NULL,
136      NULL,
137 };
138 
rt_hw_i2c_init(void)139 int rt_hw_i2c_init(void)
140 {
141 #ifdef BSP_USING_I2C0
142     i2c0_bus.ops= &_i2c_ops;
143     i2c0_bus.timeout = 0;
144     i2c0_bus.priv = (void *)&drv_i2c_0;
145     twi_master_init(&i2c0_bus);
146     rt_i2c_bus_device_register(&i2c0_bus, "i2c0");
147 #endif
148 #ifdef BSP_USING_I2C1
149     i2c1_bus.ops= &_i2c_ops;
150     i2c1_bus.timeout = 0;
151     i2c1_bus.priv = (void *)&drv_i2c_1;
152     twi_master_init(&i2c1_bus);
153     rt_i2c_bus_device_register(&i2c1_bus, "i2c1");
154 #endif
155 #ifdef BSP_USING_I2C2
156         i2c_bus.ops= &_i2c_ops;
157         i2c_bus.timeout = 0;
158         i2c_bus.priv = (void *)&drv_i2c_2;
159         twi_master_init(&i2c_bus);
160         rt_i2c_bus_device_register(&i2c_bus, "i2c2");
161 #endif
162 #ifdef BSP_USING_I2C3
163         i2c3_bus.ops= &_i2c_ops;
164         i2c3_bus.timeout = 0;
165         i2c3_bus.priv = (void *)&drv_i2c_3;
166         twi_master_init(&i2c3_bus);
167         rt_i2c_bus_device_register(&i2c3_bus, "i2c3");
168 #endif
169 
170 
171     return 0;
172 }
173 
174 INIT_BOARD_EXPORT(rt_hw_i2c_init);
175 #endif /* defined(BSP_USING_I2C0) || defined(BSP_USING_I2C1) */
176 
177