Skip to content

Commit

Permalink
drivers: rtc: rts5912: add rtc driver
Browse files Browse the repository at this point in the history
Add rtc driver for Realtek rts5912.

Signed-off-by: Chia-Yang Lin <[email protected]>
  • Loading branch information
cylin-realtek committed Feb 27, 2025
1 parent 7e18f80 commit 910f865
Show file tree
Hide file tree
Showing 8 changed files with 267 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/rtc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ zephyr_library_sources_ifdef(CONFIG_RTC_SMARTBOND rtc_smartbond.c)
zephyr_library_sources_ifdef(CONFIG_RTC_ATMEL_SAM rtc_sam.c)
zephyr_library_sources_ifdef(CONFIG_RTC_ATMEL_SAM0 rtc_sam0.c)
zephyr_library_sources_ifdef(CONFIG_RTC_RPI_PICO rtc_rpi_pico.c)
zephyr_library_sources_ifdef(CONFIG_RTC_RTS5912 rtc_rts5912.c)
zephyr_library_sources_ifdef(CONFIG_RTC_RV3028 rtc_rv3028.c)
zephyr_library_sources_ifdef(CONFIG_RTC_NUMAKER rtc_numaker.c)
zephyr_library_sources_ifdef(CONFIG_RTC_XMC4XXX rtc_xmc4xxx.c)
Expand Down
1 change: 1 addition & 0 deletions drivers/rtc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ source "drivers/rtc/Kconfig.mc146818"
source "drivers/rtc/Kconfig.pcf8523"
source "drivers/rtc/Kconfig.pcf8563"
source "drivers/rtc/Kconfig.rpi_pico"
source "drivers/rtc/Kconfig.rts5912"
source "drivers/rtc/Kconfig.rv3028"
source "drivers/rtc/Kconfig.sam"
source "drivers/rtc/Kconfig.sam0"
Expand Down
9 changes: 9 additions & 0 deletions drivers/rtc/Kconfig.rts5912
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright (c) 2025, Realtek, SIBG-SD7
# SPDX-License-Identifier: Apache-2.0

config RTC_RTS5912
bool "Realtek RTS5912 rtc driver"
default y
depends on DT_HAS_REALTEK_RTS5912_RTC_ENABLED
help
Enable support for Realtek RTC driver.
158 changes: 158 additions & 0 deletions drivers/rtc/rtc_rts5912.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2025 Realtek Semiconductor Corporation, SIBG-SD7
* Author: Chia-Yang Lin <[email protected]>
*/

#define DT_DRV_COMPAT realtek_rts5912_rtc

#include <soc.h>
#include <errno.h>
#include <zephyr/device.h>
#include <zephyr/drivers/rtc.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/clock_control/clock_control_rts5912.h>
#include "rtc_utils.h"

#include "reg/reg_system.h"
#include "reg/reg_rtc.h"

LOG_MODULE_REGISTER(rtc_rts5912, CONFIG_RTC_LOG_LEVEL);

#define RTS5912_RTC_TIME_MASK \
(RTC_ALARM_TIME_MASK_SECOND | RTC_ALARM_TIME_MASK_MINUTE | RTC_ALARM_TIME_MASK_HOUR | \
RTC_ALARM_TIME_MASK_WEEKDAY | RTC_ALARM_TIME_MASK_MONTHDAY | RTC_ALARM_TIME_MASK_MONTH | \
RTC_ALARM_TIME_MASK_YEAR)

#define RTS5912_RTC_DIVCTL_NORMAL_OPERATION BIT(1)

#define RTS5912_RTC_DAYWEEK_OFFSET 1
#define RTS5912_RTC_MONTH_OFFSET 1
#define RTS5912_RTC_YEAR_OFFSET 100

struct rtc_rts5912_config {
RTC_Type *regs;
uint32_t rtc_base;
uint32_t rtc_clk_grp;
uint32_t rtc_clk_idx;
const struct device *clk_dev;
};

struct rtc_rts5912_data {
struct k_spinlock lock;
};

