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    Email                    Notes
8  * 2022-04-11  Kevin.Liu kevin.liu.mchp@gmail.com First Release
9  */
10 
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 
14 #include <atmel_start.h>
15 
16 #ifdef SAM_I2C_EXAMPLE
17 
18 struct sam_i2c_bus
19 {
20     struct rt_i2c_bus_device parent;
21     struct i2c_m_sync_desc  *i2c_desc;
22     char                    *device_name;
23 };
24 
25 #define I2CBUS_NAME          "i2c0"
26 
27 static struct sam_i2c_bus sam_i2c0 =
28 {
29     .i2c_desc    = &I2C_0,
30     .device_name = I2CBUS_NAME,
31 };
32 
33 static rt_ssize_t sam_i2c_master_xfer(struct rt_i2c_bus_device *bus,
34                                      struct rt_i2c_msg msgs[],
35                                      rt_uint32_t num);
36 static rt_ssize_t sam_i2c_slave_xfer(struct rt_i2c_bus_device *bus,
37                                     struct rt_i2c_msg msgs[],
38                                     rt_uint32_t num);
39 static rt_err_t sam_i2c_bus_control(struct rt_i2c_bus_device *bus,
40                                     int cmd, void *args);
41 
42 static const struct rt_i2c_bus_device_ops sam_i2c_ops =
43 {
44     .master_xfer     = sam_i2c_master_xfer,
45     .slave_xfer      = sam_i2c_slave_xfer,
46     .i2c_bus_control = sam_i2c_bus_control,
47 };
48 
sam_i2c_update_control(struct rt_i2c_msg * src,struct _i2c_m_msg * dest)49 static inline void sam_i2c_update_control(struct rt_i2c_msg *src,
50                                           struct _i2c_m_msg *dest)
51 {
52     dest->len    = (int32_t)src->len;
53     dest->addr   = src->addr;
54     dest->buffer = src->buf;
55 
56     /* Get I2C message R/W attribute first */
57     dest->flags = dest->flags & 0x0001;
58 
59     if (dest->flags & RT_I2C_ADDR_10BIT)
60         dest->flags |= I2C_M_TEN;
61     else
62         dest->flags |= I2C_M_SEVEN;
63 }
64 
sam_i2c_master_xfer(struct rt_i2c_bus_device * bus,struct rt_i2c_msg msgs[],rt_uint32_t num)65 static rt_ssize_t sam_i2c_master_xfer(struct rt_i2c_bus_device *bus,
66                                      struct rt_i2c_msg msgs[],
67                                      rt_uint32_t num)
68 {
69     struct sam_i2c_bus *sam_i2c = (struct sam_i2c_bus *)bus;
70     struct _i2c_m_msg   i2c_msg;
71     rt_size_t i;
72 
73     RT_ASSERT(bus != RT_NULL);
74 
75     for (i = 0; i < num; i++)
76     {
77         sam_i2c_update_control(&msgs[i], &i2c_msg);
78         if (i2c_m_sync_transfer(sam_i2c->i2c_desc, &i2c_msg) != 0)
79             break;
80     }
81 
82     return i;
83 }
84 
sam_i2c_slave_xfer(struct rt_i2c_bus_device * bus,struct rt_i2c_msg msgs[],rt_uint32_t num)85 static rt_ssize_t sam_i2c_slave_xfer(struct rt_i2c_bus_device *bus,
86                                     struct rt_i2c_msg msgs[],
87                                     rt_uint32_t num)
88 {
89     return 0;
90 }
91 
sam_i2c_bus_control(struct rt_i2c_bus_device * bus,int cmd,void * args)92 static rt_err_t sam_i2c_bus_control(struct rt_i2c_bus_device *bus,
93                                     int cmd,
94                                     void *args)
95 {
96     return -RT_ERROR;
97     struct sam_i2c_bus *sam_i2c = (struct sam_i2c_bus *)bus;
98 
99     RT_ASSERT(bus != RT_NULL);
100 
101     switch (cmd)
102     {
103     case RT_I2C_DEV_CTRL_CLK:
104         i2c_m_sync_set_baudrate(sam_i2c->i2c_desc, 0, *(rt_uint32_t *)args);
105         break;
106     default:
107         return -RT_EIO;
108     }
109 
110     return RT_EOK;
111 }
112 
rt_hw_i2c_init(void)113 int rt_hw_i2c_init(void)
114 {
115     rt_i2c_bus_device_register(&sam_i2c0.parent, sam_i2c0.device_name);
116     return 0;
117 }
118 #ifdef RT_USING_COMPONENTS_INIT
119 INIT_BOARD_EXPORT(rt_hw_i2c_init);
120 #endif
121 #endif
122 /*@}*/
123