drivers: rtc: rpi_pico: Add support for the Raspberry Pi Pico RTC
This adds the minimal get_time/set_time support for the rp2040 and enables support by default on the Pico boards. This doesn't support configuring the clock source or alarm interrupts yet. Signed-off-by: Andrew Featherstone <andrew.featherstone@gmail.com>
This commit is contained in:
parent
4c880f4b0a
commit
df8c89b528
9 changed files with 161 additions and 2 deletions
|
@ -19,3 +19,4 @@ zephyr_library_sources_ifdef(CONFIG_RTC_SHELL rtc_shell.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_RTC_FAKE rtc_fake.c)
|
||||
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_RPI_PICO rtc_rpi_pico.c)
|
||||
|
|
|
@ -45,11 +45,12 @@ source "drivers/rtc/Kconfig.am1805"
|
|||
source "drivers/rtc/Kconfig.ds1307"
|
||||
source "drivers/rtc/Kconfig.emul"
|
||||
source "drivers/rtc/Kconfig.fake"
|
||||
source "drivers/rtc/Kconfig.mc146818"
|
||||
source "drivers/rtc/Kconfig.pcf8523"
|
||||
source "drivers/rtc/Kconfig.pcf8563"
|
||||
source "drivers/rtc/Kconfig.mc146818"
|
||||
source "drivers/rtc/Kconfig.rpi_pico"
|
||||
source "drivers/rtc/Kconfig.sam"
|
||||
source "drivers/rtc/Kconfig.stm32"
|
||||
source "drivers/rtc/Kconfig.smartbond"
|
||||
source "drivers/rtc/Kconfig.stm32"
|
||||
|
||||
endif # RTC
|
||||
|
|
9
drivers/rtc/Kconfig.rpi_pico
Normal file
9
drivers/rtc/Kconfig.rpi_pico
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Copyright (c) 2023 Andrew Featherstone
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config RTC_RPI_PICO
|
||||
bool "Raspberry Pi Pico RTC driver"
|
||||
default y
|
||||
depends on DT_HAS_RASPBERRYPI_PICO_RTC_ENABLED
|
||||
select PICOSDK_USE_RTC
|
||||
depends on RESET
|
112
drivers/rtc/rtc_rpi_pico.c
Normal file
112
drivers/rtc/rtc_rpi_pico.c
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Andrew Featherstone
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/drivers/clock_control.h>
|
||||
#include <zephyr/drivers/rtc.h>
|
||||
#include <zephyr/irq.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/spinlock.h>
|
||||
|
||||
#include <hardware/rtc.h>
|
||||
|
||||
#define DT_DRV_COMPAT raspberrypi_pico_rtc
|
||||
|
||||
#define CLK_DRV DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(0))
|
||||
#define CLK_ID (clock_control_subsys_t) DT_INST_PHA_BY_IDX(0, clocks, 0, clk_id)
|
||||
|
||||
/* struct tm start time: 1st, Jan, 1900 */
|
||||
#define TM_YEAR_REF 1900
|
||||
/* See section 4.8.1 of the RP2040 datasheet. */
|
||||
#define RP2040_RTC_YEAR_MAX 4095
|
||||
struct rtc_rpi_pico_data {
|
||||
struct k_spinlock lock;
|
||||
};
|
||||
|
||||
LOG_MODULE_REGISTER(rtc_rpi, CONFIG_RTC_LOG_LEVEL);
|
||||
|
||||
static int rtc_rpi_pico_init(const struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = clock_control_on(CLK_DRV, CLK_ID);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
rtc_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtc_rpi_pico_set_time(const struct device *dev, const struct rtc_time *timeptr)
|
||||
{
|
||||
struct rtc_rpi_pico_data *data = dev->data;
|
||||
int err = 0;
|
||||
|
||||
if (timeptr->tm_year + TM_YEAR_REF > RP2040_RTC_YEAR_MAX) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (timeptr->tm_wday == -1) {
|
||||
/* day of the week is expected */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
k_spinlock_key_t key = k_spin_lock(&data->lock);
|
||||
datetime_t dt = {
|
||||
.year = timeptr->tm_year + TM_YEAR_REF,
|
||||
.month = timeptr->tm_mon + 1,
|
||||
.day = timeptr->tm_mday,
|
||||
.dotw = timeptr->tm_wday,
|
||||
.hour = timeptr->tm_hour,
|
||||
.min = timeptr->tm_min,
|
||||
.sec = timeptr->tm_sec,
|
||||
};
|
||||
/* Use the validation in the Pico SDK. */
|
||||
if (!rtc_set_datetime(&dt)) {
|
||||
err = -EINVAL;
|
||||
}
|
||||
k_spin_unlock(&data->lock, key);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int rtc_rpi_pico_get_time(const struct device *dev, struct rtc_time *timeptr)
|
||||
{
|
||||
struct rtc_rpi_pico_data *data = dev->data;
|
||||
datetime_t dt;
|
||||
int err = 0;
|
||||
k_spinlock_key_t key = k_spin_lock(&data->lock);
|
||||
|
||||
if (!rtc_get_datetime(&dt)) {
|
||||
err = -ENODATA;
|
||||
}
|
||||
|
||||
timeptr->tm_sec = dt.sec;
|
||||
timeptr->tm_min = dt.min;
|
||||
timeptr->tm_hour = dt.hour;
|
||||
timeptr->tm_mday = dt.day;
|
||||
timeptr->tm_mon = dt.month - 1;
|
||||
timeptr->tm_year = dt.year - TM_YEAR_REF;
|
||||
timeptr->tm_wday = dt.dotw;
|
||||
/* unknown values */
|
||||
timeptr->tm_yday = -1;
|
||||
timeptr->tm_isdst = -1;
|
||||
timeptr->tm_nsec = 0;
|
||||
k_spin_unlock(&data->lock, key);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct rtc_driver_api rtc_rpi_pico_driver_api = {
|
||||
.set_time = rtc_rpi_pico_set_time,
|
||||
.get_time = rtc_rpi_pico_get_time,
|
||||
};
|
||||
|
||||
static struct rtc_rpi_pico_data rtc_data;
|
||||
|
||||
DEVICE_DT_INST_DEFINE(0, &rtc_rpi_pico_init, NULL, &rtc_data, NULL, POST_KERNEL,
|
||||
CONFIG_RTC_INIT_PRIORITY, &rtc_rpi_pico_driver_api);
|
Loading…
Add table
Add a link
Reference in a new issue