1e419bc7fSGatien Chevallier // SPDX-License-Identifier: BSD-2-Clause 2e419bc7fSGatien Chevallier /* 3d60c61e1SGatien Chevallier * Copyright (C) 2018-2025, STMicroelectronics 4e419bc7fSGatien Chevallier */ 5e419bc7fSGatien Chevallier #include <assert.h> 6e419bc7fSGatien Chevallier #include <drivers/clk.h> 7e419bc7fSGatien Chevallier #include <drivers/clk_dt.h> 8e419bc7fSGatien Chevallier #include <drivers/rtc.h> 9e419bc7fSGatien Chevallier #include <drivers/stm32_rif.h> 10d60c61e1SGatien Chevallier #include <drivers/stm32_rtc.h> 11e419bc7fSGatien Chevallier #include <io.h> 12*7818ae9bSClément Le Goffic #include <keep.h> 13e419bc7fSGatien Chevallier #include <kernel/dt.h> 14e419bc7fSGatien Chevallier #include <kernel/dt_driver.h> 15*7818ae9bSClément Le Goffic #include <kernel/interrupt.h> 16*7818ae9bSClément Le Goffic #include <kernel/notif.h> 17e419bc7fSGatien Chevallier #include <kernel/panic.h> 18d60c61e1SGatien Chevallier #include <kernel/spinlock.h> 19e419bc7fSGatien Chevallier #include <libfdt.h> 20e419bc7fSGatien Chevallier #include <mm/core_memprot.h> 21e419bc7fSGatien Chevallier 22e419bc7fSGatien Chevallier /* 23e419bc7fSGatien Chevallier * Registers 24e419bc7fSGatien Chevallier */ 25e419bc7fSGatien Chevallier #define RTC_TR U(0x00) 26e419bc7fSGatien Chevallier #define RTC_DR U(0x04) 27e419bc7fSGatien Chevallier #define RTC_SSR U(0x08) 28e419bc7fSGatien Chevallier #define RTC_ICSR U(0x0C) 29e419bc7fSGatien Chevallier #define RTC_PRER U(0x10) 30e419bc7fSGatien Chevallier #define RTC_WUTR U(0x14) 31e419bc7fSGatien Chevallier #define RTC_CR U(0x18) 32e419bc7fSGatien Chevallier #define RTC_PRIVCFGR U(0x1C) 33e419bc7fSGatien Chevallier /* RTC_SMCR is linked to RTC3v1_2 */ 34e419bc7fSGatien Chevallier #define RTC_SMCR U(0x20) 35e419bc7fSGatien Chevallier /* RTC_SECCFGR is linked to RTC3v3_2 and above */ 36e419bc7fSGatien Chevallier #define RTC_SECCFGR U(0x20) 37e419bc7fSGatien Chevallier #define RTC_WPR U(0x24) 38e419bc7fSGatien Chevallier #define RTC_CALR U(0x28) 39e419bc7fSGatien Chevallier #define RTC_SHIFTR U(0x2C) 40e419bc7fSGatien Chevallier #define RTC_TSTR U(0x30) 41e419bc7fSGatien Chevallier #define RTC_TSDR U(0x34) 42e419bc7fSGatien Chevallier #define RTC_TSSSR U(0x38) 43e419bc7fSGatien Chevallier #define RTC_ALRMAR U(0x40) 44e419bc7fSGatien Chevallier #define RTC_ALRMASSR U(0x44) 45e419bc7fSGatien Chevallier #define RTC_ALRMBR U(0x48) 46e419bc7fSGatien Chevallier #define RTC_ALRMBSSR U(0x4C) 47e419bc7fSGatien Chevallier #define RTC_SR U(0x50) 48e419bc7fSGatien Chevallier #define RTC_SCR U(0x5C) 49e419bc7fSGatien Chevallier #define RTC_OR U(0x60) 50e419bc7fSGatien Chevallier #define RTC_CIDCFGR(x) (U(0x80) + U(0x4) * (x)) 51e419bc7fSGatien Chevallier 52e419bc7fSGatien Chevallier #define RTC_TR_SU_MASK GENMASK_32(3, 0) 53e419bc7fSGatien Chevallier #define RTC_TR_ST_MASK GENMASK_32(6, 4) 54e419bc7fSGatien Chevallier #define RTC_TR_ST_SHIFT U(4) 55e419bc7fSGatien Chevallier #define RTC_TR_MNU_MASK GENMASK_32(11, 8) 56e419bc7fSGatien Chevallier #define RTC_TR_MNU_SHIFT U(8) 57e419bc7fSGatien Chevallier #define RTC_TR_MNT_MASK GENMASK_32(14, 12) 58e419bc7fSGatien Chevallier #define RTC_TR_MNT_SHIFT U(12) 59e419bc7fSGatien Chevallier #define RTC_TR_HU_MASK GENMASK_32(19, 16) 60e419bc7fSGatien Chevallier #define RTC_TR_HU_SHIFT U(16) 61e419bc7fSGatien Chevallier #define RTC_TR_HT_MASK GENMASK_32(21, 20) 62e419bc7fSGatien Chevallier #define RTC_TR_HT_SHIFT U(20) 63e419bc7fSGatien Chevallier #define RTC_TR_PM BIT(22) 64e419bc7fSGatien Chevallier 65e419bc7fSGatien Chevallier #define RTC_DR_DU_MASK GENMASK_32(3, 0) 66e419bc7fSGatien Chevallier #define RTC_DR_DT_MASK GENMASK_32(5, 4) 67e419bc7fSGatien Chevallier #define RTC_DR_DT_SHIFT U(4) 68e419bc7fSGatien Chevallier #define RTC_DR_MU_MASK GENMASK_32(11, 8) 69e419bc7fSGatien Chevallier #define RTC_DR_MU_SHIFT U(8) 70e419bc7fSGatien Chevallier #define RTC_DR_MT_MASK BIT(12) 71e419bc7fSGatien Chevallier #define RTC_DR_MT_SHIFT U(12) 72e419bc7fSGatien Chevallier #define RTC_DR_WDU_MASK GENMASK_32(15, 13) 73e419bc7fSGatien Chevallier #define RTC_DR_WDU_SHIFT U(13) 74e419bc7fSGatien Chevallier #define RTC_DR_YU_MASK GENMASK_32(19, 16) 75e419bc7fSGatien Chevallier #define RTC_DR_YU_SHIFT U(16) 76e419bc7fSGatien Chevallier #define RTC_DR_YT_MASK GENMASK_32(23, 20) 77e419bc7fSGatien Chevallier #define RTC_DR_YT_SHIFT U(20) 78e419bc7fSGatien Chevallier 79e419bc7fSGatien Chevallier #define RTC_SSR_SS_MASK GENMASK_32(15, 0) 80e419bc7fSGatien Chevallier 81e419bc7fSGatien Chevallier #define RTC_ICSR_RSF BIT(5) 82e419bc7fSGatien Chevallier #define RTC_ICSR_INITF BIT(6) 83e419bc7fSGatien Chevallier #define RTC_ICSR_INIT BIT(7) 84e419bc7fSGatien Chevallier 85446da993SClément Le Goffic #define RTC_PRER_PREDIV_S_SHIFT U(0) 86e419bc7fSGatien Chevallier #define RTC_PRER_PREDIV_S_MASK GENMASK_32(14, 0) 87446da993SClément Le Goffic #define RTC_PRER_PREDIV_A_SHIFT U(16) 88446da993SClément Le Goffic #define RTC_PRER_PREDIV_A_MASK GENMASK_32(22, 16) 89e419bc7fSGatien Chevallier 90e419bc7fSGatien Chevallier #define RTC_CR_BYPSHAD BIT(5) 91e419bc7fSGatien Chevallier #define RTC_CR_BYPSHAD_SHIFT U(5) 92446da993SClément Le Goffic #define RTC_CR_FMT BIT(6) 93*7818ae9bSClément Le Goffic #define RTC_CR_ALRAE BIT(8) 94*7818ae9bSClément Le Goffic #define RTC_CR_ALRAIE BIT(12) 95e419bc7fSGatien Chevallier #define RTC_CR_TAMPTS BIT(25) 96e419bc7fSGatien Chevallier 97e419bc7fSGatien Chevallier #define RTC_PRIVCFGR_VALUES GENMASK_32(3, 0) 98e419bc7fSGatien Chevallier #define RTC_PRIVCFGR_VALUES_TO_SHIFT GENMASK_32(5, 4) 99e419bc7fSGatien Chevallier #define RTC_PRIVCFGR_SHIFT U(9) 100e419bc7fSGatien Chevallier #define RTC_PRIVCFGR_MASK (GENMASK_32(14, 13) | GENMASK_32(3, 0)) 101e419bc7fSGatien Chevallier #define RTC_PRIVCFGR_FULL_PRIV BIT(15) 102e419bc7fSGatien Chevallier 103e419bc7fSGatien Chevallier #define RTC_SMCR_TS_DPROT BIT(3) 104e419bc7fSGatien Chevallier 105e419bc7fSGatien Chevallier #define RTC_SECCFGR_VALUES GENMASK_32(3, 0) 106e419bc7fSGatien Chevallier #define RTC_SECCFGR_TS_SEC BIT(3) 107e419bc7fSGatien Chevallier #define RTC_SECCFGR_VALUES_TO_SHIFT GENMASK_32(5, 4) 108e419bc7fSGatien Chevallier #define RTC_SECCFGR_SHIFT U(9) 109e419bc7fSGatien Chevallier #define RTC_SECCFGR_MASK (GENMASK_32(14, 13) | GENMASK_32(3, 0)) 110e419bc7fSGatien Chevallier #define RTC_SECCFGR_FULL_SEC BIT(15) 111e419bc7fSGatien Chevallier 112e419bc7fSGatien Chevallier #define RTC_WPR_KEY1 U(0xCA) 113e419bc7fSGatien Chevallier #define RTC_WPR_KEY2 U(0x53) 114e419bc7fSGatien Chevallier #define RTC_WPR_KEY_LOCK U(0xFF) 115e419bc7fSGatien Chevallier 116e419bc7fSGatien Chevallier #define RTC_TSDR_MU_MASK GENMASK_32(11, 8) 117e419bc7fSGatien Chevallier #define RTC_TSDR_MU_SHIFT U(8) 118e419bc7fSGatien Chevallier #define RTC_TSDR_DT_MASK GENMASK_32(5, 4) 119e419bc7fSGatien Chevallier #define RTC_TSDR_DT_SHIFT U(4) 120e419bc7fSGatien Chevallier #define RTC_TSDR_DU_MASK GENMASK_32(3, 0) 121e419bc7fSGatien Chevallier #define RTC_TSDR_DU_SHIFT U(0) 122e419bc7fSGatien Chevallier 123*7818ae9bSClément Le Goffic #define RTC_ALRMXR_SEC_UNITS_MASK GENMASK_32(3, 0) 124*7818ae9bSClément Le Goffic #define RTC_ALRMXR_SEC_UNITS_SHIFT U(0) 125*7818ae9bSClément Le Goffic #define RTC_ALRMXR_SEC_TENS_MASK GENMASK_32(6, 4) 126*7818ae9bSClément Le Goffic #define RTC_ALRMXR_SEC_TENS_SHIFT U(4) 127*7818ae9bSClément Le Goffic #define RTC_ALRMXR_SEC_MASK BIT(7) 128*7818ae9bSClément Le Goffic #define RTC_ALRMXR_MIN_UNITS_MASK GENMASK_32(11, 8) 129*7818ae9bSClément Le Goffic #define RTC_ALRMXR_MIN_UNITS_SHIFT U(8) 130*7818ae9bSClément Le Goffic #define RTC_ALRMXR_MIN_TENS_MASK GENMASK_32(14, 12) 131*7818ae9bSClément Le Goffic #define RTC_ALRMXR_MIN_TENS_SHIFT U(12) 132*7818ae9bSClément Le Goffic #define RTC_ALRMXR_MIN_MASK BIT(15) 133*7818ae9bSClément Le Goffic #define RTC_ALRMXR_HOUR_UNITS_MASK GENMASK_32(19, 16) 134*7818ae9bSClément Le Goffic #define RTC_ALRMXR_HOUR_UNITS_SHIFT U(16) 135*7818ae9bSClément Le Goffic #define RTC_ALRMXR_HOUR_TENS_MASK GENMASK_32(21, 20) 136*7818ae9bSClément Le Goffic #define RTC_ALRMXR_HOUR_TENS_SHIFT U(20) 137*7818ae9bSClément Le Goffic #define RTC_ALRMXR_PM BIT(22) 138*7818ae9bSClément Le Goffic #define RTC_ALRMXR_HOUR_MASK BIT(23) 139*7818ae9bSClément Le Goffic #define RTC_ALRMXR_DATE_UNITS_MASK GENMASK_32(27, 24) 140*7818ae9bSClément Le Goffic #define RTC_ALRMXR_DATE_UNITS_SHIFT U(24) 141*7818ae9bSClément Le Goffic #define RTC_ALRMXR_DATE_TENS_MASK GENMASK_32(29, 28) 142*7818ae9bSClément Le Goffic #define RTC_ALRMXR_DATE_TENS_SHIFT U(28) 143*7818ae9bSClément Le Goffic 144*7818ae9bSClément Le Goffic #define RTC_SR_ALRAF BIT(0) 145e419bc7fSGatien Chevallier #define RTC_SR_TSF BIT(3) 146e419bc7fSGatien Chevallier #define RTC_SR_TSOVF BIT(4) 147e419bc7fSGatien Chevallier 148*7818ae9bSClément Le Goffic #define RTC_SCR_CALRAF BIT(0) 149e419bc7fSGatien Chevallier #define RTC_SCR_CTSF BIT(3) 150e419bc7fSGatien Chevallier #define RTC_SCR_CTSOVF BIT(4) 151e419bc7fSGatien Chevallier 152e419bc7fSGatien Chevallier #define RTC_CIDCFGR_SCID_MASK GENMASK_32(6, 4) 153e419bc7fSGatien Chevallier #define RTC_CIDCFGR_SCID_MASK_SHIFT U(4) 154e419bc7fSGatien Chevallier #define RTC_CIDCFGR_CONF_MASK (_CIDCFGR_CFEN | \ 155e419bc7fSGatien Chevallier RTC_CIDCFGR_SCID_MASK) 156e419bc7fSGatien Chevallier 157e419bc7fSGatien Chevallier /* 158e419bc7fSGatien Chevallier * RIF miscellaneous 159e419bc7fSGatien Chevallier */ 160e419bc7fSGatien Chevallier #define RTC_NB_RIF_RESOURCES U(6) 161e419bc7fSGatien Chevallier 162e419bc7fSGatien Chevallier #define RTC_RIF_FULL_PRIVILEGED U(0x3F) 163e419bc7fSGatien Chevallier #define RTC_RIF_FULL_SECURED U(0x3F) 164e419bc7fSGatien Chevallier 165e419bc7fSGatien Chevallier #define RTC_NB_MAX_CID_SUPPORTED U(7) 166e419bc7fSGatien Chevallier 167e419bc7fSGatien Chevallier /* 168e419bc7fSGatien Chevallier * Driver miscellaneous 169e419bc7fSGatien Chevallier */ 170e419bc7fSGatien Chevallier #define RTC_RES_TIMESTAMP U(3) 171e419bc7fSGatien Chevallier #define RTC_RES_CALIBRATION U(4) 172e419bc7fSGatien Chevallier #define RTC_RES_INITIALIZATION U(5) 173e419bc7fSGatien Chevallier 174e419bc7fSGatien Chevallier #define RTC_FLAGS_READ_TWICE BIT(0) 175e419bc7fSGatien Chevallier 176e419bc7fSGatien Chevallier #define TIMEOUT_US_RTC_SHADOW U(10000) 177e419bc7fSGatien Chevallier #define TIMEOUT_US_RTC_GENERIC U(100000) 178e419bc7fSGatien Chevallier 179e419bc7fSGatien Chevallier #define YEAR_REF ULL(2000) 180e419bc7fSGatien Chevallier #define YEAR_MAX (YEAR_REF + ULL(99)) 181e419bc7fSGatien Chevallier 182e419bc7fSGatien Chevallier struct rtc_compat { 183e419bc7fSGatien Chevallier bool has_seccfgr; 184e419bc7fSGatien Chevallier bool has_rif_support; 185e419bc7fSGatien Chevallier }; 186e419bc7fSGatien Chevallier 187e419bc7fSGatien Chevallier /* 188e419bc7fSGatien Chevallier * struct rtc_device - RTC device data 189e419bc7fSGatien Chevallier * @base: RTC IOMEM base address 190e419bc7fSGatien Chevallier * @compat: RTC compatible data 191e419bc7fSGatien Chevallier * @pclk: RTC bus clock 192e419bc7fSGatien Chevallier * @rtc_ck: RTC kernel clock 193e419bc7fSGatien Chevallier * @conf_data: RTC RIF configuration data, when supported 194e419bc7fSGatien Chevallier * @nb_res: Number of protectible RTC resources 195d60c61e1SGatien Chevallier * @ts_lock: Lock used for time stamping events handling 196e419bc7fSGatien Chevallier * @flags: RTC driver flags 197e419bc7fSGatien Chevallier * @is_secured: True if the RTC is fully secured 198*7818ae9bSClément Le Goffic * @itr_chip: Interrupt chip 199*7818ae9bSClément Le Goffic * @itr_num: Interrupt number 200*7818ae9bSClément Le Goffic * @itr_handler: Interrupt handler 201*7818ae9bSClément Le Goffic * @notif_id: Notification ID 202*7818ae9bSClément Le Goffic * @wait_alarm_return_status: Status of the wait alarm thread 203e419bc7fSGatien Chevallier */ 204e419bc7fSGatien Chevallier struct rtc_device { 205e419bc7fSGatien Chevallier struct io_pa_va base; 206e419bc7fSGatien Chevallier const struct rtc_compat *compat; 207e419bc7fSGatien Chevallier struct clk *pclk; 208e419bc7fSGatien Chevallier struct clk *rtc_ck; 209e419bc7fSGatien Chevallier struct rif_conf_data *conf_data; 210e419bc7fSGatien Chevallier unsigned int nb_res; 211d60c61e1SGatien Chevallier unsigned int ts_lock; 212e419bc7fSGatien Chevallier uint8_t flags; 213e419bc7fSGatien Chevallier bool is_secured; 214*7818ae9bSClément Le Goffic struct itr_chip *itr_chip; 215*7818ae9bSClément Le Goffic size_t itr_num; 216*7818ae9bSClément Le Goffic struct itr_handler *itr_handler; 217*7818ae9bSClément Le Goffic uint32_t notif_id; 218*7818ae9bSClément Le Goffic enum rtc_wait_alarm_status wait_alarm_return_status; 219e419bc7fSGatien Chevallier }; 220e419bc7fSGatien Chevallier 221e419bc7fSGatien Chevallier /* Expect a single RTC instance */ 222e419bc7fSGatien Chevallier static struct rtc_device rtc_dev; 223e419bc7fSGatien Chevallier 224e419bc7fSGatien Chevallier static vaddr_t get_base(void) 225e419bc7fSGatien Chevallier { 226e419bc7fSGatien Chevallier assert(rtc_dev.base.pa); 227e419bc7fSGatien Chevallier 228e419bc7fSGatien Chevallier return io_pa_or_va(&rtc_dev.base, 1); 229e419bc7fSGatien Chevallier } 230e419bc7fSGatien Chevallier 231e419bc7fSGatien Chevallier static void stm32_rtc_write_unprotect(void) 232e419bc7fSGatien Chevallier { 233e419bc7fSGatien Chevallier vaddr_t rtc_base = get_base(); 234e419bc7fSGatien Chevallier 235e419bc7fSGatien Chevallier io_write32(rtc_base + RTC_WPR, RTC_WPR_KEY1); 236e419bc7fSGatien Chevallier io_write32(rtc_base + RTC_WPR, RTC_WPR_KEY2); 237e419bc7fSGatien Chevallier } 238e419bc7fSGatien Chevallier 239e419bc7fSGatien Chevallier static void stm32_rtc_write_protect(void) 240e419bc7fSGatien Chevallier { 241e419bc7fSGatien Chevallier vaddr_t rtc_base = get_base(); 242e419bc7fSGatien Chevallier 243e419bc7fSGatien Chevallier io_write32(rtc_base + RTC_WPR, RTC_WPR_KEY_LOCK); 244e419bc7fSGatien Chevallier } 245e419bc7fSGatien Chevallier 246e419bc7fSGatien Chevallier static bool stm32_rtc_get_bypshad(void) 247e419bc7fSGatien Chevallier { 248e419bc7fSGatien Chevallier return io_read32(get_base() + RTC_CR) & RTC_CR_BYPSHAD; 249e419bc7fSGatien Chevallier } 250e419bc7fSGatien Chevallier 251e419bc7fSGatien Chevallier /* Get the subsecond value. */ 252e419bc7fSGatien Chevallier static uint32_t stm32_rtc_get_subsecond(uint32_t ssr) 253e419bc7fSGatien Chevallier { 254e419bc7fSGatien Chevallier uint32_t prediv_s = io_read32(get_base() + RTC_PRER) & 255e419bc7fSGatien Chevallier RTC_PRER_PREDIV_S_MASK; 256e419bc7fSGatien Chevallier 257e419bc7fSGatien Chevallier return prediv_s - ssr; 258e419bc7fSGatien Chevallier } 259e419bc7fSGatien Chevallier 260e419bc7fSGatien Chevallier /* 261e419bc7fSGatien Chevallier * Get the subsecond scale. 262e419bc7fSGatien Chevallier * 263e419bc7fSGatien Chevallier * Number of subseconds in a second is linked to RTC PREDIV_S value. 264e419bc7fSGatien Chevallier * The higher PREDIV_S is, the more subsecond is precise. 265e419bc7fSGatien Chevallier */ 266e419bc7fSGatien Chevallier static uint32_t stm32_rtc_get_subsecond_scale(void) 267e419bc7fSGatien Chevallier { 268e419bc7fSGatien Chevallier return (io_read32(get_base() + RTC_PRER) & RTC_PRER_PREDIV_S_MASK) + 1; 269e419bc7fSGatien Chevallier } 270e419bc7fSGatien Chevallier 271e419bc7fSGatien Chevallier static bool cid1_has_access(unsigned int resource) 272e419bc7fSGatien Chevallier { 273e419bc7fSGatien Chevallier uint32_t cidcfgr = io_read32(get_base() + RTC_CIDCFGR(resource)); 274e419bc7fSGatien Chevallier 275e419bc7fSGatien Chevallier return !(cidcfgr & _CIDCFGR_CFEN) || 276e419bc7fSGatien Chevallier get_field_u32(cidcfgr, RTC_CIDCFGR_SCID_MASK) == RIF_CID1; 277e419bc7fSGatien Chevallier } 278e419bc7fSGatien Chevallier 279e419bc7fSGatien Chevallier static TEE_Result check_rif_config(void) 280e419bc7fSGatien Chevallier { 281e419bc7fSGatien Chevallier if (!cid1_has_access(RTC_RES_TIMESTAMP) || 282e419bc7fSGatien Chevallier !cid1_has_access(RTC_RES_CALIBRATION) || 283e419bc7fSGatien Chevallier !cid1_has_access(RTC_RES_INITIALIZATION)) 284e419bc7fSGatien Chevallier return TEE_ERROR_ACCESS_DENIED; 285e419bc7fSGatien Chevallier 286e419bc7fSGatien Chevallier return TEE_SUCCESS; 287e419bc7fSGatien Chevallier } 288e419bc7fSGatien Chevallier 289e419bc7fSGatien Chevallier static void apply_rif_config(bool is_tdcid) 290e419bc7fSGatien Chevallier { 291e419bc7fSGatien Chevallier vaddr_t base = get_base(); 292e419bc7fSGatien Chevallier unsigned int shifted_values = 0; 293e419bc7fSGatien Chevallier uint32_t seccfgr = 0; 294e419bc7fSGatien Chevallier uint32_t privcfgr = 0; 295e419bc7fSGatien Chevallier uint32_t access_mask_reg = 0; 296e419bc7fSGatien Chevallier unsigned int i = 0; 297e419bc7fSGatien Chevallier 298e419bc7fSGatien Chevallier if (!rtc_dev.conf_data) 299e419bc7fSGatien Chevallier return; 300e419bc7fSGatien Chevallier 301e419bc7fSGatien Chevallier /* Build access mask for RTC_SECCFGR and RTC_PRIVCFGR */ 302e419bc7fSGatien Chevallier for (i = 0; i < RTC_NB_RIF_RESOURCES; i++) { 303e419bc7fSGatien Chevallier if (rtc_dev.conf_data->access_mask[0] & BIT(i)) { 304e419bc7fSGatien Chevallier if (i <= RTC_RES_TIMESTAMP) 305e419bc7fSGatien Chevallier access_mask_reg |= BIT(i); 306e419bc7fSGatien Chevallier else 307e419bc7fSGatien Chevallier access_mask_reg |= BIT(i) << RTC_SECCFGR_SHIFT; 308e419bc7fSGatien Chevallier } 309e419bc7fSGatien Chevallier } 310e419bc7fSGatien Chevallier 311e419bc7fSGatien Chevallier for (i = 0; i < RTC_NB_RIF_RESOURCES; i++) { 312e419bc7fSGatien Chevallier if (!(BIT(i) & rtc_dev.conf_data->access_mask[0])) 313e419bc7fSGatien Chevallier continue; 314e419bc7fSGatien Chevallier 315e419bc7fSGatien Chevallier /* 316e419bc7fSGatien Chevallier * When TDCID, OP-TEE should be the one to set the CID filtering 317e419bc7fSGatien Chevallier * configuration. Clearing previous configuration prevents 318e419bc7fSGatien Chevallier * undesired events during the only legitimate configuration. 319e419bc7fSGatien Chevallier */ 320e419bc7fSGatien Chevallier if (is_tdcid) 321e419bc7fSGatien Chevallier io_clrbits32(base + RTC_CIDCFGR(i), 322e419bc7fSGatien Chevallier RTC_CIDCFGR_CONF_MASK); 323e419bc7fSGatien Chevallier } 324e419bc7fSGatien Chevallier 325e419bc7fSGatien Chevallier /* Security RIF configuration */ 326e419bc7fSGatien Chevallier seccfgr = rtc_dev.conf_data->sec_conf[0]; 327e419bc7fSGatien Chevallier 328e419bc7fSGatien Chevallier /* Check if all resources must be secured */ 329e419bc7fSGatien Chevallier if (seccfgr == RTC_RIF_FULL_SECURED) { 330e419bc7fSGatien Chevallier io_setbits32(base + RTC_SECCFGR, RTC_SECCFGR_FULL_SEC); 331e419bc7fSGatien Chevallier rtc_dev.is_secured = true; 332e419bc7fSGatien Chevallier 333e419bc7fSGatien Chevallier if (!(io_read32(base + RTC_SECCFGR) & RTC_SECCFGR_FULL_SEC)) 334e419bc7fSGatien Chevallier panic("Bad RTC seccfgr configuration"); 335e419bc7fSGatien Chevallier } 336e419bc7fSGatien Chevallier 337e419bc7fSGatien Chevallier /* Shift some values to align with the register */ 338e419bc7fSGatien Chevallier shifted_values = SHIFT_U32(seccfgr & RTC_SECCFGR_VALUES_TO_SHIFT, 339e419bc7fSGatien Chevallier RTC_SECCFGR_SHIFT); 340e419bc7fSGatien Chevallier seccfgr = (seccfgr & RTC_SECCFGR_VALUES) + shifted_values; 341e419bc7fSGatien Chevallier 342e419bc7fSGatien Chevallier io_clrsetbits32(base + RTC_SECCFGR, 343e419bc7fSGatien Chevallier RTC_SECCFGR_MASK & access_mask_reg, seccfgr); 344e419bc7fSGatien Chevallier 345e419bc7fSGatien Chevallier /* Privilege RIF configuration */ 346e419bc7fSGatien Chevallier privcfgr = rtc_dev.conf_data->priv_conf[0]; 347e419bc7fSGatien Chevallier 348e419bc7fSGatien Chevallier /* Check if all resources must be privileged */ 349e419bc7fSGatien Chevallier if (privcfgr == RTC_RIF_FULL_PRIVILEGED) { 350e419bc7fSGatien Chevallier io_setbits32(base + RTC_PRIVCFGR, RTC_PRIVCFGR_FULL_PRIV); 351e419bc7fSGatien Chevallier 352e419bc7fSGatien Chevallier if (!(io_read32(base + RTC_PRIVCFGR) & RTC_PRIVCFGR_FULL_PRIV)) 353e419bc7fSGatien Chevallier panic("Bad RTC privcfgr configuration"); 354e419bc7fSGatien Chevallier } 355e419bc7fSGatien Chevallier 356e419bc7fSGatien Chevallier /* Shift some values to align with the register */ 357e419bc7fSGatien Chevallier shifted_values = SHIFT_U32(privcfgr & RTC_PRIVCFGR_VALUES_TO_SHIFT, 358e419bc7fSGatien Chevallier RTC_PRIVCFGR_SHIFT); 359e419bc7fSGatien Chevallier privcfgr = (privcfgr & RTC_PRIVCFGR_VALUES) + shifted_values; 360e419bc7fSGatien Chevallier 361e419bc7fSGatien Chevallier io_clrsetbits32(base + RTC_PRIVCFGR, 362e419bc7fSGatien Chevallier RTC_PRIVCFGR_MASK & access_mask_reg, privcfgr); 363e419bc7fSGatien Chevallier 364e419bc7fSGatien Chevallier if (!is_tdcid) 365e419bc7fSGatien Chevallier return; 366e419bc7fSGatien Chevallier 367e419bc7fSGatien Chevallier for (i = 0; i < RTC_NB_RIF_RESOURCES; i++) { 368e419bc7fSGatien Chevallier if (!(BIT(i) & rtc_dev.conf_data->access_mask[0])) 369e419bc7fSGatien Chevallier continue; 370e419bc7fSGatien Chevallier /* 371e419bc7fSGatien Chevallier * When at least one resource has CID filtering enabled, 372e419bc7fSGatien Chevallier * the RTC_PRIVCFGR_FULL_PRIV and RTC_SECCFGR_FULL_SEC bits are 373e419bc7fSGatien Chevallier * cleared. 374e419bc7fSGatien Chevallier */ 375e419bc7fSGatien Chevallier io_clrsetbits32(base + RTC_CIDCFGR(i), 376e419bc7fSGatien Chevallier RTC_CIDCFGR_CONF_MASK, 377e419bc7fSGatien Chevallier rtc_dev.conf_data->cid_confs[i]); 378e419bc7fSGatien Chevallier } 379e419bc7fSGatien Chevallier } 380e419bc7fSGatien Chevallier 381*7818ae9bSClément Le Goffic static void stm32_rtc_clear_events(uint32_t flags) 382*7818ae9bSClément Le Goffic { 383*7818ae9bSClément Le Goffic io_write32(get_base() + RTC_SCR, flags); 384*7818ae9bSClément Le Goffic } 385*7818ae9bSClément Le Goffic 386*7818ae9bSClément Le Goffic static enum itr_return stm32_rtc_it_handler(struct itr_handler *h __unused) 387*7818ae9bSClément Le Goffic { 388*7818ae9bSClément Le Goffic vaddr_t rtc_base = get_base(); 389*7818ae9bSClément Le Goffic uint32_t status = io_read32(rtc_base + RTC_SR); 390*7818ae9bSClément Le Goffic uint32_t cr = io_read32(rtc_base + RTC_CR); 391*7818ae9bSClément Le Goffic 392*7818ae9bSClément Le Goffic if ((status & RTC_SR_ALRAF) && (cr & RTC_CR_ALRAIE)) { 393*7818ae9bSClément Le Goffic DMSG("Alarm occurred"); 394*7818ae9bSClément Le Goffic /* Clear event's flags */ 395*7818ae9bSClément Le Goffic stm32_rtc_clear_events(RTC_SCR_CALRAF); 396*7818ae9bSClément Le Goffic /* 397*7818ae9bSClément Le Goffic * Notify the caller of 'stm32_rtc_wait_alarm' to re-schedule 398*7818ae9bSClément Le Goffic * the calling thread. 399*7818ae9bSClément Le Goffic */ 400*7818ae9bSClément Le Goffic notif_send_async(rtc_dev.notif_id, 0); 401*7818ae9bSClément Le Goffic } 402*7818ae9bSClément Le Goffic 403*7818ae9bSClément Le Goffic return ITRR_HANDLED; 404*7818ae9bSClément Le Goffic } 405*7818ae9bSClément Le Goffic DECLARE_KEEP_PAGER(stm32_rtc_it_handler); 406*7818ae9bSClément Le Goffic 407e419bc7fSGatien Chevallier static TEE_Result parse_dt(const void *fdt, int node) 408e419bc7fSGatien Chevallier { 409e419bc7fSGatien Chevallier TEE_Result res = TEE_ERROR_GENERIC; 410e419bc7fSGatien Chevallier const fdt32_t *cuint = NULL; 411e419bc7fSGatien Chevallier size_t reg_size = 0; 412e419bc7fSGatien Chevallier unsigned int i = 0; 413e419bc7fSGatien Chevallier int lenp = 0; 414e419bc7fSGatien Chevallier 415e419bc7fSGatien Chevallier if (fdt_reg_info(fdt, node, &rtc_dev.base.pa, ®_size)) 416e419bc7fSGatien Chevallier panic(); 417e419bc7fSGatien Chevallier 418e419bc7fSGatien Chevallier io_pa_or_va(&rtc_dev.base, reg_size); 419e419bc7fSGatien Chevallier assert(rtc_dev.base.va); 420e419bc7fSGatien Chevallier 421e419bc7fSGatien Chevallier res = clk_dt_get_by_name(fdt, node, "pclk", &rtc_dev.pclk); 422e419bc7fSGatien Chevallier if (res) 423e419bc7fSGatien Chevallier return res; 424e419bc7fSGatien Chevallier 425e419bc7fSGatien Chevallier res = clk_dt_get_by_name(fdt, node, "rtc_ck", &rtc_dev.rtc_ck); 426e419bc7fSGatien Chevallier if (res) 427e419bc7fSGatien Chevallier return res; 428e419bc7fSGatien Chevallier 429*7818ae9bSClément Le Goffic if (IS_ENABLED(CFG_RTC_PTA) && IS_ENABLED(CFG_DRIVERS_RTC)) { 430*7818ae9bSClément Le Goffic res = interrupt_dt_get(fdt, node, &rtc_dev.itr_chip, 431*7818ae9bSClément Le Goffic &rtc_dev.itr_num); 432*7818ae9bSClément Le Goffic if (res) 433*7818ae9bSClément Le Goffic return res; 434*7818ae9bSClément Le Goffic res = interrupt_create_handler(rtc_dev.itr_chip, 435*7818ae9bSClément Le Goffic rtc_dev.itr_num, 436*7818ae9bSClément Le Goffic stm32_rtc_it_handler, 437*7818ae9bSClément Le Goffic &rtc_dev, 0, 438*7818ae9bSClément Le Goffic &rtc_dev.itr_handler); 439*7818ae9bSClément Le Goffic if (res) 440*7818ae9bSClément Le Goffic return res; 441*7818ae9bSClément Le Goffic } 442*7818ae9bSClément Le Goffic 443e419bc7fSGatien Chevallier if (!rtc_dev.compat->has_rif_support) 444e419bc7fSGatien Chevallier return TEE_SUCCESS; 445e419bc7fSGatien Chevallier 446e419bc7fSGatien Chevallier cuint = fdt_getprop(fdt, node, "st,protreg", &lenp); 447e419bc7fSGatien Chevallier if (!cuint) { 448e419bc7fSGatien Chevallier DMSG("No RIF configuration available"); 449e419bc7fSGatien Chevallier return TEE_SUCCESS; 450e419bc7fSGatien Chevallier } 451e419bc7fSGatien Chevallier 452e419bc7fSGatien Chevallier rtc_dev.conf_data = calloc(1, sizeof(*rtc_dev.conf_data)); 453e419bc7fSGatien Chevallier if (!rtc_dev.conf_data) 454e419bc7fSGatien Chevallier panic(); 455e419bc7fSGatien Chevallier 456e419bc7fSGatien Chevallier rtc_dev.nb_res = (unsigned int)(lenp / sizeof(uint32_t)); 457e419bc7fSGatien Chevallier assert(rtc_dev.nb_res <= RTC_NB_RIF_RESOURCES); 458e419bc7fSGatien Chevallier 459e419bc7fSGatien Chevallier rtc_dev.conf_data->cid_confs = calloc(RTC_NB_RIF_RESOURCES, 460e419bc7fSGatien Chevallier sizeof(uint32_t)); 461e419bc7fSGatien Chevallier rtc_dev.conf_data->sec_conf = calloc(1, sizeof(uint32_t)); 462e419bc7fSGatien Chevallier rtc_dev.conf_data->priv_conf = calloc(1, sizeof(uint32_t)); 463e419bc7fSGatien Chevallier rtc_dev.conf_data->access_mask = calloc(1, sizeof(uint32_t)); 464e419bc7fSGatien Chevallier if (!rtc_dev.conf_data->cid_confs || !rtc_dev.conf_data->sec_conf || 465e419bc7fSGatien Chevallier !rtc_dev.conf_data->priv_conf || !rtc_dev.conf_data->access_mask) 466e419bc7fSGatien Chevallier panic("Not enough memory capacity for RTC RIF config"); 467e419bc7fSGatien Chevallier 468e419bc7fSGatien Chevallier for (i = 0; i < rtc_dev.nb_res; i++) 469e419bc7fSGatien Chevallier stm32_rif_parse_cfg(fdt32_to_cpu(cuint[i]), rtc_dev.conf_data, 470e419bc7fSGatien Chevallier RTC_NB_RIF_RESOURCES); 471e419bc7fSGatien Chevallier 472e419bc7fSGatien Chevallier return TEE_SUCCESS; 473e419bc7fSGatien Chevallier } 474e419bc7fSGatien Chevallier 475e419bc7fSGatien Chevallier static TEE_Result stm32_rtc_enter_init_mode(void) 476e419bc7fSGatien Chevallier { 477e419bc7fSGatien Chevallier vaddr_t base = get_base(); 478e419bc7fSGatien Chevallier uint32_t icsr = io_read32(base + RTC_ICSR); 479e419bc7fSGatien Chevallier uint32_t value = 0; 480e419bc7fSGatien Chevallier 481e419bc7fSGatien Chevallier if (!(icsr & RTC_ICSR_INITF)) { 482e419bc7fSGatien Chevallier icsr |= RTC_ICSR_INIT; 483e419bc7fSGatien Chevallier io_write32(base + RTC_ICSR, icsr); 484e419bc7fSGatien Chevallier 485e419bc7fSGatien Chevallier if (IO_READ32_POLL_TIMEOUT(base + RTC_ICSR, value, 486e419bc7fSGatien Chevallier value & RTC_ICSR_INITF, 487e419bc7fSGatien Chevallier 10, TIMEOUT_US_RTC_GENERIC)) 488e419bc7fSGatien Chevallier return TEE_ERROR_BUSY; 489e419bc7fSGatien Chevallier } 490e419bc7fSGatien Chevallier 491e419bc7fSGatien Chevallier return TEE_SUCCESS; 492e419bc7fSGatien Chevallier } 493e419bc7fSGatien Chevallier 494446da993SClément Le Goffic static TEE_Result stm32_rtc_exit_init_mode(void) 495e419bc7fSGatien Chevallier { 496e419bc7fSGatien Chevallier vaddr_t base = get_base(); 497e419bc7fSGatien Chevallier uint32_t value = 0; 498e419bc7fSGatien Chevallier 499446da993SClément Le Goffic io_clrbits32(base + RTC_ICSR, RTC_ICSR_INIT); 500446da993SClément Le Goffic dsb(); 501446da993SClément Le Goffic 502e419bc7fSGatien Chevallier io_clrbits32(base + RTC_ICSR, RTC_ICSR_RSF); 503e419bc7fSGatien Chevallier 504e419bc7fSGatien Chevallier if (IO_READ32_POLL_TIMEOUT(base + RTC_ICSR, value, 505e419bc7fSGatien Chevallier value & RTC_ICSR_RSF, 10, 506e419bc7fSGatien Chevallier TIMEOUT_US_RTC_GENERIC)) 507e419bc7fSGatien Chevallier return TEE_ERROR_BUSY; 508e419bc7fSGatien Chevallier 509e419bc7fSGatien Chevallier return TEE_SUCCESS; 510e419bc7fSGatien Chevallier } 511e419bc7fSGatien Chevallier 512d60c61e1SGatien Chevallier static void stm32_rtc_to_tm(uint32_t ssr, uint32_t tr, uint32_t dr, 513d60c61e1SGatien Chevallier struct optee_rtc_time *tm) 514d60c61e1SGatien Chevallier { 515d60c61e1SGatien Chevallier tm->tm_hour = ((tr & RTC_TR_HT_MASK) >> RTC_TR_HT_SHIFT) * 10 + 516d60c61e1SGatien Chevallier ((tr & RTC_TR_HU_MASK) >> RTC_TR_HU_SHIFT); 517d60c61e1SGatien Chevallier 518d60c61e1SGatien Chevallier if (tr & RTC_TR_PM) 519d60c61e1SGatien Chevallier tm->tm_hour += 12; 520d60c61e1SGatien Chevallier 521d60c61e1SGatien Chevallier tm->tm_ms = (stm32_rtc_get_subsecond(ssr) * MS_PER_SEC) / 522d60c61e1SGatien Chevallier stm32_rtc_get_subsecond_scale(); 523d60c61e1SGatien Chevallier 524d60c61e1SGatien Chevallier tm->tm_sec = ((tr & RTC_TR_ST_MASK) >> RTC_TR_ST_SHIFT) * 10 + 525d60c61e1SGatien Chevallier (tr & RTC_TR_SU_MASK); 526d60c61e1SGatien Chevallier 527d60c61e1SGatien Chevallier tm->tm_min = ((tr & RTC_TR_MNT_MASK) >> RTC_TR_MNT_SHIFT) * 10 + 528d60c61e1SGatien Chevallier ((tr & RTC_TR_MNU_MASK) >> RTC_TR_MNU_SHIFT); 529d60c61e1SGatien Chevallier 530d60c61e1SGatien Chevallier tm->tm_wday = ((dr & RTC_DR_WDU_MASK) >> RTC_DR_WDU_SHIFT) % 7; 531d60c61e1SGatien Chevallier 532d60c61e1SGatien Chevallier tm->tm_mday = ((dr & RTC_DR_DT_MASK) >> RTC_DR_DT_SHIFT) * 10 + 533d60c61e1SGatien Chevallier (dr & RTC_DR_DU_MASK); 534d60c61e1SGatien Chevallier 535d60c61e1SGatien Chevallier tm->tm_mon = ((dr & RTC_DR_MT_MASK) >> RTC_DR_MT_SHIFT) * 10 + 536d60c61e1SGatien Chevallier ((dr & RTC_DR_MU_MASK) >> RTC_DR_MU_SHIFT) - 1; 537d60c61e1SGatien Chevallier 538d60c61e1SGatien Chevallier tm->tm_year = ((dr & RTC_DR_YT_MASK) >> RTC_DR_YT_SHIFT) * 10 + 539d60c61e1SGatien Chevallier ((dr & RTC_DR_YU_MASK) >> RTC_DR_YU_SHIFT) + YEAR_REF; 540d60c61e1SGatien Chevallier } 541d60c61e1SGatien Chevallier 542446da993SClément Le Goffic static TEE_Result stm32_rtc_init(void) 543446da993SClément Le Goffic { 544446da993SClément Le Goffic uint32_t pred_a_max = RTC_PRER_PREDIV_A_MASK >> RTC_PRER_PREDIV_A_SHIFT; 545446da993SClément Le Goffic uint32_t pred_s_max = RTC_PRER_PREDIV_S_MASK >> RTC_PRER_PREDIV_S_SHIFT; 546446da993SClément Le Goffic unsigned long rate = clk_get_rate(rtc_dev.rtc_ck); 547446da993SClément Le Goffic TEE_Result res = TEE_ERROR_GENERIC; 548446da993SClément Le Goffic vaddr_t base = get_base(); 549446da993SClément Le Goffic uint32_t pred_a = 0; 550446da993SClément Le Goffic uint32_t pred_s = 0; 551446da993SClément Le Goffic uint32_t prer = io_read32(base + RTC_PRER); 552446da993SClément Le Goffic uint32_t cr = io_read32(base + RTC_CR); 553446da993SClément Le Goffic 554446da993SClément Le Goffic if (rate > (pred_a_max + 1) * (pred_s_max + 1)) 555446da993SClément Le Goffic panic("rtc_ck rate is too high"); 556446da993SClément Le Goffic 557446da993SClément Le Goffic if (cr & RTC_CR_FMT && !IS_ENABLED(CFG_STM32_RTC_HIGH_ACCURACY)) 558446da993SClément Le Goffic return TEE_SUCCESS; 559446da993SClément Le Goffic 560446da993SClément Le Goffic if (IS_ENABLED(CFG_STM32_RTC_HIGH_ACCURACY)) { 561446da993SClément Le Goffic /* 562446da993SClément Le Goffic * Compute the prescaler values whom divides the clock in order 563446da993SClément Le Goffic * to get a * 1 Hz output by maximizing accuracy 564446da993SClément Le Goffic * (maximizing PREDIV_S). 565446da993SClément Le Goffic */ 566446da993SClément Le Goffic for (pred_a = 0; pred_a <= pred_a_max; pred_a++) { 567446da993SClément Le Goffic pred_s = (rate / (pred_a + 1)) - 1; 568446da993SClément Le Goffic if (pred_s <= pred_s_max && 569446da993SClément Le Goffic ((pred_s + 1) * (pred_a + 1)) == rate) 570446da993SClément Le Goffic break; 571446da993SClément Le Goffic } 572446da993SClément Le Goffic 573446da993SClément Le Goffic /* 574446da993SClément Le Goffic * 1 Hz output not possible, give priority to RTC power 575446da993SClément Le Goffic * consumption by choosing the higher possible value for 576446da993SClément Le Goffic * prediv_a 577446da993SClément Le Goffic */ 578446da993SClément Le Goffic if (pred_s > pred_s_max || pred_a > pred_a_max) { 579446da993SClément Le Goffic pred_a = pred_a_max; 580446da993SClément Le Goffic pred_s = (rate / (pred_a + 1)) - 1; 581446da993SClément Le Goffic 582446da993SClément Le Goffic DMSG("rtc_ck is %s", 583446da993SClément Le Goffic (rate < ((pred_a + 1) * (pred_s + 1))) ? 584446da993SClément Le Goffic "fast" : "slow"); 585446da993SClément Le Goffic } 586446da993SClément Le Goffic 587446da993SClément Le Goffic prer &= RTC_PRER_PREDIV_S_MASK | RTC_PRER_PREDIV_A_MASK; 588446da993SClément Le Goffic pred_s = SHIFT_U32(pred_s, RTC_PRER_PREDIV_S_SHIFT) & 589446da993SClément Le Goffic RTC_PRER_PREDIV_S_MASK; 590446da993SClément Le Goffic pred_a = SHIFT_U32(pred_a, RTC_PRER_PREDIV_A_SHIFT) & 591446da993SClément Le Goffic RTC_PRER_PREDIV_A_MASK; 592446da993SClément Le Goffic 593446da993SClément Le Goffic /* Return if there is nothing to initialize */ 594446da993SClément Le Goffic if (cr & RTC_CR_FMT && prer == (pred_s | pred_a)) 595446da993SClément Le Goffic return TEE_SUCCESS; 596446da993SClément Le Goffic } 597446da993SClément Le Goffic 598446da993SClément Le Goffic stm32_rtc_write_unprotect(); 599446da993SClément Le Goffic 600446da993SClément Le Goffic res = stm32_rtc_enter_init_mode(); 601446da993SClément Le Goffic if (res) { 602446da993SClément Le Goffic EMSG("Can't enter init mode. Fail to initialize RTC."); 603446da993SClément Le Goffic stm32_rtc_write_protect(); 604446da993SClément Le Goffic return res; 605446da993SClément Le Goffic } 606446da993SClément Le Goffic 607446da993SClément Le Goffic if (IS_ENABLED(CFG_STM32_RTC_HIGH_ACCURACY)) { 608446da993SClément Le Goffic io_write32(base + RTC_PRER, pred_s); 609446da993SClément Le Goffic io_write32(base + RTC_PRER, pred_a | pred_s); 610446da993SClément Le Goffic } 611446da993SClément Le Goffic 612446da993SClément Le Goffic /* Force 24h time format */ 613446da993SClément Le Goffic cr &= ~RTC_CR_FMT; 614446da993SClément Le Goffic io_write32(base + RTC_CR, cr); 615446da993SClément Le Goffic 616446da993SClément Le Goffic res = stm32_rtc_exit_init_mode(); 617446da993SClément Le Goffic if (res) 618446da993SClément Le Goffic EMSG("Can't exit init mode. Fail to initialize RTC."); 619446da993SClément Le Goffic 620446da993SClément Le Goffic stm32_rtc_write_protect(); 621446da993SClément Le Goffic 622446da993SClément Le Goffic return res; 623446da993SClément Le Goffic } 624446da993SClément Le Goffic 625e419bc7fSGatien Chevallier static TEE_Result stm32_rtc_get_time(struct rtc *rtc __unused, 626e419bc7fSGatien Chevallier struct optee_rtc_time *tm) 627e419bc7fSGatien Chevallier { 628e419bc7fSGatien Chevallier vaddr_t base = get_base(); 629e419bc7fSGatien Chevallier uint32_t ssr = 0; 630e419bc7fSGatien Chevallier uint32_t dr = 0; 631e419bc7fSGatien Chevallier uint32_t tr = 0; 632e419bc7fSGatien Chevallier 633e419bc7fSGatien Chevallier if (!stm32_rtc_get_bypshad()) { 634e419bc7fSGatien Chevallier uint32_t icsr = 0; 635e419bc7fSGatien Chevallier 636e419bc7fSGatien Chevallier /* Wait calendar registers are ready */ 637e419bc7fSGatien Chevallier io_clrbits32(base + RTC_ICSR, RTC_ICSR_RSF); 638e419bc7fSGatien Chevallier 639e419bc7fSGatien Chevallier if (IO_READ32_POLL_TIMEOUT(base + RTC_ICSR, icsr, 640e419bc7fSGatien Chevallier icsr & RTC_ICSR_RSF, 0, 641e419bc7fSGatien Chevallier TIMEOUT_US_RTC_SHADOW)) 642e419bc7fSGatien Chevallier panic(); 643e419bc7fSGatien Chevallier } 644e419bc7fSGatien Chevallier 645e419bc7fSGatien Chevallier /* 646e419bc7fSGatien Chevallier * In our RTC we start : 647e419bc7fSGatien Chevallier * - year at 0 648e419bc7fSGatien Chevallier * - month at 1 649e419bc7fSGatien Chevallier * - day at 1 650e419bc7fSGatien Chevallier * - weekday at Monday = 1 651e419bc7fSGatien Chevallier * Change month value so it becomes 0=January, 1 = February, ... 652e419bc7fSGatien Chevallier * Change week day value so it becomes 0=Sunday, 1 = Monday, ... 653e419bc7fSGatien Chevallier */ 654e419bc7fSGatien Chevallier 655e419bc7fSGatien Chevallier ssr = io_read32(base + RTC_SSR); 656e419bc7fSGatien Chevallier tr = io_read32(base + RTC_TR); 657e419bc7fSGatien Chevallier dr = io_read32(base + RTC_DR); 658e419bc7fSGatien Chevallier 659d60c61e1SGatien Chevallier stm32_rtc_to_tm(ssr, tr, dr, tm); 660e419bc7fSGatien Chevallier 661e419bc7fSGatien Chevallier return TEE_SUCCESS; 662e419bc7fSGatien Chevallier } 663e419bc7fSGatien Chevallier 664e419bc7fSGatien Chevallier static TEE_Result stm32_rtc_set_time(struct rtc *rtc, struct optee_rtc_time *tm) 665e419bc7fSGatien Chevallier { 666e419bc7fSGatien Chevallier TEE_Result res = TEE_ERROR_GENERIC; 667e419bc7fSGatien Chevallier vaddr_t rtc_base = get_base(); 668e419bc7fSGatien Chevallier uint32_t tr = 0; 669e419bc7fSGatien Chevallier uint32_t dr = 0; 670e419bc7fSGatien Chevallier 671e419bc7fSGatien Chevallier /* 672e419bc7fSGatien Chevallier * In our RTC we start : 673e419bc7fSGatien Chevallier * - year at 0 674e419bc7fSGatien Chevallier * - month at 1 675e419bc7fSGatien Chevallier * - day at 1 676e419bc7fSGatien Chevallier * - weekday at Monday = 1 677e419bc7fSGatien Chevallier * Change month value so it becomes 1=January, 2 = February, ... 678e419bc7fSGatien Chevallier * Change week day value so it becomes 7=Sunday, 1 = Monday, ... 679e419bc7fSGatien Chevallier */ 680e419bc7fSGatien Chevallier tr = ((tm->tm_sec % 10) & RTC_TR_SU_MASK) | 681e419bc7fSGatien Chevallier (SHIFT_U32(tm->tm_sec / 10, RTC_TR_ST_SHIFT) & RTC_TR_ST_MASK) | 682e419bc7fSGatien Chevallier (SHIFT_U32(tm->tm_min % 10, RTC_TR_MNU_SHIFT) & RTC_TR_MNU_MASK) | 683e419bc7fSGatien Chevallier (SHIFT_U32(tm->tm_min / 10, RTC_TR_MNT_SHIFT) & RTC_TR_MNT_MASK) | 684e419bc7fSGatien Chevallier (SHIFT_U32(tm->tm_hour % 10, RTC_TR_HU_SHIFT) & RTC_TR_HU_MASK) | 685e419bc7fSGatien Chevallier (SHIFT_U32(tm->tm_hour / 10, RTC_TR_HT_SHIFT) & RTC_TR_HT_MASK); 686e419bc7fSGatien Chevallier 687e419bc7fSGatien Chevallier dr = ((tm->tm_mday % 10) & RTC_DR_DU_MASK) | 688e419bc7fSGatien Chevallier (SHIFT_U32(tm->tm_mday / 10, RTC_DR_DT_SHIFT) & RTC_DR_DT_MASK) | 689e419bc7fSGatien Chevallier (SHIFT_U32((tm->tm_mon + 1) % 10, RTC_DR_MU_SHIFT) & 690e419bc7fSGatien Chevallier RTC_DR_MU_MASK) | 691e419bc7fSGatien Chevallier (SHIFT_U32((tm->tm_mon + 1) / 10, RTC_DR_MT_SHIFT) & 692e419bc7fSGatien Chevallier RTC_DR_MT_MASK) | 693e419bc7fSGatien Chevallier (SHIFT_U32(tm->tm_wday ? tm->tm_wday : 7, RTC_DR_WDU_SHIFT) & 694e419bc7fSGatien Chevallier RTC_DR_WDU_MASK) | 695e419bc7fSGatien Chevallier (SHIFT_U32((tm->tm_year - rtc->range_min.tm_year) % 10, 696e419bc7fSGatien Chevallier RTC_DR_YU_SHIFT) & RTC_DR_YU_MASK) | 697e419bc7fSGatien Chevallier (SHIFT_U32((tm->tm_year - rtc->range_min.tm_year) / 10, 698e419bc7fSGatien Chevallier RTC_DR_YT_SHIFT) & RTC_DR_YT_MASK); 699e419bc7fSGatien Chevallier 700e419bc7fSGatien Chevallier stm32_rtc_write_unprotect(); 701e419bc7fSGatien Chevallier 702e419bc7fSGatien Chevallier res = stm32_rtc_enter_init_mode(); 703e419bc7fSGatien Chevallier if (res) 704e419bc7fSGatien Chevallier goto end; 705e419bc7fSGatien Chevallier 706e419bc7fSGatien Chevallier io_write32(rtc_base + RTC_TR, tr); 707e419bc7fSGatien Chevallier io_write32(rtc_base + RTC_DR, dr); 708e419bc7fSGatien Chevallier 709446da993SClément Le Goffic res = stm32_rtc_exit_init_mode(); 710e419bc7fSGatien Chevallier end: 711e419bc7fSGatien Chevallier stm32_rtc_write_protect(); 712e419bc7fSGatien Chevallier 713e419bc7fSGatien Chevallier return res; 714e419bc7fSGatien Chevallier } 715e419bc7fSGatien Chevallier 716d60c61e1SGatien Chevallier TEE_Result stm32_rtc_get_timestamp(struct optee_rtc_time *tm) 717d60c61e1SGatien Chevallier { 718d60c61e1SGatien Chevallier vaddr_t base = get_base(); 719d60c61e1SGatien Chevallier uint32_t exceptions = 0; 720d60c61e1SGatien Chevallier uint32_t value = 0; 721d60c61e1SGatien Chevallier uint32_t ssr = 0; 722d60c61e1SGatien Chevallier uint32_t dr = 0; 723d60c61e1SGatien Chevallier uint32_t tr = 0; 724d60c61e1SGatien Chevallier 725d60c61e1SGatien Chevallier exceptions = cpu_spin_lock_xsave(&rtc_dev.ts_lock); 726d60c61e1SGatien Chevallier 727d60c61e1SGatien Chevallier if (IO_READ32_POLL_TIMEOUT(base + RTC_SR, value, 728d60c61e1SGatien Chevallier value & RTC_SR_TSF, 729d60c61e1SGatien Chevallier 10, TIMEOUT_US_RTC_GENERIC)) { 730d60c61e1SGatien Chevallier cpu_spin_unlock_xrestore(&rtc_dev.ts_lock, exceptions); 731d60c61e1SGatien Chevallier return TEE_ERROR_NO_DATA; 732d60c61e1SGatien Chevallier } 733d60c61e1SGatien Chevallier 734d60c61e1SGatien Chevallier ssr = io_read32(base + RTC_TSSSR); 735d60c61e1SGatien Chevallier tr = io_read32(base + RTC_TSTR); 736d60c61e1SGatien Chevallier dr = io_read32(base + RTC_TSDR); 737d60c61e1SGatien Chevallier 738d60c61e1SGatien Chevallier io_setbits32(base + RTC_SCR, RTC_SCR_CTSF); 739d60c61e1SGatien Chevallier 740d60c61e1SGatien Chevallier /* Tamper event overflow detection */ 741d60c61e1SGatien Chevallier if (io_read32(base + RTC_SR) & RTC_SR_TSOVF) { 742d60c61e1SGatien Chevallier io_setbits32(base + RTC_SCR, RTC_SCR_CTSOVF); 743d60c61e1SGatien Chevallier DMSG("A timestamp event occurred while handling current event"); 744d60c61e1SGatien Chevallier } 745d60c61e1SGatien Chevallier 746d60c61e1SGatien Chevallier cpu_spin_unlock_xrestore(&rtc_dev.ts_lock, exceptions); 747d60c61e1SGatien Chevallier 748d60c61e1SGatien Chevallier stm32_rtc_to_tm(ssr, tr, dr, tm); 749d60c61e1SGatien Chevallier 750d60c61e1SGatien Chevallier /* No year timestamp available */ 751d60c61e1SGatien Chevallier tm->tm_year = 0; 752d60c61e1SGatien Chevallier 753d60c61e1SGatien Chevallier return TEE_SUCCESS; 754d60c61e1SGatien Chevallier } 755d60c61e1SGatien Chevallier 756d60c61e1SGatien Chevallier TEE_Result stm32_rtc_set_tamper_timestamp(void) 757d60c61e1SGatien Chevallier { 758d60c61e1SGatien Chevallier vaddr_t base = get_base(); 759d60c61e1SGatien Chevallier 760d60c61e1SGatien Chevallier stm32_rtc_write_unprotect(); 761d60c61e1SGatien Chevallier 762d60c61e1SGatien Chevallier /* Secure Timestamp bit */ 763d60c61e1SGatien Chevallier if (!rtc_dev.compat->has_seccfgr) { 764d60c61e1SGatien Chevallier /* Inverted logic */ 765d60c61e1SGatien Chevallier io_clrbits32(base + RTC_SMCR, RTC_SMCR_TS_DPROT); 766d60c61e1SGatien Chevallier } else { 767d60c61e1SGatien Chevallier io_setbits32(base + RTC_SECCFGR, RTC_SECCFGR_TS_SEC); 768d60c61e1SGatien Chevallier } 769d60c61e1SGatien Chevallier 770d60c61e1SGatien Chevallier /* Enable tamper timestamper */ 771d60c61e1SGatien Chevallier io_setbits32(base + RTC_CR, RTC_CR_TAMPTS); 772d60c61e1SGatien Chevallier 773d60c61e1SGatien Chevallier stm32_rtc_write_protect(); 774d60c61e1SGatien Chevallier 775d60c61e1SGatien Chevallier return TEE_SUCCESS; 776d60c61e1SGatien Chevallier } 777d60c61e1SGatien Chevallier 778d60c61e1SGatien Chevallier TEE_Result stm32_rtc_is_timestamp_enabled(bool *ret) 779d60c61e1SGatien Chevallier { 780d60c61e1SGatien Chevallier *ret = io_read32(get_base() + RTC_CR) & RTC_CR_TAMPTS; 781d60c61e1SGatien Chevallier 782d60c61e1SGatien Chevallier return TEE_SUCCESS; 783d60c61e1SGatien Chevallier } 784d60c61e1SGatien Chevallier 785d60c61e1SGatien Chevallier TEE_Result stm32_rtc_driver_is_initialized(void) 786d60c61e1SGatien Chevallier { 787d60c61e1SGatien Chevallier if (rtc_dev.pclk) 788d60c61e1SGatien Chevallier return TEE_SUCCESS; 789d60c61e1SGatien Chevallier 790d60c61e1SGatien Chevallier return TEE_ERROR_DEFER_DRIVER_INIT; 791d60c61e1SGatien Chevallier } 792d60c61e1SGatien Chevallier 793*7818ae9bSClément Le Goffic static TEE_Result stm32_rtc_read_alarm(struct rtc *rtc, 794*7818ae9bSClément Le Goffic struct optee_rtc_alarm *alarm) 795*7818ae9bSClément Le Goffic { 796*7818ae9bSClément Le Goffic struct optee_rtc_time *alarm_tm = NULL; 797*7818ae9bSClément Le Goffic struct optee_rtc_time current_tm = { }; 798*7818ae9bSClément Le Goffic TEE_Result res = TEE_ERROR_GENERIC; 799*7818ae9bSClément Le Goffic vaddr_t rtc_base = get_base(); 800*7818ae9bSClément Le Goffic uint32_t alrmar = io_read32(rtc_base + RTC_ALRMAR); 801*7818ae9bSClément Le Goffic uint32_t cr = io_read32(rtc_base + RTC_CR); 802*7818ae9bSClément Le Goffic uint32_t status = io_read32(rtc_base + RTC_SR); 803*7818ae9bSClément Le Goffic 804*7818ae9bSClément Le Goffic alarm_tm = &alarm->time; 805*7818ae9bSClément Le Goffic 806*7818ae9bSClément Le Goffic res = stm32_rtc_get_time(rtc, ¤t_tm); 807*7818ae9bSClément Le Goffic if (res) 808*7818ae9bSClément Le Goffic return res; 809*7818ae9bSClément Le Goffic 810*7818ae9bSClément Le Goffic alarm_tm->tm_year = current_tm.tm_year; 811*7818ae9bSClément Le Goffic alarm_tm->tm_mon = current_tm.tm_mon; 812*7818ae9bSClément Le Goffic alarm_tm->tm_mday = ((alrmar & RTC_ALRMXR_DATE_UNITS_MASK) >> 813*7818ae9bSClément Le Goffic RTC_ALRMXR_DATE_UNITS_SHIFT) + 814*7818ae9bSClément Le Goffic ((alrmar & RTC_ALRMXR_DATE_TENS_MASK) >> 815*7818ae9bSClément Le Goffic RTC_ALRMXR_DATE_TENS_SHIFT) * 10; 816*7818ae9bSClément Le Goffic alarm_tm->tm_hour = ((alrmar & RTC_ALRMXR_HOUR_UNITS_MASK) >> 817*7818ae9bSClément Le Goffic RTC_ALRMXR_HOUR_UNITS_SHIFT) + 818*7818ae9bSClément Le Goffic ((alrmar & RTC_ALRMXR_HOUR_TENS_MASK) >> 819*7818ae9bSClément Le Goffic RTC_ALRMXR_HOUR_TENS_SHIFT) * 10; 820*7818ae9bSClément Le Goffic alarm_tm->tm_min = ((alrmar & RTC_ALRMXR_MIN_UNITS_MASK) >> 821*7818ae9bSClément Le Goffic RTC_ALRMXR_MIN_UNITS_SHIFT) + 822*7818ae9bSClément Le Goffic ((alrmar & RTC_ALRMXR_MIN_TENS_MASK) >> 823*7818ae9bSClément Le Goffic RTC_ALRMXR_MIN_TENS_SHIFT) * 10; 824*7818ae9bSClément Le Goffic alarm_tm->tm_sec = ((alrmar & RTC_ALRMXR_MIN_UNITS_MASK) >> 825*7818ae9bSClément Le Goffic RTC_ALRMXR_MIN_UNITS_SHIFT) + 826*7818ae9bSClément Le Goffic ((alrmar & RTC_ALRMXR_MIN_TENS_MASK) >> 827*7818ae9bSClément Le Goffic RTC_ALRMXR_MIN_TENS_SHIFT) * 10; 828*7818ae9bSClément Le Goffic 829*7818ae9bSClément Le Goffic if (rtc_timecmp(alarm_tm, ¤t_tm) < 0) { 830*7818ae9bSClément Le Goffic if (current_tm.tm_mon == 11) { 831*7818ae9bSClément Le Goffic alarm_tm->tm_mon = 0; 832*7818ae9bSClément Le Goffic alarm_tm->tm_year += 1; 833*7818ae9bSClément Le Goffic } else { 834*7818ae9bSClément Le Goffic alarm_tm->tm_mon += 1; 835*7818ae9bSClément Le Goffic } 836*7818ae9bSClément Le Goffic } 837*7818ae9bSClément Le Goffic 838*7818ae9bSClément Le Goffic alarm->enabled = cr & RTC_CR_ALRAE; 839*7818ae9bSClément Le Goffic alarm->pending = status & RTC_SR_ALRAF; 840*7818ae9bSClément Le Goffic 841*7818ae9bSClément Le Goffic return TEE_SUCCESS; 842*7818ae9bSClément Le Goffic } 843*7818ae9bSClément Le Goffic 844*7818ae9bSClément Le Goffic static TEE_Result stm32_rtc_enable_alarm(struct rtc *rtc __unused, bool enabled) 845*7818ae9bSClément Le Goffic { 846*7818ae9bSClément Le Goffic vaddr_t rtc_base = get_base(); 847*7818ae9bSClément Le Goffic 848*7818ae9bSClément Le Goffic stm32_rtc_write_unprotect(); 849*7818ae9bSClément Le Goffic 850*7818ae9bSClément Le Goffic if (enabled) 851*7818ae9bSClément Le Goffic io_setbits32(rtc_base + RTC_CR, RTC_CR_ALRAIE | RTC_CR_ALRAE); 852*7818ae9bSClément Le Goffic else 853*7818ae9bSClément Le Goffic io_clrbits32(rtc_base + RTC_CR, RTC_CR_ALRAIE | RTC_CR_ALRAE); 854*7818ae9bSClément Le Goffic 855*7818ae9bSClément Le Goffic stm32_rtc_clear_events(RTC_SCR_CALRAF); 856*7818ae9bSClément Le Goffic 857*7818ae9bSClément Le Goffic stm32_rtc_write_protect(); 858*7818ae9bSClément Le Goffic 859*7818ae9bSClément Le Goffic return TEE_SUCCESS; 860*7818ae9bSClément Le Goffic } 861*7818ae9bSClément Le Goffic 862*7818ae9bSClément Le Goffic static void stm32_rtc_add_one_month(struct optee_rtc_time *tm) 863*7818ae9bSClément Le Goffic { 864*7818ae9bSClément Le Goffic tm->tm_mon++; 865*7818ae9bSClément Le Goffic if (tm->tm_mon > 11) { 866*7818ae9bSClément Le Goffic tm->tm_mon = 0; 867*7818ae9bSClément Le Goffic tm->tm_year++; 868*7818ae9bSClément Le Goffic } 869*7818ae9bSClément Le Goffic 870*7818ae9bSClément Le Goffic /* Saturate to the next month last day */ 871*7818ae9bSClément Le Goffic tm->tm_mday = MIN(tm->tm_mday, 872*7818ae9bSClément Le Goffic rtc_get_month_days(tm->tm_mon, tm->tm_year)); 873*7818ae9bSClément Le Goffic } 874*7818ae9bSClément Le Goffic 875*7818ae9bSClément Le Goffic static TEE_Result stm32_rtc_valid_alarm_time(struct rtc *rtc, 876*7818ae9bSClément Le Goffic struct optee_rtc_time *tm) 877*7818ae9bSClément Le Goffic { 878*7818ae9bSClément Le Goffic struct optee_rtc_time current_tm = { }; 879*7818ae9bSClément Le Goffic TEE_Result res = TEE_ERROR_GENERIC; 880*7818ae9bSClément Le Goffic struct optee_rtc_time *max = NULL; 881*7818ae9bSClément Le Goffic 882*7818ae9bSClément Le Goffic /* 883*7818ae9bSClément Le Goffic * Assuming current date is M-D-Y H:M:S. 884*7818ae9bSClément Le Goffic * RTC alarm can't be set on a specific month and year. 885*7818ae9bSClément Le Goffic * So the valid alarm range is: 886*7818ae9bSClément Le Goffic * M-D-Y H:M:S < alarm <= (M+1)-D-Y H:M:S 887*7818ae9bSClément Le Goffic */ 888*7818ae9bSClément Le Goffic 889*7818ae9bSClément Le Goffic res = stm32_rtc_get_time(rtc, ¤t_tm); 890*7818ae9bSClément Le Goffic if (res) 891*7818ae9bSClément Le Goffic return res; 892*7818ae9bSClément Le Goffic 893*7818ae9bSClément Le Goffic /* Don't allow alarm to be set in the past. */ 894*7818ae9bSClément Le Goffic if (rtc_timecmp(¤t_tm, tm) >= 0) 895*7818ae9bSClément Le Goffic return TEE_ERROR_BAD_PARAMETERS; 896*7818ae9bSClément Le Goffic 897*7818ae9bSClément Le Goffic max = ¤t_tm; 898*7818ae9bSClément Le Goffic 899*7818ae9bSClément Le Goffic stm32_rtc_add_one_month(max); 900*7818ae9bSClément Le Goffic 901*7818ae9bSClément Le Goffic if (rtc_timecmp(max, tm) <= 0) 902*7818ae9bSClément Le Goffic return TEE_ERROR_BAD_PARAMETERS; 903*7818ae9bSClément Le Goffic 904*7818ae9bSClément Le Goffic return TEE_SUCCESS; 905*7818ae9bSClément Le Goffic } 906*7818ae9bSClément Le Goffic 907*7818ae9bSClément Le Goffic static TEE_Result stm32_rtc_set_alarm(struct rtc *rtc, 908*7818ae9bSClément Le Goffic struct optee_rtc_alarm *alarm) 909*7818ae9bSClément Le Goffic { 910*7818ae9bSClément Le Goffic struct optee_rtc_time *alarm_time = &alarm->time; 911*7818ae9bSClément Le Goffic TEE_Result res = TEE_ERROR_GENERIC; 912*7818ae9bSClément Le Goffic vaddr_t rtc_base = get_base(); 913*7818ae9bSClément Le Goffic uint32_t alrmar = 0; 914*7818ae9bSClément Le Goffic uint32_t cr = io_read32(rtc_base + RTC_CR); 915*7818ae9bSClément Le Goffic uint32_t prer = io_read32(rtc_base + RTC_PRER); 916*7818ae9bSClément Le Goffic uint32_t prediv_s = prer & RTC_PRER_PREDIV_S_MASK; 917*7818ae9bSClément Le Goffic 918*7818ae9bSClément Le Goffic /* tm_year and tm_mon are not used because not supported by RTC */ 919*7818ae9bSClément Le Goffic alrmar |= ((alarm_time->tm_mday / 10) << RTC_ALRMXR_DATE_TENS_SHIFT) & 920*7818ae9bSClément Le Goffic RTC_ALRMXR_DATE_TENS_MASK; 921*7818ae9bSClément Le Goffic alrmar |= ((alarm_time->tm_mday % 10) << RTC_ALRMXR_DATE_UNITS_SHIFT) & 922*7818ae9bSClément Le Goffic RTC_ALRMXR_DATE_UNITS_MASK; 923*7818ae9bSClément Le Goffic /* 24-hour format */ 924*7818ae9bSClément Le Goffic alrmar &= ~RTC_ALRMXR_PM; 925*7818ae9bSClément Le Goffic alrmar |= ((alarm_time->tm_hour / 10) << RTC_ALRMXR_HOUR_TENS_SHIFT) & 926*7818ae9bSClément Le Goffic RTC_ALRMXR_HOUR_TENS_MASK; 927*7818ae9bSClément Le Goffic alrmar |= ((alarm_time->tm_hour % 10) << RTC_ALRMXR_HOUR_UNITS_SHIFT) & 928*7818ae9bSClément Le Goffic RTC_ALRMXR_HOUR_UNITS_MASK; 929*7818ae9bSClément Le Goffic alrmar |= ((alarm_time->tm_min / 10) << RTC_ALRMXR_MIN_TENS_SHIFT) & 930*7818ae9bSClément Le Goffic RTC_ALRMXR_MIN_TENS_MASK; 931*7818ae9bSClément Le Goffic alrmar |= ((alarm_time->tm_min % 10) << RTC_ALRMXR_MIN_UNITS_SHIFT) & 932*7818ae9bSClément Le Goffic RTC_ALRMXR_MIN_UNITS_MASK; 933*7818ae9bSClément Le Goffic alrmar |= ((alarm_time->tm_sec / 10) << RTC_ALRMXR_SEC_TENS_SHIFT) & 934*7818ae9bSClément Le Goffic RTC_ALRMXR_SEC_TENS_MASK; 935*7818ae9bSClément Le Goffic alrmar |= ((alarm_time->tm_sec % 10) << RTC_ALRMXR_SEC_UNITS_SHIFT) & 936*7818ae9bSClément Le Goffic RTC_ALRMXR_SEC_UNITS_MASK; 937*7818ae9bSClément Le Goffic 938*7818ae9bSClément Le Goffic if ((alrmar & !RTC_ALRMXR_SEC_MASK) && prediv_s < 3) { 939*7818ae9bSClément Le Goffic EMSG("RTC Alarm conditions not met"); 940*7818ae9bSClément Le Goffic return TEE_ERROR_BAD_STATE; 941*7818ae9bSClément Le Goffic } 942*7818ae9bSClément Le Goffic 943*7818ae9bSClément Le Goffic stm32_rtc_write_unprotect(); 944*7818ae9bSClément Le Goffic 945*7818ae9bSClément Le Goffic res = stm32_rtc_valid_alarm_time(rtc, alarm_time); 946*7818ae9bSClément Le Goffic if (res) { 947*7818ae9bSClément Le Goffic stm32_rtc_write_unprotect(); 948*7818ae9bSClément Le Goffic return res; 949*7818ae9bSClément Le Goffic } 950*7818ae9bSClément Le Goffic 951*7818ae9bSClément Le Goffic /* Disable Alarm */ 952*7818ae9bSClément Le Goffic cr &= ~RTC_CR_ALRAE; 953*7818ae9bSClément Le Goffic io_write32(rtc_base + RTC_CR, cr); 954*7818ae9bSClément Le Goffic 955*7818ae9bSClément Le Goffic io_write32(rtc_base + RTC_ALRMAR, alrmar); 956*7818ae9bSClément Le Goffic 957*7818ae9bSClément Le Goffic stm32_rtc_enable_alarm(rtc, alarm->enabled); 958*7818ae9bSClément Le Goffic 959*7818ae9bSClément Le Goffic stm32_rtc_write_protect(); 960*7818ae9bSClément Le Goffic 961*7818ae9bSClément Le Goffic return TEE_SUCCESS; 962*7818ae9bSClément Le Goffic } 963*7818ae9bSClément Le Goffic 964*7818ae9bSClément Le Goffic static TEE_Result stm32_rtc_cancel_wait_alarm(struct rtc *rtc __unused) 965*7818ae9bSClément Le Goffic { 966*7818ae9bSClément Le Goffic rtc_dev.wait_alarm_return_status = RTC_WAIT_ALARM_CANCELED; 967*7818ae9bSClément Le Goffic notif_send_async(rtc_dev.notif_id, 0); 968*7818ae9bSClément Le Goffic 969*7818ae9bSClément Le Goffic return TEE_SUCCESS; 970*7818ae9bSClément Le Goffic } 971*7818ae9bSClément Le Goffic 972*7818ae9bSClément Le Goffic static TEE_Result 973*7818ae9bSClément Le Goffic stm32_rtc_wait_alarm(struct rtc *rtc __unused, 974*7818ae9bSClément Le Goffic enum rtc_wait_alarm_status *return_status) 975*7818ae9bSClément Le Goffic { 976*7818ae9bSClément Le Goffic TEE_Result res = TEE_ERROR_GENERIC; 977*7818ae9bSClément Le Goffic 978*7818ae9bSClément Le Goffic rtc_dev.wait_alarm_return_status = RTC_WAIT_ALARM_RESET; 979*7818ae9bSClément Le Goffic 980*7818ae9bSClément Le Goffic /* Wait until a notification arrives - blocking */ 981*7818ae9bSClément Le Goffic res = notif_wait(rtc_dev.notif_id); 982*7818ae9bSClément Le Goffic if (res) 983*7818ae9bSClément Le Goffic return res; 984*7818ae9bSClément Le Goffic 985*7818ae9bSClément Le Goffic if (rtc_dev.wait_alarm_return_status == 986*7818ae9bSClément Le Goffic RTC_WAIT_ALARM_CANCELED) { 987*7818ae9bSClément Le Goffic *return_status = RTC_WAIT_ALARM_CANCELED; 988*7818ae9bSClément Le Goffic stm32_rtc_enable_alarm(rtc, 0); 989*7818ae9bSClément Le Goffic } else { 990*7818ae9bSClément Le Goffic *return_status = RTC_WAIT_ALARM_ALARM_OCCURRED; 991*7818ae9bSClément Le Goffic } 992*7818ae9bSClément Le Goffic 993*7818ae9bSClément Le Goffic return TEE_SUCCESS; 994*7818ae9bSClément Le Goffic } 995*7818ae9bSClément Le Goffic 996e419bc7fSGatien Chevallier static const struct rtc_ops stm32_rtc_ops = { 997e419bc7fSGatien Chevallier .get_time = stm32_rtc_get_time, 998e419bc7fSGatien Chevallier .set_time = stm32_rtc_set_time, 999*7818ae9bSClément Le Goffic .read_alarm = stm32_rtc_read_alarm, 1000*7818ae9bSClément Le Goffic .set_alarm = stm32_rtc_set_alarm, 1001*7818ae9bSClément Le Goffic .enable_alarm = stm32_rtc_enable_alarm, 1002*7818ae9bSClément Le Goffic .wait_alarm = stm32_rtc_wait_alarm, 1003*7818ae9bSClément Le Goffic .cancel_wait = stm32_rtc_cancel_wait_alarm, 1004e419bc7fSGatien Chevallier }; 1005e419bc7fSGatien Chevallier 1006e419bc7fSGatien Chevallier static struct rtc stm32_rtc = { 1007e419bc7fSGatien Chevallier .ops = &stm32_rtc_ops, 1008e419bc7fSGatien Chevallier .range_min = RTC_TIME(YEAR_REF, 0, 1, 0, 0, 0, 0, 0), 1009e419bc7fSGatien Chevallier .range_max = RTC_TIME(YEAR_MAX, 11, 31, 4, 23, 59, 59, 999), 1010e419bc7fSGatien Chevallier }; 1011e419bc7fSGatien Chevallier 1012e419bc7fSGatien Chevallier static TEE_Result stm32_rtc_probe(const void *fdt, int node, 1013e419bc7fSGatien Chevallier const void *compat_data) 1014e419bc7fSGatien Chevallier { 1015e419bc7fSGatien Chevallier TEE_Result res = TEE_ERROR_GENERIC; 1016e419bc7fSGatien Chevallier bool is_tdcid = false; 1017e419bc7fSGatien Chevallier 1018e419bc7fSGatien Chevallier rtc_dev.compat = compat_data; 1019e419bc7fSGatien Chevallier 1020e419bc7fSGatien Chevallier if (rtc_dev.compat->has_rif_support) { 1021e419bc7fSGatien Chevallier res = stm32_rifsc_check_tdcid(&is_tdcid); 1022e419bc7fSGatien Chevallier if (res) 1023e419bc7fSGatien Chevallier return res; 1024e419bc7fSGatien Chevallier } 1025e419bc7fSGatien Chevallier 1026e419bc7fSGatien Chevallier res = parse_dt(fdt, node); 1027e419bc7fSGatien Chevallier if (res) { 1028e419bc7fSGatien Chevallier memset(&rtc_dev, 0, sizeof(rtc_dev)); 1029e419bc7fSGatien Chevallier return res; 1030e419bc7fSGatien Chevallier } 1031e419bc7fSGatien Chevallier 1032e419bc7fSGatien Chevallier /* Unbalanced clock enable to ensure RTC core clock is always on */ 1033e419bc7fSGatien Chevallier res = clk_enable(rtc_dev.rtc_ck); 1034e419bc7fSGatien Chevallier if (res) 1035e419bc7fSGatien Chevallier panic("Couldn't enable RTC clock"); 1036e419bc7fSGatien Chevallier 1037e419bc7fSGatien Chevallier if (clk_get_rate(rtc_dev.pclk) < (clk_get_rate(rtc_dev.rtc_ck) * 7)) 1038e419bc7fSGatien Chevallier rtc_dev.flags |= RTC_FLAGS_READ_TWICE; 1039e419bc7fSGatien Chevallier 1040e419bc7fSGatien Chevallier if (rtc_dev.compat->has_rif_support) { 1041e419bc7fSGatien Chevallier res = clk_enable(rtc_dev.pclk); 1042e419bc7fSGatien Chevallier if (res) 1043e419bc7fSGatien Chevallier panic("Could not enable RTC bus clock"); 1044e419bc7fSGatien Chevallier 1045e419bc7fSGatien Chevallier apply_rif_config(is_tdcid); 1046e419bc7fSGatien Chevallier 1047e419bc7fSGatien Chevallier /* 1048e419bc7fSGatien Chevallier * Verify if applied RIF config will not disable 1049e419bc7fSGatien Chevallier * other functionalities of this driver. 1050e419bc7fSGatien Chevallier */ 1051e419bc7fSGatien Chevallier res = check_rif_config(); 1052e419bc7fSGatien Chevallier if (res) 1053e419bc7fSGatien Chevallier panic("Incompatible RTC RIF configuration"); 1054e419bc7fSGatien Chevallier 1055e419bc7fSGatien Chevallier clk_disable(rtc_dev.pclk); 1056e419bc7fSGatien Chevallier } 1057e419bc7fSGatien Chevallier 1058446da993SClément Le Goffic res = stm32_rtc_init(); 1059446da993SClément Le Goffic if (res) 1060446da993SClément Le Goffic return res; 1061*7818ae9bSClément Le Goffic 1062e419bc7fSGatien Chevallier rtc_register(&stm32_rtc); 1063e419bc7fSGatien Chevallier 1064*7818ae9bSClément Le Goffic if (IS_ENABLED(CFG_RTC_PTA) && IS_ENABLED(CFG_CORE_ASYNC_NOTIF) && 1065*7818ae9bSClément Le Goffic rtc_dev.is_secured) { 1066*7818ae9bSClément Le Goffic res = notif_alloc_async_value(&rtc_dev.notif_id); 1067*7818ae9bSClément Le Goffic if (res) 1068e419bc7fSGatien Chevallier return res; 1069*7818ae9bSClément Le Goffic 1070*7818ae9bSClément Le Goffic /* Unbalanced clock enable to ensure IRQ interface is alive */ 1071*7818ae9bSClément Le Goffic res = clk_enable(rtc_dev.pclk); 1072*7818ae9bSClément Le Goffic if (res) 1073*7818ae9bSClément Le Goffic goto out_rtc_secured; 1074*7818ae9bSClément Le Goffic 1075*7818ae9bSClément Le Goffic interrupt_enable(rtc_dev.itr_chip, rtc_dev.itr_num); 1076*7818ae9bSClément Le Goffic 1077*7818ae9bSClément Le Goffic return TEE_SUCCESS; 1078*7818ae9bSClément Le Goffic 1079*7818ae9bSClément Le Goffic out_rtc_secured: 1080*7818ae9bSClément Le Goffic notif_free_async_value(rtc_dev.notif_id); 1081*7818ae9bSClément Le Goffic return res; 1082*7818ae9bSClément Le Goffic } 1083*7818ae9bSClément Le Goffic 1084*7818ae9bSClément Le Goffic return TEE_SUCCESS; 1085e419bc7fSGatien Chevallier } 1086e419bc7fSGatien Chevallier 1087e419bc7fSGatien Chevallier static const struct rtc_compat mp25_compat = { 1088e419bc7fSGatien Chevallier .has_seccfgr = true, 1089e419bc7fSGatien Chevallier .has_rif_support = true, 1090e419bc7fSGatien Chevallier }; 1091e419bc7fSGatien Chevallier 1092e419bc7fSGatien Chevallier static const struct rtc_compat mp15_compat = { 1093e419bc7fSGatien Chevallier .has_seccfgr = false, 1094e419bc7fSGatien Chevallier .has_rif_support = false, 1095e419bc7fSGatien Chevallier }; 1096e419bc7fSGatien Chevallier 1097e419bc7fSGatien Chevallier static const struct rtc_compat mp13_compat = { 1098e419bc7fSGatien Chevallier .has_seccfgr = true, 1099e419bc7fSGatien Chevallier .has_rif_support = false, 1100e419bc7fSGatien Chevallier }; 1101e419bc7fSGatien Chevallier 1102e419bc7fSGatien Chevallier static const struct dt_device_match stm32_rtc_match_table[] = { 1103e419bc7fSGatien Chevallier { 1104e419bc7fSGatien Chevallier .compatible = "st,stm32mp25-rtc", 1105e419bc7fSGatien Chevallier .compat_data = &mp25_compat, 1106e419bc7fSGatien Chevallier }, 1107e419bc7fSGatien Chevallier { 1108e419bc7fSGatien Chevallier .compatible = "st,stm32mp1-rtc", 1109e419bc7fSGatien Chevallier .compat_data = &mp15_compat, 1110e419bc7fSGatien Chevallier }, 1111e419bc7fSGatien Chevallier { 1112e419bc7fSGatien Chevallier .compatible = "st,stm32mp13-rtc", 1113e419bc7fSGatien Chevallier .compat_data = &mp13_compat, 1114e419bc7fSGatien Chevallier }, 1115e419bc7fSGatien Chevallier { } 1116e419bc7fSGatien Chevallier }; 1117e419bc7fSGatien Chevallier 1118e419bc7fSGatien Chevallier DEFINE_DT_DRIVER(stm32_rtc_dt_driver) = { 1119e419bc7fSGatien Chevallier .name = "stm32-rtc", 1120e419bc7fSGatien Chevallier .match_table = stm32_rtc_match_table, 1121e419bc7fSGatien Chevallier .probe = stm32_rtc_probe, 1122e419bc7fSGatien Chevallier }; 1123