Skip to content

Commit bf053c1

Browse files
committed
[dm][rtc] add new drivers
1. Dallas/Maxim DS1302 2. Dallas/Maxim DS1307/37/38/39/40, ST M41T11 3. Goldfish Real Time Clock 4. Haoyu Microelectronics HYM8563 5. NXP PCF8523 6. Philips PCF8563/Epson RTC8564 7. ARM PL031 8. Epson RX8010SJ Signed-off-by: GuEe-GUI <[email protected]>
1 parent a083fb9 commit bf053c1

File tree

10 files changed

+4156
-0
lines changed

10 files changed

+4156
-0
lines changed

components/drivers/rtc/Kconfig

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,60 @@ menuconfig RT_USING_RTC
3131
default n
3232
endif
3333

34+
config RT_RTC_DS1302
35+
bool "Dallas/Maxim DS1302"
36+
depends on RT_USING_DM
37+
depends on RT_USING_RTC
38+
depends on RT_USING_SPI
39+
default n
40+
41+
config RT_RTC_DS1307
42+
bool "Dallas/Maxim DS1307/37/38/39/40, ST M41T11"
43+
depends on RT_USING_DM
44+
depends on RT_USING_RTC
45+
depends on RT_USING_I2C
46+
default n
47+
48+
config RT_RTC_GOLDFISH
49+
bool "Goldfish Real Time Clock"
50+
depends on RT_USING_DM
51+
depends on RT_USING_RTC
52+
default n
53+
54+
config RT_RTC_HYM8563
55+
bool "Haoyu Microelectronics HYM8563"
56+
depends on RT_USING_DM
57+
depends on RT_USING_RTC
58+
depends on RT_USING_I2C
59+
default n
60+
61+
config RT_RTC_PCF8523
62+
bool "NXP PCF8523"
63+
depends on RT_USING_DM
64+
depends on RT_USING_RTC
65+
depends on RT_USING_I2C
66+
default n
67+
68+
config RT_RTC_PCF8563
69+
bool "Philips PCF8563/Epson RTC8564"
70+
depends on RT_USING_DM
71+
depends on RT_USING_RTC
72+
depends on RT_USING_I2C
73+
default n
74+
75+
config RT_RTC_PL031
76+
bool "ARM PL031"
77+
depends on RT_USING_DM
78+
depends on RT_USING_RTC
79+
default n
80+
81+
config RT_RTC_RX8010
82+
bool "Epson RX8010SJ"
83+
depends on RT_USING_DM
84+
depends on RT_USING_RTC
85+
depends on RT_USING_I2C
86+
default n
87+
3488
if RT_USING_DM && RT_USING_RTC
3589
osource "$(SOC_DM_RTC_DIR)/Kconfig"
3690
endif

components/drivers/rtc/SConscript

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,30 @@ if GetDepend(['RT_USING_RTC']):
1616
if GetDepend(['RT_USING_DM']):
1717
src += ['rtc_dm.c']
1818

19+
if GetDepend(['RT_RTC_DS1302']):
20+
src += ['rtc-ds1302.c']
21+
22+
if GetDepend(['RT_RTC_DS1307']):
23+
src += ['rtc-ds1307.c']
24+
25+
if GetDepend(['RT_RTC_GOLDFISH']):
26+
src += ['rtc-goldfish.c']
27+
28+
if GetDepend(['RT_RTC_HYM8563']):
29+
src += ['rtc-hym8563.c']
30+
31+
if GetDepend(['RT_RTC_PCF8523']):
32+
src += ['rtc-pcf8523.c']
33+
34+
if GetDepend(['RT_RTC_PCF8563']):
35+
src += ['rtc-pcf8563.c']
36+
37+
if GetDepend(['RT_RTC_PL031']):
38+
src += ['rtc-pl031.c']
39+
40+
if GetDepend(['RT_RTC_RX8010']):
41+
src += ['rtc-rx8010.c']
42+
1943
group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_RTC'], CPPPATH = CPPPATH)
2044

