mirror of
https://gitee.com/Vancouver2017/luban-lite.git
synced 2025-12-16 09:08:56 +00:00
252 lines
6.3 KiB
C
252 lines
6.3 KiB
C
/*
|
|
* Copyright (c) 2024, ArtInChip Technology Co., Ltd
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Change Logs:
|
|
* Date Notes
|
|
* 2024-12-11 the first version
|
|
*/
|
|
#include "rx8010.h"
|
|
#define DBG_TAG "rx8010"
|
|
#define DBG_LVL DBG_INFO
|
|
#include <rtdbg.h>
|
|
|
|
struct rx8010_device
|
|
{
|
|
struct rt_device dev;
|
|
struct rt_i2c_bus_device *i2c_device;
|
|
};
|
|
static struct rx8010_device g_rx8010_dev = {0};
|
|
|
|
/* bcd to bin */
|
|
static unsigned char bcd2bin(unsigned char data)
|
|
{
|
|
unsigned char temp;
|
|
|
|
temp = (((data) & 0x0f) + ((data) >> 4) * 10);
|
|
return temp;
|
|
}
|
|
|
|
/* bin_to_bcd */
|
|
static unsigned char bin2bcd(unsigned char data)
|
|
{
|
|
unsigned char temp;
|
|
|
|
temp = ((((data) / 10) << 4) + (data) % 10);
|
|
return temp;
|
|
}
|
|
|
|
/* rx8010 read register */
|
|
static rt_err_t rx8010_read_reg(rt_uint8_t reg, rt_uint8_t *data, rt_uint8_t data_size)
|
|
{
|
|
struct rt_i2c_msg msg[2];
|
|
|
|
msg[0].addr = RX8010_ADDR;
|
|
msg[0].flags = RT_I2C_WR;
|
|
msg[0].len = 1;
|
|
msg[0].buf = ®
|
|
|
|
msg[1].addr = RX8010_ADDR;
|
|
msg[1].flags = RT_I2C_RD;
|
|
msg[1].len = data_size;
|
|
msg[1].buf = data;
|
|
|
|
if (rt_i2c_transfer(g_rx8010_dev.i2c_device, msg, 2) == 2) {
|
|
return RT_EOK;
|
|
} else {
|
|
LOG_E("i2c bus read rx8010 failed!\r\n");
|
|
return -RT_ERROR;
|
|
}
|
|
}
|
|
|
|
/* rx8010 write register */
|
|
static rt_err_t rx8010_write_reg(rt_uint8_t reg, rt_uint8_t *data, rt_uint8_t data_size)
|
|
{
|
|
struct rt_i2c_msg msg;
|
|
rt_uint8_t buf[8] = {0};
|
|
|
|
buf[0] = reg;
|
|
rt_memcpy(&buf[1], data, data_size);
|
|
|
|
msg.addr = RX8010_ADDR;
|
|
msg.flags = RT_I2C_WR;
|
|
msg.len = data_size + 1;
|
|
msg.buf = buf;
|
|
|
|
if (rt_i2c_transfer(g_rx8010_dev.i2c_device, &msg, 1) == 1) {
|
|
return RT_EOK;
|
|
} else {
|
|
LOG_E("i2c bus write rx8010 failed!\r\n");
|
|
return -RT_ERROR;
|
|
}
|
|
}
|
|
|
|
static int rx8010_hw_init(void)
|
|
{
|
|
uint8_t data;
|
|
uint8_t ctrl[2] = {0};
|
|
int need_clear = 0;
|
|
|
|
/* Initialize reserved registers as specified in datasheet */
|
|
data = 0xD8;
|
|
if (rx8010_write_reg(RX8010_RESV17, &data, 1) != RT_EOK) {
|
|
return -RT_ERROR;
|
|
}
|
|
|
|
data = 0x00;
|
|
if (rx8010_write_reg(RX8010_RESV30, &data, 1) != RT_EOK) {
|
|
return -RT_ERROR;
|
|
}
|
|
|
|
data = 0x08;
|
|
if (rx8010_write_reg(RX8010_RESV31, &data, 1) != RT_EOK) {
|
|
return -RT_ERROR;
|
|
}
|
|
|
|
data = 0x00;
|
|
if (rx8010_write_reg(RX8010_IRQ, &data, 1) != RT_EOK) {
|
|
return -RT_ERROR;
|
|
}
|
|
|
|
if (rx8010_read_reg(RX8010_FLAG, ctrl, sizeof(ctrl)) != RT_EOK) {
|
|
return -RT_ERROR;
|
|
}
|
|
|
|
if (ctrl[0] & RX8010_FLAG_VLF)
|
|
LOG_I("Frequency Stop Was Detected\n");
|
|
|
|
if (ctrl[0] & RX8010_FLAG_AF) {
|
|
LOG_I("Alarm was detected\n");
|
|
need_clear = 1;
|
|
}
|
|
|
|
if (ctrl[0] & RX8010_FLAG_TF)
|
|
need_clear = 1;
|
|
|
|
if (ctrl[0] & RX8010_FLAG_UF)
|
|
need_clear = 1;
|
|
|
|
if (need_clear) {
|
|
ctrl[0] &= ~(RX8010_FLAG_AF | RX8010_FLAG_TF | RX8010_FLAG_UF);
|
|
|
|
if (rx8010_write_reg(RX8010_FLAG, &ctrl[0], 1) != RT_EOK)
|
|
return -RT_ERROR;
|
|
}
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
static rt_err_t rt_rx8010_init(rt_device_t dev)
|
|
{
|
|
return RT_EOK;
|
|
}
|
|
|
|
static rt_err_t rt_rx8010_open(rt_device_t dev, rt_uint16_t flag)
|
|
{
|
|
return RT_EOK;
|
|
}
|
|
|
|
static rt_err_t rt_rx8010_close(rt_device_t dev)
|
|
{
|
|
return RT_EOK;
|
|
}
|
|
|
|
static rt_err_t rt_rx8010_control(rt_device_t dev, int cmd, void *args)
|
|
{
|
|
rt_err_t ret = RT_EOK;
|
|
time_t *time;
|
|
struct tm time_temp;
|
|
rt_uint8_t buff[RX8010_YEAR - RX8010_SEC + 1] = {0};
|
|
|
|
RT_ASSERT(dev != RT_NULL);
|
|
rt_memset(&time_temp, 0, sizeof(struct tm));
|
|
|
|
switch (cmd)
|
|
{
|
|
case RT_DEVICE_CTRL_RTC_GET_TIME:
|
|
{
|
|
time = (time_t *)args;
|
|
|
|
ret = rx8010_read_reg(RX8010_SEC, buff, sizeof(buff));
|
|
if(ret == RT_EOK) {
|
|
time_temp.tm_year = bcd2bin(buff[RX8010_YEAR - RX8010_SEC]) + 100;
|
|
time_temp.tm_mon = bcd2bin(buff[RX8010_MONTH - RX8010_SEC] & 0x1f) - 1;
|
|
time_temp.tm_mday = bcd2bin(buff[RX8010_MDAY - RX8010_SEC] & 0x3f);
|
|
time_temp.tm_hour = bcd2bin(buff[RX8010_HOUR - RX8010_SEC] & 0x3f);
|
|
time_temp.tm_min = bcd2bin(buff[RX8010_MIN - RX8010_SEC] & 0x7f);
|
|
time_temp.tm_sec = bcd2bin(buff[RX8010_SEC - RX8010_SEC] & 0x7f);
|
|
*time = mktime(&time_temp);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case RT_DEVICE_CTRL_RTC_SET_TIME:
|
|
{
|
|
struct tm *time_new;
|
|
|
|
time = (time_t *)args;
|
|
time_new = localtime(time);
|
|
buff[RX8010_YEAR - RX8010_SEC] = bin2bcd(time_new->tm_year - 100);
|
|
buff[RX8010_MONTH - RX8010_SEC] = bin2bcd(time_new->tm_mon + 1);
|
|
buff[RX8010_WDAY - RX8010_SEC] = bin2bcd(time_new->tm_wday + 1);
|
|
buff[RX8010_MDAY - RX8010_SEC] = bin2bcd(time_new->tm_mday);
|
|
buff[RX8010_HOUR - RX8010_SEC] = bin2bcd(time_new->tm_hour);
|
|
buff[RX8010_MIN - RX8010_SEC] = bin2bcd(time_new->tm_min);
|
|
buff[RX8010_SEC - RX8010_SEC] = bin2bcd(time_new->tm_sec);
|
|
ret = rx8010_write_reg(RX8010_SEC, buff , sizeof(buff));
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
return RT_EOK;
|
|
}
|
|
|
|
#ifdef RT_USING_DEVICE_OPS
|
|
static const struct rt_device_ops rx8010_ops =
|
|
{
|
|
.init = rt_rx8010_init,
|
|
.open = rt_rx8010_open,
|
|
.close = rt_rx8010_close,
|
|
.control = rt_rx8010_control,
|
|
};
|
|
#endif
|
|
|
|
/* rx8010 device int */
|
|
int rt_hw_rx8010_init(void)
|
|
{
|
|
struct rt_i2c_bus_device *i2c_device;
|
|
|
|
i2c_device = rt_i2c_bus_device_find(AIC_RTC_I2C_CHAN);
|
|
if (i2c_device == RT_NULL) {
|
|
rt_kprintf("i2c bus device not found!\r\n");
|
|
return RT_ERROR;
|
|
}
|
|
g_rx8010_dev.i2c_device = i2c_device;
|
|
/* register rtc device */
|
|
#ifdef RT_USING_DEVICE_OPS
|
|
g_rx8010_dev.dev.ops = &rx8010_ops;
|
|
#else
|
|
g_rx8010_dev.dev.init = rt_rx8010_init;
|
|
g_rx8010_dev.dev.open = rt_rx8010_open;
|
|
g_rx8010_dev.dev.close = rt_rx8010_close;
|
|
g_rx8010_dev.dev.control = rt_rx8010_control;
|
|
#endif
|
|
g_rx8010_dev.dev.type = RT_Device_Class_RTC;
|
|
|
|
/* init rx8010 */
|
|
rt_device_register(&g_rx8010_dev.dev, "rtc", RT_DEVICE_FLAG_RDWR);
|
|
|
|
if (rx8010_hw_init() != RT_EOK) {
|
|
LOG_E("RTC RX8010 I2C Init Fail!\n");
|
|
return -RT_ERROR;
|
|
}
|
|
|
|
LOG_I("Init RTC RX8010 Success!\n");
|
|
|
|
return RT_EOK;
|
|
}
|
|
INIT_DEVICE_EXPORT(rt_hw_rx8010_init);
|