| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388 |
- /*
- * Copyright (C) 2010 MediaTek, Inc.
- *
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
- #ifdef pr_fmt
- #undef pr_fmt
- #endif
- #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
- #include <linux/delay.h>
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/rtc.h>
- #include <mach/upmu_hw.h>
- #include <linux/spinlock.h>
- #include <linux/interrupt.h>
- #include <linux/platform_device.h>
- #include <linux/delay.h>
- #include <linux/types.h>
- #include <mach/irqs.h>
- #include <mach/mtk_rtc_hal.h>
- #include <mtk_rtc_hal_common.h>
- #include <mach/mt_rtc_hw.h>
- #include <mt_pmic_wrap.h>
- #if defined CONFIG_MTK_KERNEL_POWER_OFF_CHARGING
- #include <mt_boot.h>
- #endif
- #include <mt_gpio.h>
- #include <mt-plat/charging.h>
- #define hal_rtc_xinfo(fmt, args...) \
- pr_notice(fmt, ##args)
- #define hal_rtc_xerror(fmt, args...) \
- pr_err(fmt, ##args)
- #define hal_rtc_xfatal(fmt, args...) \
- pr_emerg(fmt, ##args)
- /* Causion, for SRCLKENA drop speed too slow (align VIO18) to cause current leakage for 32K less */
- #define GPIO_SRCLKEN_PIN (148 | 0x80000000)
- /*TODO extern bool pmic_chrdet_status(void);*/
- /*
- RTC_FGSOC = 0,
- RTC_ANDROID,
- RTC_RECOVERY,
- RTC_FAC_RESET,
- RTC_BYPASS_PWR,
- RTC_PWRON_TIME,
- RTC_FAST_BOOT,
- RTC_KPOC,
- RTC_DEBUG,
- RTC_PWRON_AL,
- RTC_UART,
- RTC_AUTOBOOT,
- RTC_PWRON_LOGO,
- RTC_32K_LESS,
- RTC_LP_DET,
- RTC_SPAR_NUM
- */
- /*
- * RTC_PDN1:
- * bit 0 - 3 : Android bits
- * bit 4 - 5 : Recovery bits (0x10: factory data reset)
- * bit 6 : Bypass PWRKEY bit
- * bit 7 : Power-On Time bit
- * bit 8 : RTC_GPIO_USER_WIFI bit
- * bit 9 : RTC_GPIO_USER_GPS bit
- * bit 10 : RTC_GPIO_USER_BT bit
- * bit 11 : RTC_GPIO_USER_FM bit
- * bit 12 : RTC_GPIO_USER_PMIC bit
- * bit 13 : Fast Boot
- * bit 14 : Kernel Power Off Charging
- * bit 15 : Debug bit
- */
- /*
- * RTC_PDN2:
- * bit 0 - 3 : MTH in power-on time
- * bit 4 : Power-On Alarm bit
- * bit 5 - 6 : UART bits
- * bit 7 : autoboot bit
- * bit 8 - 14: YEA in power-on time
- * bit 15 : Power-On Logo bit
- */
- /*
- * RTC_SPAR0:
- * bit 0 - 5 : SEC in power-on time
- * bit 6 : 32K less bit. True:with 32K, False:Without 32K
- * bit 7 - 15: reserved bits
- */
- u16 rtc_spare_reg[][3] = {
- {RTC_AL_HOU, 0x7f, 8},
- {RTC_PDN1, 0xf, 0},
- {RTC_PDN1, 0x3, 4},
- {RTC_PDN1, 0x1, 6},
- {RTC_PDN1, 0x1, 7},
- {RTC_PDN1, 0x1, 13},
- {RTC_PDN1, 0x1, 14},
- {RTC_PDN1, 0x1, 15},
- {RTC_PDN2, 0x1, 4},
- {RTC_PDN2, 0x3, 5},
- {RTC_PDN2, 0x1, 7},
- {RTC_PDN2, 0x1, 15},
- {RTC_SPAR0, 0x1, 6},
- {RTC_SPAR0, 0x1, 7}
- };
- void hal_rtc_set_abb_32k(u16 enable)
- {
- hal_rtc_xinfo("ABB 32k not support\n");
- }
- u16 hal_rtc_get_gpio_32k_status(void)
- {
- u16 con;
- con = rtc_read(RTC_CON);
- hal_rtc_xinfo("RTC_GPIO 32k status(RTC_CON=0x%x)\n", con);
- if (con & RTC_CON_F32KOB)
- return 0;
- else
- return 1;
- }
- 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 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_get_pwron_alarm(struct rtc_time *tm, struct rtc_wkalrm *alm)
- {
- u16 pdn1, pdn2;
- pdn1 = rtc_read(RTC_PDN1);
- pdn2 = rtc_read(RTC_PDN2);
- alm->enabled = (pdn1 & RTC_PDN1_PWRON_TIME ? (pdn2 & RTC_PDN2_PWRON_LOGO ? 3 : 2) : 0);
- alm->pending = !!(pdn2 & RTC_PDN2_PWRON_ALARM); /* return Power-On Alarm bit */
- hal_rtc_get_alarm_time(tm);
- }
- bool hal_rtc_is_lp_irq(void)
- {
- u16 irqsta;
- 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
- return true;
- }
- return false;
- }
- bool hal_rtc_is_pwron_alarm(struct rtc_time *nowtm, struct rtc_time *tm)
- {
- u16 pdn1;
- pdn1 = rtc_read(RTC_PDN1);
- hal_rtc_xinfo("pdn1 = 0x%4x\n", pdn1);
- if (pdn1 & RTC_PDN1_PWRON_TIME) { /* power-on time is available */
- hal_rtc_xinfo("pdn1 = 0x%4x\n", pdn1);
- hal_rtc_get_tick_time(nowtm);
- hal_rtc_xinfo("pdn1 = 0x%4x\n", pdn1);
- if (rtc_read(RTC_TC_SEC) < nowtm->tm_sec) { /* SEC has carried */
- hal_rtc_get_tick_time(nowtm);
- }
- hal_rtc_get_pwron_alarm_time(tm);
- return true;
- }
- return false;
- }
- void hal_rtc_get_alarm(struct rtc_time *tm, struct rtc_wkalrm *alm)
- {
- u16 irqen, pdn2;
- irqen = rtc_read(RTC_IRQ_EN);
- hal_rtc_get_alarm_time(tm);
- pdn2 = rtc_read(RTC_PDN2);
- alm->enabled = !!(irqen & RTC_IRQ_EN_AL);
- alm->pending = !!(pdn2 & RTC_PDN2_PWRON_ALARM); /* return Power-On Alarm bit */
- }
- 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();
- }
- 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);
- }
- 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_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();
- }
- #ifdef VRTC_PWM_ENABLE
- void hal_rtc_pwm_enable(void)
- {
- rtc_write(MT_VRTC_PWM_CON0, 0); /*clear*/
- hal_rtc_xinfo("hal_rtc_pwm_enable(), RTC_CAP_SEL=%d\n", RTC_CAP_SEL);
- switch (RTC_CAP_SEL) {
- case 0: /*0.1uF only*/
- rtc_write(MT_VRTC_PWM_CON0,
- VRTC_PWM_H_DUTY_0_64_MS | VRTC_PWM_L_DUTY_6_4_MS | VRTC_PWM_MODE);
- hal_rtc_xinfo("H=0.64ms,L=6.4ms, VRTC_PWM=%x\n", rtc_read(MT_VRTC_PWM_CON0));
- break;
- case 1: /*0.1uF + 1uF + 1.5Kohm*/
- rtc_write(MT_VRTC_PWM_CON0,
- VRTC_PWM_H_DUTY_5_12_MS | VRTC_PWM_L_DUTY_51_2_MS | VRTC_PWM_MODE);
- hal_rtc_xinfo("H=5.12ms,L=51.2ms, VRTC_PWM=%x\n", rtc_read(MT_VRTC_PWM_CON0));
- break;
- case 2: /*0.1uF + 2.2uF + 1.5Kohm*/
- rtc_write(MT_VRTC_PWM_CON0,
- VTRC_CAP_SEL | VRTC_PWM_H_DUTY_25_6_MS | VRTC_PWM_L_DUTY_128_0_MS |
- VRTC_PWM_MODE);
- hal_rtc_xinfo("H=25.6ms,L=128ms, VRTC_PWM=%x\n", rtc_read(MT_VRTC_PWM_CON0));
- break;
- case 3: /*0.1uF + 4.7uF + 1.5Kohm*/
- rtc_write(MT_VRTC_PWM_CON0,
- VTRC_CAP_SEL | VRTC_PWM_H_DUTY_51_2_MS | VRTC_PWM_L_DUTY_256_0_MS |
- VRTC_PWM_MODE);
- hal_rtc_xinfo("H=51.2ms,L=256ms, VRTC_PWM=%x\n", rtc_read(MT_VRTC_PWM_CON0));
- break;
- case 4: /*0.1uF + 10uF + 1.5Kohm*/
- rtc_write(MT_VRTC_PWM_CON0,
- VTRC_CAP_SEL | VRTC_PWM_H_DUTY_102_4_MS | VRTC_PWM_L_DUTY_512_0_MS |
- VRTC_PWM_MODE);
- hal_rtc_xinfo("H=102.4ms,L=512ms, VRTC_PWM=%x\n", rtc_read(MT_VRTC_PWM_CON0));
- break;
- case 5: /*0.1uF + 22uF + 1.5Kohm*/
- rtc_write(MT_VRTC_PWM_CON0,
- VTRC_CAP_SEL | VRTC_PWM_H_DUTY_204_8_MS | VRTC_PWM_L_DUTY_1024_0_MS |
- VRTC_PWM_MODE);
- hal_rtc_xinfo("H=204.8ms,L=1024ms, VRTC_PWM=%x\n", rtc_read(MT_VRTC_PWM_CON0));
- break;
- case 6: /*0.1uF + super cap(>>22uF) + 1.5Kohm*/
- rtc_write(MT_VRTC_PWM_CON0,
- VTRC_CAP_SEL | VRTC_PWM_H_DUTY_204_8_MS | VRTC_PWM_L_DUTY_1024_0_MS |
- VRTC_PWM_MODE);
- hal_rtc_xinfo("H=204.8ms,L=1024ms, VRTC_PWM=%x\n", rtc_read(MT_VRTC_PWM_CON0));
- break;
- case 7: /*0.1uF + little Li battery + 1.5Kohm*/
- rtc_write(MT_VRTC_PWM_CON0,
- VTRC_CAP_SEL | VRTC_PWM_H_DUTY_204_8_MS | VRTC_PWM_L_DUTY_512_0_MS |
- VRTC_PWM_MODE);
- hal_rtc_xinfo("H=204.8ms,L=512ms, VRTC_PWM=%x\n", rtc_read(MT_VRTC_PWM_CON0));
- break;
- default:
- hal_rtc_xinfo("RTC CAP SEL is wrong !!!!");
- break;
- }
- }
- #endif
|