| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141 |
- /* Copyright Statement:
- *
- * This software/firmware and related documentation ("MediaTek Software") are
- * protected under relevant copyright laws. The information contained herein is
- * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
- * the prior written permission of MediaTek inc. and/or its licensors, any
- * reproduction, modification, use or disclosure of MediaTek Software, and
- * information contained herein, in whole or in part, shall be strictly
- * prohibited.
- *
- * MediaTek Inc. (C) 2010. All rights reserved.
- *
- * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
- * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
- * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
- * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
- * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
- * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
- * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
- * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
- * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
- * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
- * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
- * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
- * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
- * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
- * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
- * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
- * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
- * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
- *
- * The following software/firmware and/or related documentation ("MediaTek
- * Software") have been modified by MediaTek Inc. All revisions are subject to
- * any receiver's applicable license agreements with MediaTek Inc.
- */
- /* Use PMIC common API for PMIC full reset detection */
- #define CFG_APWDT_PMIC_FULL_RST_COMMON_API 1
- /* Timestamp for WDT */
- #define CFG_APWDT_DBG_TIMESTAMP 0
- #include "typedefs.h"
- #include "platform.h"
- #include "wdt.h"
- #include "dramc_common.h"
- #include "dramc_register.h"
- #include "dramc_pi_api.h"
- #include "emi_hw.h"
- #include "pmic.h"
- #include "pal_log.h"
- #include "dconfig_env.h"
- #if !CFG_APWDT_PMIC_FULL_RST_COMMON_API
- #include "upmu_hw.h"
- #endif
- #define RGUTAG "[RGU] "
- #define RGULOG(fmt, arg...) pal_log_info(RGUTAG fmt, ##arg)
- #define RGULOG_NO_MODULE_NAME(fmt, arg...) pal_log_info(fmt, ##arg)
- #define WDT_TIMEOUT_DEFAULT_VAL (10)
- unsigned int g_rgu_status = RE_BOOT_REASON_UNKNOW;
- #if defined(CFG_APWDT) && (CFG_APWDT == V2)
- static unsigned int timeout;
- static unsigned int rgu_mode;
- static int g_rgu_inited = 0;
- static char *g_doe_apwdt_en = NULL;
- #if CONFIG_WDT_DBG_TIMESTAMP
- #include "timer.h"
- static ulong time;
- #endif
- static void mtk_wdt_check_last_stage(void)
- {
- unsigned int reg;
- unsigned int last_stage;
- /* check reboot source */
- reg = DRV_Reg32(MTK_WDT_NONRST_REG2);
- RGULOG("rst from: ");
- last_stage = (reg >> MTK_WDT_NONRST2_STAGE_OFS) & RGU_STAGE_MASK;
- if (last_stage == RGU_STAGE_PRELOADER)
- RGULOG_NO_MODULE_NAME("pl\n");
- else if (last_stage == RGU_STAGE_LK)
- RGULOG_NO_MODULE_NAME("lk\n");
- else if (last_stage == RGU_STAGE_KERNEL)
- RGULOG_NO_MODULE_NAME("kernel\n");
- else
- RGULOG_NO_MODULE_NAME("?\n");
- reg = (reg & ~(RGU_STAGE_MASK << MTK_WDT_NONRST2_LAST_STAGE_OFS)) |
- (last_stage << MTK_WDT_NONRST2_LAST_STAGE_OFS);
- DRV_WriteReg32(MTK_WDT_NONRST_REG2, reg);
- }
- static void mtk_wdt_mark_stage(unsigned int stage)
- {
- unsigned int reg = DRV_Reg32(MTK_WDT_NONRST_REG2);
- reg = (reg & ~(RGU_STAGE_MASK << MTK_WDT_NONRST2_STAGE_OFS))
- | (stage << MTK_WDT_NONRST2_STAGE_OFS);
- DRV_WriteReg32(MTK_WDT_NONRST_REG2, reg);
- }
- static void mtk_wdt_reset_deglitch_enable(void)
- {
- DRV_WriteReg32(MTK_WDT_RSTDEG_EN1, MTK_WDT_RSTDEG_EN1_KEY);
- DRV_WriteReg32(MTK_WDT_RSTDEG_EN2, MTK_WDT_RSTDEG_EN2_KEY |
- (MTK_WDT_RSTDEG_CLOCK_32K << MTK_WDT_RSTDEG_CLOCK_SELETC_SHIFT) |
- (MTK_WDT_RSTDEG_LATENCY_230NS_183US << MTK_WDT_RSTDEG_LATENCY_SHIFT));
- RGULOG("%s: MTK_WDT_RSTDEG_EN1(%x), MTK_WDT_RSTDEG_EN2(%x)\n", __func__,
- READ_REG(MTK_WDT_RSTDEG_EN1), READ_REG(MTK_WDT_RSTDEG_EN2));
- }
- void mtk_wdt_disable(void)
- {
- u32 tmp;
- tmp = DRV_Reg32(MTK_WDT_MODE);
- tmp &= ~MTK_WDT_MODE_ENABLE; /* disable watchdog */
- tmp |= (MTK_WDT_MODE_KEY); /* need key then write is allowed */
- DRV_WriteReg32(MTK_WDT_MODE, tmp);
- }
- void mtk_wdt_enable(void)
- {
- u32 tmp;
- tmp = DRV_Reg32(MTK_WDT_MODE);
- tmp |= MTK_WDT_MODE_ENABLE; /* enable watchdog */
- tmp |= (MTK_WDT_MODE_KEY); /* need key then write is allowed */
- DRV_WriteReg32(MTK_WDT_MODE, tmp);
- }
- static void mtk_wdt_reset(char mode)
- {
- /* Watchdog Rest */
- unsigned int wdt_mode_val;
- DRV_WriteReg32(MTK_WDT_RESTART, MTK_WDT_RESTART_KEY);
- /*set latch register to 0 before sw reset*/
- /* DRV_WriteReg32(MTK_WDT_LATCH_CTL, (MTK_WDT_LENGTH_CTL_KEY | 0x0)); */
- wdt_mode_val = DRV_Reg32(MTK_WDT_MODE);
- /* clear autorestart bit: autoretart: 1, bypass power key, 0: not bypass power key */
- #if CFG_USB_AUTO_DETECT
- wdt_mode_val &= (~MTK_WDT_MODE_AUTO_RESTART);
- #endif
- /* make sure WDT mode is hw reboot mode, can not config isr mode */
- wdt_mode_val &= (~(MTK_WDT_MODE_IRQ|MTK_WDT_MODE_DUAL_MODE));
- if (mode) { /* mode != 0 means by pass power key reboot, We using auto_restart bit as by pass power key flag */
- wdt_mode_val = wdt_mode_val | (MTK_WDT_MODE_KEY|MTK_WDT_MODE_EXTEN|MTK_WDT_MODE_AUTO_RESTART);
- DRV_WriteReg32(MTK_WDT_MODE, wdt_mode_val);
- } else{
- wdt_mode_val = wdt_mode_val | (MTK_WDT_MODE_KEY|MTK_WDT_MODE_EXTEN);
- DRV_WriteReg32(MTK_WDT_MODE, wdt_mode_val);
- }
- RGULOG("mtk_wdt_reset WDT MODE=%x\n", DRV_Reg32(MTK_WDT_MODE));
- gpt_busy_wait_us(100);
- DRV_WriteReg32(MTK_WDT_SWRST, MTK_WDT_SWRST_KEY);
- }
- static unsigned int mtk_wdt_get_status(void)
- {
- static unsigned int wdt_sta = 0;
- static unsigned int wdt_sta_handled = 0;
- unsigned int reg;
- /*
- * Note:
- * Because WDT_STA register will be cleared after writing WDT_MODE,
- * we use a static variable to keep orinigal WDT_STA.
- *
- * After reset, static varialbe will always be clear to 0,
- * so only read WDT_STA when static variable is 0 is OK
- *
- * Use "wdt_sta_handled" to indicate if WDT_STATUS is preserved.
- * Do not use "wdt_sta" as indication because dummy handling will be
- * executed in case WDT_STATUS is 0 originally.
- */
- if (wdt_sta_handled == 0) {
- wdt_sta = DRV_Reg32(MTK_WDT_STATUS);
- wdt_sta_handled = 1;
- /* Check if any special flag is in non-reset register */
- reg = DRV_Reg32(MTK_WDT_NONRST_REG2);
- /* Check SSPM reset flag */
- if (reg & MTK_WDT_NONRST2_SSPM_RESET) {
- RGULOG("NONRST_REG2: SSPM reset flag found, 0x%x\n", reg);
- wdt_sta = wdt_sta | MTK_WDT_STATUS_SSPM_RST;
- /* clear deliberate SW reset flag */
- reg = reg & ~(MTK_WDT_NONRST2_SSPM_RESET);
- DRV_WriteReg32(MTK_WDT_NONRST_REG2, reg);
- }
- }
- return wdt_sta;
- }
- static unsigned int mtk_wdt_get_debug_ctl(void)
- {
- static unsigned int wdt_debug_ctl = 0;
- /*
- * Note:
- * Because some bits in register DEBUG_CTL will be cleared after
- * writing WDT_MODE, we use a static variable to keep original DEBUG_CTL.
- *
- * Effected Bits:
- * 16: ddr_reserve_success
- * 18: emi_dcs_success
- * 20: dvfsrc_success
- */
- if (wdt_debug_ctl == 0)
- wdt_debug_ctl = DRV_Reg32(MTK_WDT_DEBUG_CTL);
- return wdt_debug_ctl;
- }
- void mtk_wdt_keep_essential_info(void)
- {
- mtk_wdt_get_status();
- mtk_wdt_get_debug_ctl();
- }
- int mtk_wdt_boot_check(void);
- static void mtk_wdt_check_trig_reboot_reason(void)
- {
- int ret;
- /* check bypass power key info */
- ret = mtk_wdt_boot_check();
- /* 3. By pass power key info */
- RGULOG("bypass pwrkey: ");
- if (ret == WDT_BY_PASS_PWK_REBOOT)
- RGULOG_NO_MODULE_NAME("set\n");
- else if (ret == WDT_NORMAL_REBOOT)
- RGULOG_NO_MODULE_NAME("NOT set\n");
- else
- RGULOG_NO_MODULE_NAME("wdt does not trigger rst\n");
- }
- static void mtk_wdt_mode_config(BOOL dual_mode_en,
- BOOL irq,
- BOOL ext_en,
- BOOL ext_pol,
- BOOL wdt_en)
- {
- unsigned int tmp;
- /* RGULOG(" mtk_wdt_mode_config mode value=%x\n",DRV_Reg32(MTK_WDT_MODE)); */
- tmp = DRV_Reg32(MTK_WDT_MODE);
- tmp |= MTK_WDT_MODE_KEY;
- /* Bit 0 : Whether enable watchdog or not */
- if (wdt_en == TRUE)
- tmp |= MTK_WDT_MODE_ENABLE;
- else
- tmp &= ~MTK_WDT_MODE_ENABLE;
- /* Bit 1 : Configure extern reset signal polarity. */
- if (ext_pol == TRUE)
- tmp |= MTK_WDT_MODE_EXT_POL;
- else
- tmp &= ~MTK_WDT_MODE_EXT_POL;
- /* Bit 2 : Whether enable external reset signal */
- if (ext_en == TRUE)
- tmp |= MTK_WDT_MODE_EXTEN;
- else
- tmp &= ~MTK_WDT_MODE_EXTEN;
- /* Bit 3 : Whether generating interrupt instead of reset signal */
- if (irq == TRUE)
- tmp |= MTK_WDT_MODE_IRQ;
- else
- tmp &= ~MTK_WDT_MODE_IRQ;
- /* Bit 6 : Whether enable debug module reset */
- if (dual_mode_en == TRUE)
- tmp |= MTK_WDT_MODE_DUAL_MODE;
- else
- tmp &= ~MTK_WDT_MODE_DUAL_MODE;
- /* Bit 4: WDT_Auto_restart, this is a reserved bit, we use it as bypass powerkey flag. */
- /* Because HW reboot always need reboot to kernel, we set it always. */
- tmp |= MTK_WDT_MODE_AUTO_RESTART;
- DRV_WriteReg32(MTK_WDT_MODE, tmp);
- /* dual_mode(1); //always dual mode */
- /* mdelay(100); */
- RGULOG("mtk_wdt_mode_config mode value=%x, tmp:%x\n", DRV_Reg32(MTK_WDT_MODE), tmp);
- }
- /* EXPORT_SYMBOL(mtk_wdt_mode_config); */
- static void mtk_wdt_set_time_out_value(UINT32 value)
- {
- /*
- * TimeOut = BitField 15:5
- * Key = BitField 4:0 = 0x08
- */
- /* sec * 32768 / 512 = sec * 64 = sec * 1 << 6 */
- timeout = (unsigned int)(value * (1 << 6));
- timeout = timeout << 5;
- DRV_WriteReg32(MTK_WDT_LENGTH, (timeout | MTK_WDT_LENGTH_KEY));
- }
- void mtk_wdt_timestamp_init(void)
- {
- #if CONFIG_WDT_DBG_TIMESTAMP
- RGULOG("init done! elapsed time: %d ms\n", get_timer(time));
- time = get_timer(0);
- #endif
- }
- void mtk_wdt_timestamp_update(void)
- {
- #if CONFIG_WDT_DBG_TIMESTAMP
- ulong time_elapse;
- time_elapse = get_timer(time);
- if (time_elapse) {
- /*
- * Since wdt kicking may be very frequency, set threshold to avoid
- * lousy message.
- *
- * Preloader does not reset system while WDT timeout, thus debug message
- * shall appear for timeout cases (long elapsed time).
- */
- if (time_elapse > 5)
- RGULOG("kick wdt! elapsed time: %d ms\n", get_timer(time));
- time = get_timer(0);
- }
- #endif
- }
- void mtk_wdt_restart(void)
- {
- /* Reset WatchDogTimer's counting value to time out value */
- /* ie., keepalive() */
- DRV_WriteReg32(MTK_WDT_RESTART, MTK_WDT_RESTART_KEY);
- mtk_wdt_timestamp_update();
- }
- void mtk_wdt_sw_reset(void)
- {
- RGULOG("WDT SW RESET\n");
- /* DRV_WriteReg32 (0x70025000, 0x2201); */
- /* DRV_WriteReg32 (0x70025008, 0x1971); */
- /* DRV_WriteReg32 (0x7002501C, 0x1209); */
- mtk_wdt_reset(1);/* NOTE here, this reset will cause by pass power key */
- /* system will reset */
- while (1)
- {
- RGULOG("SW reset happen ...\n");
- };
- }
- static void mtk_wdt_hw_reset(void)
- {
- RGULOG("WDT_HW_Reset_test\n");
- /* 1. set WDT timeout 1 secs, 1*64*512/32768 = 1sec */
- mtk_wdt_set_time_out_value(1);
- /* 2. enable WDT debug reset enable, generating irq disable, ext reset disable */
- /* ext reset signal low, wdt enalbe */
- mtk_wdt_mode_config(TRUE, FALSE, FALSE, FALSE, TRUE);
- /* 3. reset the watch dog timer to the value set in WDT_LENGTH register */
- mtk_wdt_restart();
- /* 4. system will reset */
- while (1);
- }
- int mtk_wdt_boot_check(void)
- {
- unsigned int wdt_sta = mtk_wdt_get_status();
- int ret = WDT_NOT_WDT_REBOOT;
- /*
- * For DA download hope to timeout reboot, and boot to u-boot/kernel configurable reason,
- * we set both timeout reboot and software reboot can check whether bypass power key.
- */
- if (wdt_sta & (MTK_WDT_STATUS_HWWDT_RST | MTK_WDT_STATUS_SWWDT_RST |
- MTK_WDT_STATUS_SPM_THERMAL_RST | MTK_WDT_STATUS_SPMWDT_RST |
- MTK_WDT_STATUS_THERMAL_DIRECT_RST | MTK_WDT_STATUS_SECURITY_RST |
- MTK_WDT_STATUS_DEBUGWDT_RST | MTK_WDT_STATUS_EINT_RST |
- MTK_WDT_STATUS_SYSRST_RST | MTK_WDT_STATUS_DVFSP_RST |
- MTK_WDT_STATUS_SSPM_RST)) {
- if (rgu_mode & MTK_WDT_MODE_AUTO_RESTART) {
- /* HW or SW reboot, and auto restart is set, means bypass power key */
- ret = WDT_BY_PASS_PWK_REBOOT;
- } else {
- /* HW or SW reboot, but auto restart is not set, means NOT bypass power key */
- ret = WDT_NORMAL_REBOOT;
- }
- } else {
- /*
- * For PMIC full reset, return "bypass pwr key reboot" to help AEE works.
- * I.e., Prevent entering charger mode.
- */
- if (mtk_wdt_is_pmic_full_reset()) {
- RGULOG("PMIC full rst: true\n");
- ret = WDT_BY_PASS_PWK_REBOOT;
- }
- }
- return ret;
- }
- int mtk_wdt_is_pmic_full_reset(void)
- {
- #if CFG_APWDT_PMIC_FULL_RST_COMMON_API
- unsigned int val;
- /* Use PMIC common API for PMIC full reset detection */
- val = is_pmic_cold_reset();
- #else
- static unsigned int val = 0;
- static unsigned int handled = 0;
- /*
- * PMIC common API may be failed in some platforms.
- *
- * Use a non-volatile register (reset only after battery is removed)
- * for PMIC full reset detection.
- *
- * In such platforms, use bit 0 in register PMIC_RG_RSV_SWREG.
- */
- if (!handled) {
- pmic_read_interface(PMIC_RG_RSV_SWREG_ADDR, &val, 0x1, 0);
- if (val)
- pmic_config_interface(PMIC_RG_RSV_SWREG_ADDR, 0, 0x1, 0);
- RGULOG("PMIC full rst: %d\n", val);
- handled = 1;
- }
- #endif
- return val ? 1 : 0;
- }
- void mtk_arch_reset(char mode)
- {
- RGULOG("mtk_arch_reset at pre-loader!\n");
- /* mtk_wdt_hw_reset(); */
- mtk_wdt_reset(mode);
- while (1);
- }
- int rgu_dram_reserved(int enable)
- {
- volatile unsigned int tmp = 0, ret = 0;
- /*
- * DDR reserved mode may be switched on/off anytime by caller.
- *
- * DDR reserved mode switch on/off flow will modify register MODE.
- * Since register STATUS and some bits in DEBUG_CTL will be reset
- * if register MODE has any changes. Keep those register values first
- * before register MODE is written later.
- */
- mtk_wdt_keep_essential_info();
- if (enable == 1)
- {
- /* enable ddr reserved mode */
- tmp = READ_REG(MTK_WDT_MODE);
- tmp |= (MTK_WDT_MODE_DDR_RESERVE|MTK_WDT_MODE_KEY);
- WRITE_REG(tmp, MTK_WDT_MODE);
- } else if (enable == 0)
- {
- /* disable ddr reserved mode, set reset mode,
- disable watchdog output reset signal */
- tmp = READ_REG(MTK_WDT_MODE);
- tmp &= (~MTK_WDT_MODE_DDR_RESERVE);
- tmp |= MTK_WDT_MODE_KEY;
- WRITE_REG(tmp, MTK_WDT_MODE);
- } else
- {
- RGULOG("Wrong input %d, should be 1(enable) or 0(disable) in %s\n", enable, __func__);
- ret = -1;
- }
- RGULOG("%s: MTK_WDT_MODE(%x)\n", __func__, tmp);
- return ret;
- }
- int rgu_is_reserve_ddr_enabled(void)
- {
- unsigned int wdt_mode;
- wdt_mode = READ_REG(MTK_WDT_MODE);
- if (wdt_mode & MTK_WDT_MODE_DDR_RESERVE)
- return 1;
- else
- return 0;
- }
- int rgu_is_dram_slf(void)
- {
- unsigned int wdt_dbg_ctrl;
- wdt_dbg_ctrl = READ_REG(MTK_WDT_DEBUG_CTL);
- if (wdt_dbg_ctrl & MTK_DDR_SREF_STA) {
- RGULOG("DDR is in self-refresh. %x\n", wdt_dbg_ctrl);
- return 1;
- } else {
- RGULOG("DDR is not in self-refresh. %x\n", wdt_dbg_ctrl);
- return 0;
- }
- }
- int rgu_wait_for_reg_update_done(unsigned int reg_addr, unsigned mask, unsigned target_val)
- {
- unsigned timeout_ms = 5;
- unsigned int read_val;
- unsigned int read_times = 0;
- unsigned int elapsed_ms = 0;
- while (1) {
- read_val = READ_REG(reg_addr);
- if (target_val == (read_val & mask))
- break;
- read_times++;
- if (read_times && 0 == (read_times % 100)) {
- mdelay(1);
- elapsed_ms += 1;
- if (elapsed_ms > timeout_ms) {
- RGULOG("%s: ERROR! Update reg 0x%x timeout! Mask: 0x%x Target: 0x%x\n",
- __func__, reg_addr, mask, target_val);
- return -1;
- }
- }
- }
- return 0;
- }
- int rgu_update_reg(unsigned int reg, u32 func, u32 bits)
- {
- volatile unsigned int val;
- int ret;
- val = READ_REG(reg);
- if (func == RGU_REG_SET)
- val |= bits;
- else if (func == RGU_REG_CLR)
- val &= (~bits);
- else
- return -1;
- /* add unlock key */
- if (reg == MTK_WDT_DEBUG_CTL)
- val |= MTK_DEBUG_CTL_KEY;
- else if (reg == MTK_WDT_DEBUG_CTL2)
- val |= MTK_DEBUG_CTL2_KEY;
- else {
- RGULOG("%s: Invalid! Set bit 0x%x in reg 0x%x fail!\n", __func__,
- bits, reg);
- return -1;
- }
- /* update register */
- WRITE_REG(val, reg);
- /* wait until register updating done */
- if (func == RGU_REG_SET)
- val = bits;
- else
- val = 0;
- /*
- * Must ensure waiting-done API has timeout mechanism
- * because in some scenarios with security feature toggled,
- * below registers will be read-only. Writting operation
- * will get timeout here.
- *
- * DEBUG_CTL / DEBUG_CLT2 / DDR_RESERVE_MODE bit in MODE
- */
- ret = rgu_wait_for_reg_update_done(reg, bits, val);
- RGULOG("%s: %d, bits: 0x%x, addr: 0x%x, val: 0x%x\n", __func__,
- func, bits, reg, READ_REG(reg));
- return ret;
- }
- int rgu_is_reserve_ddr_mode_success(void)
- {
- unsigned int wdt_dbg_ctrl;
- /*
- * MTK_DDR_RESERVE_RTA bit will be reset by modifying register MODE.
- * Read DEBUG_CTL value kept by mtk_wdt_get_debug_ctl().
- */
- wdt_dbg_ctrl = mtk_wdt_get_debug_ctl();
- if (wdt_dbg_ctrl & MTK_DDR_RESERVE_RTA) {
- RGULOG("WDT DDR reserve mode success! %x\n", wdt_dbg_ctrl);
- return 1;
- } else {
- RGULOG("WDT DDR reserve mode FAIL! %x\n", wdt_dbg_ctrl);
- return 0;
- }
- }
- int rgu_cfg_emi_dcs_en(int enable)
- {
- volatile unsigned int tmp;
- int ret;
- if (enable == 1) {
- ret = rgu_update_reg(MTK_WDT_DEBUG_CTL2,
- RGU_REG_SET, MTK_RGU_EMI_DCS_EN);
- } else if (enable == 0) {
- ret = rgu_update_reg(MTK_WDT_DEBUG_CTL2,
- RGU_REG_CLR, MTK_RGU_EMI_DCS_EN);
- } else
- ret = -1;
- return ret;
- }
- int rgu_release_rg_dramc_conf_iso(void)
- {
- int ret;
- int success;
- ret = rgu_update_reg(MTK_WDT_DEBUG_CTL,
- RGU_REG_CLR, MTK_RG_CONF_ISO);
- success = rgu_is_reserve_ddr_mode_success();
- RGULOG("DDR RESERVE Success %d\n", success);
- return ret;
- }
- int rgu_release_rg_dramc_iso(void)
- {
- return rgu_update_reg(MTK_WDT_DEBUG_CTL, RGU_REG_CLR, MTK_RG_DRAMC_ISO);
- }
- int rgu_release_rg_dramc_sref(void)
- {
- return rgu_update_reg(MTK_WDT_DEBUG_CTL, RGU_REG_CLR, MTK_RG_DRAMC_SREF);
- }
- int rgu_is_emi_dcs_success(void)
- {
- unsigned int wdt_dbg_ctrl;
- unsigned int success;
- /*
- * MTK_RGU_EMI_DCS_SUCCESS bit will be reset by modifying register MODE.
- * Read DEBUG_CTL value kept by mtk_wdt_get_debug_ctl().
- */
- wdt_dbg_ctrl = mtk_wdt_get_debug_ctl();
- success = (wdt_dbg_ctrl & MTK_RGU_EMI_DCS_SUCCESS) >> MTK_RGU_EMI_DCS_SUCCESS_OFFSET;
- RGULOG("EMI_DCS_SUCCESS %d\n", success);
- return success;
- }
- int rgu_is_emi_dcs_enable(void)
- {
- unsigned int reg;
- reg = READ_REG(MTK_WDT_DEBUG_CTL2);
- if (reg & MTK_RGU_EMI_DCS_EN)
- return 1;
- else
- return 0;
- }
- int rgu_is_dvfsrc_success(void)
- {
- unsigned int wdt_dbg_ctrl;
- unsigned int success;
- /*
- * MTK_RGU_EMI_DCS_SUCCESS bit will be reset by modifying register MODE.
- * Read DEBUG_CTL value kept by mtk_wdt_get_debug_ctl().
- */
- wdt_dbg_ctrl = mtk_wdt_get_debug_ctl();
- success = (wdt_dbg_ctrl & MTK_RGU_DVFSRC_SUCCESS) >> MTK_RGU_DVFSRC_SUCCESS_OFFSET;
- RGULOG("DVFSRC_SUCCESS %d\n", success);
- return success;
- }
- int rgu_is_dvfsrc_enable(void)
- {
- unsigned int reg;
- reg = READ_REG(MTK_WDT_DEBUG_CTL2);
- if (reg & MTK_RGU_DVFSRC_EN)
- return 1;
- else
- return 0;
- }
- void rgu_swsys_reset(WD_SYS_RST_TYPE reset_type)
- {
- if (reset_type == WD_MD_RST) {
- unsigned int wdt_dbg_ctrl;
- wdt_dbg_ctrl = READ_REG(MTK_WDT_SWSYSRST);
- wdt_dbg_ctrl |= MTK_WDT_SWSYS_RST_KEY;
- wdt_dbg_ctrl |= 0x80; /* 1<<7 */
- WRITE_REG(wdt_dbg_ctrl, MTK_WDT_SWSYSRST);
- udelay(1000);
- wdt_dbg_ctrl = READ_REG(MTK_WDT_SWSYSRST);
- wdt_dbg_ctrl |= MTK_WDT_SWSYS_RST_KEY;
- wdt_dbg_ctrl &= (~0x80); /* ~(1<<7) */
- WRITE_REG(wdt_dbg_ctrl, MTK_WDT_SWSYSRST);
- /* RGULOG("rgu pl md reset\n"); */
- }
- }
- int mtk_wdt_request_en_set(int mark_bit, WD_REQ_CTL en)
- {
- unsigned int tmp, ext_req_con;
- if ((mark_bit != MTK_WDT_STATUS_SSPM_RST) &&
- (mark_bit != MTK_WDT_STATUS_SYSRST_RST) &&
- (mark_bit != MTK_WDT_STATUS_EINT_RST) &&
- (mark_bit != MTK_WDT_STATUS_SPM_THERMAL_RST))
- return -1;
- tmp = READ_REG(MTK_WDT_REQ_MODE);
- tmp |= MTK_WDT_REQ_MODE_KEY;
- if (en == WD_REQ_EN)
- tmp |= (mark_bit);
- if (en == WD_REQ_DIS)
- tmp &= ~(mark_bit);
- WRITE_REG(tmp, MTK_WDT_REQ_MODE);
- return 0;
- }
- int mtk_wdt_request_mode_set(int mark_bit, WD_REQ_MODE mode)
- {
- unsigned int tmp;
- if ((mark_bit != MTK_WDT_STATUS_SSPM_RST) &&
- (mark_bit != MTK_WDT_STATUS_SYSRST_RST) &&
- (mark_bit != MTK_WDT_STATUS_EINT_RST) &&
- (mark_bit != MTK_WDT_STATUS_SPM_THERMAL_RST))
- return -1;
- tmp = READ_REG(MTK_WDT_REQ_IRQ_EN);
- tmp |= MTK_WDT_REQ_IRQ_KEY;
- if (mode == WD_REQ_IRQ_MODE)
- tmp |= (mark_bit);
- if (mode == WD_REQ_RST_MODE)
- tmp &= ~(mark_bit);
- WRITE_REG(tmp, MTK_WDT_REQ_IRQ_EN);
- return 0;
- }
- void mtk_wdt_pre_init(void)
- {
- unsigned int wdt_ctrl;
- unsigned int nonrst;
- /* skip if platform already run mtk_wdt_pre_init in early stage*/
- if (g_rgu_inited == 1) {
- RGULOG("WDT is already inited\n");
- return;
- }
- /* get last stage and mark current stage to preloader */
- mtk_wdt_check_last_stage();
- mtk_wdt_mark_stage(RGU_STAGE_PRELOADER);
- /*
- * Since RGU init flow will modify WDT_MODE which will reset WDT_STA and some bits
- * in WDT_DEBUG_CTL, preserve these registers in static global variable first.
- */
- mtk_wdt_keep_essential_info();
- /* Dump RGU regisers */
- RGULOG("MODE: 0x%x\n", DRV_Reg32(MTK_WDT_MODE));
- RGULOG("STA: 0x%x\n", mtk_wdt_get_status());
- RGULOG("LENGTH: 0x%x\n", DRV_Reg32(MTK_WDT_LENGTH));
- RGULOG("INTERVAL: 0x%x\n", DRV_Reg32(MTK_WDT_INTERVAL));
- RGULOG("SWSYSRST: 0x%x\n", DRV_Reg32(MTK_WDT_SWSYSRST));
- RGULOG("LATCH_CTL: 0x%x\n", DRV_Reg32(MTK_WDT_LATCH_CTL));
- RGULOG("NONRST_REG2: 0x%x\n", DRV_Reg32(MTK_WDT_NONRST_REG2));
- RGULOG("DEBUG_CTL: 0x%x\n", mtk_wdt_get_debug_ctl());
- rgu_mode = DRV_Reg32(MTK_WDT_MODE);
- mtk_wdt_mode_config(FALSE, FALSE, FALSE, FALSE, FALSE); /* Wirte Mode register will clear status register */
- /* Setting timeout 10s */
- mtk_wdt_set_time_out_value(WDT_TIMEOUT_DEFAULT_VAL);
- #if (!CFG_APWDT_DISABLE)
- /* Config HW reboot mode */
- #if MTK_DOE_CONFIG_ENV_SUPPORT
- g_doe_apwdt_en = dconfig_getenv("apwdt_en");
- #endif
- if (g_doe_apwdt_en == NULL || *g_doe_apwdt_en == '1') {
- mtk_wdt_mode_config(TRUE, TRUE, TRUE, FALSE, TRUE);
- mtk_wdt_restart();
- }
- #endif
- mtk_wdt_timestamp_init();
- mtk_wdt_reset_deglitch_enable();
- /* Configure WDT_LATCH_CTL */
- wdt_ctrl = READ_REG(MTK_WDT_LATCH_CTL);
- wdt_ctrl |= MTK_LATCH_CTL_KEY;
- wdt_ctrl |= MTK_RG_LATH_EN;
- wdt_ctrl |= MTK_RG_MCU_LATH_EN | MTK_RG_SPM_LATH_EN;
- wdt_ctrl |= MTK_RG_GPU_EXT_OFF_EN | MTK_RG_MD_EXT_OFF_EN;
- wdt_ctrl &= ~(MTK_RG_MCU_LATCH_SELECT | MTK_RG_SPM_LATCH_SELECT);
- wdt_ctrl |= MTK_RG_DRAMC_LATH_EN;
- wdt_ctrl |= MTK_RG_DEBUGSYS_LATCH_EN;
- wdt_ctrl |= (MTK_RG_DRAMC_RD_TEST_EN | MTK_RG_DRAMC_RDWT_TEST_EN);
- WRITE_REG(wdt_ctrl, MTK_WDT_LATCH_CTL);
- /* Configure WDT_LATCH_CTL2 */
- wdt_ctrl = READ_REG(MTK_WDT_LATCH_CTL2);
- wdt_ctrl |= MTK_LATCH_CTL2_KEY;
- /* DFD feature */
- wdt_ctrl |= MTK_RG_MCU_DFD_EN;
- wdt_ctrl &= ~(MTK_RG_MCU_DFD_TIMEOUT_MASK << MTK_RG_MCU_DFD_TIMEOUT_OFS);
- wdt_ctrl |= (MTK_RG_MCU_DFD_TIMEOUT_VALUE << MTK_RG_MCU_DFD_TIMEOUT_OFS);
- WRITE_REG(wdt_ctrl, MTK_WDT_LATCH_CTL2);
- /*
- * Configure WDT_DEBUG_CTL
- *
- * Release DDR reserve mode related control.
- *
- * Release DCS EN/PAUSE and DVFSRC EN/PAUSE in RGU initialization.
- * NOTE: This job must be done earlier than DVS/DVFSRC initialization.
- */
- rgu_update_reg(MTK_WDT_DEBUG_CTL, RGU_REG_CLR,
- MTK_RGU_EMI_DCS_PAUSE | MTK_RGU_DVFSRC_PAUSE);
- rgu_update_reg(MTK_WDT_DEBUG_CTL2, RGU_REG_CLR,
- MTK_RGU_EMI_DCS_EN | MTK_RGU_DVFSRC_EN);
- RGULOG("%s: MTK_WDT_DEBUG_CTL(0x%x)\n", __func__,
- READ_REG(MTK_WDT_DEBUG_CTL));
- RGULOG("%s: MTK_WDT_DEBUG_CTL2(0x%x)\n", __func__,
- READ_REG(MTK_WDT_DEBUG_CTL2));
- RGULOG("%s: MTK_WDT_LATCH_CTL(0x%x)\n", __func__,
- READ_REG(MTK_WDT_LATCH_CTL));
- /* disable spm thermal rst */
- mtk_wdt_request_en_set(MTK_WDT_STATUS_SPM_THERMAL_RST, WD_REQ_DIS);
- mtk_wdt_request_mode_set(MTK_WDT_STATUS_SPM_THERMAL_RST, WD_REQ_RST_MODE);
- /* disable sysrst */
- mtk_wdt_request_en_set(MTK_WDT_STATUS_SYSRST_RST, WD_REQ_DIS);
- /* disable irq of sysrst */
- mtk_wdt_request_mode_set(MTK_WDT_STATUS_SYSRST_RST, WD_REQ_RST_MODE);
- /* disable irq of eint */
- mtk_wdt_request_mode_set(MTK_WDT_STATUS_EINT_RST, WD_REQ_RST_MODE);
- RGULOG("%s: MTK_WDT_REQ_MODE(%x), MTK_WDT_REQ_IRQ_EN(%x)\n", __func__,
- READ_REG(MTK_WDT_REQ_MODE), READ_REG(MTK_WDT_REQ_IRQ_EN));
- mtk_wdt_timestamp_update();
- g_rgu_inited = 1;
- }
- void mtk_wdt_init(void)
- {
- unsigned int wdt_sta;
- if (g_rgu_inited == 0) {
- mtk_wdt_pre_init();
- } else {
- /* RGU clock source might be changed since pre_init which might
- * make rgu work abnormal due clock source switch. We restart wdt
- * by disable and enable it again */
- mtk_wdt_mode_config(FALSE, FALSE, FALSE, FALSE, FALSE);
- mtk_wdt_set_time_out_value(WDT_TIMEOUT_DEFAULT_VAL);
- #if (!CFG_APWDT_DISABLE)
- /* Config HW reboot mode */
- mtk_wdt_mode_config(TRUE, TRUE, TRUE, FALSE, TRUE);
- mtk_wdt_restart();
- #endif
- }
- wdt_sta = mtk_wdt_get_status();
- if ((wdt_sta & MTK_WDT_STATUS_HWWDT_RST) && (rgu_mode & MTK_WDT_MODE_AUTO_RESTART)) {
- /* Time out reboot always by pass power key */
- g_rgu_status = RE_BOOT_BY_WDT_HW;
- } else if (wdt_sta & MTK_WDT_STATUS_SWWDT_RST)
- g_rgu_status = RE_BOOT_BY_WDT_SW;
- else
- g_rgu_status = RE_BOOT_REASON_UNKNOW;
- if (wdt_sta & MTK_WDT_STATUS_IRQWDT_RST)
- g_rgu_status |= RE_BOOT_WITH_INTTERUPT;
- if (wdt_sta & MTK_WDT_STATUS_SPM_THERMAL_RST)
- g_rgu_status |= RE_BOOT_BY_SPM_THERMAL;
- if (wdt_sta & MTK_WDT_STATUS_SPMWDT_RST)
- g_rgu_status |= RE_BOOT_BY_SPM;
- if (wdt_sta & MTK_WDT_STATUS_THERMAL_DIRECT_RST)
- g_rgu_status |= RE_BOOT_BY_THERMAL_DIRECT;
- if (wdt_sta & MTK_WDT_STATUS_DEBUGWDT_RST)
- g_rgu_status |= RE_BOOT_BY_DEBUG;
- if (wdt_sta & MTK_WDT_STATUS_SECURITY_RST)
- g_rgu_status |= RE_BOOT_BY_SECURITY;
- if (wdt_sta & MTK_WDT_STATUS_SYSRST_RST)
- g_rgu_status |= RE_BOOT_BY_SYSRST;
- if (wdt_sta & MTK_WDT_STATUS_SSPM_RST)
- g_rgu_status |= RE_BOOT_BY_SSPM_RST;
- /* SW workaround to avoid EINT_RST be triggered with other RST behavior */
- if ((wdt_sta & MTK_WDT_STATUS_EINT_RST) && (g_rgu_status == RE_BOOT_REASON_UNKNOW))
- g_rgu_status |= RE_BOOT_BY_EINT;
- if (mtk_wdt_is_pmic_full_reset())
- g_rgu_status |= RE_BOOT_BY_PMIC_FULL_RST;
- RGULOG("g_rgu_status: %d (0x%x)\n", g_rgu_status, g_rgu_status);
- mtk_wdt_check_trig_reboot_reason();
- #if MTK_DOE_CONFIG_ENV_SUPPORT
- if (g_doe_apwdt_en == NULL)
- g_doe_apwdt_en = dconfig_getenv("apwdt_en");
- if (g_doe_apwdt_en != NULL && *g_doe_apwdt_en == '0')
- mtk_wdt_disable();
- #endif
- }
- #else /* Using dummy WDT functions */
- void mtk_wdt_pre_init(void)
- {
- RGULOG("PL WDT Dummy pre_init called\n");
- }
- void mtk_wdt_init(void)
- {
- RGULOG("PL WDT Dummy init called\n");
- }
- BOOL mtk_is_rgu_trigger_reset(void)
- {
- RGULOG("PL Dummy mtk_is_rgu_trigger_reset called\n");
- return FALSE;
- }
- void mtk_arch_reset(char mode)
- {
- RGULOG("PL WDT Dummy arch reset called\n");
- }
- int mtk_wdt_boot_check(void)
- {
- RGULOG("PL WDT Dummy mtk_wdt_boot_check called\n");
- return 0;
- }
- void mtk_wdt_disable(void)
- {
- RGULOG("UB WDT Dummy mtk_wdt_disable called\n");
- }
- void mtk_wdt_restart(void)
- {
- RGULOG("UB WDT Dummy mtk_wdt_restart called\n");
- }
- static void mtk_wdt_sw_reset(void)
- {
- /* RGULOG("UB WDT Dummy mtk_wdt_sw_reset called\n"); */
- }
- static void mtk_wdt_hw_reset(void)
- {
- RGULOG("UB WDT Dummy mtk_wdt_hw_reset called\n");
- }
- int rgu_dram_reserved(int enable)
- {
- volatile unsigned int ret = 0;
- RGULOG("dummy RGU %s\n", __func__);
- return ret;
- }
- int rgu_is_reserve_ddr_enabled(void)
- {
- RGULOG("dummy RGU %s\n", __func__);
- return 0;
- }
- int rgu_is_dram_slf(void)
- {
- RGULOG("dummy RGU %s\n", __func__);
- return 0;
- }
- int rgu_release_rg_dramc_conf_iso(void)
- {
- RGULOG("dummy RGU %s\n", __func__);
- return 0;
- }
- int rgu_release_rg_dram_setting(void)
- {
- RGULOG("dummy RGU %s\n", __func__);
- return 0;
- }
- int rgu_release_rg_dramc_iso(void)
- {
- RGULOG("dummy RGU %s\n", __func__);
- return 0;
- }
- int rgu_release_rg_dramc_sref(void)
- {
- RGULOG("dummy RGU %s\n", __func__);
- return 0;
- }
- int rgu_is_reserve_ddr_mode_success(void)
- {
- RGULOG("dummy RGU %s\n", __func__);
- return 0;
- }
- void rgu_swsys_reset(WD_SYS_RST_TYPE reset_type)
- {
- /* RGULOG("dummy RGU %s\n", __func__); */
- }
- int mtk_wdt_request_en_set(int mark_bit, WD_REQ_CTL en)
- {
- RGULOG("dummy RGU %s\n", __func__);
- }
- int mtk_wdt_request_mode_set(int mark_bit, WD_REQ_MODE mode)
- {
- RGULOG("dummy RGU %s\n", __func__);
- }
- #endif
|