blob: 5211d0758689cf2b889f7ae887ef7664e938dc76 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Priyanka Jain09344532010-10-26 14:52:19 +05302/*
3 * Copyright 2010 Freescale Semiconductor, Inc.
Biwen Li22e0a842020-05-01 20:03:57 +08004 * Copyright 2020 NXP
Priyanka Jain09344532010-10-26 14:52:19 +05305 *
6 * Author: Priyanka Jain <Priyanka.Jain@freescale.com>
Priyanka Jain09344532010-10-26 14:52:19 +05307 */
8
9/*
10 * This file provides Date & Time support (no alarms) for PT7C4338 chip.
11 *
12 * This file is based on drivers/rtc/ds1337.c
13 *
14 * PT7C4338 chip is manufactured by Pericom Technology Inc.
15 * It is a serial real-time clock which provides
16 * 1)Low-power clock/calendar.
17 * 2)Programmable square-wave output.
18 * It has 56 bytes of nonvolatile RAM.
19 */
20
21#include <common.h>
22#include <command.h>
Biwen Li22e0a842020-05-01 20:03:57 +080023#include <dm.h>
Priyanka Jain09344532010-10-26 14:52:19 +053024#include <rtc.h>
25#include <i2c.h>
26
27/* RTC register addresses */
28#define RTC_SEC_REG_ADDR 0x0
29#define RTC_MIN_REG_ADDR 0x1
30#define RTC_HR_REG_ADDR 0x2
31#define RTC_DAY_REG_ADDR 0x3
32#define RTC_DATE_REG_ADDR 0x4
33#define RTC_MON_REG_ADDR 0x5
34#define RTC_YR_REG_ADDR 0x6
35#define RTC_CTL_STAT_REG_ADDR 0x7
36
37/* RTC second register address bit */
38#define RTC_SEC_BIT_CH 0x80 /* Clock Halt (in Register 0) */
39
40/* RTC control and status register bits */
41#define RTC_CTL_STAT_BIT_RS0 0x1 /* Rate select 0 */
42#define RTC_CTL_STAT_BIT_RS1 0x2 /* Rate select 1 */
43#define RTC_CTL_STAT_BIT_SQWE 0x10 /* Square Wave Enable */
44#define RTC_CTL_STAT_BIT_OSF 0x20 /* Oscillator Stop Flag */
45#define RTC_CTL_STAT_BIT_OUT 0x80 /* Output Level Control */
46
47/* RTC reset value */
48#define RTC_PT7C4338_RESET_VAL \
49 (RTC_CTL_STAT_BIT_RS0 | RTC_CTL_STAT_BIT_RS1 | RTC_CTL_STAT_BIT_OUT)
50
Biwen Li22e0a842020-05-01 20:03:57 +080051#if !CONFIG_IS_ENABLED(DM_RTC)
Priyanka Jain09344532010-10-26 14:52:19 +053052/****** Helper functions ****************************************/
53static u8 rtc_read(u8 reg)
54{
55 return i2c_reg_read(CONFIG_SYS_I2C_RTC_ADDR, reg);
56}
57
58static void rtc_write(u8 reg, u8 val)
59{
60 i2c_reg_write(CONFIG_SYS_I2C_RTC_ADDR, reg, val);
61}
62/****************************************************************/
63
64/* Get the current time from the RTC */
65int rtc_get(struct rtc_time *tmp)
66{
67 int ret = 0;
68 u8 sec, min, hour, mday, wday, mon, year, ctl_stat;
69
70 ctl_stat = rtc_read(RTC_CTL_STAT_REG_ADDR);
71 sec = rtc_read(RTC_SEC_REG_ADDR);
72 min = rtc_read(RTC_MIN_REG_ADDR);
73 hour = rtc_read(RTC_HR_REG_ADDR);
74 wday = rtc_read(RTC_DAY_REG_ADDR);
75 mday = rtc_read(RTC_DATE_REG_ADDR);
76 mon = rtc_read(RTC_MON_REG_ADDR);
77 year = rtc_read(RTC_YR_REG_ADDR);
78 debug("Get RTC year: %02x mon: %02x mday: %02x wday: %02x "
79 "hr: %02x min: %02x sec: %02x control_status: %02x\n",
80 year, mon, mday, wday, hour, min, sec, ctl_stat);
81
82 if (ctl_stat & RTC_CTL_STAT_BIT_OSF) {
83 printf("### Warning: RTC oscillator has stopped\n");
84 /* clear the OSF flag */
85 rtc_write(RTC_CTL_STAT_REG_ADDR,
86 rtc_read(RTC_CTL_STAT_REG_ADDR)\
87 & ~RTC_CTL_STAT_BIT_OSF);
88 ret = -1;
89 }
90
91 tmp->tm_sec = bcd2bin(sec & 0x7F);
92 tmp->tm_min = bcd2bin(min & 0x7F);
93 tmp->tm_hour = bcd2bin(hour & 0x3F);
94 tmp->tm_mday = bcd2bin(mday & 0x3F);
95 tmp->tm_mon = bcd2bin(mon & 0x1F);
96 tmp->tm_year = bcd2bin(year) + 2000;
97 tmp->tm_wday = bcd2bin((wday - 1) & 0x07);
98 tmp->tm_yday = 0;
99 tmp->tm_isdst = 0;
100 debug("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
101 tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
102 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
103
104 return ret;
105}
106
107/* Set the RTC */
108int rtc_set(struct rtc_time *tmp)
109{
110 debug("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
111 tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
112 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
113
114 rtc_write(RTC_YR_REG_ADDR, bin2bcd(tmp->tm_year % 100));
115 rtc_write(RTC_MON_REG_ADDR, bin2bcd(tmp->tm_mon));
116 rtc_write(RTC_DAY_REG_ADDR, bin2bcd(tmp->tm_wday + 1));
117 rtc_write(RTC_DATE_REG_ADDR, bin2bcd(tmp->tm_mday));
118 rtc_write(RTC_HR_REG_ADDR, bin2bcd(tmp->tm_hour));
119 rtc_write(RTC_MIN_REG_ADDR, bin2bcd(tmp->tm_min));
120 rtc_write(RTC_SEC_REG_ADDR, bin2bcd(tmp->tm_sec));
121
122 return 0;
123}
124
125/* Reset the RTC */
126void rtc_reset(void)
127{
128 rtc_write(RTC_SEC_REG_ADDR, 0x00); /* clearing Clock Halt */
129 rtc_write(RTC_CTL_STAT_REG_ADDR, RTC_PT7C4338_RESET_VAL);
130}
Biwen Li22e0a842020-05-01 20:03:57 +0800131#else
132static u8 rtc_read(struct udevice *dev, u8 reg)
133{
134 return dm_i2c_reg_read(dev, reg);
135}
136
137static void rtc_write(struct udevice *dev, u8 reg, u8 val)
138{
139 dm_i2c_reg_write(dev, reg, val);
140}
141
142static int pt7c4338_rtc_get(struct udevice *dev, struct rtc_time *tmp)
143{
144 int ret = 0;
145 u8 sec, min, hour, mday, wday, mon, year, ctl_stat;
146
147 ctl_stat = rtc_read(dev, RTC_CTL_STAT_REG_ADDR);
148 sec = rtc_read(dev, RTC_SEC_REG_ADDR);
149 min = rtc_read(dev, RTC_MIN_REG_ADDR);
150 hour = rtc_read(dev, RTC_HR_REG_ADDR);
151 wday = rtc_read(dev, RTC_DAY_REG_ADDR);
152 mday = rtc_read(dev, RTC_DATE_REG_ADDR);
153 mon = rtc_read(dev, RTC_MON_REG_ADDR);
154 year = rtc_read(dev, RTC_YR_REG_ADDR);
155 debug("Get RTC year: %02x mon: %02x mday: %02x wday: %02x\n",
156 year, mon, mday, wday);
157 debug("hr: %02x min: %02x sec: %02x control_status: %02x\n",
158 hour, min, sec, ctl_stat);
159
160 if (ctl_stat & RTC_CTL_STAT_BIT_OSF) {
161 printf("### Warning: RTC oscillator has stopped\n");
162 /* clear the OSF flag */
163 rtc_write(dev, RTC_CTL_STAT_REG_ADDR,
164 rtc_read(dev,
165 RTC_CTL_STAT_REG_ADDR)
166 & ~RTC_CTL_STAT_BIT_OSF);
167 ret = -1;
168 }
169
170 tmp->tm_sec = bcd2bin(sec & 0x7F);
171 tmp->tm_min = bcd2bin(min & 0x7F);
172 tmp->tm_hour = bcd2bin(hour & 0x3F);
173 tmp->tm_mday = bcd2bin(mday & 0x3F);
174 tmp->tm_mon = bcd2bin(mon & 0x1F);
175 tmp->tm_year = bcd2bin(year) + 2000;
176 tmp->tm_wday = bcd2bin((wday - 1) & 0x07);
177 tmp->tm_yday = 0;
178 tmp->tm_isdst = 0;
179 debug("Get DATE: %4d-%02d-%02d [wday=%d] TIME: %2d:%02d:%02d\n",
180 tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
181 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
182
183 return ret;
184}
185
186static int pt7c4338_rtc_set(struct udevice *dev, const struct rtc_time *tmp)
187{
188 debug("Set DATE: %4d-%02d-%02d [wday=%d] TIME: %2d:%02d:%02d\n",
189 tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
190 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
191
192 rtc_write(dev, RTC_YR_REG_ADDR, bin2bcd(tmp->tm_year % 100));
193 rtc_write(dev, RTC_MON_REG_ADDR, bin2bcd(tmp->tm_mon));
194 rtc_write(dev, RTC_DAY_REG_ADDR, bin2bcd(tmp->tm_wday + 1));
195 rtc_write(dev, RTC_DATE_REG_ADDR, bin2bcd(tmp->tm_mday));
196 rtc_write(dev, RTC_HR_REG_ADDR, bin2bcd(tmp->tm_hour));
197 rtc_write(dev, RTC_MIN_REG_ADDR, bin2bcd(tmp->tm_min));
198 rtc_write(dev, RTC_SEC_REG_ADDR, bin2bcd(tmp->tm_sec));
199
200 return 0;
201}
202
203static int pt7c4338_rtc_reset(struct udevice *dev)
204{
205 rtc_write(dev, RTC_SEC_REG_ADDR, 0x00); /* clearing Clock Halt */
206 rtc_write(dev, RTC_CTL_STAT_REG_ADDR, RTC_PT7C4338_RESET_VAL);
207 return 0;
208}
209
210static const struct rtc_ops pt7c4338_rtc_ops = {
211 .get = pt7c4338_rtc_get,
212 .set = pt7c4338_rtc_set,
213 .reset = pt7c4338_rtc_reset,
214};
215
216static const struct udevice_id pt7c4338_rtc_ids[] = {
217 { .compatible = "pericom,pt7c4338" },
218 { }
219};
220
221U_BOOT_DRIVER(rtc_pt7c4338) = {
222 .name = "rtc-pt7c4338",
223 .id = UCLASS_RTC,
224 .of_match = pt7c4338_rtc_ids,
225 .ops = &pt7c4338_rtc_ops,
226};
227#endif