static void rtc_rts5912_reset_rtc_time(const struct device *dev)
{
const struct rtc_rts5912_config *const dev_cfg = dev->config;
RTC_Type *rtc_regs = dev_cfg->regs;

rtc_regs->CTRL1 |= RTC_CTRL1_SETMODE_Msk;
rtc_regs->CTRL0 &= ~RTC_CTRL0_DIVCTL_Msk;
rtc_regs->CTRL0 |= (RTS5912_RTC_DIVCTL_NORMAL_OPERATION << RTC_CTRL0_DIVCTL_Pos);
rtc_regs->CTRL1 |= RTC_CTRL1_DATEMODE_Msk;
rtc_regs->CTRL1 |= RTC_CTRL1_HRMODE_Msk;
rtc_regs->SEC = 0;
rtc_regs->MIN = 0;
rtc_regs->HR &= ~(RTC_HR_AMPM_Msk | RTC_HR_VAL_Msk);
rtc_regs->DAYWEEK = BIT(0);
rtc_regs->DAYMONTH = BIT(0);
rtc_regs->MONTH = BIT(0);
rtc_regs->YEAR = 0;
rtc_regs->WEEK &= ~RTC_WEEK_NUM_Msk;
}

static int rtc_rts5912_set_time(const struct device *dev, const struct rtc_time *timeptr)
{
const struct rtc_rts5912_config *const dev_cfg = dev->config;
RTC_Type *rtc_regs = dev_cfg->regs;

if (!rtc_utils_validate_rtc_time(timeptr, RTS5912_RTC_TIME_MASK)) {
rtc_rts5912_reset_rtc_time(dev);
k_msleep(1);
return -EINVAL;
}

rtc_regs->CTRL1 |= RTC_CTRL1_SETMODE_Msk;
rtc_regs->SEC = timeptr->tm_sec;
rtc_regs->MIN = timeptr->tm_min;
rtc_regs->HR = timeptr->tm_hour;
rtc_regs->DAYWEEK = timeptr->tm_wday + RTS5912_RTC_DAYWEEK_OFFSET;
rtc_regs->DAYMONTH = timeptr->tm_mday;
rtc_regs->MONTH = timeptr->tm_mon + RTS5912_RTC_MONTH_OFFSET;
rtc_regs->YEAR = timeptr->tm_year % RTS5912_RTC_YEAR_OFFSET;
/* Need to delay in order to update register after setting RTC time */
k_msleep(1);
rtc_regs->CTRL1 &= ~RTC_CTRL1_SETMODE_Msk;

return 0;
}

static int rtc_rts5912_get_time(const struct device *dev, struct rtc_time *timeptr)
{
const struct rtc_rts5912_config *const dev_cfg = dev->config;
RTC_Type *rtc_regs = dev_cfg->regs;

timeptr->tm_sec = rtc_regs->SEC;
timeptr->tm_min = rtc_regs->MIN;
timeptr->tm_hour = rtc_regs->HR;
timeptr->tm_wday = rtc_regs->DAYWEEK - RTS5912_RTC_DAYWEEK_OFFSET;
timeptr->tm_mday = rtc_regs->DAYMONTH;
timeptr->tm_mon = rtc_regs->MONTH - RTS5912_RTC_MONTH_OFFSET;
timeptr->tm_year = rtc_regs->YEAR + RTS5912_RTC_YEAR_OFFSET;

/* No support for daylight saving time flag and nanoseconds in rts5912 RTC */
timeptr->tm_isdst = -1;
timeptr->tm_nsec = 0;

return 0;
}

static DEVICE_API(rtc, rtc_rts5912_driver_api) = {
.set_time = rtc_rts5912_set_time,
.get_time = rtc_rts5912_get_time,
};

static int rtc_rts5912_init(const struct device *dev)
{
const struct rtc_rts5912_config *const rtc_config = dev->config;
struct rts5912_sccon_subsys sccon;

int rc;
#if defined(CONFIG_CLOCK_CONTROL)
if (!device_is_ready(rtc_config->clk_dev)) {
LOG_ERR("RTC device not ready");
return -ENODEV;
}

sccon.clk_grp = rtc_config->rtc_clk_grp;
sccon.clk_idx = rtc_config->rtc_clk_idx;
rc = clock_control_on(rtc_config->clk_dev, (clock_control_subsys_t)&sccon);
if (rc < 0) {
LOG_ERR("Failed to turn on RTC clock (%d)", rc);
return rc;
}

rtc_rts5912_reset_rtc_time(dev);
#endif
return rc;
}

#define RTC_RTS5912_CONFIG(inst) \
static struct rtc_rts5912_config rtc_rts5912_config_##inst = { \
.regs = (RTC_Type *)(DT_INST_REG_ADDR(inst)), \
.rtc_base = DT_INST_REG_ADDR(inst), \
.rtc_clk_grp = DT_INST_CLOCKS_CELL_BY_NAME(inst, rtc, clk_grp), \
.rtc_clk_idx = DT_INST_CLOCKS_CELL_BY_NAME(inst, rtc, clk_idx), \
.clk_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(inst)), \
};

