void hal_rtc_set_gpio_32k_status(u16 user, bool enable) { u16 con, pdn1; if (enable) { pdn1 = rtc_read(RTC_PDN1); } else { pdn1 = rtc_read(RTC_PDN1) & ~(1U << user); rtc_write(RTC_PDN1, pdn1); rtc_write_trigger(); } con = rtc_read(RTC_CON); if (enable) { con &= ~RTC_CON_F32KOB; } else { if (!(pdn1 & RTC_GPIO_USER_MASK)) { /* no users */ con |= RTC_CON_F32KOB; } } rtc_write(RTC_CON, con); rtc_write_trigger(); if (enable) { pdn1 |= (1U << user); rtc_write(RTC_PDN1, pdn1); rtc_write_trigger(); } hal_rtc_xinfo("RTC_GPIO user %d enable = %d 32k (0x%x)\n", user, enable, pdn1); }
void rtc_gpio_disable_32k(rtc_gpio_user_t user) { u16 con, pdn1; unsigned long flags; if (user < RTC_GPIO_USER_WIFI || user > RTC_GPIO_USER_FM) return; spin_lock_irqsave(&rtc_lock, flags); pdn1 = rtc_read(RTC_PDN1) & ~(1U << user); rtc_write(RTC_PDN1, pdn1); rtc_write_trigger(); if (!(pdn1 & RTC_GPIO_USER_MASK)) { /* no users */ if (get_chip_eco_ver() == CHIP_E1) { /* keep exporting 32K to avoid f32k_ck drift */ } else { con = rtc_read(RTC_CON) | RTC_CON_F32KOB; rtc_write(RTC_CON, con); rtc_write_trigger(); con = rtc_read(RTC_OSC32CON) & ~RTC_OSC32CON_GPIOCKEN; rtc_xosc_write(con, true); } } spin_unlock_irqrestore(&rtc_lock, flags); printk(RTC_SAY "RTC_GPIO user %d disables 32k (0x%x)\n", user, pdn1); }
void rtc_gpio_enable_32k(rtc_gpio_user_t user) { u16 con, pdn1; unsigned long flags; if (user < RTC_GPIO_USER_WIFI || user > RTC_GPIO_USER_FM) return; spin_lock_irqsave(&rtc_lock, flags); pdn1 = rtc_read(RTC_PDN1); if (!(pdn1 & RTC_GPIO_USER_MASK)) { /* first user */ con = rtc_read(RTC_OSC32CON) | RTC_OSC32CON_GPIOCKEN; rtc_xosc_write(con, true); con = rtc_read(RTC_CON) & ~RTC_CON_F32KOB; rtc_write(RTC_CON, con); rtc_write_trigger(); } pdn1 |= (1U << user); rtc_write(RTC_PDN1, pdn1); rtc_write_trigger(); spin_unlock_irqrestore(&rtc_lock, flags); printk(RTC_SAY "RTC_GPIO user %d enables 32k (0x%x)\n", user, pdn1); }
/* initialize rtc setting of using dcxo clock */ static int rtc_enable_dcxo(void) { u16 bbpu, con, osc32con, sec; rtc_read(RTC_BBPU, &bbpu); rtc_write(RTC_BBPU, bbpu | RTC_BBPU_KEY | RTC_BBPU_RELOAD); rtc_write_trigger(); mdelay(1); if (!rtc_writeif_unlock()) { /* Unlock for reload */ rtc_info("rtc_writeif_unlock() fail\n"); return 0; } rtc_read(RTC_OSC32CON, &osc32con); osc32con &= ~RTC_EMBCK_SRC_SEL; osc32con |= RTC_XOSC32_ENB | RTC_REG_XOSC32_ENB; if (!rtc_xosc_write(osc32con)) { rtc_info("rtc_xosc_write() fail\n"); return 0; } rtc_read(RTC_BBPU, &bbpu); rtc_write(RTC_BBPU, bbpu | RTC_BBPU_KEY | RTC_BBPU_RELOAD); rtc_write_trigger(); rtc_read(RTC_CON, &con); rtc_read(RTC_OSC32CON, &osc32con); rtc_read(RTC_AL_SEC, &sec); rtc_info("con=0x%x, osc32con=0x%x, sec=0x%x\n", con, osc32con, sec); return 1; }
static void rtc_writeif_unlock(void) { rtc_write(RTC_PROT, 0x586a); rtc_write_trigger(); rtc_write(RTC_PROT, 0x9136); rtc_write_trigger(); }
void rtc_enable_writeif(void) { unsigned long flags; spin_lock_irqsave(&rtc_lock, flags); rtc_write(RTC_PROT, 0x586a); rtc_write_trigger(); rtc_write(RTC_PROT, 0x9136); rtc_write_trigger(); spin_unlock_irqrestore(&rtc_lock, flags); }
void hal_rtc_bbpu_pwdn(void) { u16 ret_val, con; /* disable 32K export if there are no RTC_GPIO users */ if (!(rtc_read(RTC_PDN1) & RTC_GPIO_USER_MASK)) { con = rtc_read(RTC_CON) | RTC_CON_F32KOB; rtc_write(RTC_CON, con); rtc_write_trigger(); } ret_val = hal_rtc_get_spare_register(RTC_32K_LESS); #if !defined(CONFIG_MTK_FPGA) if (!ret_val && pmic_chrdet_status() == KAL_FALSE) { /* 1. Set SRCLKENAs GPIO GPIO as Output Mode, Output Low */ mt_set_gpio_dir(GPIO_SRCLKEN_PIN, GPIO_DIR_OUT); mt_set_gpio_out(GPIO_SRCLKEN_PIN, GPIO_OUT_ZERO); /* 2. pull PWRBB low */ rtc_bbpu_pwrdown(true); /* 3. Switch SRCLKENAs GPIO MUX function to GPIO Mode */ mt_set_gpio_mode(GPIO_SRCLKEN_PIN, GPIO_MODE_GPIO); } else #endif { rtc_bbpu_pwrdown(true); } }
void hal_rtc_set_alarm(struct rtc_time *tm) { u16 irqen; hal_rtc_set_alarm_time(tm); irqen = rtc_read(RTC_IRQ_EN) | RTC_IRQ_EN_ONESHOT_AL; rtc_write(RTC_IRQ_EN, irqen); rtc_write_trigger(); }
/* enable lpd subroutine */ static int rtc_lpen(u16 con) { con &= ~RTC_CON_LPRST; rtc_write(RTC_CON, con); if (!rtc_write_trigger()) return 0; con |= RTC_CON_LPRST; rtc_write(RTC_CON, con); if (!rtc_write_trigger()) return 0; con &= ~RTC_CON_LPRST; rtc_write(RTC_CON, con); if (!rtc_write_trigger()) return 0; return 1; }
void rtc_mark_swreset(void) { u16 pdn1; unsigned long flags; spin_lock_irqsave(&rtc_lock, flags); pdn1 = rtc_read(RTC_PDN1) & ~0x0030; rtc_write(RTC_PDN1, pdn1 | 0x0020); rtc_write_trigger(); spin_unlock_irqrestore(&rtc_lock, flags); }
void hal_rtc_set_lp_irq(void) { u16 irqen; #ifndef USER_BUILD_KERNEL irqen = rtc_read(RTC_IRQ_EN) | RTC_IRQ_EN_LP; #else irqen = rtc_read(RTC_IRQ_EN) & ~RTC_IRQ_EN_LP; #endif rtc_write(RTC_IRQ_EN, irqen); rtc_write_trigger(); }
void hal_rtc_clear_alarm(struct rtc_time *tm) { u16 irqsta, irqen, pdn2; irqen = rtc_read(RTC_IRQ_EN) & ~RTC_IRQ_EN_AL; pdn2 = rtc_read(RTC_PDN2) & ~RTC_PDN2_PWRON_ALARM; rtc_write(RTC_IRQ_EN, irqen); rtc_write(RTC_PDN2, pdn2); rtc_write_trigger(); irqsta = rtc_read(RTC_IRQ_STA); /* read clear */ hal_rtc_set_alarm_time(tm); }
static bool rtc_hw_init(void) { u16 bbpu; rtc_read(RTC_BBPU, &bbpu); rtc_write(RTC_BBPU, bbpu | RTC_BBPU_KEY | RTC_BBPU_INIT); rtc_write_trigger(); udelay(500); rtc_read(RTC_BBPU, &bbpu); rtc_write(RTC_BBPU, bbpu | RTC_BBPU_KEY | RTC_BBPU_RELOAD); rtc_write_trigger(); rtc_read(RTC_BBPU, &bbpu); if (bbpu & RTC_BBPU_INIT) { rtc_info("timeout\n"); return false; } return true; }
/* low power detect setting */ static int rtc_lpd_init(void) { u16 con, sec; /* set RTC_LPD_OPT */ rtc_read(RTC_AL_SEC, &sec); sec |= RTC_LPD_OPT_F32K_CK_ALIVE; rtc_write(RTC_AL_SEC, sec); if (!rtc_write_trigger()) return 0; /* init XOSC32 to detect 32k clock stop */ rtc_read(RTC_CON, &con); con |= RTC_CON_XOSC32_LPEN; if (!rtc_lpen(con)) return 0; /* init EOSC32 to detect rtc low power */ rtc_read(RTC_CON, &con); con |= RTC_CON_EOSC32_LPEN; if (!rtc_lpen(con)) return 0; rtc_read(RTC_CON, &con); con &= ~RTC_CON_XOSC32_LPEN; rtc_write(RTC_CON, con); /* set RTC_LPD_OPT */ rtc_read(RTC_AL_SEC, &sec); sec &= ~RTC_LPD_OPT_MASK; sec |= RTC_LPD_OPT_EOSC_LPD; rtc_write(RTC_AL_SEC, sec); if (!rtc_write_trigger()) return 0; return 1; }
void rtc_bbpu_power_down(void) { u16 bbpu, con; unsigned long flags; spin_lock_irqsave(&rtc_lock, flags); rtc_writeif_unlock(); /* disable 32K export if there are no RTC_GPIO users */ if (!(rtc_read(RTC_PDN1) & RTC_GPIO_USER_MASK)) { con = rtc_read(RTC_CON) | RTC_CON_F32KOB; rtc_write(RTC_CON, con); rtc_write_trigger(); con = rtc_read(RTC_OSC32CON) & ~RTC_OSC32CON_GPIOCKEN; rtc_xosc_write(con, false); } /* pull PWRBB low */ bbpu = RTC_BBPU_KEY | RTC_BBPU_AUTO | RTC_BBPU_PWREN; rtc_write(RTC_BBPU, bbpu); rtc_write_trigger(); spin_unlock_irqrestore(&rtc_lock, flags); }
u16 rtc_rdwr_uart_bits(u16 *val) { u16 pdn2; unsigned long flags; spin_lock_irqsave(&rtc_lock, flags); if (val) { pdn2 = rtc_read(RTC_PDN2) & ~0x0060; pdn2 |= (*val & 0x0003) << 5; rtc_write(RTC_PDN2, pdn2); rtc_write_trigger(); } pdn2 = rtc_read(RTC_PDN2); spin_unlock_irqrestore(&rtc_lock, flags); return (pdn2 & 0x0060) >> 5; }
/* enable rtc bbpu */ void rtc_bbpu_power_on(void) { u16 bbpu; int ret; /* pull powerhold high, control by pmic */ pmic_set_power_hold(true); /* pull PWRBB high */ bbpu = RTC_BBPU_KEY | RTC_BBPU_AUTO | RTC_BBPU_RELOAD | RTC_BBPU_PWREN; rtc_write(RTC_BBPU, bbpu); ret = rtc_write_trigger(); rtc_info("rtc_write_trigger=%d\n", ret); rtc_read(RTC_BBPU, &bbpu); rtc_info("done BBPU=%#x\n", bbpu); }
static void rtc_xosc_write(u16 val, bool reload) { u16 bbpu; rtc_write(RTC_OSC32CON, 0x1a57); rtc_busy_wait(); rtc_write(RTC_OSC32CON, 0x2b68); rtc_busy_wait(); rtc_write(RTC_OSC32CON, val); rtc_busy_wait(); if (reload) { bbpu = rtc_read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD; rtc_write(RTC_BBPU, bbpu); rtc_write_trigger(); } }
void hal_rtc_save_pwron_time(bool enable, struct rtc_time *tm, bool logo) { u16 pdn1, pdn2; hal_rtc_set_pwron_alarm_time(tm); if (logo) pdn2 = rtc_read(RTC_PDN2) | RTC_PDN2_PWRON_LOGO; else pdn2 = rtc_read(RTC_PDN2) & ~RTC_PDN2_PWRON_LOGO; rtc_write(RTC_PDN2, pdn2); if (enable) pdn1 = rtc_read(RTC_PDN1) | RTC_PDN1_PWRON_TIME; else pdn1 = rtc_read(RTC_PDN1) & ~RTC_PDN1_PWRON_TIME; rtc_write(RTC_PDN1, pdn1); rtc_write_trigger(); }
/* initialize rtc related gpio */ static int rtc_gpio_init(void) { u16 con; /* RTC_32K1V8 clock change from 128k div 4 source * to RTC 32k source */ pwrap_write_field(PMIC_RG_TOP_CKSEL_CON0_SET, 0x1, 0x1, 3); /* Export 32K clock RTC_32K1V8_1 */ pwrap_write_field(PMIC_RG_TOP_CKPDN_CON1_CLR, 0x1, 0x1, 1); /* Export 32K clock RTC_32K2V8 */ rtc_read(RTC_CON, &con); con &= (RTC_CON_LPSTA_RAW | RTC_CON_LPRST | RTC_CON_EOSC32_LPEN | RTC_CON_XOSC32_LPEN); con |= (RTC_CON_GPEN | RTC_CON_GOE); con &= ~(RTC_CON_F32KOB); rtc_write(RTC_CON, con); return rtc_write_trigger(); }
/* write powerkeys to enable rtc functions */ static int rtc_powerkey_init(void) { rtc_write(RTC_POWERKEY1, RTC_POWERKEY1_KEY); rtc_write(RTC_POWERKEY2, RTC_POWERKEY2_KEY); return rtc_write_trigger(); }
static void rtc_tasklet_handler(unsigned long data) { u16 irqsta, pdn1, pdn2, spar1; bool pwron_alm = false; spin_lock(&rtc_lock); irqsta = rtc_read(RTC_IRQ_STA); /* read clear */ if (unlikely(!(irqsta & RTC_IRQ_STA_AL))) { #ifndef USER_BUILD_KERNEL if (irqsta & RTC_IRQ_STA_LP) rtc_lp_exception(); #endif spin_unlock(&rtc_lock); enable_irq(MT6573_RTC_IRQ_LINE); return; } #if RTC_RELPWR_WHEN_XRST { /* set AUTO bit because AUTO = 0 when PWREN = 1 and alarm occurs */ u16 bbpu = rtc_read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_AUTO; rtc_write(RTC_BBPU, bbpu); rtc_write_trigger(); } #endif pdn1 = rtc_read(RTC_PDN1); pdn2 = rtc_read(RTC_PDN2); spar1 = rtc_read(RTC_SPAR1); if (pdn1 & 0x0080) { /* power-on time is available */ u16 now_sec, now_min, now_hou, now_dom, now_mth; u16 irqen, min, hou, dom, mth; now_sec = rtc_read(RTC_TC_SEC); now_min = rtc_read(RTC_TC_MIN); now_hou = rtc_read(RTC_TC_HOU); now_dom = rtc_read(RTC_TC_DOM); now_mth = rtc_read(RTC_TC_MTH); if (rtc_read(RTC_TC_SEC) < now_sec) { /* SEC has carried */ now_sec = rtc_read(RTC_TC_SEC); now_min = rtc_read(RTC_TC_MIN); now_hou = rtc_read(RTC_TC_HOU); now_dom = rtc_read(RTC_TC_DOM); now_mth = rtc_read(RTC_TC_MTH); } min = spar1 & 0x003f; hou = (spar1 & 0x07c0) >> 6; dom = (spar1 & 0xf800) >> 11; mth = pdn2 & 0x000f; if (now_mth == mth && now_dom == dom && now_hou == hou && now_min == min && now_sec >= (RTC_PWRON_SEC - 1) && now_sec <= (RTC_PWRON_SEC + 4)) { rtc_write(RTC_PDN1, pdn1 & ~0x0080); rtc_write(RTC_PDN2, pdn2 | 0x0010); rtc_write_trigger(); pwron_alm = true; } else { /* set power-on alarm when power-on time is available */ rtc_write(RTC_AL_MTH, mth); rtc_write(RTC_AL_DOM, dom); rtc_write(RTC_AL_HOU, hou); rtc_write(RTC_AL_MIN, min); rtc_write(RTC_AL_SEC, RTC_PWRON_SEC); rtc_write(RTC_AL_MASK, 0x0050); /* mask YEA and DOW */ rtc_write_trigger(); irqen = rtc_read(RTC_IRQ_EN) | RTC_IRQ_EN_ONESHOT_AL; rtc_write(RTC_IRQ_EN, irqen); rtc_write_trigger(); } }