1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2017-12-04     Haley        the first version
9  */
10 
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include "am_mcu_apollo.h"
14 
15 /* I2C0 */
16 #define AM_I2C0_IOM_INST    0
17 
18 #define I2C0_GPIO_SCL       5
19 #define I2C0_GPIO_CFG_SCK   AM_HAL_PIN_5_M0SCL
20 #define I2C0_GPIO_SDA       6
21 #define I2C0_GPIO_CFG_SDA   AM_HAL_PIN_6_M0SDA
22 
23 /* I2C2 */
24 #define AM_I2C2_IOM_INST    2
25 
26 #define I2C2_GPIO_SCL       27
27 #define I2C2_GPIO_CFG_SCK   AM_HAL_PIN_27_M2SCL
28 #define I2C2_GPIO_SDA       25
29 #define I2C2_GPIO_CFG_SDA   AM_HAL_PIN_25_M2SDA
30 
31 /* I2C3 */
32 #define AM_I2C3_IOM_INST    3
33 
34 #define I2C3_GPIO_SCL       42
35 #define I2C3_GPIO_CFG_SCK   AM_HAL_PIN_42_M3SCL
36 #define I2C3_GPIO_SDA       43
37 #define I2C3_GPIO_CFG_SDA   AM_HAL_PIN_43_M3SDA
38 
39 /* I2C4 */
40 #define AM_I2C4_IOM_INST    4
41 
42 #define I2C4_GPIO_SCL       39
43 #define I2C4_GPIO_CFG_SCK   AM_HAL_PIN_39_M4SCL
44 #define I2C4_GPIO_SDA       40
45 #define I2C4_GPIO_CFG_SDA   AM_HAL_PIN_40_M4SDA
46 
47 static am_hal_iom_config_t g_sIOMConfig =
48 {
49     AM_HAL_IOM_I2CMODE, // ui32InterfaceMode
50     AM_HAL_IOM_100KHZ, // ui32ClockFrequency
51     0, // bSPHA
52     0, // bSPOL
53     4, // ui8WriteThreshold
54     60, // ui8ReadThreshold
55 };
56 
57 /* AM i2c driver */
58 struct am_i2c_bus
59 {
60     struct rt_i2c_bus_device parent;
61     rt_uint32_t u32Module;
62 };
63 
64 //connect am drv to rt drv.
rt_i2c_master_xfer(struct rt_i2c_bus_device * bus,struct rt_i2c_msg * msgs,rt_uint32_t num)65 rt_size_t rt_i2c_master_xfer(struct rt_i2c_bus_device *bus,
66                           struct rt_i2c_msg         *msgs,
67                           rt_uint32_t               num)
68 {
69     struct am_i2c_bus * am_i2c_bus = (struct am_i2c_bus *)bus;
70     struct rt_i2c_msg *msg;
71     int i;
72     rt_uint32_t msg_len = 0;
73 
74     for (i = 0; i < num; i++)
75     {
76         msg = &msgs[i];
77         if (msg->flags == RT_I2C_RD)
78         {
79             am_hal_iom_i2c_read(am_i2c_bus->u32Module, msg->addr, (uint32_t *)msg->buf, msg->len, AM_HAL_IOM_RAW);
80             msg_len += msg->len;
81         }
82         else if(msg->flags == RT_I2C_WR)
83         {
84             am_hal_iom_i2c_write(am_i2c_bus->u32Module, msg->addr, (uint32_t *)msg->buf, msg->len, AM_HAL_IOM_RAW);
85             msg_len += (msg->len - 1);
86         }
87     }
88 
89     return msg_len;
90 }
91 
rt_i2c_bus_control(struct rt_i2c_bus_device * bus,int cmd,void * args)92 rt_err_t rt_i2c_bus_control(struct rt_i2c_bus_device *bus,
93                           int                cmd,
94                           void               *args)
95 {
96     struct am_i2c_bus * am_i2c_bus = (struct am_i2c_bus *)bus;
97     //rt_uint32_t ctrl_arg = *(rt_uint32_t *)args;
98 
99     RT_ASSERT(bus != RT_NULL);
100     am_i2c_bus = (struct am_i2c_bus *)bus->parent.user_data;
101 
102     RT_ASSERT(am_i2c_bus != RT_NULL);
103 
104     switch (cmd)
105     {
106         /* I2C config */
107         case RT_DEVICE_CTRL_CONFIG :
108             break;
109     }
110 
111     return RT_EOK;
112 }
113 
114 static const struct rt_i2c_bus_device_ops am_i2c_ops =
115 {
116     rt_i2c_master_xfer,
117     RT_NULL,
118     rt_i2c_bus_control
119 };
120 
121 #ifdef RT_USING_I2C0
122 static struct am_i2c_bus am_i2c_bus_0 =
123 {
124     {0},
125     AM_I2C0_IOM_INST
126 };
127 #endif
128 
129 #ifdef RT_USING_I2C1
130 static struct am_i2c_bus am_i2c_bus_1 =
131 {
132     {1},
133     AM_I2C1_IOM_INST
134 };
135 #endif
136 
137 #ifdef RT_USING_I2C2
138 static struct am_i2c_bus am_i2c_bus_2 =
139 {
140     {2},
141     AM_I2C2_IOM_INST
142 };
143 #endif
144 
145 #ifdef RT_USING_I2C3
146 static struct am_i2c_bus am_i2c_bus_3 =
147 {
148     {3},
149     AM_I2C3_IOM_INST
150 };
151 #endif
152 
153 #ifdef RT_USING_I2C4
154 static struct am_i2c_bus am_i2c_bus_4 =
155 {
156     {4},
157     AM_I2C4_IOM_INST
158 };
159 #endif
160 
rt_i2c_init(void)161 int rt_i2c_init(void)
162 {
163     struct am_i2c_bus* am_i2c;
164 
165 #ifdef RT_USING_I2C0
166     /* init i2c gpio */
167     am_hal_gpio_pin_config(I2C0_GPIO_SCL, I2C0_GPIO_CFG_SCK | AM_HAL_GPIO_PULL6K);
168     am_hal_gpio_pin_config(I2C0_GPIO_SDA, I2C0_GPIO_CFG_SDA | AM_HAL_GPIO_PULL6K);
169 
170     /* Initialize IOM 0 in I2C mode at 100KHz */
171     am_hal_iom_pwrctrl_enable(AM_I2C0_IOM_INST);
172     g_sIOMConfig.ui32ClockFrequency = AM_HAL_IOM_100KHZ;
173     am_hal_iom_config(AM_I2C0_IOM_INST, &g_sIOMConfig);
174     am_hal_iom_enable(AM_I2C0_IOM_INST);
175 
176     /* init i2c bus device */
177     am_i2c = &am_i2c_bus_0;
178     am_i2c->parent.ops = &am_i2c_ops;
179     rt_i2c_bus_device_register(&am_i2c->parent, "i2c0");
180 #endif
181 
182 #ifdef RT_USING_I2C2
183     /* init i2c gpio */
184     am_hal_gpio_pin_config(I2C2_GPIO_SCL, I2C2_GPIO_CFG_SCK | AM_HAL_GPIO_PULL6K);
185     am_hal_gpio_pin_config(I2C2_GPIO_SDA, I2C2_GPIO_CFG_SDA | AM_HAL_GPIO_PULL6K);
186 
187     /* Initialize IOM 2 in I2C mode at 400KHz */
188     am_hal_iom_pwrctrl_enable(AM_I2C2_IOM_INST);
189     g_sIOMConfig.ui32ClockFrequency = AM_HAL_IOM_400KHZ;
190     am_hal_iom_config(AM_I2C2_IOM_INST, &g_sIOMConfig);
191     am_hal_iom_enable(AM_I2C2_IOM_INST);
192 
193     /* init i2c bus device */
194     am_i2c = &am_i2c_bus_2;
195     am_i2c->parent.ops = &am_i2c_ops;
196     rt_i2c_bus_device_register(&am_i2c->parent, "i2c2");
197 #endif
198 
199 #ifdef RT_USING_I2C3
200     /* init i2c gpio */
201     am_hal_gpio_pin_config(I2C3_GPIO_SCL, I2C3_GPIO_CFG_SCK | AM_HAL_GPIO_PULL6K);
202     am_hal_gpio_pin_config(I2C3_GPIO_SDA, I2C3_GPIO_CFG_SDA | AM_HAL_GPIO_PULL6K);
203 
204     /* Initialize IOM 3 in I2C mode at 400KHz */
205     am_hal_iom_pwrctrl_enable(AM_I2C3_IOM_INST);
206     g_sIOMConfig.ui32ClockFrequency = AM_HAL_IOM_400KHZ;
207     am_hal_iom_config(AM_I2C3_IOM_INST, &g_sIOMConfig);
208     am_hal_iom_enable(AM_I2C3_IOM_INST);
209 
210     /* init i2c bus device */
211     am_i2c = &am_i2c_bus_3;
212     am_i2c->parent.ops = &am_i2c_ops;
213     rt_i2c_bus_device_register(&am_i2c->parent, "i2c3");
214 #endif
215 
216 #ifdef RT_USING_I2C4
217     /* init i2c gpio */
218     am_hal_gpio_pin_config(I2C4_GPIO_SCL, I2C4_GPIO_CFG_SCK | AM_HAL_GPIO_PULL6K);
219     am_hal_gpio_pin_config(I2C4_GPIO_SDA, I2C4_GPIO_CFG_SDA | AM_HAL_GPIO_PULL6K);
220 
221     /* Initialize IOM 4 in I2C mode at 400KHz */
222     am_hal_iom_pwrctrl_enable(AM_I2C4_IOM_INST);
223     g_sIOMConfig.ui32ClockFrequency = AM_HAL_IOM_400KHZ;
224     am_hal_iom_config(AM_I2C4_IOM_INST, &g_sIOMConfig);
225     am_hal_iom_enable(AM_I2C4_IOM_INST);
226 
227     /* init i2c bus device */
228     am_i2c = &am_i2c_bus_4;
229     am_i2c->parent.ops = &am_i2c_ops;
230     rt_i2c_bus_device_register(&am_i2c->parent, "i2c4");
231 #endif
232 
233     //rt_kprintf("i2c_init!\n");
234 
235     return 0;
236 }
237 #ifdef RT_USING_COMPONENTS_INIT
238 INIT_BOARD_EXPORT(rt_i2c_init);
239 #endif
240 
241 /*@}*/
242