diff -drupN a/drivers/rtc/rtc-bm8563.c b/drivers/rtc/rtc-bm8563.c --- a/drivers/rtc/rtc-bm8563.c 1970-01-01 03:00:00.000000000 +0300 +++ b/drivers/rtc/rtc-bm8563.c 2022-06-09 05:02:33.000000000 +0300 @@ -0,0 +1,186 @@ +//驱动代码 +/* +* An rtc/i2c driver for the BM8563 +* +* Based on rtc-bm8563.c +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Registers */ +#define REG_CTRL_1 0x00 +#define REG_CTRL_2 0x01 +#define REG_WATCH_SEC 0x02 +#define REG_WATCH_MIN 0x03 +#define REG_WATCH_HOUR 0x04 +#define REG_WATCH_DATE 0x05 +#define REG_WATCH_DAY 0x06 +#define REG_WATCH_MON 0x07 +#define REG_WATCH_YEAR 0x08 +#define RTC_I2C_NUM 1 +#define RTC_ADDR 0x51 + +#define I2C_WRITE 0 +#define I2C_READ 1 + +static struct i2c_board_info bm8563_info = { + I2C_BOARD_INFO("bm8563", RTC_ADDR), +}; + +static struct i2c_client *bm8563_client; + +static int bm8563_get_time(struct device *dev, struct rtc_time *tm) +{ + struct i2c_client *client = to_i2c_client(dev); + + unsigned char addr = REG_WATCH_SEC; + unsigned char buf[7] = {0}; + + struct i2c_msg msgs[2] = { + [0] = { + .addr = client->addr, + .flags = I2C_WRITE, + .len = 1, + .buf = &addr, + }, /* setup read addr */ + [1] = { + .addr = client->addr, + .flags = I2C_READ, + .len = 7, + .buf = buf, + }, /* read time/date */ + }; + + /* read time/date registers */ + if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { + dev_err(&client->dev, "%s: read error\n", __func__); + return -EIO; + } + + //printk("kernel get time\n"); + tm->tm_sec = bcd2bin(buf[0]&0x7f) ; + tm->tm_min = bcd2bin(buf[1]); + tm->tm_hour = bcd2bin(buf[2]); + tm->tm_mday = bcd2bin(buf[3]); + tm->tm_wday = bcd2bin(buf[4]); + tm->tm_mon = bcd2bin(buf[5])-1; + tm->tm_year = bcd2bin(buf[6]) + 100; + if((tm->tm_sec == 0) && (tm->tm_min == 0) && (tm->tm_hour == 0) ) + rtc_time_to_tm(0, tm); + return 0; +} + +static int bm8563_set_time(struct device *dev, struct rtc_time *tm) +{ + struct i2c_client *client = to_i2c_client(dev); + unsigned char buf[8] = {0}; + unsigned char data[2] = {0}; + + struct i2c_msg msg[2] = { + [0] = { + .addr = client->addr, + .flags = I2C_WRITE, + .len = 8, + .buf = buf, + }, /* setup rtc time */ + [1] = { + .addr = client->addr, + .flags = I2C_READ, + .len = 1, + .buf = data, + }, /* read time/date */ + }; + + //printk("kernel set time\n"); + buf[0] = REG_WATCH_SEC; + buf[1] = bin2bcd(tm->tm_sec); + buf[2] = bin2bcd(tm->tm_min); + buf[3] = bin2bcd(tm->tm_hour); + buf[4] = bin2bcd(tm->tm_mday); + buf[5] = bin2bcd(tm->tm_wday); + buf[6] = bin2bcd(tm->tm_mon)+1; + buf[7] = bin2bcd(tm->tm_year % 100); + + /* write time/date registers */ + if ((i2c_transfer(client->adapter, msg, 2)) != 1) { + dev_err(&client->dev, "%s: write error\n", __func__); + return -EIO; + } + + return 0; +} + +static const struct rtc_class_ops bm8563_rtc_ops = { + .read_time = bm8563_get_time, + .set_time = bm8563_set_time, +}; + +static int bm8563_dev_init(void) +{ + struct rtc_device *rtc; + struct i2c_adapter *i2c_adap; + struct i2c_client *client; + unsigned char buf[2]; + struct i2c_msg msg = { + RTC_ADDR, I2C_WRITE, 2, buf, /* write time/date */ + }; + + i2c_adap = i2c_get_adapter(RTC_I2C_NUM); + bm8563_client = i2c_new_device(i2c_adap, &bm8563_info); + i2c_put_adapter(i2c_adap); + client = bm8563_client; + + + buf[0] = REG_CTRL_1; + buf[1] = 0; + if ((i2c_transfer(client->adapter, &msg, 1)) != 1) { + dev_err(&client->dev, "%s: write error\n", __func__); + return -EIO; + } + rtc = rtc_device_register("bm8563", &client->dev, + &bm8563_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); + + i2c_set_clientdata(client, rtc); + + return 0; +} +static void bm8563_dev_exit(void) +{ + struct rtc_device *rtc = i2c_get_clientdata(bm8563_client); + + if (rtc) + rtc_device_unregister(rtc); + i2c_unregister_device(bm8563_client); +} +module_init(bm8563_dev_init); +module_exit(bm8563_dev_exit); + +MODULE_AUTHOR("damon.jszhang@ingenic.com"); +MODULE_DESCRIPTION("rtc driver"); +MODULE_LICENSE("GPL");