aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorDianlong Li <long17.cool@163.com>2018-12-13 05:13:50 -0500
committerAlexandre Belloni <alexandre.belloni@bootlin.com>2019-01-10 15:51:22 -0500
commit1d67a232105b4dec2b10b2689f9cb89cc366d62f (patch)
tree1406e04e62ecb4e086295fd8bb74c860855300d4 /drivers/rtc
parenta1c1eae4690aacd3a7ce9df97b47194ac2bf44e2 (diff)
rtc: sd3078: new driver.
The sd3078 is a combination RTC and SRAM device with I2C interface. Signed-off-by: Dianlong Li <long17.cool@163.com> Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/Kconfig9
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/rtc-sd3078.c232
3 files changed, 242 insertions, 0 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 225b0b8516f3..a24fe8b7b98a 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -646,6 +646,15 @@ config RTC_DRV_S5M
646 This driver can also be built as a module. If so, the module 646 This driver can also be built as a module. If so, the module
647 will be called rtc-s5m. 647 will be called rtc-s5m.
648 648
649config RTC_DRV_SD3078
650 tristate "ZXW Crystal SD3078"
651 help
652 If you say yes here you get support for the ZXW Crystal
653 SD3078 RTC chips.
654
655 This driver can also be built as a module. If so, the module
656 will be called rtc-sd3078
657
649endif # I2C 658endif # I2C
650 659
651comment "SPI RTC drivers" 660comment "SPI RTC drivers"
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index df022d820bee..39eb6de4ad74 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -149,6 +149,7 @@ obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o
149obj-$(CONFIG_RTC_DRV_S5M) += rtc-s5m.o 149obj-$(CONFIG_RTC_DRV_S5M) += rtc-s5m.o
150obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o 150obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o
151obj-$(CONFIG_RTC_DRV_SC27XX) += rtc-sc27xx.o 151obj-$(CONFIG_RTC_DRV_SC27XX) += rtc-sc27xx.o
152obj-$(CONFIG_RTC_DRV_SD3078) += rtc-sd3078.o
152obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o 153obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o
153obj-$(CONFIG_RTC_DRV_SIRFSOC) += rtc-sirfsoc.o 154obj-$(CONFIG_RTC_DRV_SIRFSOC) += rtc-sirfsoc.o
154obj-$(CONFIG_RTC_DRV_SNVS) += rtc-snvs.o 155obj-$(CONFIG_RTC_DRV_SNVS) += rtc-snvs.o
diff --git a/drivers/rtc/rtc-sd3078.c b/drivers/rtc/rtc-sd3078.c
new file mode 100644
index 000000000000..a70d7311d039
--- /dev/null
+++ b/drivers/rtc/rtc-sd3078.c
@@ -0,0 +1,232 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Real Time Clock (RTC) Driver for sd3078
4 * Copyright (C) 2018 Zoro Li
5 */
6
7#include <linux/bcd.h>
8#include <linux/i2c.h>
9#include <linux/module.h>
10#include <linux/regmap.h>
11#include <linux/rtc.h>
12#include <linux/slab.h>
13
14#define SD3078_REG_SC 0x00
15#define SD3078_REG_MN 0x01
16#define SD3078_REG_HR 0x02
17#define SD3078_REG_DW 0x03
18#define SD3078_REG_DM 0x04
19#define SD3078_REG_MO 0x05
20#define SD3078_REG_YR 0x06
21
22#define SD3078_REG_CTRL1 0x0f
23#define SD3078_REG_CTRL2 0x10
24#define SD3078_REG_CTRL3 0x11
25
26#define KEY_WRITE1 0x80
27#define KEY_WRITE2 0x04
28#define KEY_WRITE3 0x80
29
30#define NUM_TIME_REGS (SD3078_REG_YR - SD3078_REG_SC + 1)
31
32/*
33 * The sd3078 has write protection
34 * and we can choose whether or not to use it.
35 * Write protection is turned off by default.
36 */
37#define WRITE_PROTECT_EN 0
38
39struct sd3078 {
40 struct rtc_device *rtc;
41 struct regmap *regmap;
42};
43
44/*
45 * In order to prevent arbitrary modification of the time register,
46 * when modification of the register,
47 * the "write" bit needs to be written in a certain order.
48 * 1. set WRITE1 bit
49 * 2. set WRITE2 bit
50 * 3. set WRITE3 bit
51 */
52static void sd3078_enable_reg_write(struct sd3078 *sd3078)
53{
54 regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL2,
55 KEY_WRITE1, KEY_WRITE1);
56 regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL1,
57 KEY_WRITE2, KEY_WRITE2);
58 regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL1,
59 KEY_WRITE3, KEY_WRITE3);
60}
61
62#if WRITE_PROTECT_EN
63/*
64 * In order to prevent arbitrary modification of the time register,
65 * we should disable the write function.
66 * when disable write,
67 * the "write" bit needs to be clear in a certain order.
68 * 1. clear WRITE2 bit
69 * 2. clear WRITE3 bit
70 * 3. clear WRITE1 bit
71 */
72static void sd3078_disable_reg_write(struct sd3078 *sd3078)
73{
74 regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL1,
75 KEY_WRITE2, 0);
76 regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL1,
77 KEY_WRITE3, 0);
78 regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL2,
79 KEY_WRITE1, 0);
80}
81#endif
82
83static int sd3078_rtc_read_time(struct device *dev, struct rtc_time *tm)
84{
85 unsigned char hour;
86 unsigned char rtc_data[NUM_TIME_REGS] = {0};
87 struct i2c_client *client = to_i2c_client(dev);
88 struct sd3078 *sd3078 = i2c_get_clientdata(client);
89 int ret;
90
91 ret = regmap_bulk_read(sd3078->regmap, SD3078_REG_SC, rtc_data,
92 NUM_TIME_REGS);
93 if (ret < 0) {
94 dev_err(dev, "reading from RTC failed with err:%d\n", ret);
95 return ret;
96 }
97
98 tm->tm_sec = bcd2bin(rtc_data[SD3078_REG_SC] & 0x7F);
99 tm->tm_min = bcd2bin(rtc_data[SD3078_REG_MN] & 0x7F);
100
101 /*
102 * The sd3078 supports 12/24 hour mode.
103 * When getting time,
104 * we need to convert the 12 hour mode to the 24 hour mode.
105 */
106 hour = rtc_data[SD3078_REG_HR];
107 if (hour & 0x80) /* 24H MODE */
108 tm->tm_hour = bcd2bin(rtc_data[SD3078_REG_HR] & 0x3F);
109 else if (hour & 0x20) /* 12H MODE PM */
110 tm->tm_hour = bcd2bin(rtc_data[SD3078_REG_HR] & 0x1F) + 12;
111 else /* 12H MODE AM */
112 tm->tm_hour = bcd2bin(rtc_data[SD3078_REG_HR] & 0x1F);
113
114 tm->tm_mday = bcd2bin(rtc_data[SD3078_REG_DM] & 0x3F);
115 tm->tm_wday = rtc_data[SD3078_REG_DW] & 0x07;
116 tm->tm_mon = bcd2bin(rtc_data[SD3078_REG_MO] & 0x1F) - 1;
117 tm->tm_year = bcd2bin(rtc_data[SD3078_REG_YR]) + 100;
118
119 return 0;
120}
121
122static int sd3078_rtc_set_time(struct device *dev, struct rtc_time *tm)
123{
124 unsigned char rtc_data[NUM_TIME_REGS];
125 struct i2c_client *client = to_i2c_client(dev);
126 struct sd3078 *sd3078 = i2c_get_clientdata(client);
127 int ret;
128
129 rtc_data[SD3078_REG_SC] = bin2bcd(tm->tm_sec);
130 rtc_data[SD3078_REG_MN] = bin2bcd(tm->tm_min);
131 rtc_data[SD3078_REG_HR] = bin2bcd(tm->tm_hour) | 0x80;
132 rtc_data[SD3078_REG_DM] = bin2bcd(tm->tm_mday);
133 rtc_data[SD3078_REG_DW] = tm->tm_wday & 0x07;
134 rtc_data[SD3078_REG_MO] = bin2bcd(tm->tm_mon) + 1;
135 rtc_data[SD3078_REG_YR] = bin2bcd(tm->tm_year - 100);
136
137#if WRITE_PROTECT_EN
138 sd3078_enable_reg_write(sd3078);
139#endif
140
141 ret = regmap_bulk_write(sd3078->regmap, SD3078_REG_SC, rtc_data,
142 NUM_TIME_REGS);
143 if (ret < 0) {
144 dev_err(dev, "writing to RTC failed with err:%d\n", ret);
145 return ret;
146 }
147
148#if WRITE_PROTECT_EN
149 sd3078_disable_reg_write(sd3078);
150#endif
151
152 return 0;
153}
154
155static const struct rtc_class_ops sd3078_rtc_ops = {
156 .read_time = sd3078_rtc_read_time,
157 .set_time = sd3078_rtc_set_time,
158};
159
160static const struct regmap_config regmap_config = {
161 .reg_bits = 8,
162 .val_bits = 8,
163 .max_register = 0x11,
164};
165
166static int sd3078_probe(struct i2c_client *client,
167 const struct i2c_device_id *id)
168{
169 int ret;
170 struct sd3078 *sd3078;
171
172 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
173 return -ENODEV;
174
175 sd3078 = devm_kzalloc(&client->dev, sizeof(*sd3078), GFP_KERNEL);
176 if (!sd3078)
177 return -ENOMEM;
178
179 sd3078->regmap = devm_regmap_init_i2c(client, &regmap_config);
180 if (IS_ERR(sd3078->regmap)) {
181 dev_err(&client->dev, "regmap allocation failed\n");
182 return PTR_ERR(sd3078->regmap);
183 }
184
185 i2c_set_clientdata(client, sd3078);
186
187 sd3078->rtc = devm_rtc_allocate_device(&client->dev);
188 if (IS_ERR(sd3078->rtc))
189 return PTR_ERR(sd3078->rtc);
190
191 sd3078->rtc->ops = &sd3078_rtc_ops;
192 sd3078->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
193 sd3078->rtc->range_max = RTC_TIMESTAMP_END_2099;
194
195 ret = rtc_register_device(sd3078->rtc);
196 if (ret) {
197 dev_err(&client->dev, "failed to register rtc device\n");
198 return ret;
199 }
200
201 sd3078_enable_reg_write(sd3078);
202
203 return 0;
204}
205
206static const struct i2c_device_id sd3078_id[] = {
207 {"sd3078", 0},
208 { }
209};
210MODULE_DEVICE_TABLE(i2c, sd3078_id);
211
212static const struct of_device_id rtc_dt_match[] = {
213 { .compatible = "whwave,sd3078" },
214 {},
215};
216MODULE_DEVICE_TABLE(of, rtc_dt_match);
217
218struct i2c_driver sd3078_driver = {
219 .driver = {
220 .name = "sd3078",
221 .owner = THIS_MODULE,
222 .of_match_table = of_match_ptr(rtc_dt_match),
223 },
224 .probe = sd3078_probe,
225 .id_table = sd3078_id,
226};
227
228module_i2c_driver(sd3078_driver);
229
230MODULE_AUTHOR("Dianlong Li <long17.cool@163.com>");
231MODULE_DESCRIPTION("SD3078 RTC driver");
232MODULE_LICENSE("GPL v2");