1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * RTC driver for the Micro Crystal RV3028
4  *
5  * based on linux driver from
6  * Copyright (C) 2019 Micro Crystal SA
7  *
8  * Alexandre Belloni <alexandre.belloni@bootlin.com>
9  *
10  */
11 
12 #include <dm.h>
13 #include <i2c.h>
14 #include <rtc.h>
15 
16 #define RV3028_SEC			0x00
17 #define RV3028_MIN			0x01
18 #define RV3028_HOUR			0x02
19 #define RV3028_WDAY			0x03
20 #define RV3028_DAY			0x04
21 #define RV3028_MONTH			0x05
22 #define RV3028_YEAR			0x06
23 #define RV3028_ALARM_MIN		0x07
24 #define RV3028_ALARM_HOUR		0x08
25 #define RV3028_ALARM_DAY		0x09
26 #define RV3028_STATUS			0x0E
27 #define RV3028_CTRL1			0x0F
28 #define RV3028_CTRL2			0x10
29 #define RV3028_EVT_CTRL			0x13
30 #define RV3028_TS_COUNT			0x14
31 #define RV3028_TS_SEC			0x15
32 #define RV3028_RAM1			0x1F
33 #define RV3028_EEPROM_ADDR		0x25
34 #define RV3028_EEPROM_DATA		0x26
35 #define RV3028_EEPROM_CMD		0x27
36 #define RV3028_CLKOUT			0x35
37 #define RV3028_OFFSET			0x36
38 #define RV3028_BACKUP			0x37
39 
40 #define RV3028_STATUS_PORF		BIT(0)
41 #define RV3028_STATUS_EVF		BIT(1)
42 #define RV3028_STATUS_AF		BIT(2)
43 #define RV3028_STATUS_TF		BIT(3)
44 #define RV3028_STATUS_UF		BIT(4)
45 #define RV3028_STATUS_BSF		BIT(5)
46 #define RV3028_STATUS_CLKF		BIT(6)
47 #define RV3028_STATUS_EEBUSY		BIT(7)
48 
49 #define RV3028_CLKOUT_FD_MASK		GENMASK(2, 0)
50 #define RV3028_CLKOUT_PORIE		BIT(3)
51 #define RV3028_CLKOUT_CLKSY		BIT(6)
52 #define RV3028_CLKOUT_CLKOE		BIT(7)
53 
54 #define RV3028_CTRL1_EERD		BIT(3)
55 #define RV3028_CTRL1_WADA		BIT(5)
56 
57 #define RV3028_CTRL2_RESET		BIT(0)
58 #define RV3028_CTRL2_12_24		BIT(1)
59 #define RV3028_CTRL2_EIE		BIT(2)
60 #define RV3028_CTRL2_AIE		BIT(3)
61 #define RV3028_CTRL2_TIE		BIT(4)
62 #define RV3028_CTRL2_UIE		BIT(5)
63 #define RV3028_CTRL2_TSE		BIT(7)
64 
65 #define RV3028_EVT_CTRL_TSR		BIT(2)
66 
67 #define RV3028_EEPROM_CMD_UPDATE	0x11
68 #define RV3028_EEPROM_CMD_WRITE		0x21
69 #define RV3028_EEPROM_CMD_READ		0x22
70 
71 #define RV3028_EEBUSY_POLL		10000
72 #define RV3028_EEBUSY_TIMEOUT		100000
73 
74 #define RV3028_BACKUP_TCE		BIT(5)
75 #define RV3028_BACKUP_TCR_MASK		GENMASK(1, 0)
76 
77 #define OFFSET_STEP_PPT			953674
78 
79 #define RTC_RV3028_LEN			7
80 
rv3028_rtc_get(struct udevice * dev,struct rtc_time * tm)81 static int rv3028_rtc_get(struct udevice *dev, struct rtc_time *tm)
82 {
83 	u8 regs[RTC_RV3028_LEN];
84 	u8 status;
85 	int ret;
86 
87 	ret = dm_i2c_read(dev, RV3028_STATUS, &status, 1);
88 	if (ret < 0) {
89 		printf("%s: error reading RTC status: %x\n", __func__, ret);
90 		return -EIO;
91 	}
92 
93 	if (status & RV3028_STATUS_PORF) {
94 		printf("Voltage low, data is invalid.\n");
95 		return -EINVAL;
96 	}
97 
98 	ret = dm_i2c_read(dev, RV3028_SEC, regs, sizeof(regs));
99 	if (ret < 0) {
100 		printf("%s: error reading RTC: %x\n", __func__, ret);
101 		return -EIO;
102 	}
103 
104 	tm->tm_sec = bcd2bin(regs[RV3028_SEC] & 0x7f);
105 	tm->tm_min = bcd2bin(regs[RV3028_MIN] & 0x7f);
106 	tm->tm_hour = bcd2bin(regs[RV3028_HOUR] & 0x3f);
107 	tm->tm_wday = regs[RV3028_WDAY] & 0x7;
108 	tm->tm_mday = bcd2bin(regs[RV3028_DAY] & 0x3f);
109 	tm->tm_mon  = bcd2bin(regs[RV3028_MONTH] & 0x1f);
110 	tm->tm_year = bcd2bin(regs[RV3028_YEAR]) + 2000;
111 	tm->tm_yday = 0;
112 	tm->tm_isdst = 0;
113 
114 	debug("%s: %4d-%02d-%02d (wday=%d) %2d:%02d:%02d\n",
115 	      __func__, tm->tm_year, tm->tm_mon, tm->tm_mday,
116 	      tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec);
117 
118 	return 0;
119 }
120 
rv3028_rtc_set(struct udevice * dev,const struct rtc_time * tm)121 static int rv3028_rtc_set(struct udevice *dev, const struct rtc_time *tm)
122 {
123 	u8 regs[RTC_RV3028_LEN];
124 	u8 status;
125 	int ret;
126 
127 	debug("%s: %4d-%02d-%02d (wday=%d( %2d:%02d:%02d\n",
128 	      __func__, tm->tm_year, tm->tm_mon, tm->tm_mday,
129 	      tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec);
130 
131 	if (tm->tm_year < 2000) {
132 		printf("%s: year %d (before 2000) not supported\n",
133 		       __func__, tm->tm_year);
134 		return -EINVAL;
135 	}
136 
137 	regs[RV3028_SEC] = bin2bcd(tm->tm_sec);
138 	regs[RV3028_MIN] = bin2bcd(tm->tm_min);
139 	regs[RV3028_HOUR] = bin2bcd(tm->tm_hour);
140 	regs[RV3028_WDAY]  = tm->tm_wday;
141 	regs[RV3028_DAY]   = bin2bcd(tm->tm_mday);
142 	regs[RV3028_MONTH] = bin2bcd(tm->tm_mon);
143 	regs[RV3028_YEAR]  = bin2bcd(tm->tm_year - 2000);
144 
145 	ret = dm_i2c_write(dev, RV3028_SEC, regs, sizeof(regs));
146 	if (ret) {
147 		printf("%s: set rtc error: %d\n", __func__, ret);
148 		return ret;
149 	}
150 
151 	ret = dm_i2c_read(dev, RV3028_STATUS, &status, 1);
152 	if (ret < 0) {
153 		printf("%s: error reading RTC status: %x\n", __func__, ret);
154 		return -EIO;
155 	}
156 	status |= RV3028_STATUS_PORF;
157 	return dm_i2c_write(dev, RV3028_STATUS, &status, 1);
158 }
159 
rv3028_rtc_reset(struct udevice * dev)160 static int rv3028_rtc_reset(struct udevice *dev)
161 {
162 	return 0;
163 }
164 
rv3028_rtc_read8(struct udevice * dev,unsigned int reg)165 static int rv3028_rtc_read8(struct udevice *dev, unsigned int reg)
166 {
167 	u8 data;
168 	int ret;
169 
170 	ret = dm_i2c_read(dev, reg, &data, sizeof(data));
171 	return ret < 0 ? ret : data;
172 }
173 
rv3028_rtc_write8(struct udevice * dev,unsigned int reg,int val)174 static int rv3028_rtc_write8(struct udevice *dev, unsigned int reg, int val)
175 {
176 	u8 data = val;
177 
178 	return dm_i2c_write(dev, reg, &data, 1);
179 }
180 
rv3028_probe(struct udevice * dev)181 static int rv3028_probe(struct udevice *dev)
182 {
183 	i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS |
184 				DM_I2C_CHIP_WR_ADDRESS);
185 
186 	return 0;
187 }
188 
189 static const struct rtc_ops rv3028_rtc_ops = {
190 	.get = rv3028_rtc_get,
191 	.set = rv3028_rtc_set,
192 	.read8 = rv3028_rtc_read8,
193 	.write8 = rv3028_rtc_write8,
194 	.reset = rv3028_rtc_reset,
195 };
196 
197 static const struct udevice_id rv3028_rtc_ids[] = {
198 	{ .compatible = "microcrystal,rv3028" },
199 	{ }
200 };
201 
202 U_BOOT_DRIVER(rtc_rv3028) = {
203 	.name	= "rtc-rv3028",
204 	.id	= UCLASS_RTC,
205 	.probe	= rv3028_probe,
206 	.of_match = rv3028_rtc_ids,
207 	.ops	= &rv3028_rtc_ops,
208 };
209