xref: /OK3568_Linux_fs/kernel/drivers/rtc/rtc-sd3078.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Real Time Clock (RTC) Driver for sd3078
4*4882a593Smuzhiyun  * Copyright (C) 2018 Zoro Li
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #include <linux/bcd.h>
8*4882a593Smuzhiyun #include <linux/i2c.h>
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/regmap.h>
11*4882a593Smuzhiyun #include <linux/rtc.h>
12*4882a593Smuzhiyun #include <linux/slab.h>
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #define SD3078_REG_SC			0x00
15*4882a593Smuzhiyun #define SD3078_REG_MN			0x01
16*4882a593Smuzhiyun #define SD3078_REG_HR			0x02
17*4882a593Smuzhiyun #define SD3078_REG_DW			0x03
18*4882a593Smuzhiyun #define SD3078_REG_DM			0x04
19*4882a593Smuzhiyun #define SD3078_REG_MO			0x05
20*4882a593Smuzhiyun #define SD3078_REG_YR			0x06
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #define SD3078_REG_CTRL1		0x0f
23*4882a593Smuzhiyun #define SD3078_REG_CTRL2		0x10
24*4882a593Smuzhiyun #define SD3078_REG_CTRL3		0x11
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #define KEY_WRITE1		0x80
27*4882a593Smuzhiyun #define KEY_WRITE2		0x04
28*4882a593Smuzhiyun #define KEY_WRITE3		0x80
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #define NUM_TIME_REGS   (SD3078_REG_YR - SD3078_REG_SC + 1)
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun /*
33*4882a593Smuzhiyun  * The sd3078 has write protection
34*4882a593Smuzhiyun  * and we can choose whether or not to use it.
35*4882a593Smuzhiyun  * Write protection is turned off by default.
36*4882a593Smuzhiyun  */
37*4882a593Smuzhiyun #define WRITE_PROTECT_EN	0
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun struct sd3078 {
40*4882a593Smuzhiyun 	struct rtc_device	*rtc;
41*4882a593Smuzhiyun 	struct regmap		*regmap;
42*4882a593Smuzhiyun };
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun /*
45*4882a593Smuzhiyun  * In order to prevent arbitrary modification of the time register,
46*4882a593Smuzhiyun  * when modification of the register,
47*4882a593Smuzhiyun  * the "write" bit needs to be written in a certain order.
48*4882a593Smuzhiyun  * 1. set WRITE1 bit
49*4882a593Smuzhiyun  * 2. set WRITE2 bit
50*4882a593Smuzhiyun  * 3. set WRITE3 bit
51*4882a593Smuzhiyun  */
sd3078_enable_reg_write(struct sd3078 * sd3078)52*4882a593Smuzhiyun static void sd3078_enable_reg_write(struct sd3078 *sd3078)
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun 	regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL2,
55*4882a593Smuzhiyun 			   KEY_WRITE1, KEY_WRITE1);
56*4882a593Smuzhiyun 	regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL1,
57*4882a593Smuzhiyun 			   KEY_WRITE2, KEY_WRITE2);
58*4882a593Smuzhiyun 	regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL1,
59*4882a593Smuzhiyun 			   KEY_WRITE3, KEY_WRITE3);
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun #if WRITE_PROTECT_EN
63*4882a593Smuzhiyun /*
64*4882a593Smuzhiyun  * In order to prevent arbitrary modification of the time register,
65*4882a593Smuzhiyun  * we should disable the write function.
66*4882a593Smuzhiyun  * when disable write,
67*4882a593Smuzhiyun  * the "write" bit needs to be clear in a certain order.
68*4882a593Smuzhiyun  * 1. clear WRITE2 bit
69*4882a593Smuzhiyun  * 2. clear WRITE3 bit
70*4882a593Smuzhiyun  * 3. clear WRITE1 bit
71*4882a593Smuzhiyun  */
sd3078_disable_reg_write(struct sd3078 * sd3078)72*4882a593Smuzhiyun static void sd3078_disable_reg_write(struct sd3078 *sd3078)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun 	regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL1,
75*4882a593Smuzhiyun 			   KEY_WRITE2, 0);
76*4882a593Smuzhiyun 	regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL1,
77*4882a593Smuzhiyun 			   KEY_WRITE3, 0);
78*4882a593Smuzhiyun 	regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL2,
79*4882a593Smuzhiyun 			   KEY_WRITE1, 0);
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun #endif
82*4882a593Smuzhiyun 
sd3078_rtc_read_time(struct device * dev,struct rtc_time * tm)83*4882a593Smuzhiyun static int sd3078_rtc_read_time(struct device *dev, struct rtc_time *tm)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun 	unsigned char hour;
86*4882a593Smuzhiyun 	unsigned char rtc_data[NUM_TIME_REGS] = {0};
87*4882a593Smuzhiyun 	struct i2c_client *client = to_i2c_client(dev);
88*4882a593Smuzhiyun 	struct sd3078 *sd3078 = i2c_get_clientdata(client);
89*4882a593Smuzhiyun 	int ret;
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	ret = regmap_bulk_read(sd3078->regmap, SD3078_REG_SC, rtc_data,
92*4882a593Smuzhiyun 			       NUM_TIME_REGS);
93*4882a593Smuzhiyun 	if (ret < 0) {
94*4882a593Smuzhiyun 		dev_err(dev, "reading from RTC failed with err:%d\n", ret);
95*4882a593Smuzhiyun 		return ret;
96*4882a593Smuzhiyun 	}
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	tm->tm_sec	= bcd2bin(rtc_data[SD3078_REG_SC] & 0x7F);
99*4882a593Smuzhiyun 	tm->tm_min	= bcd2bin(rtc_data[SD3078_REG_MN] & 0x7F);
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	/*
102*4882a593Smuzhiyun 	 * The sd3078 supports 12/24 hour mode.
103*4882a593Smuzhiyun 	 * When getting time,
104*4882a593Smuzhiyun 	 * we need to convert the 12 hour mode to the 24 hour mode.
105*4882a593Smuzhiyun 	 */
106*4882a593Smuzhiyun 	hour = rtc_data[SD3078_REG_HR];
107*4882a593Smuzhiyun 	if (hour & 0x80) /* 24H MODE */
108*4882a593Smuzhiyun 		tm->tm_hour = bcd2bin(rtc_data[SD3078_REG_HR] & 0x3F);
109*4882a593Smuzhiyun 	else if (hour & 0x20) /* 12H MODE PM */
110*4882a593Smuzhiyun 		tm->tm_hour = bcd2bin(rtc_data[SD3078_REG_HR] & 0x1F) + 12;
111*4882a593Smuzhiyun 	else /* 12H MODE AM */
112*4882a593Smuzhiyun 		tm->tm_hour = bcd2bin(rtc_data[SD3078_REG_HR] & 0x1F);
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	tm->tm_mday = bcd2bin(rtc_data[SD3078_REG_DM] & 0x3F);
115*4882a593Smuzhiyun 	tm->tm_wday = rtc_data[SD3078_REG_DW] & 0x07;
116*4882a593Smuzhiyun 	tm->tm_mon	= bcd2bin(rtc_data[SD3078_REG_MO] & 0x1F) - 1;
117*4882a593Smuzhiyun 	tm->tm_year = bcd2bin(rtc_data[SD3078_REG_YR]) + 100;
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	return 0;
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun 
sd3078_rtc_set_time(struct device * dev,struct rtc_time * tm)122*4882a593Smuzhiyun static int sd3078_rtc_set_time(struct device *dev, struct rtc_time *tm)
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun 	unsigned char rtc_data[NUM_TIME_REGS];
125*4882a593Smuzhiyun 	struct i2c_client *client = to_i2c_client(dev);
126*4882a593Smuzhiyun 	struct sd3078 *sd3078 = i2c_get_clientdata(client);
127*4882a593Smuzhiyun 	int ret;
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	rtc_data[SD3078_REG_SC] = bin2bcd(tm->tm_sec);
130*4882a593Smuzhiyun 	rtc_data[SD3078_REG_MN] = bin2bcd(tm->tm_min);
131*4882a593Smuzhiyun 	rtc_data[SD3078_REG_HR] = bin2bcd(tm->tm_hour) | 0x80;
132*4882a593Smuzhiyun 	rtc_data[SD3078_REG_DM] = bin2bcd(tm->tm_mday);
133*4882a593Smuzhiyun 	rtc_data[SD3078_REG_DW] = tm->tm_wday & 0x07;
134*4882a593Smuzhiyun 	rtc_data[SD3078_REG_MO] = bin2bcd(tm->tm_mon) + 1;
135*4882a593Smuzhiyun 	rtc_data[SD3078_REG_YR] = bin2bcd(tm->tm_year - 100);
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun #if WRITE_PROTECT_EN
138*4882a593Smuzhiyun 	sd3078_enable_reg_write(sd3078);
139*4882a593Smuzhiyun #endif
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	ret = regmap_bulk_write(sd3078->regmap, SD3078_REG_SC, rtc_data,
142*4882a593Smuzhiyun 				NUM_TIME_REGS);
143*4882a593Smuzhiyun 	if (ret < 0) {
144*4882a593Smuzhiyun 		dev_err(dev, "writing to RTC failed with err:%d\n", ret);
145*4882a593Smuzhiyun 		return ret;
146*4882a593Smuzhiyun 	}
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun #if WRITE_PROTECT_EN
149*4882a593Smuzhiyun 	sd3078_disable_reg_write(sd3078);
150*4882a593Smuzhiyun #endif
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	return 0;
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun static const struct rtc_class_ops sd3078_rtc_ops = {
156*4882a593Smuzhiyun 	.read_time	= sd3078_rtc_read_time,
157*4882a593Smuzhiyun 	.set_time	= sd3078_rtc_set_time,
158*4882a593Smuzhiyun };
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun static const struct regmap_config regmap_config = {
161*4882a593Smuzhiyun 	.reg_bits = 8,
162*4882a593Smuzhiyun 	.val_bits = 8,
163*4882a593Smuzhiyun 	.max_register = 0x11,
164*4882a593Smuzhiyun };
165*4882a593Smuzhiyun 
sd3078_probe(struct i2c_client * client,const struct i2c_device_id * id)166*4882a593Smuzhiyun static int sd3078_probe(struct i2c_client *client,
167*4882a593Smuzhiyun 			const struct i2c_device_id *id)
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun 	int ret;
170*4882a593Smuzhiyun 	struct sd3078 *sd3078;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
173*4882a593Smuzhiyun 		return -ENODEV;
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	sd3078 = devm_kzalloc(&client->dev, sizeof(*sd3078), GFP_KERNEL);
176*4882a593Smuzhiyun 	if (!sd3078)
177*4882a593Smuzhiyun 		return -ENOMEM;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	sd3078->regmap = devm_regmap_init_i2c(client, &regmap_config);
180*4882a593Smuzhiyun 	if (IS_ERR(sd3078->regmap)) {
181*4882a593Smuzhiyun 		dev_err(&client->dev, "regmap allocation failed\n");
182*4882a593Smuzhiyun 		return PTR_ERR(sd3078->regmap);
183*4882a593Smuzhiyun 	}
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	i2c_set_clientdata(client, sd3078);
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	sd3078->rtc = devm_rtc_allocate_device(&client->dev);
188*4882a593Smuzhiyun 	if (IS_ERR(sd3078->rtc))
189*4882a593Smuzhiyun 		return PTR_ERR(sd3078->rtc);
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	sd3078->rtc->ops = &sd3078_rtc_ops;
192*4882a593Smuzhiyun 	sd3078->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
193*4882a593Smuzhiyun 	sd3078->rtc->range_max = RTC_TIMESTAMP_END_2099;
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun 	ret = rtc_register_device(sd3078->rtc);
196*4882a593Smuzhiyun 	if (ret)
197*4882a593Smuzhiyun 		return ret;
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 	sd3078_enable_reg_write(sd3078);
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	return 0;
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun static const struct i2c_device_id sd3078_id[] = {
205*4882a593Smuzhiyun 	{"sd3078", 0},
206*4882a593Smuzhiyun 	{ }
207*4882a593Smuzhiyun };
208*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, sd3078_id);
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun static const struct of_device_id rtc_dt_match[] = {
211*4882a593Smuzhiyun 	{ .compatible = "whwave,sd3078" },
212*4882a593Smuzhiyun 	{},
213*4882a593Smuzhiyun };
214*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, rtc_dt_match);
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun static struct i2c_driver sd3078_driver = {
217*4882a593Smuzhiyun 	.driver     = {
218*4882a593Smuzhiyun 		.name   = "sd3078",
219*4882a593Smuzhiyun 		.of_match_table = of_match_ptr(rtc_dt_match),
220*4882a593Smuzhiyun 	},
221*4882a593Smuzhiyun 	.probe      = sd3078_probe,
222*4882a593Smuzhiyun 	.id_table   = sd3078_id,
223*4882a593Smuzhiyun };
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun module_i2c_driver(sd3078_driver);
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun MODULE_AUTHOR("Dianlong Li <long17.cool@163.com>");
228*4882a593Smuzhiyun MODULE_DESCRIPTION("SD3078 RTC driver");
229*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
230