diff options
-rw-r--r-- | src/soc/rockchip/rk3288/rk808.c | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/src/soc/rockchip/rk3288/rk808.c b/src/soc/rockchip/rk3288/rk808.c index de19a55135..b763454903 100644 --- a/src/soc/rockchip/rk3288/rk808.c +++ b/src/soc/rockchip/rk3288/rk808.c @@ -18,9 +18,11 @@ */ #include <assert.h> +#include <bcd.h> #include <console/console.h> #include <delay.h> #include <device/i2c.h> +#include <rtc.h> #include <soc/rk808.h> #include <stdint.h> #include <stdlib.h> @@ -38,6 +40,20 @@ #define LDO_ONSEL(i) (0x39 + 2 * i) #define LDO_SLPSEL(i) (0x3a + 2 * i) +#define RTC_SECOND 0x00 +#define RTC_MINUTE 0x01 +#define RTC_HOUR 0x02 +#define RTC_DAY 0x03 +#define RTC_MONTH 0x04 +#define RTC_YEAR 0x05 +#define RTC_WEEKS 0x06 +#define RTC_CTRL 0x10 +#define RTC_STATUS 0x11 + +#define RTC_CTRL_STOP_RTC (1 << 0) +#define RTC_CTRL_GET_TIME (1 << 6) +#define RTC_CTRL_RTC_READSEL (1 << 7) + static int rk808_read(uint8_t reg, uint8_t *value) { return i2c_readb(CONFIG_PMIC_BUS, RK808_ADDR, reg, value); @@ -118,3 +134,66 @@ void rk808_configure_buck(int buck, int millivolts) rk808_clrsetbits(buck_reg, 0x3f, vsel); rk808_clrsetbits(DCDC_EN, 0, 1 << (buck - 1)); } + +static void rk808rtc_stop(void) +{ + rk808_clrsetbits(RTC_CTRL, RTC_CTRL_STOP_RTC, 0); +} + +static void rk808rtc_start(void) +{ + rk808_clrsetbits(RTC_CTRL, 0, RTC_CTRL_STOP_RTC); +} + +int rtc_set(const struct rtc_time *time) +{ + int ret = 0; + + /* RTC time can only be set when RTC is frozen */ + rk808rtc_stop(); + + ret |= rk808_write(RTC_SECOND, bin2bcd(time->sec)); + ret |= rk808_write(RTC_MINUTE, bin2bcd(time->min)); + ret |= rk808_write(RTC_HOUR, bin2bcd(time->hour)); + ret |= rk808_write(RTC_DAY, bin2bcd(time->mday)); + ret |= rk808_write(RTC_MONTH, bin2bcd(time->mon)); + ret |= rk808_write(RTC_YEAR, bin2bcd(time->year)); + + rk808rtc_start(); + return ret; +} + +int rtc_get(struct rtc_time *time) +{ + uint8_t value; + int ret = 0; + + /* + * Set RTC_READSEL to cause reads to access shadow registers and + * transition GET_TIME from 0 to 1 to cause dynamic register content + * to be copied into shadow registers. This ensures a coherent reading + * of time values as we access each register using slow I2C transfers. + */ + rk808_clrsetbits(RTC_CTRL, RTC_CTRL_GET_TIME, 0); + rk808_clrsetbits(RTC_CTRL, 0, RTC_CTRL_GET_TIME | RTC_CTRL_RTC_READSEL); + + ret |= rk808_read(RTC_SECOND, &value); + time->sec = bcd2bin(value & 0x7f); + + ret |= rk808_read(RTC_MINUTE, &value); + time->min = bcd2bin(value & 0x7f); + + ret |= rk808_read(RTC_HOUR, &value); + time->hour = bcd2bin(value & 0x3f); + + ret |= rk808_read(RTC_DAY, &value); + time->mday = bcd2bin(value & 0x3f); + + ret |= rk808_read(RTC_MONTH, &value); + time->mon = bcd2bin(value & 0x1f); + + ret |= rk808_read(RTC_YEAR, &value); + time->year = bcd2bin(value); + + return ret; +} |