1 /*
2  * Copyright (c) 2019 Winner Microelectronics Co., Ltd.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2018-11-9      fanwenl      1st version
9  */
10 
11 #include <rtdevice.h>
12 #include <rtthread.h>
13 #include "board.h"
14 #include "wm_i2c.h"
15 #include "wm_io.h"
16 #include "wm_gpio_afsel.h"
17 #include "pin_map.h"
18 #include "drv_i2c.h"
19 
20 #ifdef BSP_USING_I2C
21 
22 struct wm_i2c_bus
23 {
24     struct rt_i2c_bus_device parent;
25     struct rt_i2c_msg *msg;
26     rt_uint32_t msg_cnt;
27     volatile rt_uint32_t msg_ptr;
28     volatile rt_uint32_t dptr;
29 };
30 
31 static struct wm_i2c_bus wm_i2c;
32 
33 static rt_ssize_t wm_i2c_mst_xfer(struct rt_i2c_bus_device *bus,
34                                  struct rt_i2c_msg msgs[],
35                                  rt_uint32_t num);
36 static rt_ssize_t wm_i2c_slv_xfer(struct rt_i2c_bus_device *bus,
37                                  struct rt_i2c_msg msgs[],
38                                  rt_uint32_t num);
39 static rt_err_t wm_i2c_bus_control(struct rt_i2c_bus_device *bus,
40                                    int cmd,
41                                    void *args);
42 
43 static const struct rt_i2c_bus_device_ops wm_i2c_ops =
44 {
45     wm_i2c_mst_xfer,
46     wm_i2c_slv_xfer,
47     wm_i2c_bus_control,
48 };
49 
wm_i2c_send_address(struct rt_i2c_bus_device * bus,struct rt_i2c_msg * msg)50 static rt_err_t wm_i2c_send_address(struct rt_i2c_bus_device *bus,
51                                     struct rt_i2c_msg *msg)
52 {
53     uint8_t addr_msb, addr_lsb;
54 
55     if (msg->flags & RT_I2C_ADDR_10BIT)
56     {
57         addr_msb = 0xf0 | ((msg->addr >> 7) & 0x06);
58         addr_lsb = msg->addr & 0xff;
59 
60         if (msg->flags & RT_I2C_RD)
61         {
62             addr_msb |= 0x01;
63         }
64         tls_i2c_write_byte(addr_msb, 1);
65         tls_i2c_wait_ack();
66         tls_i2c_write_byte(addr_lsb, 0);
67         tls_i2c_wait_ack();
68     }
69     else
70     {
71         tls_i2c_write_byte((msg->addr << 1) | msg->flags, 1);
72         tls_i2c_wait_ack();
73     }
74 
75     return RT_EOK;
76 }
77 
wm_i2c_mst_xfer(struct rt_i2c_bus_device * bus,struct rt_i2c_msg msgs[],rt_uint32_t num)78 static rt_ssize_t wm_i2c_mst_xfer(struct rt_i2c_bus_device *bus,
79                                  struct rt_i2c_msg msgs[],
80                                  rt_uint32_t num)
81 {
82     struct wm_i2c_bus *wm_i2c;
83     rt_size_t i;
84     RT_ASSERT(bus != RT_NULL);
85     wm_i2c = (struct wm_i2c_bus *)bus;
86 
87     wm_i2c->msg = msgs;
88     wm_i2c->msg_ptr = 0;
89     wm_i2c->msg_cnt = num;
90     wm_i2c->dptr = 0;
91 
92     for (i = 0; i < wm_i2c->msg_cnt; i++)
93     {
94         if (!(wm_i2c->msg[i].flags & RT_I2C_NO_START))
95         {
96             wm_i2c_send_address(bus, &(wm_i2c->msg[i]));
97         }
98         if (wm_i2c->msg[i].flags & RT_I2C_RD)
99         {
100             while (wm_i2c->msg[i].len > 1)
101             {
102                 *wm_i2c->msg[i].buf++ = tls_i2c_read_byte(1, 0);
103                 wm_i2c->msg[i].len--;
104             }
105             *wm_i2c->msg[i].buf = tls_i2c_read_byte(0, 0);
106         }
107         else
108         {
109             while (wm_i2c->msg[i].len > 0)
110             {
111                 tls_i2c_write_byte(*wm_i2c->msg[i].buf, 0);
112                 tls_i2c_wait_ack();
113                 wm_i2c->msg[i].len--;
114                 wm_i2c->msg[i].buf++;
115             }
116         }
117     }
118     wm_i2c->msg = RT_NULL;
119     wm_i2c->msg_ptr = 0;
120     wm_i2c->msg_cnt = 0;
121     wm_i2c->dptr = 0;
122 
123     tls_i2c_stop();
124     for (int j = 0; j < 3000; j++);
125 
126     return i;
127 }
wm_i2c_slv_xfer(struct rt_i2c_bus_device * bus,struct rt_i2c_msg msgs[],rt_uint32_t num)128 static rt_ssize_t wm_i2c_slv_xfer(struct rt_i2c_bus_device *bus,
129                                  struct rt_i2c_msg msgs[],
130                                  rt_uint32_t num)
131 {
132     return 0;
133 }
wm_i2c_bus_control(struct rt_i2c_bus_device * bus,int cmd,void * args)134 static rt_err_t wm_i2c_bus_control(struct rt_i2c_bus_device *bus,
135                                    int cmd,
136                                    void *args)
137 {
138     return -RT_ERROR;
139 }
140 
WM_I2C_IRQHandler(void)141 void WM_I2C_IRQHandler(void)
142 {
143     extern void I2C_IRQHandler(void);
144     /* enter interrupt */
145     rt_interrupt_enter();
146 
147     I2C_IRQHandler();
148 
149     /* leave interrupt */
150     rt_interrupt_leave();
151 }
152 
wm_hw_i2c_init(void)153 int wm_hw_i2c_init(void)
154 {
155     rt_int16_t gpio_pin;
156 
157     gpio_pin = wm_get_pin(WM_I2C_SCL_PIN);
158     if (gpio_pin >= 0)
159     {
160         wm_i2c_scl_config((enum tls_io_name)gpio_pin);
161     }
162     gpio_pin = wm_get_pin(WM_I2C_DAT_PIN);
163     if (gpio_pin >= 0)
164     {
165         wm_i2c_sda_config((enum tls_io_name)gpio_pin);
166     }
167 
168     tls_i2c_init(WM_HW_I2C_FREQ);
169 
170     wm_i2c.parent.ops = &wm_i2c_ops;
171 #ifdef WM_I2C_BUS_NAME
172     rt_i2c_bus_device_register(&wm_i2c.parent, WM_I2C_BUS_NAME);
173 #else
174     rt_i2c_bus_device_register(&wm_i2c.parent, "i2c");
175 #endif
176 
177     return 0;
178 }
179 INIT_DEVICE_EXPORT(wm_hw_i2c_init);
180 
181 #endif /* BSP_USING_I2C */
182