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/12/01 Raman Gopalan First version
9 */
10 #include "drv_soft_i2c.h"
11
12 #ifdef BSP_USING_SOFT_I2C
13 #define DBG_LEVEL DBG_LOG
14 #include <rtdbg.h>
15 #define LOG_TAG "DRV.I2C"
16
17 static const struct avr32_soft_i2c_config soft_i2c_config[] =
18 {
19 #ifdef BSP_USING_SOFT_I2C1
20 I2C1_BUS_CONFIG,
21 #endif
22 };
23
24 static struct avr32_i2c i2c_obj[sizeof(soft_i2c_config) / sizeof(soft_i2c_config[0])];
25
26 /**
27 * This function initializes the I2C pin.
28 *
29 * @param AVR32 I2C driver class.
30 */
avr32_i2c_gpio_init(struct avr32_i2c * i2c)31 static void avr32_i2c_gpio_init(struct avr32_i2c *i2c)
32 {
33 struct avr32_soft_i2c_config* cfg = (struct avr32_soft_i2c_config*)i2c->ops.data;
34
35 rt_pin_mode(cfg->scl, PIN_MODE_OUTPUT_OD);
36 gpio_set_gpio_open_drain_pin(cfg->scl);
37
38 rt_pin_mode(cfg->sda, PIN_MODE_OUTPUT_OD);
39 gpio_set_gpio_open_drain_pin(cfg->sda);
40 }
41
avr32_i2c_pin_init(void)42 static void avr32_i2c_pin_init(void)
43 {
44 rt_size_t obj_num = sizeof(i2c_obj) / sizeof(struct avr32_i2c);
45
46 for(rt_size_t i = 0; i < obj_num; i++)
47 {
48 avr32_i2c_gpio_init(&i2c_obj[i]);
49 }
50 }
51
52 /**
53 * This function sets the SDA pin.
54 *
55 * @param AVR32 config class.
56 * @param The SDA pin state.
57 */
avr32_set_sda(void * data,rt_int32_t state)58 static void avr32_set_sda(void *data, rt_int32_t state)
59 {
60 struct avr32_soft_i2c_config* cfg = (struct avr32_soft_i2c_config*)data;
61 if (state)
62 {
63 gpio_set_gpio_open_drain_pin(cfg->sda);
64 }
65 else
66 {
67 gpio_clr_gpio_open_drain_pin(cfg->sda);
68 }
69 }
70
71 /**
72 * This function sets the SCL pin.
73 *
74 * @param AVR32 config class.
75 * @param The SCL pin state.
76 */
avr32_set_scl(void * data,rt_int32_t state)77 static void avr32_set_scl(void *data, rt_int32_t state)
78 {
79 struct avr32_soft_i2c_config* cfg = (struct avr32_soft_i2c_config*)data;
80 if (state)
81 {
82 gpio_set_gpio_open_drain_pin(cfg->scl);
83 }
84 else
85 {
86 gpio_clr_gpio_open_drain_pin(cfg->scl);
87 }
88 }
89
90 /**
91 * This function gets the SDA pin state.
92 *
93 * @param The SDA pin state.
94 */
avr32_get_sda(void * data)95 static rt_int32_t avr32_get_sda(void *data)
96 {
97 struct avr32_soft_i2c_config* cfg = (struct avr32_soft_i2c_config*)data;
98 return gpio_get_gpio_open_drain_pin_output_value(cfg->sda);
99 }
100
101 /**
102 * This function gets the SCL pin state.
103 *
104 * @param The SCL pin state.
105 */
avr32_get_scl(void * data)106 static rt_int32_t avr32_get_scl(void *data)
107 {
108 struct avr32_soft_i2c_config* cfg = (struct avr32_soft_i2c_config*)data;
109 return gpio_get_gpio_open_drain_pin_output_value(cfg->scl);
110 }
111
112 static const struct rt_i2c_bit_ops avr32_bit_ops_default =
113 {
114 .data = RT_NULL,
115 .pin_init = avr32_i2c_pin_init,
116 .set_sda = avr32_set_sda,
117 .set_scl = avr32_set_scl,
118 .get_sda = avr32_get_sda,
119 .get_scl = avr32_get_scl,
120 .udelay = rt_hw_us_delay,
121 .delay_us = 1,
122 .timeout = 100,
123 .i2c_pin_init_flag = RT_FALSE
124 };
125
126 /**
127 * If I2C is locked, this function will unlock it.
128 *
129 * @param AVR32 config class
130 *
131 * @return RT_EOK indicates successful unlock.
132 */
avr32_i2c_bus_unlock(const struct avr32_soft_i2c_config * cfg)133 static rt_err_t avr32_i2c_bus_unlock(const struct avr32_soft_i2c_config *cfg)
134 {
135 rt_int32_t i = 0;
136
137 if (PIN_LOW == gpio_get_gpio_open_drain_pin_output_value(cfg->sda))
138 {
139 while (i++ < 9)
140 {
141 gpio_set_gpio_open_drain_pin(cfg->scl);
142 rt_hw_us_delay(100);
143 gpio_clr_gpio_open_drain_pin(cfg->scl);
144 rt_hw_us_delay(100);
145 }
146 }
147 if (PIN_LOW == gpio_get_gpio_open_drain_pin_output_value(cfg->sda))
148 {
149 return -RT_ERROR;
150 }
151
152 return RT_EOK;
153 }
154
155 /* I2C initialization function */
rt_sw_i2c_init(void)156 int rt_sw_i2c_init(void)
157 {
158 rt_err_t result;
159 rt_size_t i;
160
161 for (i = 0; i < sizeof(i2c_obj) / sizeof(struct avr32_i2c); i++)
162 {
163 i2c_obj[i].ops = avr32_bit_ops_default;
164 i2c_obj[i].ops.data = (void*)&soft_i2c_config[i];
165 i2c_obj[i].i2c_bus.priv = &i2c_obj[i].ops;
166
167 result = rt_i2c_bit_add_bus(&i2c_obj[i].i2c_bus, soft_i2c_config[i].bus_name);
168 RT_ASSERT(result == RT_EOK);
169 avr32_i2c_bus_unlock(&soft_i2c_config[i]);
170
171 LOG_D("Software simulation %s init done, pin SCL: %d, pin SDA %d",
172 soft_i2c_config[i].bus_name,
173 soft_i2c_config[i].scl,
174 soft_i2c_config[i].sda);
175 }
176
177 return RT_EOK;
178 }
179
180 #endif /* BSP_USING_SOFT_I2C */
181