123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- /*
- * Copyright (c) 2019 Winner Microelectronics Co., Ltd.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2018-11-9 fanwenl 1st version
- */
- #include <rtdevice.h>
- #include <rtthread.h>
- #include "board.h"
- #include "wm_i2c.h"
- #include "wm_io.h"
- #include "wm_gpio_afsel.h"
- #include "pin_map.h"
- #include "drv_i2c.h"
- #ifdef BSP_USING_I2C
- struct wm_i2c_bus
- {
- struct rt_i2c_bus_device parent;
- struct rt_i2c_msg *msg;
- rt_uint32_t msg_cnt;
- volatile rt_uint32_t msg_ptr;
- volatile rt_uint32_t dptr;
- };
- static struct wm_i2c_bus wm_i2c;
- static rt_size_t wm_i2c_mst_xfer(struct rt_i2c_bus_device *bus,
- struct rt_i2c_msg msgs[],
- rt_uint32_t num);
- static rt_size_t wm_i2c_slv_xfer(struct rt_i2c_bus_device *bus,
- struct rt_i2c_msg msgs[],
- rt_uint32_t num);
- static rt_err_t wm_i2c_bus_control(struct rt_i2c_bus_device *bus,
- rt_uint32_t,
- rt_uint32_t);
- static const struct rt_i2c_bus_device_ops wm_i2c_ops =
- {
- wm_i2c_mst_xfer,
- wm_i2c_slv_xfer,
- wm_i2c_bus_control,
- };
- static rt_err_t wm_i2c_send_address(struct rt_i2c_bus_device *bus,
- struct rt_i2c_msg *msg)
- {
- uint8_t addr_msb, addr_lsb;
- if (msg->flags & RT_I2C_ADDR_10BIT)
- {
- addr_msb = 0xf0 | ((msg->addr >> 7) & 0x06);
- addr_lsb = msg->addr & 0xff;
- if (msg->flags & RT_I2C_RD)
- {
- addr_msb |= 0x01;
- }
- tls_i2c_write_byte(addr_msb, 1);
- tls_i2c_wait_ack();
- tls_i2c_write_byte(addr_lsb, 0);
- tls_i2c_wait_ack();
- }
- else
- {
- tls_i2c_write_byte((msg->addr << 1) | msg->flags, 1);
- tls_i2c_wait_ack();
- }
- return RT_EOK;
- }
- static rt_size_t wm_i2c_mst_xfer(struct rt_i2c_bus_device *bus,
- struct rt_i2c_msg msgs[],
- rt_uint32_t num)
- {
- struct wm_i2c_bus *wm_i2c;
- rt_size_t i;
- RT_ASSERT(bus != RT_NULL);
- wm_i2c = (struct wm_i2c_bus *)bus;
- wm_i2c->msg = msgs;
- wm_i2c->msg_ptr = 0;
- wm_i2c->msg_cnt = num;
- wm_i2c->dptr = 0;
- for (i = 0; i < wm_i2c->msg_cnt; i++)
- {
- if (!(wm_i2c->msg[i].flags & RT_I2C_NO_START))
- {
- wm_i2c_send_address(bus, &(wm_i2c->msg[i]));
- }
- if (wm_i2c->msg[i].flags & RT_I2C_RD)
- {
- while (wm_i2c->msg[i].len > 1)
- {
- *wm_i2c->msg[i].buf++ = tls_i2c_read_byte(1, 0);
- wm_i2c->msg[i].len--;
- }
- *wm_i2c->msg[i].buf = tls_i2c_read_byte(0, 0);
- }
- else
- {
- while (wm_i2c->msg[i].len > 0)
- {
- tls_i2c_write_byte(*wm_i2c->msg[i].buf, 0);
- tls_i2c_wait_ack();
- wm_i2c->msg[i].len--;
- wm_i2c->msg[i].buf++;
- }
- }
- }
- wm_i2c->msg = RT_NULL;
- wm_i2c->msg_ptr = 0;
- wm_i2c->msg_cnt = 0;
- wm_i2c->dptr = 0;
- tls_i2c_stop();
- for (int j = 0; j < 3000; j++);
- return i;
- }
- static rt_size_t wm_i2c_slv_xfer(struct rt_i2c_bus_device *bus,
- struct rt_i2c_msg msgs[],
- rt_uint32_t num)
- {
- return 0;
- }
- static rt_err_t wm_i2c_bus_control(struct rt_i2c_bus_device *bus,
- rt_uint32_t cmd,
- rt_uint32_t arg)
- {
- return RT_ERROR;
- }
- void WM_I2C_IRQHandler(void)
- {
- extern void I2C_IRQHandler(void);
- /* enter interrupt */
- rt_interrupt_enter();
- I2C_IRQHandler();
- /* leave interrupt */
- rt_interrupt_leave();
- }
- int wm_hw_i2c_init(void)
- {
- rt_int16_t gpio_pin;
- gpio_pin = wm_get_pin(WM_I2C_SCL_PIN);
- if (gpio_pin >= 0)
- {
- wm_i2c_scl_config((enum tls_io_name)gpio_pin);
- }
- gpio_pin = wm_get_pin(WM_I2C_DAT_PIN);
- if (gpio_pin >= 0)
- {
- wm_i2c_sda_config((enum tls_io_name)gpio_pin);
- }
- tls_i2c_init(WM_HW_I2C_FREQ);
- wm_i2c.parent.ops = &wm_i2c_ops;
- #ifdef WM_I2C_BUS_NAME
- rt_i2c_bus_device_register(&wm_i2c.parent, WM_I2C_BUS_NAME);
- #else
- rt_i2c_bus_device_register(&wm_i2c.parent, "i2c");
- #endif
- return 0;
- }
- INIT_DEVICE_EXPORT(wm_hw_i2c_init);
- #endif /* BSP_USING_I2C */
|