2145
Return('group')
Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
/*
2+
* Copyright (c) 2006-2022, RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Change Logs:
7+
* Date Author Notes
8+
* 2023-09-23 GuEe-GUI first version
9+
*/
10+
11+
#include "rtc_dm.h"
12+
13+
#define DBG_TAG "rtc.ds1302"
14+
#define DBG_LVL DBG_INFO
15+
#include <rtdbg.h>
16+
17+
#define RTC_CMD_READ 0x81 /* Read command */
18+
#define RTC_CMD_WRITE 0x80 /* Write command */
19+
20+
#define RTC_CMD_WRITE_ENABLE 0x00 /* Write enable */
21+
#define RTC_CMD_WRITE_DISABLE 0x80 /* Write disable */
22+
23+
#define RTC_ADDR_RAM0 0x20 /* Address of RAM0 */
24+
#define RTC_ADDR_TCR 0x08 /* Address of trickle charge register */
25+
#define RTC_CLCK_BURST 0x1F /* Address of clock burst */
26+
#define RTC_CLCK_LEN 0x08 /* Size of clock burst */
27+
#define RTC_ADDR_CTRL 0x07 /* Address of control register */
28+
#define RTC_ADDR_YEAR 0x06 /* Address of year register */
29+
#define RTC_ADDR_DAY 0x05 /* Address of day of week register */
30+
#define RTC_ADDR_MON 0x04 /* Address of month register */
31+
#define RTC_ADDR_DATE 0x03 /* Address of day of month register */
32+
#define RTC_ADDR_HOUR 0x02 /* Address of hour register */
33+
#define RTC_ADDR_MIN 0x01 /* Address of minute register */
34+
#define RTC_ADDR_SEC 0x00 /* Address of second register */
35+
36+
static rt_err_t ds1302_rtc_get_time(struct rt_spi_device *spi_dev, time_t *sec)
37+
{
38+
struct tm tm;
39+
rt_err_t err;
40+
rt_uint8_t addr = RTC_CLCK_BURST << 1 | RTC_CMD_READ, buf[RTC_CLCK_LEN - 1];
41+
42+
err = rt_spi_send_then_recv(spi_dev, &addr, sizeof(addr), buf, sizeof(buf));
43+
44+
if (err)
45+
{
46+
return err;
47+
}
48+
49+
/* Decode the registers */
50+
tm.tm_sec = rt_bcd2bin(buf[RTC_ADDR_SEC]);
51+
tm.tm_min = rt_bcd2bin(buf[RTC_ADDR_MIN]);
52+
tm.tm_hour = rt_bcd2bin(buf[RTC_ADDR_HOUR]);
53+
tm.tm_wday = buf[RTC_ADDR_DAY] - 1;
54+
tm.tm_mday = rt_bcd2bin(buf[RTC_ADDR_DATE]);
55+
tm.tm_mon = rt_bcd2bin(buf[RTC_ADDR_MON]) - 1;
56+
tm.tm_year = rt_bcd2bin(buf[RTC_ADDR_YEAR]) + 100;
57+
58+
*sec = timegm(&tm);
59+
60+
return RT_EOK;
61+
}
62+
63+
static rt_err_t ds1302_rtc_set_time(struct rt_spi_device *spi_dev, time_t *sec)
64+
{
65+
rt_err_t err;
66+
struct tm *tm;
67+
rt_uint8_t buf[1 + RTC_CLCK_LEN], *bp;
68+
69+
tm = localtime(sec);
70+
71+
/* Enable writing */
72+
bp = buf;
73+
*bp++ = RTC_ADDR_CTRL << 1 | RTC_CMD_WRITE;
74+
*bp++ = RTC_CMD_WRITE_ENABLE;
75+
76+
err = rt_spi_send_then_recv(spi_dev, buf, 2, RT_NULL, 0);
77+
78+
if (err)
79+
{
80+
return err;
81+
}
82+
83+
/* Write registers starting at the first time/date address. */
84+
bp = buf;
85+
*bp++ = RTC_CLCK_BURST << 1 | RTC_CMD_WRITE;
86+
87+
*bp++ = rt_bin2bcd(tm->tm_sec);
88+
*bp++ = rt_bin2bcd(tm->tm_min);
89+
*bp++ = rt_bin2bcd(tm->tm_hour);
90+
*bp++ = rt_bin2bcd(tm->tm_mday);
91+
*bp++ = rt_bin2bcd(tm->tm_mon + 1);
92+
*bp++ = tm->tm_wday + 1;
93+
*bp++ = rt_bin2bcd(tm->tm_year % 100);
94+
*bp++ = RTC_CMD_WRITE_DISABLE;
95+
96+
return rt_spi_send_then_recv(spi_dev, buf, sizeof(buf), RT_NULL, 0);
97+
}
98+
99+
static rt_err_t ds1302_rtc_control(rt_device_t dev, int cmd, void *args)
100+
{
101+
rt_err_t err = RT_EOK;
102+
struct rt_spi_device *spi_dev = dev->user_data;
103+
104+
if (!args)
105+
{
106+
return -RT_EINVAL;
107+
}
108+
109+
switch (cmd)
110+
{
111+
case RT_DEVICE_CTRL_RTC_GET_TIME:
112+
err = ds1302_rtc_get_time(spi_dev, args);
113+
break;
114+
115+
case RT_DEVICE_CTRL_RTC_SET_TIME:
116+
err = ds1302_rtc_set_time(spi_dev, args);
117+
break;
118+
119+
case RT_DEVICE_CTRL_RTC_GET_TIMEVAL:
120+
err = ds1302_rtc_get_time(spi_dev, (time_t *)&((struct timeval *)args)->tv_sec);
121+
break;
122+
123+
case RT_DEVICE_CTRL_RTC_SET_TIMEVAL:
124+
err = ds1302_rtc_set_time(spi_dev, (time_t *)&((struct timeval *)args)->tv_sec);
125+
break;
126+
127+
case RT_DEVICE_CTRL_RTC_GET_ALARM:
128+
case RT_DEVICE_CTRL_RTC_SET_ALARM:
129+
err = -RT_ENOSYS;
130+
break;
131+
132+
default:
133+
err = -RT_EINVAL;
134+
break;
135+
}
136+
137+
return err;
138+
}
139+
140+
#ifdef RT_USING_DEVICE_OPS
141+
const static struct rt_device_ops ds1302_rtc_ops =
142+
{
143+
.control = ds1302_rtc_control,
144+
};
145+
#endif
146+
147+
static rt_err_t ds1302_rtc_probe(struct rt_spi_device *spi_dev)
148+
{
149+
rt_err_t err = RT_EOK;
150+
const char *dev_name;
151+
rt_uint8_t addr, buf[4];
152+
153+
if (spi_dev->config.max_hz > 2000000)
154+
{
155+
LOG_E("Speed is too high");
156+
return -RT_EINVAL;
157+
}
158+
else if (spi_dev->config.mode & RT_SPI_CPHA)
159+
{
160+
LOG_E("Bad mode");
161+
return -RT_EINVAL;
162+
}
163+
164+
addr = RTC_ADDR_CTRL << 1 | RTC_CMD_READ;
165+
166+
if ((err = rt_spi_send_then_recv(spi_dev, &addr, sizeof(addr), buf, 1)))
167+
{
168+
LOG_E("Control register read error = %s", rt_strerror(err));
169+
return err;
170+
}
171+
172+
if ((buf[0] & ~RTC_CMD_WRITE_DISABLE) != 0)
173+
{
174+
if ((err = rt_spi_send_then_recv(spi_dev, &addr, sizeof(addr), buf, 1)))
175+
{
176+
LOG_E("Control register read error = %s", rt_strerror(err));
177+
return err;
178+
}
179+
180+
if ((buf[0] & ~RTC_CMD_WRITE_DISABLE) != 0)
181+
{
182+
LOG_E("Junk in control register");
183+
return -RT_EIO;
184+
}
185+
}
186+
187+
if (buf[0] == 0)
188+
{
189+
buf[0] = RTC_ADDR_CTRL << 1 | RTC_CMD_WRITE;
190+
buf[1] = RTC_CMD_WRITE_DISABLE;
191+
192+
if ((err = rt_spi_send_then_recv(spi_dev, buf, 2, RT_NULL, 0)))
193+
{
194+
LOG_E("Control register write error = %s", rt_strerror(err));
195+
return err;
196+
}
197+
198+
addr = RTC_ADDR_CTRL << 1 | RTC_CMD_READ;
199+
200+
if ((err = rt_spi_send_then_recv(spi_dev, &addr, sizeof(addr), buf, 1)))
201+
{
202+
LOG_E("Reading control register error = %s", rt_strerror(err));
203+
return err;
204+
}
205+
206+
if (buf[0] != RTC_CMD_WRITE_DISABLE)
207+
{
208+
LOG_E("Failed to detect chip");
209+
return -RT_EIO;
210+
}
211+
}
212+
213+
spi_dev->parent.user_data = spi_dev;
214+
215+
spi_dev->parent.type = RT_Device_Class_RTC;
216+
#ifdef RT_USING_DEVICE_OPS
217+
spi_dev->parent.ops = &ds1302_rtc_ops;
218+
#else
219+
spi_dev->parent.control = ds1302_rtc_control;
220+
#endif
221+
222+
rtc_dev_set_name(&spi_dev->parent);
223+
dev_name = rt_dm_dev_get_name(&spi_dev->parent);
224+
err = rt_device_register(&spi_dev->parent, dev_name, RT_DEVICE_FLAG_RDWR);
225+
226+
return err;
227+
}
228+
229+
static rt_err_t ds1302_rtc_remove(struct rt_spi_device *spi_dev)
230+
{
231+
rt_device_unregister(&spi_dev->parent);
232+
233+
return RT_EOK;
234+
}
235+
236+
static const struct rt_spi_device_id ds1302_rtc_ids[] =
237+
{
238+
{ .name = "ds1302" },
239+
{ /* sentinel */ },
240+
};
241+
242+
static const struct rt_ofw_node_id ds1302_rtc_ofw_ids[] =
243+
{
244+
{ .compatible = "maxim,ds1302" },
245+
{ /* sentinel */ },
246+
};
247+
248+
static struct rt_spi_driver ds1302_rtc_driver =
249+
{
250+
.ids = ds1302_rtc_ids,
251+
.ofw_ids = ds1302_rtc_ofw_ids,
252+
253+
.probe = ds1302_rtc_probe,
254+
.remove = ds1302_rtc_remove,
255+
};
256+
RT_SPI_DRIVER_EXPORT(ds1302_rtc_driver);

0 commit comments

Comments
 (0)