Hello Roger Lu, Yuchen Huang,
I'd like you to do a code review. Please visit
https://review.coreboot.org/c/coreboot/+/46877
to review the following change.
Change subject: soc/mediatek/mt8192: add rtc MT6359P driver ......................................................................
soc/mediatek/mt8192: add rtc MT6359P driver
fix rtc for boot reason check
TEST=boot asurada
Signed-off-by: Yuchen Huang yuchen.huang@mediatek.corp-partner.google.com Change-Id: I86b5c1b8d8ccedbb51bbc6e4c9d490c893fb4506 --- M src/soc/mediatek/common/rtc.c M src/soc/mediatek/mt8192/include/soc/rtc.h M src/soc/mediatek/mt8192/rtc.c 3 files changed, 71 insertions(+), 34 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/77/46877/1
diff --git a/src/soc/mediatek/common/rtc.c b/src/soc/mediatek/common/rtc.c index d0b90f7..5ac19eb 100755 --- a/src/soc/mediatek/common/rtc.c +++ b/src/soc/mediatek/common/rtc.c @@ -141,9 +141,6 @@
rtc_info("con=%x, pwrkey1=%x, pwrkey2=%x\n", con, pwrky1, pwrky2);
- if (con & RTC_CON_LPSTA_RAW) - return RTC_STATE_INIT; - if (!rtc_busy_wait()) return RTC_STATE_RECOVER;
@@ -168,9 +165,11 @@ rtc_write(RTC_BBPU, bbpu | RTC_BBPU_KEY | RTC_BBPU_RELOAD); rtc_write_trigger(); rtc_osc_init(); + rtc_info("RTC_STATE_REBOOT\n"); break; case RTC_STATE_RECOVER: rtc_init(1); + rtc_info("RTC_STATE_RECOVER\n"); break; case RTC_STATE_INIT: default: diff --git a/src/soc/mediatek/mt8192/include/soc/rtc.h b/src/soc/mediatek/mt8192/include/soc/rtc.h index b1be85c..bad7c68 100755 --- a/src/soc/mediatek/mt8192/include/soc/rtc.h +++ b/src/soc/mediatek/mt8192/include/soc/rtc.h @@ -108,10 +108,18 @@ RTC_EMBCK_SRC_SEL = 1U << 8, RTC_EMBCK_SEL_OPTION = 1U << 9, RTC_GPS_CKOUT_EN = 1U << 10, + RTC_EOSC32_VCT_EN = 1U << 11, + RTC_EOSC32_CHOP_EN = 1U << 12, + RTC_GP_OSC32_CON = 2U << 13, /* Keep RG_EOSC_RSV[0] to low for lower leakage current hw design change */ RTC_REG_XOSC32_ENB = 1U << 15 };
enum { + OSC32CON_ANALOG_SETTING = RTC_GP_OSC32_CON | RTC_EOSC32_CHOP_EN | RTC_EOSC32_VCT_EN |\ + RTC_GPS_CKOUT_EN | RTC_EMBCK_SEL_OPTION | RTC_EMB_K_EOSC32_MODE +}; + +enum { RTC_LPD_OPT_XOSC_AND_EOSC_LPD = 0U << 13, RTC_LPD_OPT_EOSC_LPD = 1U << 13, RTC_LPD_OPT_XOSC_LPD = 2U << 13, @@ -142,6 +150,15 @@ PMIC_RG_FQMTR_CK_PDN_SHIFT = 11 };
+enum { + PMIC_RG_BANK_FQMTR_RST = 0x522 +}; + +enum { + PMIC_RG_FQMTR_DCXO26M_EN_SHIFT = 4, + PMIC_RG_BANK_FQMTR_RST_SHIFT = 6 +}; + /* PMIC DCXO Register Definition */ enum { PMIC_RG_DCXO_CW00 = 0x0788, @@ -208,6 +225,12 @@ RTC_TC_MTH_MASK = 0xf };
+enum { + RTC_K_EOSC_RSV_0 = 1 << 8, + RTC_K_EOSC_RSV_1 = 1 << 9, + RTC_K_EOSC_RSV_2 = 1 << 10 +}; + int rtc_read(u16 addr, u16 *rdata); int rtc_write(u16 addr, u16 wdata); void rtc_write_field(u16 reg, u16 val, u16 mask, u16 shift); diff --git a/src/soc/mediatek/mt8192/rtc.c b/src/soc/mediatek/mt8192/rtc.c index a8e28b5..f02c633 100755 --- a/src/soc/mediatek/mt8192/rtc.c +++ b/src/soc/mediatek/mt8192/rtc.c @@ -57,15 +57,12 @@ }
u16 bbpu, con, osc32con, sec; - rtc_read(RTC_BBPU, &bbpu); rtc_write(RTC_BBPU, bbpu | RTC_BBPU_KEY | RTC_BBPU_RELOAD); rtc_write_trigger(); rtc_read(RTC_OSC32CON, &osc32con); - osc32con &= ~(RTC_EMBCK_SRC_SEL | RTC_EMBCK_SEL_MODE_MASK - | RTC_GPS_CKOUT_EN); - osc32con |= RTC_XOSC32_ENB | RTC_REG_XOSC32_ENB - | RTC_EMB_K_EOSC32_MODE | RTC_EMBCK_SEL_OPTION; + osc32con &= ~(RTC_EMBCK_SRC_SEL | RTC_EMBCK_SEL_MODE_MASK); + osc32con |= (OSC32CON_ANALOG_SETTING | RTC_REG_XOSC32_ENB);
if (!rtc_xosc_write(osc32con)) { rtc_info("rtc_xosc_write() failed\n"); @@ -99,7 +96,7 @@ static u16 rtc_get_frequency_meter(u16 val, u16 measure_src, u16 window_size) { u16 bbpu, osc32con; - u16 fqmtr_busy, fqmtr_data, fqmtr_rst, fqmtr_tcksel; + u16 fqmtr_busy, fqmtr_data, fqmtr_tcksel; struct stopwatch sw;
if (val) { @@ -111,32 +108,34 @@ (val & RTC_XOSCCALI_MASK)); }
+ /* RG_BANK_FQMTR_RST=1, reset FQMTR*/ + rtc_write_field(PMIC_RG_BANK_FQMTR_RST, 1, 1, + PMIC_RG_BANK_FQMTR_RST_SHIFT); + udelay(20); + /* RG_BANK_FQMTR_RST=0, release FQMTR*/ + rtc_write_field(PMIC_RG_BANK_FQMTR_RST, 0, 1, + PMIC_RG_BANK_FQMTR_RST_SHIFT); + /* enable FQMTR clock */ rtc_write_field(PMIC_RG_TOP_CKPDN_CON0_CLR, 1, 1, - PMIC_RG_FQMTR_32K_CK_PDN_SHIFT); - rtc_write_field(PMIC_RG_TOP_CKPDN_CON0_CLR, 1, 1, PMIC_RG_FQMTR_CK_PDN_SHIFT); - /* FQMTR reset */ - rtc_write_field(PMIC_RG_FQMTR_RST, 1, 1, PMIC_FQMTR_RST_SHIFT); + rtc_write_field(PMIC_RG_TOP_CKPDN_CON0_CLR, 1, 1, + PMIC_RG_FQMTR_32K_CK_PDN_SHIFT);
- do { - rtc_read(PMIC_RG_FQMTR_DATA, &fqmtr_data); - rtc_read(PMIC_RG_FQMTR_CON0, &fqmtr_busy); - } while (fqmtr_data && (fqmtr_busy & PMIC_FQMTR_CON0_BUSY));
- rtc_read(PMIC_RG_FQMTR_RST, &fqmtr_rst); - /* FQMTR normal */ - rtc_write_field(PMIC_RG_FQMTR_RST, 0, 1, PMIC_FQMTR_RST_SHIFT); + rtc_write_field(PMIC_RG_FQMTR_CON0, 1, 1, + PMIC_RG_FQMTR_DCXO26M_EN_SHIFT); + /* set frequency meter window value (0=1X32K(fixed clock)) */ rtc_write(PMIC_RG_FQMTR_WINSET, window_size); /* enable 26M and set test clock source */ rtc_write(PMIC_RG_FQMTR_CON0, PMIC_FQMTR_CON0_DCXO26M_EN | measure_src); /* enable 26M -> delay 100us -> enable FQMTR */ - udelay(100); + mdelay(1); rtc_read(PMIC_RG_FQMTR_CON0, &fqmtr_tcksel); /* enable FQMTR */ rtc_write(PMIC_RG_FQMTR_CON0, fqmtr_tcksel | PMIC_FQMTR_CON0_FQMTR_EN); - udelay(100); + mdelay(1); stopwatch_init_usecs_expire(&sw, FQMTR_TIMEOUT_US); /* FQMTR read until ready */ do { @@ -149,30 +148,35 @@
/* read data should be closed to 26M/32k = 794 */ rtc_read(PMIC_RG_FQMTR_DATA, &fqmtr_data); - rtc_read(PMIC_RG_FQMTR_CON0, &fqmtr_tcksel); + /* disable FQMTR */ + rtc_read(PMIC_RG_FQMTR_CON0, &fqmtr_tcksel); rtc_write(PMIC_RG_FQMTR_CON0, fqmtr_tcksel & ~PMIC_FQMTR_CON0_FQMTR_EN); /* disable FQMTR -> delay 100us -> disable 26M */ - udelay(100); + mdelay(1); /* disable 26M */ rtc_read(PMIC_RG_FQMTR_CON0, &fqmtr_tcksel); rtc_write(PMIC_RG_FQMTR_CON0, fqmtr_tcksel & ~PMIC_FQMTR_CON0_DCXO26M_EN); - rtc_info("input=0x%x, output=%d\n", val, fqmtr_data); + rtc_info("input=%d, output=%d\n", val, fqmtr_data); + /* disable FQMTR clock */ rtc_write_field(PMIC_RG_TOP_CKPDN_CON0_SET, 1, 1, - PMIC_RG_FQMTR_32K_CK_PDN_SHIFT); - rtc_write_field(PMIC_RG_TOP_CKPDN_CON0_SET, 1, 1, PMIC_RG_FQMTR_CK_PDN_SHIFT); + rtc_write_field(PMIC_RG_TOP_CKPDN_CON0_SET, 1, 1, + PMIC_RG_FQMTR_32K_CK_PDN_SHIFT); + return fqmtr_data; }
/* 32k clock calibration */ static u16 rtc_eosc_cali(void) { - u16 middle, diff1, diff2, cksel; + u16 diff1, diff2, cksel; u16 val = 0; - u16 left = RTC_XOSCCALI_START, right = RTC_XOSCCALI_END; + static u16 middle = 0; + static u16 left = RTC_XOSCCALI_START; + static u16 right = RTC_XOSCCALI_END;
rtc_read(PMIC_RG_FQMTR_CKSEL, &cksel); cksel &= ~PMIC_FQMTR_CKSEL_MASK; @@ -183,16 +187,20 @@
while (left <= right) { middle = (right + left) / 2; - if (middle == left) + if (middle == left) { break; + } /* select 26M as target clock */ val = rtc_get_frequency_meter(middle, PMIC_FQMTR_CON0_FQM26M_CK, 0); - if (val >= RTC_FQMTR_LOW_BASE && val <= RTC_FQMTR_HIGH_BASE) + if (val >= RTC_FQMTR_LOW_BASE && val <= RTC_FQMTR_HIGH_BASE) { break; - if (val > RTC_FQMTR_HIGH_BASE) + } + if (val > RTC_FQMTR_HIGH_BASE) { right = middle; - else + } + else { left = middle; + } }
if (val >= RTC_FQMTR_LOW_BASE && val <= RTC_FQMTR_HIGH_BASE) @@ -212,6 +220,7 @@ else diff2 = RTC_FQMTR_LOW_BASE - val;
+ rtc_info("left:%d, middle:%d, right: %d\n", left, middle, right); if (diff1 < diff2) return left; else @@ -332,6 +341,7 @@ int rtc_init(u8 recover) { int ret; + u16 year;
rtc_info("recovery: %d\n", recover);
@@ -347,7 +357,7 @@ goto err; }
- //rtc_osc_init(); + rtc_osc_init();
if (recover) mdelay(20); @@ -367,6 +377,11 @@ goto err; }
+ /* solution1 for EOSC cali*/ + rtc_read(RTC_AL_YEA, &year); + rtc_write(RTC_AL_YEA, (year | RTC_K_EOSC_RSV_0) & (~RTC_K_EOSC_RSV_1) & (~RTC_K_EOSC_RSV_2)); + rtc_write_trigger(); + if (!rtc_lpd_init()) { ret = -RTC_STATUS_LPD_INIT_FAIL; goto err;