/* * Copyright (C) 2016 MediaTek Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. */ #include #include #include #include #include #include #include "scp_ipi_pin.h" #include "scp_helper.h" #include "scp_excep.h" #include "scp_dvfs.h" /* * handler for wdt irq for scp * dump scp register */ static void scp_A_wdt_handler(void) { pr_notice("[SCP] %s\n", __func__); scp_dump_last_regs(); #if SCP_RECOVERY_SUPPORT if (scp_set_reset_status() == RESET_STATUS_STOP) { pr_debug("[SCP] start to reset scp...\n"); scp_send_reset_wq(RESET_TYPE_WDT); } else pr_notice("scp resetting\n"); #endif } static void wait_scp_wdt_irq_done(void) { int retry = 0; unsigned long c0; /* clr after SCP side INT trigger, * or SCP may lost INT max wait = 200ms */ for (retry = SCP_AWAKE_TIMEOUT; retry > 0; retry--) { c0 = readl(SCP_GPR_CORE0_REBOOT); if (c0 == CORE_RDY_TO_REBOOT) break; udelay(2); } if (retry == 0) pr_debug("[SCP] SCP wakeup timeout c0:%x\n", c0); udelay(10); } /* * dispatch scp irq * reset scp and generate exception if needed * @param irq: irq id * @param dev_id: should be NULL */ irqreturn_t scp_A_irq_handler(int irq, void *dev_id) { unsigned int reg0 = readl(R_CORE0_WDT_IRQ); pr_err("[SCP] %s %x\n", __func__, reg0); if (reg0) { scp_A_wdt_handler(); /* clear IRQ */ wait_scp_wdt_irq_done(); writel(B_WDT_IRQ, R_CORE0_WDT_IRQ); } return IRQ_HANDLED; }