drivers: rtc: new maxim ds1307 rtc driver
Added rtc driver for ds1307. It allows to read and set the date and time Signed-off-by: Arunmani Alagarsamy <arunmani27100@gmail.com>
This commit is contained in:
parent
503422b91e
commit
e9ecc83eea
5 changed files with 184 additions and 0 deletions
|
@ -6,6 +6,7 @@ zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/rtc.h)
|
|||
zephyr_library()
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_RTC_AM1805 rtc_am1805.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_RTC_DS1307 rtc_ds1307.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_USERSPACE rtc_handlers.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_RTC_EMUL rtc_emul.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_RTC_PCF8523 rtc_pcf8523.c)
|
||||
|
|
|
@ -42,6 +42,7 @@ config RTC_SHELL
|
|||
RTC Shell commands
|
||||
|
||||
source "drivers/rtc/Kconfig.am1805"
|
||||
source "drivers/rtc/Kconfig.ds1307"
|
||||
source "drivers/rtc/Kconfig.emul"
|
||||
source "drivers/rtc/Kconfig.fake"
|
||||
source "drivers/rtc/Kconfig.pcf8523"
|
||||
|
|
11
drivers/rtc/Kconfig.ds1307
Normal file
11
drivers/rtc/Kconfig.ds1307
Normal file
|
@ -0,0 +1,11 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
# Copyright (c) 2023 Arunmani Alagarsamy
|
||||
# Author: Arunmani Alagarsamy <arunmani27100@gmail.com>
|
||||
|
||||
config RTC_DS1307
|
||||
bool "MAXIM DS1307 RTC driver"
|
||||
default y
|
||||
depends on DT_HAS_MAXIM_DS1307_ENABLED
|
||||
select I2C
|
||||
help
|
||||
Enable the MAXIM DS1307 RTC driver.
|
160
drivers/rtc/rtc_ds1307.c
Normal file
160
drivers/rtc/rtc_ds1307.c
Normal file
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Copyright (c) 2023 Arunmani Alagarsamy
|
||||
* Author: Arunmani Alagarsamy <arunmani27100@gmail.com>
|
||||
*/
|
||||
|
||||
#include <zephyr/drivers/i2c.h>
|
||||
#include <zephyr/drivers/rtc.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/pm/device.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
|
||||
#define DT_DRV_COMPAT maxim_ds1307
|
||||
|
||||
LOG_MODULE_REGISTER(ds1307, CONFIG_RTC_LOG_LEVEL);
|
||||
|
||||
/* DS1307 registers */
|
||||
#define DS1307_REG_SECONDS 0x00
|
||||
#define DS1307_REG_MINUTES 0x01
|
||||
#define DS1307_REG_HOURS 0x02
|
||||
#define DS1307_REG_DAY 0x03
|
||||
#define DS1307_REG_DATE 0x04
|
||||
#define DS1307_REG_MONTH 0x05
|
||||
#define DS1307_REG_YEAR 0x06
|
||||
#define DS1307_REG_CTRL 0x07
|
||||
|
||||
#define SECONDS_BITS GENMASK(6, 0)
|
||||
#define MINUTES_BITS GENMASK(7, 0)
|
||||
#define HOURS_BITS GENMASK(5, 0)
|
||||
#define DATE_BITS GENMASK(5, 0)
|
||||
#define MONTHS_BITS GENMASK(4, 0)
|
||||
#define WEEKDAY_BITS GENMASK(2, 0)
|
||||
#define YEAR_BITS GENMASK(7, 0)
|
||||
#define VALIDATE_24HR BIT(6)
|
||||
|
||||
struct ds1307_config {
|
||||
struct i2c_dt_spec i2c_bus;
|
||||
};
|
||||
|
||||
struct ds1307_data {
|
||||
struct k_spinlock lock;
|
||||
};
|
||||
|
||||
static int ds1307_set_time(const struct device *dev, const struct rtc_time *tm)
|
||||
{
|
||||
int err;
|
||||
uint8_t regs[7];
|
||||
|
||||
struct ds1307_data *data = dev->data;
|
||||
const struct ds1307_config *config = dev->config;
|
||||
|
||||
k_spinlock_key_t key = k_spin_lock(&data->lock);
|
||||
|
||||
LOG_DBG("set time: year = %d, mon = %d, mday = %d, wday = %d, hour = %d, "
|
||||
"min = %d, sec = %d",
|
||||
tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday, tm->tm_hour, tm->tm_min,
|
||||
tm->tm_sec);
|
||||
|
||||
regs[0] = bin2bcd(tm->tm_sec) & SECONDS_BITS;
|
||||
regs[1] = bin2bcd(tm->tm_min);
|
||||
regs[2] = bin2bcd(tm->tm_hour);
|
||||
regs[3] = bin2bcd(tm->tm_wday);
|
||||
regs[4] = bin2bcd(tm->tm_mday);
|
||||
regs[5] = bin2bcd(tm->tm_mon);
|
||||
regs[6] = bin2bcd((tm->tm_year % 100));
|
||||
|
||||
err = i2c_burst_write_dt(&config->i2c_bus, DS1307_REG_SECONDS, regs, sizeof(regs));
|
||||
|
||||
k_spin_unlock(&data->lock, key);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ds1307_get_time(const struct device *dev, struct rtc_time *timeptr)
|
||||
{
|
||||
int err;
|
||||
uint8_t regs[7];
|
||||
|
||||
struct ds1307_data *data = dev->data;
|
||||
const struct ds1307_config *config = dev->config;
|
||||
|
||||
k_spinlock_key_t key = k_spin_lock(&data->lock);
|
||||
|
||||
err = i2c_burst_read_dt(&config->i2c_bus, DS1307_REG_SECONDS, regs, sizeof(regs));
|
||||
if (err != 0) {
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
timeptr->tm_sec = bcd2bin(regs[0] & SECONDS_BITS);
|
||||
timeptr->tm_min = bcd2bin(regs[1] & MINUTES_BITS);
|
||||
timeptr->tm_hour = bcd2bin(regs[2] & HOURS_BITS); /* 24hr mode */
|
||||
timeptr->tm_wday = bcd2bin(regs[3] & WEEKDAY_BITS);
|
||||
timeptr->tm_mday = bcd2bin(regs[4] & DATE_BITS);
|
||||
timeptr->tm_mon = bcd2bin(regs[5] & MONTHS_BITS);
|
||||
timeptr->tm_year = bcd2bin(regs[6] & YEAR_BITS);
|
||||
timeptr->tm_year = timeptr->tm_year + 100;
|
||||
|
||||
/* Not used */
|
||||
timeptr->tm_nsec = 0;
|
||||
timeptr->tm_isdst = -1;
|
||||
timeptr->tm_yday = -1;
|
||||
|
||||
/* Validate the chip in 24hr mode */
|
||||
if (regs[2] & VALIDATE_24HR) {
|
||||
err = -ENODATA;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
LOG_DBG("get time: year = %d, mon = %d, mday = %d, wday = %d, hour = %d, "
|
||||
"min = %d, sec = %d",
|
||||
timeptr->tm_year, timeptr->tm_mon, timeptr->tm_mday, timeptr->tm_wday,
|
||||
timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec);
|
||||
|
||||
unlock:
|
||||
k_spin_unlock(&data->lock, key);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct rtc_driver_api ds1307_driver_api = {
|
||||
.set_time = ds1307_set_time,
|
||||
.get_time = ds1307_get_time,
|
||||
};
|
||||
|
||||
static int ds1307_init(const struct device *dev)
|
||||
{
|
||||
int err;
|
||||
const struct ds1307_config *config = dev->config;
|
||||
|
||||
if (!i2c_is_ready_dt(&config->i2c_bus)) {
|
||||
LOG_ERR("I2C bus not ready");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Disable squarewave output */
|
||||
err = i2c_reg_write_byte_dt(&config->i2c_bus, DS1307_REG_CTRL, 0x00);
|
||||
if (err < 0) {
|
||||
LOG_ERR("Error: SQW:%d\n", err);
|
||||
}
|
||||
|
||||
/* Make clock halt = 0 */
|
||||
err = i2c_reg_write_byte_dt(&config->i2c_bus, DS1307_REG_SECONDS, 0x00);
|
||||
if (err < 0) {
|
||||
LOG_ERR("Error: Set clock halt bit:%d\n", err);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DS1307_DEFINE(inst) \
|
||||
static struct ds1307_data ds1307_data_##inst; \
|
||||
static const struct ds1307_config ds1307_config_##inst = { \
|
||||
.i2c_bus = I2C_DT_SPEC_INST_GET(inst), \
|
||||
}; \
|
||||
DEVICE_DT_INST_DEFINE(inst, &ds1307_init, NULL, &ds1307_data_##inst, \
|
||||
&ds1307_config_##inst, POST_KERNEL, CONFIG_RTC_INIT_PRIORITY, \
|
||||
&ds1307_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(DS1307_DEFINE)
|
Loading…
Add table
Add a link
Reference in a new issue