1 // SPDX-License-Identifier: GPL-2.0
3 * Real Time Clock (RTC) Driver for sd3078
4 * Copyright (C) 2018 Zoro Li
9 #include <linux/module.h>
10 #include <linux/regmap.h>
11 #include <linux/rtc.h>
12 #include <linux/slab.h>
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
22 #define SD3078_REG_CTRL1 0x0f
23 #define SD3078_REG_CTRL2 0x10
24 #define SD3078_REG_CTRL3 0x11
26 #define KEY_WRITE1 0x80
27 #define KEY_WRITE2 0x04
28 #define KEY_WRITE3 0x80
30 #define NUM_TIME_REGS (SD3078_REG_YR - SD3078_REG_SC + 1)
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.
37 #define WRITE_PROTECT_EN 0
40 struct rtc_device
*rtc
;
41 struct regmap
*regmap
;
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.
52 static void sd3078_enable_reg_write(struct sd3078
*sd3078
)
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
);
64 * In order to prevent arbitrary modification of the time register,
65 * we should disable the write function.
67 * the "write" bit needs to be clear in a certain order.
72 static void sd3078_disable_reg_write(struct sd3078
*sd3078
)
74 regmap_update_bits(sd3078
->regmap
, SD3078_REG_CTRL1
,
76 regmap_update_bits(sd3078
->regmap
, SD3078_REG_CTRL1
,
78 regmap_update_bits(sd3078
->regmap
, SD3078_REG_CTRL2
,
83 static int sd3078_rtc_read_time(struct device
*dev
, struct rtc_time
*tm
)
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
);
91 ret
= regmap_bulk_read(sd3078
->regmap
, SD3078_REG_SC
, rtc_data
,
94 dev_err(dev
, "reading from RTC failed with err:%d\n", ret
);
98 tm
->tm_sec
= bcd2bin(rtc_data
[SD3078_REG_SC
] & 0x7F);
99 tm
->tm_min
= bcd2bin(rtc_data
[SD3078_REG_MN
] & 0x7F);
102 * The sd3078 supports 12/24 hour mode.
104 * we need to convert the 12 hour mode to the 24 hour mode.
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);
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;
122 static int sd3078_rtc_set_time(struct device
*dev
, struct rtc_time
*tm
)
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
);
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);
138 sd3078_enable_reg_write(sd3078
);
141 ret
= regmap_bulk_write(sd3078
->regmap
, SD3078_REG_SC
, rtc_data
,
144 dev_err(dev
, "writing to RTC failed with err:%d\n", ret
);
149 sd3078_disable_reg_write(sd3078
);
155 static const struct rtc_class_ops sd3078_rtc_ops
= {
156 .read_time
= sd3078_rtc_read_time
,
157 .set_time
= sd3078_rtc_set_time
,
160 static const struct regmap_config regmap_config
= {
163 .max_register
= 0x11,
166 static int sd3078_probe(struct i2c_client
*client
,
167 const struct i2c_device_id
*id
)
170 struct sd3078
*sd3078
;
172 if (!i2c_check_functionality(client
->adapter
, I2C_FUNC_I2C
))
175 sd3078
= devm_kzalloc(&client
->dev
, sizeof(*sd3078
), GFP_KERNEL
);
179 sd3078
->regmap
= devm_regmap_init_i2c(client
, ®map_config
);
180 if (IS_ERR(sd3078
->regmap
)) {
181 dev_err(&client
->dev
, "regmap allocation failed\n");
182 return PTR_ERR(sd3078
->regmap
);
185 i2c_set_clientdata(client
, sd3078
);
187 sd3078
->rtc
= devm_rtc_allocate_device(&client
->dev
);
188 if (IS_ERR(sd3078
->rtc
))
189 return PTR_ERR(sd3078
->rtc
);
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
;
195 ret
= rtc_register_device(sd3078
->rtc
);
199 sd3078_enable_reg_write(sd3078
);
204 static const struct i2c_device_id sd3078_id
[] = {
208 MODULE_DEVICE_TABLE(i2c
, sd3078_id
);
210 static const struct of_device_id rtc_dt_match
[] = {
211 { .compatible
= "whwave,sd3078" },
214 MODULE_DEVICE_TABLE(of
, rtc_dt_match
);
216 static struct i2c_driver sd3078_driver
= {
219 .of_match_table
= of_match_ptr(rtc_dt_match
),
221 .probe
= sd3078_probe
,
222 .id_table
= sd3078_id
,
225 module_i2c_driver(sd3078_driver
);
227 MODULE_AUTHOR("Dianlong Li <long17.cool@163.com>");
228 MODULE_DESCRIPTION("SD3078 RTC driver");
229 MODULE_LICENSE("GPL v2");