1 /*
2  * Copyright (c) 2006-2024, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2024-04-08     QT-one       first version
9  */
10 
11 #include "drv_i2c.h"
12 
13 #ifdef RT_USING_I2C
14 #if !defined(BSP_USING_I2C0_HW) && !defined(BSP_USING_I2C1_HW)
15     #error "Please define at least one BSP_USING_I2Cx_HW"
16     /* this driver can be disabled at menuconfig RT-Thread Components Device Drivers */
17 #endif
18 
19 struct ht32_i2c_config
20 {
21     HT_I2C_TypeDef *i2c_x;
22     const char *i2c_name;
23     IRQn_Type irq;
24 };
25 
26 struct ht32_i2c
27 {
28     struct ht32_i2c_config *config;
29     struct rt_i2c_bus_device i2c_bus;
30 };
31 
32 enum
33 {
34 #ifdef BSP_USING_I2C0_HW
35     I2C0_INDEX,
36 #endif
37 #ifdef BSP_USING_I2C1_HW
38     I2C1_INDEX,
39 #endif
40 };
41 
42 static struct ht32_i2c_config i2c_config[] =
43 {
44 #ifdef BSP_USING_I2C0_HW
45     {
46         .i2c_x      = HT_I2C0,
47         .i2c_name   = BSP_USING_I2C0_HW_NAME,
48         .irq        = I2C0_IRQn
49     },
50 #endif
51 #ifdef BSP_USING_I2C1_HW
52     {
53         .i2c_x      = HT_I2C1,
54         .i2c_name   = BSP_USING_I2C1_HW_NAME,
55         .irq        = I2C1_IRQn
56     },
57 #endif
58 };
59 
60 static struct ht32_i2c i2cs[sizeof(i2c_config) / sizeof(i2c_config[0])] = {0};
61 
ht32_i2c_init(struct ht32_i2c * i2c_drv)62 static rt_size_t ht32_i2c_init(struct ht32_i2c *i2c_drv)
63 {
64     struct ht32_i2c_config *i2c_config = i2c_drv->config;
65 
66     CKCU_PeripClockConfig_TypeDef   CKCUClock = {{0}};
67 #ifdef BSP_USING_I2C0_HW
68     if (HT_I2C0 == i2c_config->i2c_x)
69     {
70         CKCUClock.Bit.I2C0  = 1;
71     }
72 #endif
73 #ifdef BSP_USING_I2C1_HW
74     if (HT_I2C1 == i2c_config->i2c_x)
75     {
76         CKCUClock.Bit.I2C1  = 1;
77     }
78 #endif
79     CKCUClock.Bit.AFIO  = 1;
80     CKCU_PeripClockConfig(CKCUClock, ENABLE);
81 
82     ht32_hardware_i2c_gpio_init(i2c_config->i2c_x);
83 
84     I2C_InitTypeDef I2C_InitStructure;
85     I2C_InitStructure.I2C_GeneralCall   =   DISABLE;
86     I2C_InitStructure.I2C_AddressingMode    =   I2C_ADDRESSING_7BIT;
87     I2C_InitStructure.I2C_Acknowledge   =   DISABLE;
88     I2C_InitStructure.I2C_OwnAddress    =   0x00;
89     I2C_InitStructure.I2C_Speed         =   400000;
90     I2C_InitStructure.I2C_SpeedOffset   =   0;
91 
92     I2C_Init(i2c_config->i2c_x, &I2C_InitStructure);
93     I2C_Cmd(i2c_config->i2c_x, ENABLE);
94 
95     return RT_EOK;
96 }
97 
ht32_i2c_read(struct ht32_i2c_config * hi2c,rt_uint16_t slave_address,rt_uint8_t * p_buffer,rt_uint16_t data_byte)98 static int ht32_i2c_read(struct ht32_i2c_config *hi2c,
99                         rt_uint16_t slave_address,
100                         rt_uint8_t *p_buffer,
101                         rt_uint16_t data_byte)
102 {
103     uint16_t date_num = 0;
104     uint8_t data = 0xFF;
105 
106     /* Determine if the bus is idle */
107     while (I2C_GetFlagStatus(hi2c->i2c_x, I2C_FLAG_BUSBUSY));
108     /* Send start bit, slave address and read/write bit */
109     I2C_TargetAddressConfig(hi2c->i2c_x, slave_address, I2C_MASTER_READ);
110 
111     while (!I2C_CheckStatus(hi2c->i2c_x, I2C_MASTER_SEND_START));
112     while (!I2C_CheckStatus(hi2c->i2c_x, I2C_MASTER_RECEIVER_MODE));
113     I2C_AckCmd(hi2c->i2c_x, ENABLE);
114     while (date_num < data_byte)
115     {
116         date_num++;
117 
118         while (!I2C_CheckStatus(hi2c->i2c_x, I2C_MASTER_RX_NOT_EMPTY));
119         data = I2C_ReceiveData(hi2c->i2c_x);
120 
121         if (date_num == (data_byte - 1))
122         {
123             I2C_AckCmd(hi2c->i2c_x, DISABLE);
124         }
125         if (p_buffer != RT_NULL)
126         {
127             *p_buffer++ = data;
128         }
129     }
130     I2C_GenerateSTOP(hi2c->i2c_x);
131     while (I2C_ReadRegister(hi2c->i2c_x, I2C_REGISTER_SR) & 0x80000);
132 
133     return 0;
134 }
135 
ht32_i2c_write(struct ht32_i2c_config * hi2c,uint16_t slave_address,uint8_t * p_buffer,uint16_t data_byte)136 static int ht32_i2c_write(struct ht32_i2c_config *hi2c,
137                         uint16_t slave_address,
138                         uint8_t *p_buffer,
139                         uint16_t data_byte)
140 {
141     uint16_t date_num = data_byte;
142 
143     /* Determine if the bus is idle */
144     while (I2C_GetFlagStatus(hi2c->i2c_x, I2C_FLAG_BUSBUSY));
145     /* Send start bit, slave address and read/write bit */
146     I2C_TargetAddressConfig(hi2c->i2c_x, slave_address, I2C_MASTER_WRITE);
147 
148     while (!I2C_CheckStatus(hi2c->i2c_x, I2C_MASTER_SEND_START));
149 
150     while (!I2C_CheckStatus(hi2c->i2c_x, I2C_MASTER_TRANSMITTER_MODE));
151     while (date_num--)
152     {
153         while (!I2C_CheckStatus(hi2c->i2c_x, I2C_MASTER_TX_EMPTY));
154         I2C_SendData(hi2c->i2c_x, *p_buffer);
155         p_buffer++;
156     }
157 
158     while (!I2C_CheckStatus(hi2c->i2c_x, I2C_MASTER_TX_EMPTY));
159     I2C_GenerateSTOP(hi2c->i2c_x);
160     while (I2C_ReadRegister(hi2c->i2c_x, I2C_REGISTER_SR) & 0x80000);
161     return 0;
162 }
163 
ht32_master_xfer(struct rt_i2c_bus_device * bus,struct rt_i2c_msg msgs[],rt_uint32_t num)164 static rt_ssize_t ht32_master_xfer(struct rt_i2c_bus_device *bus,
165                                    struct rt_i2c_msg msgs[],
166                                    rt_uint32_t num)
167 {
168     struct ht32_i2c *i2c_instance;
169     struct rt_i2c_msg *msg;
170     rt_uint32_t i;
171 
172     i2c_instance = rt_container_of(bus, struct ht32_i2c, i2c_bus);
173     RT_ASSERT(bus != RT_NULL);
174     RT_ASSERT(msgs != RT_NULL);
175 
176     for (i = 0; i < num; i++)
177     {
178         msg = &msgs[i];
179 
180         if (msg->flags & RT_I2C_RD)
181         {
182             if (ht32_i2c_read(i2c_instance->config, msg->addr, msg->buf, msg->len) != 0)
183             {
184                 return i;
185             }
186         }
187         else
188         {
189             if (ht32_i2c_write(i2c_instance->config, msg->addr, msg->buf, msg->len) != 0)
190             {
191                 return i;
192             }
193         }
194     }
195     return i;
196 }
197 
198 static struct rt_i2c_bus_device_ops ht32_i2c_ops =
199 {
200     .master_xfer = ht32_master_xfer,
201     .slave_xfer = RT_NULL,
202     .i2c_bus_control = RT_NULL
203 };
204 
rt_hw_i2c_init(void)205 int rt_hw_i2c_init(void)
206 {
207     int i;
208     rt_err_t result;
209     rt_size_t obj_num = sizeof(i2cs) / sizeof(struct ht32_i2c);
210 
211     for (i = 0; i < obj_num; i++)
212     {
213         i2cs[i].config = &i2c_config[i];
214         i2cs[i].i2c_bus.parent.user_data = (void *)&i2cs[i];
215         i2cs[i].i2c_bus.ops = &ht32_i2c_ops;
216 
217         ht32_i2c_init(&i2cs[i]);
218         result = rt_i2c_bus_device_register(&i2cs[i].i2c_bus, i2cs[i].config->i2c_name);
219     }
220     return result;
221 }
222 INIT_BOARD_EXPORT(rt_hw_i2c_init);
223 
224 #endif /* RT_USING_I2C */
225