1 /*
2  * Copyright (c) 2006-2022, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2022-02-22     airm2m       first version
9  */
10 
11 #include <rtdevice.h>
12 #include <rtthread.h>
13 #include "board.h"
14 #ifdef BSP_USING_I2C
15 
16 static struct rt_i2c_bus_device prv_air105_i2c;
17 static rt_ssize_t air105_i2c_mst_xfer(struct rt_i2c_bus_device *bus,
18                                  struct rt_i2c_msg msgs[],
19                                  rt_uint32_t num);
20 static rt_ssize_t air105_i2c_slv_xfer(struct rt_i2c_bus_device *bus,
21                                  struct rt_i2c_msg msgs[],
22                                  rt_uint32_t num);
23 static rt_err_t air105_i2c_bus_control(struct rt_i2c_bus_device *bus,
24                                    int cmd,
25                                    void *args);
26 
27 static const struct rt_i2c_bus_device_ops air105_i2c_ops =
28 {
29     .master_xfer        = air105_i2c_mst_xfer,
30     .slave_xfer         = RT_NULL,
31     .i2c_bus_control    = air105_i2c_bus_control
32 };
33 
34 
air105_i2c_mst_xfer(struct rt_i2c_bus_device * bus,struct rt_i2c_msg msgs[],rt_uint32_t num)35 static rt_ssize_t air105_i2c_mst_xfer(struct rt_i2c_bus_device *bus,
36                                  struct rt_i2c_msg msgs[],
37                                  rt_uint32_t num)
38 {
39     rt_size_t i;
40     uint64_t tick;
41     struct rt_i2c_msg *msg = msgs;
42     RT_ASSERT(bus != RT_NULL);
43     rt_uint32_t i2c_id = (rt_uint32_t)bus->priv;
44     rt_int32_t Result;
45     while(!I2C_WaitResult(i2c_id, &Result)) {;}
46     for (i = 0; i < num; i++)
47     {
48         if (!(msg[i].flags & RT_I2C_NO_START))
49         {
50             if (msg[i].flags & RT_I2C_ADDR_10BIT)
51             {
52                 I2C_Prepare(i2c_id, msg[i].addr, 2, NULL, NULL);
53             }
54             else
55             {
56                 I2C_Prepare(i2c_id, msg[i].addr, 1, NULL, NULL);
57             }
58         }
59         if (msg[i].flags & RT_I2C_RD)
60         {
61             tick = GetSysTick();
62             I2C_MasterXfer(i2c_id, I2C_OP_READ, 0, msg[i].buf, msg[i].len, bus->timeout);
63             while(!I2C_WaitResult(i2c_id, &Result) && !SysTickCheckTimeout(tick, bus->timeout * CORE_TICK_1MS)){;}
64             if (!I2C_WaitResult(i2c_id, &Result))
65             {
66                 I2C_ForceStop(i2c_id);
67                 return -RT_EIO;
68             }
69         }
70         else
71         {
72             tick = GetSysTick();
73             I2C_MasterXfer(i2c_id, I2C_OP_WRITE, 0, msg[i].buf, msg[i].len, bus->timeout);
74             while(!I2C_WaitResult(i2c_id, &Result) && !SysTickCheckTimeout(tick, bus->timeout * CORE_TICK_1MS)){;}
75             if (!I2C_WaitResult(i2c_id, &Result))
76             {
77                 I2C_ForceStop(i2c_id);
78                 return -RT_EIO;
79             }
80         }
81     }
82     return i;
83 }
air105_i2c_slv_xfer(struct rt_i2c_bus_device * bus,struct rt_i2c_msg msgs[],rt_uint32_t num)84 static rt_ssize_t air105_i2c_slv_xfer(struct rt_i2c_bus_device *bus,
85                                  struct rt_i2c_msg msgs[],
86                                  rt_uint32_t num)
87 {
88     return -RT_ENOSYS;
89 }
air105_i2c_bus_control(struct rt_i2c_bus_device * bus,int cmd,void * args)90 static rt_err_t air105_i2c_bus_control(struct rt_i2c_bus_device *bus,
91                                    int cmd,
92                                    void *args)
93 {
94 
95     RT_ASSERT(bus != RT_NULL);
96     rt_uint32_t i2c_id = (rt_uint32_t)bus->priv;
97     switch (cmd)
98     {
99     case RT_I2C_DEV_CTRL_CLK:
100         I2C_MasterSetup(i2c_id, *(rt_uint32_t *)args);
101         break;
102     default:
103         return -RT_EIO;
104     }
105 
106     return RT_EOK;
107 }
108 
air105_hw_i2c_init(void)109 int air105_hw_i2c_init(void)
110 {
111     I2C_GlobalInit();
112     prv_air105_i2c.ops = &air105_i2c_ops;
113     prv_air105_i2c.priv = 0;
114     I2C_MasterSetup(0, 400000);
115     GPIO_Iomux(GPIOE_06, 2);
116     GPIO_Iomux(GPIOE_07, 2);
117 #ifdef I2C_BUS_NAME
118     rt_i2c_bus_device_register(&prv_air105_i2c, I2C_BUS_NAME);
119 #else
120     rt_i2c_bus_device_register(&prv_air105_i2c, "i2c");
121 #endif
122 
123     return 0;
124 }
125 INIT_DEVICE_EXPORT(air105_hw_i2c_init);
126 
127 #endif /* BSP_USING_I2C */
128