#define RTC_RTS5912_DEVICE_INIT(index) \
RTC_RTS5912_CONFIG(index) \
DEVICE_DT_INST_DEFINE(index, &rtc_rts5912_init, NULL, NULL, &rtc_rts5912_config_##index, \
POST_KERNEL, CONFIG_RTC_INIT_PRIORITY, &rtc_rts5912_driver_api);

DT_INST_FOREACH_STATUS_OKAY(RTC_RTS5912_DEVICE_INIT)
8 changes: 8 additions & 0 deletions dts/arm/realtek/ec/rts5912.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@
clock-names = "rc25m", "pll";
};

rtc: rtc@4000c100 {
compatible = "realtek,rts5912-rtc";
reg = <0x4000c100 0x20>;
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP2 PERIPH_GRP2_RTC_CLKPWR>;
clock-names = "rtc";
status = "disabled";
};

slwtmr0: slwtmr0@4000c200 {
compatible = "realtek,rts5912-slwtimer";
reg = <0x4000c200 0x10>;
Expand Down
12 changes: 12 additions & 0 deletions dts/bindings/rtc/realtek,rts5912-rtc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Copyright (c) 2025 Realtek, SIBG-SD7
# SPDX-License-Identifier: Apache-2.0

description: RTC on Realtek RTS5912 EC

compatible: "realtek,rts5912-rtc"

include: rtc-device.yaml

properties:
reg:
required: true
62 changes: 62 additions & 0 deletions soc/realtek/ec/rts5912/reg/reg_rtc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright (c) 2025 Realtek, SIBG-SD7
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef ZEPHYR_SOC_REALTEK_RTS5912_REG_RTC_H
#define ZEPHYR_SOC_REALTEK_RTS5912_REG_RTC_H

/*
* @brief RTC Controller (RTC)
*/

typedef struct {
volatile uint8_t SEC;
volatile uint8_t SECALARM;
volatile uint8_t MIN;
volatile uint8_t MINALARM;
volatile uint8_t HR;
volatile uint8_t HRALARM;
volatile uint8_t DAYWEEK;
volatile uint8_t DAYMONTH;
volatile uint8_t MONTH;
volatile uint8_t YEAR;
volatile uint8_t CTRL0;
volatile uint8_t CTRL1;
volatile uint8_t CTRL2;
volatile uint8_t DAYWEEKALARM;
volatile uint8_t DAYMONTHALARM;
volatile const uint8_t RESERVED;
volatile const uint32_t RESERVED1[2];
volatile uint32_t DLSFW;
volatile uint32_t DLSBW;
volatile uint32_t WEEK;
} RTC_Type;

/* HR */
#define RTC_HR_VAL_Pos (0UL)
#define RTC_HR_VAL_Msk GENMASK(5, 0)
#define RTC_HR_AMPM_Pos (7UL)
#define RTC_HR_AMPM_Msk BIT(RTC_HR_AMPM_Pos)
/* DAYWEEK */
#define RTC_DAYWEEK_Pos (0UL)
#define RTC_DAYWEEK_Msk GENMASK(3, 0)
/* DAYMONTH */
#define RTC_DAYMONTH_Pos (0UL)
#define RTC_DAYMONTH_Msk GENMASK(5, 0)
/* CTRL0 */
#define RTC_CTRL0_DIVCTL_Pos (4UL)
#define RTC_CTRL0_DIVCTL_Msk GENMASK(6, 4)
/* CTRL1 */
#define RTC_CTRL1_HRMODE_Pos (1UL)
#define RTC_CTRL1_HRMODE_Msk BIT(RTC_CTRL1_HRMODE_Pos)
#define RTC_CTRL1_DATEMODE_Pos (2UL)
#define RTC_CTRL1_DATEMODE_Msk BIT(RTC_CTRL1_DATEMODE_Pos)
#define RTC_CTRL1_SETMODE_Pos (7UL)
#define RTC_CTRL1_SETMODE_Msk BIT(RTC_CTRL1_SETMODE_Pos)
/* WEEK */
#define RTC_WEEK_NUM_Pos (0UL)
#define RTC_WEEK_NUM_Msk GENMASK(7, 0)

#endif /* ZEPHYR_SOC_REALTEK_RTS5912_REG_RTC_H */
16 changes: 16 additions & 0 deletions tests/drivers/rtc/rtc_api/boards/rts5912_evb.overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2025 Realtek Semiconductor Corporation, SIBG-SD7
*
*/

/ {
aliases {
rtc = &rtc;
};
};

&rtc {
status = "okay";
};

0 comments on commit 910f865

Please sign in to comment.