xref: /linux/drivers/rtc/rtc-spacemit-p1.c (revision e3966940559d52aa1800a008dcfeec218dd31f88)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Driver for the RTC found in the SpacemiT P1 PMIC
4  *
5  * Copyright (C) 2025 by RISCstar Solutions Corporation.  All rights reserved.
6  */
7 
8 #include <linux/bits.h>
9 #include <linux/device.h>
10 #include <linux/module.h>
11 #include <linux/platform_device.h>
12 #include <linux/regmap.h>
13 #include <linux/rtc.h>
14 
15 #define MOD_NAME	"spacemit-p1-rtc"
16 
17 /*
18  * Six consecutive 1-byte registers hold the seconds, minutes, hours,
19  * day-of-month, month, and year (respectively).
20  *
21  * The range of values in these registers is:
22  *    seconds	0-59
23  *    minutes	0-59
24  *    hours	0-59
25  *    day	0-30 (struct tm is 1-31)
26  *    month	0-11
27  *    year	years since 2000 (struct tm is since 1900)
28  *
29  * Note that the day and month must be converted after reading and
30  * before writing.
31  */
32 #define RTC_TIME		0x0d	/* Offset of the seconds register */
33 
34 #define RTC_CTRL		0x1d
35 #define RTC_EN		BIT(2)
36 
37 /* Number of attempts to read a consistent time stamp before giving up */
38 #define RTC_READ_TRIES		20	/* At least 1 */
39 
40 struct p1_rtc {
41 	struct regmap *regmap;
42 	struct rtc_device *rtc;
43 };
44 
45 /*
46  * The P1 hardware documentation states that the register values are
47  * latched to ensure a consistent time snapshot within the registers,
48  * but these are in fact unstable due to a bug in the hardware design.
49  * So we loop until we get two identical readings.
50  */
51 static int p1_rtc_read_time(struct device *dev, struct rtc_time *t)
52 {
53 	struct p1_rtc *p1 = dev_get_drvdata(dev);
54 	struct regmap *regmap = p1->regmap;
55 	u32 count = RTC_READ_TRIES;
56 	u8 seconds;
57 	u8 time[6];
58 	int ret;
59 
60 	if (!regmap_test_bits(regmap, RTC_CTRL, RTC_EN))
61 		return -EINVAL;		/* RTC is disabled */
62 
63 	ret = regmap_bulk_read(regmap, RTC_TIME, time, sizeof(time));
64 	if (ret)
65 		return ret;
66 
67 	do {
68 		seconds = time[0];
69 		ret = regmap_bulk_read(regmap, RTC_TIME, time, sizeof(time));
70 		if (ret)
71 			return ret;
72 	} while (time[0] != seconds && --count);
73 
74 	if (!count)
75 		return -EIO;		/* Unable to get a consistent result */
76 
77 	t->tm_sec = time[0] & GENMASK(5, 0);
78 	t->tm_min = time[1] & GENMASK(5, 0);
79 	t->tm_hour = time[2] & GENMASK(4, 0);
80 	t->tm_mday = (time[3] & GENMASK(4, 0)) + 1;
81 	t->tm_mon = time[4] & GENMASK(3, 0);
82 	t->tm_year = (time[5] & GENMASK(5, 0)) + 100;
83 
84 	return 0;
85 }
86 
87 /*
88  * The P1 hardware documentation states that values in the registers are
89  * latched so when written they represent a consistent time snapshot.
90  * Nevertheless, this is not guaranteed by the implementation, so we must
91  * disable the RTC while updating it.
92  */
93 static int p1_rtc_set_time(struct device *dev, struct rtc_time *t)
94 {
95 	struct p1_rtc *p1 = dev_get_drvdata(dev);
96 	struct regmap *regmap = p1->regmap;
97 	u8 time[6];
98 	int ret;
99 
100 	time[0] = t->tm_sec;
101 	time[1] = t->tm_min;
102 	time[2] = t->tm_hour;
103 	time[3] = t->tm_mday - 1;
104 	time[4] = t->tm_mon;
105 	time[5] = t->tm_year - 100;
106 
107 	/* Disable the RTC to update; re-enable again when done */
108 	ret = regmap_clear_bits(regmap, RTC_CTRL, RTC_EN);
109 	if (ret)
110 		return ret;
111 
112 	/* If something goes wrong, leave the RTC disabled */
113 	ret = regmap_bulk_write(regmap, RTC_TIME, time, sizeof(time));
114 	if (ret)
115 		return ret;
116 
117 	return regmap_set_bits(regmap, RTC_CTRL, RTC_EN);
118 }
119 
120 static const struct rtc_class_ops p1_rtc_class_ops = {
121 	.read_time = p1_rtc_read_time,
122 	.set_time = p1_rtc_set_time,
123 };
124 
125 static int p1_rtc_probe(struct platform_device *pdev)
126 {
127 	struct device *dev = &pdev->dev;
128 	struct rtc_device *rtc;
129 	struct p1_rtc *p1;
130 
131 	p1 = devm_kzalloc(dev, sizeof(*p1), GFP_KERNEL);
132 	if (!p1)
133 		return -ENOMEM;
134 	dev_set_drvdata(dev, p1);
135 
136 	p1->regmap = dev_get_regmap(dev->parent, NULL);
137 	if (!p1->regmap)
138 		return dev_err_probe(dev, -ENODEV, "failed to get regmap\n");
139 
140 	rtc = devm_rtc_allocate_device(dev);
141 	if (IS_ERR(rtc))
142 		return dev_err_probe(dev, PTR_ERR(rtc),
143 				     "error allocating device\n");
144 	p1->rtc = rtc;
145 
146 	rtc->ops = &p1_rtc_class_ops;
147 	rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
148 	rtc->range_max = RTC_TIMESTAMP_END_2063;
149 
150 	clear_bit(RTC_FEATURE_ALARM, rtc->features);
151 	clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->features);
152 
153 	return devm_rtc_register_device(rtc);
154 }
155 
156 static struct platform_driver p1_rtc_driver = {
157 	.probe = p1_rtc_probe,
158 	.driver = {
159 		.name = MOD_NAME,
160 	},
161 };
162 
163 module_platform_driver(p1_rtc_driver);
164 
165 MODULE_DESCRIPTION("SpacemiT P1 RTC driver");
166 MODULE_LICENSE("GPL");
167 MODULE_ALIAS("platform:" MOD_NAME);
168