| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674 |
- #include <linux/cpu.h>
- #include <linux/delay.h>
- #include <linux/init.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/platform_device.h>
- #include <linux/proc_fs.h>
- #include <linux/spinlock.h>
- #include <mach/hotplug.h>
- #include <mach/irqs.h>
- #include <mach/mt_boot.h>
- #include <mach/mt_cirq.h>
- #include <mach/mt_cpuidle.h>
- #include <mach/mt_gpt.h>
- #include <mach/mt_spm_idle.h>
- #include <mach/mt_spm_misc.h>
- #include "mt_spm_internal.h"
- /**************************************
- * only for internal debug
- **************************************/
- /* FIXME: for FPGA early porting */
- /* #define CONFIG_MTK_LDVT */
- #ifdef CONFIG_MTK_LDVT
- #define SPM_BYPASS_SYSPWREQ 1
- #else
- #define SPM_BYPASS_SYSPWREQ 0
- #endif
- #define SPM_AEE_RR_REC 0
- #define WAKE_SRC_FOR_MCDI (WAKE_SRC_R12_CSYSPWREQ_B | WAKE_SRC_R12_CPU_IRQ_B)
- #define WAKE_SRC_FOR_MD32 0 /* (WAKE_SRC_AUD_MD32) */
- #define SPM_MCDI_CORE_MAX_EXIT_TIME 100000
- /*
- * MCDI DVT GPT test
- * GPT need to modify mt_idle.c and mt_spm_mcdi.c
- */
- #define MCDI_DVT_IPI 0 /*0:disable, 1: enable : mt_idle.c , mt_spm_mcdi.c and mt_cpuidle.c */
- #define MCDI_DVT_CPUxGPT 0 /*0:disable, 1: enable : GPT need to modify mt_idle.c and mt_spm_mcdi.c mt_cpuidle.c */
- #define MCDI_DVT_W_DORMANT 0 /*1: with dormant, 0: without dormant */
- #define __weak __attribute__((weak))
- __weak unsigned int mt_get_chip_sw_ver(void) {return 0; }
- /* TODO:[fixme:setting] */
- static struct pwr_ctrl mcdi_ctrl = {
- .wake_src = WAKE_SRC_FOR_MCDI,
- .wake_src_md32 = WAKE_SRC_FOR_MD32,
- .wfi_op = WFI_OP_OR,
- .mcusys_idle_mask = 1,
- .mp0top_idle_mask = 1,
- .mp1top_idle_mask = 1,
- .md1_req_mask_b = 1,
- .md2_req_mask_b = 1,
- .disp_req_mask_b = 1,
- .mfg_req_mask_b = 1,
- .scp_req_mask_b = 1,
- #if SPM_BYPASS_SYSPWREQ
- .syspwreq_mask = 1,
- #endif
- #if ((MCDI_DVT_CPUxGPT) || (MCDI_DVT_IPI)) && (!MCDI_DVT_W_DORMANT)
- .pcm_reserve = 0xff,
- #endif
- };
- static const u32 mcdi_binary[] = {
- 0x1840001f, 0x00000001, 0x1990001f, 0x10006600, 0x11407c1f, 0xe8208000,
- 0x10006614, 0x00000000, 0x1b00001f, 0x21000001, 0x1b80001f, 0xd0010000,
- 0x1880001f, 0x10006098, 0x18d0001f, 0x10006098, 0x69200003, 0xbeefbeef,
- 0xd8200444, 0x17c07c1f, 0x18c0001f, 0xdeaddead, 0xe0800003, 0x18d0001f,
- 0x10006098, 0x69200003, 0xabcdabcd, 0xd82002e4, 0x17c07c1f, 0x1880001f,
- 0x10006098, 0x18c0001f, 0x12345678, 0xe0800003, 0x60a07c05, 0xa9100004,
- 0x10006530, 0xa9100004, 0x10006534, 0xa9100004, 0x10006538, 0xa9100004,
- 0x1000653c, 0xa9100004, 0x10006540, 0xa9100004, 0x10006544, 0xa9100004,
- 0x10006548, 0xa9100004, 0x1000654c, 0x80a01002, 0x89100002, 0x10006614,
- 0x80801001, 0xd8003ee2, 0x17c07c1f, 0x1a10001f, 0x10006174, 0x82002001,
- 0x82201408, 0xd8200968, 0x17c07c1f, 0x1a10001f, 0x10006608, 0x82002001,
- 0xd8000948, 0x17c07c1f, 0x1a40001f, 0x10006208, 0x1a80001f, 0x10006248,
- 0xc2404300, 0x17c07c1f, 0xa1400405, 0x1a10001f, 0x10006174, 0x8200a001,
- 0x82209408, 0xd8200ba8, 0x17c07c1f, 0x1a10001f, 0x10006608, 0x8200a001,
- 0xd8000b88, 0x17c07c1f, 0x1a40001f, 0x1000620c, 0x1a80001f, 0x1000624c,
- 0xc2404300, 0x17c07c1f, 0xa1508405, 0x1a10001f, 0x10006174, 0x82012001,
- 0x82211408, 0xd8200de8, 0x17c07c1f, 0x1a10001f, 0x10006608, 0x82012001,
- 0xd8000dc8, 0x17c07c1f, 0x1a40001f, 0x10006210, 0x1a80001f, 0x10006250,
- 0xc2404300, 0x17c07c1f, 0xa1510405, 0x1a10001f, 0x10006174, 0x8201a001,
- 0x82219408, 0xd8201028, 0x17c07c1f, 0x1a10001f, 0x10006608, 0x8201a001,
- 0xd8001008, 0x17c07c1f, 0x1a40001f, 0x10006214, 0x1a80001f, 0x10006254,
- 0xc2404300, 0x17c07c1f, 0xa1518405, 0x1a10001f, 0x10006174, 0x88800008,
- 0x0000000f, 0x80c01402, 0x6a200003, 0x0000000f, 0x82241408, 0xd8201228,
- 0x17c07c1f, 0x1a10001f, 0x10006608, 0x82042001, 0xd8001208, 0x17c07c1f,
- 0xa1540405, 0x1a10001f, 0x10006174, 0x82022001, 0x82221408, 0xd8201468,
- 0x17c07c1f, 0x1a10001f, 0x10006608, 0x82022001, 0xd8001448, 0x17c07c1f,
- 0x1a40001f, 0x1000621c, 0x1a80001f, 0x10006260, 0xc2404300, 0x17c07c1f,
- 0xa1520405, 0x1a10001f, 0x10006174, 0x8202a001, 0x82229408, 0xd82016a8,
- 0x17c07c1f, 0x1a10001f, 0x10006608, 0x8202a001, 0xd8001688, 0x17c07c1f,
- 0x1a40001f, 0x10006220, 0x1a80001f, 0x10006264, 0xc2404300, 0x17c07c1f,
- 0xa1528405, 0x1a10001f, 0x10006174, 0x82032001, 0x82231408, 0xd82018e8,
- 0x17c07c1f, 0x1a10001f, 0x10006608, 0x82032001, 0xd80018c8, 0x17c07c1f,
- 0x1a40001f, 0x10006224, 0x1a80001f, 0x10006268, 0xc2404300, 0x17c07c1f,
- 0xa1530405, 0x1a10001f, 0x10006174, 0x8203a001, 0x82239408, 0xd8201b28,
- 0x17c07c1f, 0x1a10001f, 0x10006608, 0x8203a001, 0xd8001b08, 0x17c07c1f,
- 0x1a40001f, 0x10006228, 0x1a80001f, 0x1000626c, 0xc2404300, 0x17c07c1f,
- 0xa1538405, 0x1a10001f, 0x10006174, 0x88800008, 0x000000f0, 0x80c01402,
- 0x6a200003, 0x000000f0, 0x82249408, 0xd8201d28, 0x17c07c1f, 0x1a10001f,
- 0x10006608, 0x8204a001, 0xd8001d08, 0x17c07c1f, 0xa1548405, 0x1b80001f,
- 0x20000550, 0x1a10001f, 0x10006608, 0x820fa001, 0xd8003ea8, 0x17c07c1f,
- 0x81041401, 0xd8202044, 0x17c07c1f, 0x1a10001f, 0x10006164, 0x88800008,
- 0x00000f0f, 0x71207c02, 0xb1003081, 0xb10c3081, 0xd8202e64, 0x17c07c1f,
- 0x1a10001f, 0x10006608, 0x82042001, 0xd8002028, 0x17c07c1f, 0x81740405,
- 0x81001401, 0xd82023e4, 0x17c07c1f, 0xc28049c0, 0x1280041f, 0xb10c3081,
- 0xd82023e4, 0x17c07c1f, 0x1a10001f, 0x10006608, 0x82002001, 0xd80022a8,
- 0x17c07c1f, 0x1a40001f, 0x10006208, 0x1a80001f, 0x10006248, 0xc2404060,
- 0x17c07c1f, 0x81700405, 0xe8208000, 0x10006530, 0x00000000, 0xe8208000,
- 0x10006500, 0x00000000, 0xe8208000, 0x10006090, 0x00000001, 0x81009401,
- 0xd8202764, 0x17c07c1f, 0xc28049c0, 0x1290841f, 0xd8202764, 0x17c07c1f,
- 0x1a10001f, 0x10006608, 0x8200a001, 0xd8002628, 0x17c07c1f, 0x1a40001f,
- 0x1000620c, 0x1a80001f, 0x1000624c, 0xc2404060, 0x17c07c1f, 0x81708405,
- 0xe8208000, 0x10006534, 0x00000000, 0xe8208000, 0x10006504, 0x00000000,
- 0xe8208000, 0x10006090, 0x00000002, 0x81011401, 0xd8202ae4, 0x17c07c1f,
- 0xc28049c0, 0x1291041f, 0xd8202ae4, 0x17c07c1f, 0x1a10001f, 0x10006608,
- 0x82012001, 0xd80029a8, 0x17c07c1f, 0x1a40001f, 0x10006210, 0x1a80001f,
- 0x10006250, 0xc2404060, 0x17c07c1f, 0x81710405, 0xe8208000, 0x10006538,
- 0x00000000, 0xe8208000, 0x10006508, 0x00000000, 0xe8208000, 0x10006090,
- 0x00000004, 0x81019401, 0xd8202e64, 0x17c07c1f, 0xc28049c0, 0x1291841f,
- 0xd8202e64, 0x17c07c1f, 0x1a10001f, 0x10006608, 0x8201a001, 0xd8002d28,
- 0x17c07c1f, 0x1a40001f, 0x10006214, 0x1a80001f, 0x10006254, 0xc2404060,
- 0x17c07c1f, 0x81718405, 0xe8208000, 0x1000653c, 0x00000000, 0xe8208000,
- 0x1000650c, 0x00000000, 0xe8208000, 0x10006090, 0x00000008, 0x81049401,
- 0xd82030a4, 0x17c07c1f, 0x1a10001f, 0x10006164, 0x88800008, 0x0000f0f0,
- 0x71207c02, 0xb1003081, 0xb10c3081, 0xd8203ea4, 0x17c07c1f, 0x1a10001f,
- 0x10006608, 0x8204a001, 0xd8003088, 0x17c07c1f, 0x81748405, 0x81021401,
- 0xd8203424, 0x17c07c1f, 0xc28049c0, 0x1292041f, 0xd8203424, 0x17c07c1f,
- 0x1a10001f, 0x10006608, 0x82022001, 0xd80032e8, 0x17c07c1f, 0x1a40001f,
- 0x1000621c, 0x1a80001f, 0x10006260, 0xc2404060, 0x17c07c1f, 0x81720405,
- 0xe8208000, 0x10006540, 0x00000000, 0xe8208000, 0x10006510, 0x00000000,
- 0xe8208000, 0x10006090, 0x00000010, 0x81029401, 0xd82037a4, 0x17c07c1f,
- 0xc28049c0, 0x1292841f, 0xd82037a4, 0x17c07c1f, 0x1a10001f, 0x10006608,
- 0x8202a001, 0xd8003668, 0x17c07c1f, 0x1a40001f, 0x10006220, 0x1a80001f,
- 0x10006264, 0xc2404060, 0x17c07c1f, 0x81728405, 0xe8208000, 0x10006544,
- 0x00000000, 0xe8208000, 0x10006514, 0x00000000, 0xe8208000, 0x10006090,
- 0x00000020, 0x81031401, 0xd8203b24, 0x17c07c1f, 0xc28049c0, 0x1293041f,
- 0xd8203b24, 0x17c07c1f, 0x1a10001f, 0x10006608, 0x82032001, 0xd80039e8,
- 0x17c07c1f, 0x1a40001f, 0x10006224, 0x1a80001f, 0x10006268, 0xc2404060,
- 0x17c07c1f, 0x81730405, 0xe8208000, 0x10006548, 0x00000000, 0xe8208000,
- 0x10006518, 0x00000000, 0xe8208000, 0x10006090, 0x00000040, 0x81039401,
- 0xd8203ea4, 0x17c07c1f, 0xc28049c0, 0x1293841f, 0xd8203ea4, 0x17c07c1f,
- 0x1a10001f, 0x10006608, 0x8203a001, 0xd8003d68, 0x17c07c1f, 0x1a40001f,
- 0x10006228, 0x1a80001f, 0x1000626c, 0xc2404060, 0x17c07c1f, 0x81738405,
- 0xe8208000, 0x1000654c, 0x00000000, 0xe8208000, 0x1000651c, 0x00000000,
- 0xe8208000, 0x10006090, 0x00000080, 0xd0000100, 0x17c07c1f, 0xe8208000,
- 0x10006614, 0x00000000, 0xe8208000, 0x10006608, 0x00000000, 0x1940001f,
- 0xaa55aa55, 0x1b80001f, 0x00001000, 0xf0000000, 0x17c07c1f, 0x1212841f,
- 0xe2e00036, 0x17c07c1f, 0x17c07c1f, 0xe2e0003e, 0x1380201f, 0xe2e0003c,
- 0xe2a00000, 0x18b0000a, 0x17c07c1f, 0x81040801, 0xd8004164, 0x17c07c1f,
- 0xe2e0007c, 0x1b80001f, 0x20000007, 0xe2e0005c, 0xe2e0004c, 0xe2e0004d,
- 0xf0000000, 0x17c07c1f, 0xe2e0004f, 0xe2e0006f, 0xe2e0002f, 0xe2a00001,
- 0x18b0000a, 0x17c07c1f, 0x81040801, 0xd8204384, 0x17c07c1f, 0xe2e0002e,
- 0xe2e0003e, 0xe2e00032, 0xf0000000, 0x17c07c1f, 0x18f00002, 0x17c07c1f,
- 0xa0d98403, 0xe0800003, 0x18f00002, 0x17c07c1f, 0x81090c01, 0xd8204544,
- 0x17c07c1f, 0x80f98403, 0xe0800003, 0x18f00009, 0x17c07c1f, 0xa0d20403,
- 0xe2400003, 0x1a10001f, 0x10006174, 0x82002808, 0xd82046a8, 0x17c07c1f,
- 0x1880001f, 0x10001220, 0x18d0001f, 0x10001220, 0xa0d4a803, 0xe0800003,
- 0x1a10001f, 0x10001228, 0x8214a808, 0xd8204808, 0x17c07c1f, 0x1880001f,
- 0x10200684, 0x18d0001f, 0x10200684, 0xa0ca2803, 0xa0c92803, 0xe0800003,
- 0xf0000000, 0x17c07c1f, 0x1a10001f, 0x10006164, 0x81002808, 0xb1142888,
- 0xb1003081, 0xf0000000, 0x17c07c1f
- };
- static struct pcm_desc mcdi_pcm = {
- .version = "pcm_mcdi_ddrdfs_v6.1_20150629",
- .base = mcdi_binary,
- .size = 597,
- .sess = 1,
- .replace = 1,
- .addr_2nd = 0,
- };
- struct spm_lp_scen __spm_mcdi = {
- .pcmdesc = &mcdi_pcm,
- .pwrctrl = &mcdi_ctrl,
- };
- static unsigned int spm_mcdi_lock; /* offload MCDI */
- static bool SPM_MCDI_isKICK;
- #if SPM_AEE_RR_REC
- unsigned int *p_is_mcdi_wfi;
- #endif
- DEFINE_SPINLOCK(__spm_mcdi_lock);
- DEFINE_SPINLOCK(__mcdi_lock);
- #if (MCDI_DVT_IPI)
- unsigned int core0_IPI_issue_count = 0;
- u8 mcdi_enter = 0;
- int cpu0_enter_forLoop = 0;
- static void empty_function(void *info)
- {
- unsigned long flags;
- int cpu = smp_processor_id();
- spin_lock_irqsave(&__mcdi_lock, flags);
- mcdi_enter &= ~(1 << cpu);
- spin_unlock_irqrestore(&__mcdi_lock, flags);
- mdelay(1);
- spm_idle_dbg("core %x ipi received, core IPI command count: %d\n",
- cpu, core0_IPI_issue_count);
- }
- #endif
- unsigned int g_SPM_MCDI_Abnormal_WakeUp = 0;
- unsigned int g_pre_SPM_MCDI_Abnormal_WakeUp = 0;
- bool go_to_mcidle(int cpu)
- {
- bool ret = 0;
- #if (MCDI_DVT_IPI)
- while (1) {
- if (cpu == 0) {
- /* make sure cpu0 enter for loop first */
- cpu0_enter_forLoop = 1;
- /*check except core0 Standby WFI */
- if ((spm_read(CPU_IDLE_STA) & 0xfe) != 0x0) {
- mdelay(1);
- smp_call_function(empty_function, NULL, 0);
- spm_idle_dbg("core0 IPI\n");
- core0_IPI_issue_count++;
- }
- } else {
- if (cpu0_enter_forLoop) {
- if (spm_mcdi_wfi(cpu) == 1) {
- mdelay(1);
- spm_idle_dbg("CPU %d awake\n", cpu);
- ret = 1;
- } else
- return false;
- mdelay(1);
- } else
- return false;
- }
- }
- #elif (MCDI_DVT_CPUxGPT)
- while (1) {
- if (cpu != 0) {
- if (spm_mcdi_wfi(cpu) == 1) {
- mdelay(1);
- spm_idle_dbg("CPU %d awake\n", cpu);
- ret = 1;
- } else
- return false;
- }
- }
- #else
- if (spm_mcdi_wfi(cpu) == 1)
- ret = 1;
- if (g_SPM_MCDI_Abnormal_WakeUp != g_pre_SPM_MCDI_Abnormal_WakeUp) {
- spm_idle_dbg("SPM-MCDI Abnormal %x\n", g_SPM_MCDI_Abnormal_WakeUp);
- g_pre_SPM_MCDI_Abnormal_WakeUp = g_SPM_MCDI_Abnormal_WakeUp;
- }
- #endif
- return ret;
- }
- static void spm_mcdi_cpu_wake_up_event(bool wake_up_event, bool disable_dormant_power)
- {
- /* Use DUMMY1_PWR_CON[1] to decide if offload MCDI firmware */
- if (((spm_read(SPM_CPU_WAKEUP_EVENT) & 0x1) == 1)
- && ((spm_read(DUMMY1_PWR_CON) & 0x1) == 0)) {
- spm_idle_ver("spm_mcdi_cpu_wake_up_event: SPM_CPU_WAKEUP_EVENT:%x, DUMMY1_PWR_CON %x",
- spm_read(SPM_CPU_WAKEUP_EVENT), spm_read(DUMMY1_PWR_CON));
- return;
- }
- /* Inform SPM that CPU wants to program CPU_WAKEUP_EVENT and DISABLE_CPU_DROM */
- spm_write(SPM_SCP_MAILBOX, 0xbeefbeef);
- /* Wait SPM's response, can't use sleep api */
- while (spm_read(SPM_SCP_MAILBOX) != 0xdeaddead)
- ;
- if (disable_dormant_power) {
- spm_write(DUMMY1_PWR_CON, spm_read(DUMMY1_PWR_CON) | 0x1);
- while (spm_read(DUMMY1_PWR_CON) != (spm_read(DUMMY1_PWR_CON) | 0x1))
- ;
- } else {
- spm_write(DUMMY1_PWR_CON, spm_read(DUMMY1_PWR_CON) & ~0x1);
- while (spm_read(DUMMY1_PWR_CON) != (spm_read(DUMMY1_PWR_CON) & ~0x1))
- ;
- }
- spm_write(SPM_CPU_WAKEUP_EVENT, wake_up_event);
- while (spm_read(SPM_CPU_WAKEUP_EVENT) != wake_up_event)
- ;
- /* Inform SPM to see updated setting */
- spm_write(SPM_SCP_MAILBOX, 0xabcdabcd);
- while (spm_read(SPM_SCP_MAILBOX) != 0x12345678)
- ;
- /* END OF sequence */
- spm_write(SPM_SCP_MAILBOX, 0x0);
- }
- void spm_go_to_mcdi(u32 spm_flags, u32 spm_data)
- {
- unsigned long flags;
- struct pcm_desc *pcmdesc = __spm_mcdi.pcmdesc;
- struct pwr_ctrl *pwrctrl = __spm_mcdi.pwrctrl;
- spin_lock_irqsave(&__spm_mcdi_lock, flags);
- if (SPM_MCDI_isKICK != 0) {
- spin_unlock_irqrestore(&__spm_mcdi_lock, flags);
- return;
- }
- set_pwrctrl_pcm_flags(pwrctrl, spm_flags);
- #if SPM_AEE_RR_REC
- *p_is_mcdi_wfi = 0;
- #endif
- __spm_reset_and_init_pcm(pcmdesc);
- __spm_kick_im_to_fetch(pcmdesc);
- __spm_sync_vcore_dvfs_power_control(pwrctrl, __spm_vcore_dvfs.pwrctrl);
- __spm_set_power_control(pwrctrl);
- __spm_set_wakeup_event(pwrctrl);
- __spm_kick_pcm_to_run(pwrctrl);
- SPM_MCDI_isKICK = 1;
- spin_unlock_irqrestore(&__spm_mcdi_lock, flags);
- spm_idle_ver("spm_go_to_mcdi()\n");
- }
- void spm_leave_MCDI(void)
- {
- unsigned long flags;
- spin_lock_irqsave(&__spm_mcdi_lock, flags);
- if (SPM_MCDI_isKICK == 0) {
- spin_unlock_irqrestore(&__spm_mcdi_lock, flags);
- return;
- }
- SPM_MCDI_isKICK = 0;
- spm_mcdi_cpu_wake_up_event(1, 1);
- #if SPM_AEE_RR_REC
- u32 spm_counter = 0;
- while (*p_is_mcdi_wfi != 0) { /* don't use sleep command(wfi/wfe) */
- if (spm_counter >= SPM_MCDI_CORE_MAX_EXIT_TIME) {
- spm_idle_ver("spm_leave_MCDI: g_is_mcdi_wfi:%x\n", *p_is_mcdi_wfi);
- spm_counter = 0;
- }
- spm_counter++;
- }
- #endif
- /*offload MCDI F/W */
- spm_mcdi_cpu_wake_up_event(1, 0);
- __spm_clean_after_wakeup();
- spin_unlock_irqrestore(&__spm_mcdi_lock, flags);
- spm_idle_ver("spm_leave_MCDI : OK\n");
- }
- static void spm_mcdi_wfi_sel_enter(int core_id)
- {
- int core_id_val = core_id;
- /*SPM WFI Select by core number */
- switch (core_id_val) {
- case 0:
- spm_write(MP0_CPU0_IRQ_MASK, 1);
- spm_write(MP0_CPU0_WFI_EN, 1);
- break;
- case 1:
- spm_write(MP0_CPU1_IRQ_MASK, 1);
- spm_write(MP0_CPU1_WFI_EN, 1);
- break;
- case 2:
- spm_write(MP0_CPU2_IRQ_MASK, 1);
- spm_write(MP0_CPU2_WFI_EN, 1);
- break;
- case 3:
- spm_write(MP0_CPU3_IRQ_MASK, 1);
- spm_write(MP0_CPU3_WFI_EN, 1);
- break;
- case 4:
- spm_write(MP1_CPU0_IRQ_MASK, 1);
- spm_write(MP1_CPU0_WFI_EN, 1);
- break;
- case 5:
- spm_write(MP1_CPU1_IRQ_MASK, 1);
- spm_write(MP1_CPU1_WFI_EN, 1);
- break;
- case 6:
- spm_write(MP1_CPU2_IRQ_MASK, 1);
- spm_write(MP1_CPU2_WFI_EN, 1);
- break;
- case 7:
- spm_write(MP1_CPU3_IRQ_MASK, 1);
- spm_write(MP1_CPU3_WFI_EN, 1);
- break;
- default:
- break;
- }
- }
- static void spm_mcdi_wfi_sel_leave(int core_id)
- {
- int core_id_val = core_id;
- /*SPM WFI Select by core number */
- switch (core_id_val) {
- case 0:
- spm_write(MP0_CPU0_WFI_EN, 0);
- spm_write(MP0_CPU0_IRQ_MASK, 0);
- break;
- case 1:
- spm_write(MP0_CPU1_WFI_EN, 0);
- spm_write(MP0_CPU1_IRQ_MASK, 0);
- break;
- case 2:
- spm_write(MP0_CPU2_WFI_EN, 0);
- spm_write(MP0_CPU2_IRQ_MASK, 0);
- break;
- case 3:
- spm_write(MP0_CPU3_WFI_EN, 0);
- spm_write(MP0_CPU3_IRQ_MASK, 0);
- break;
- case 4:
- spm_write(MP1_CPU0_WFI_EN, 0);
- spm_write(MP1_CPU0_IRQ_MASK, 0);
- break;
- case 5:
- spm_write(MP1_CPU1_WFI_EN, 0);
- spm_write(MP1_CPU1_IRQ_MASK, 0);
- break;
- case 6:
- spm_write(MP1_CPU2_WFI_EN, 0);
- spm_write(MP1_CPU2_IRQ_MASK, 0);
- break;
- case 7:
- spm_write(MP1_CPU3_WFI_EN, 0);
- spm_write(MP1_CPU3_IRQ_MASK, 0);
- break;
- default:
- break;
- }
- }
- bool spm_is_cpu_irq_occur(int core_id)
- {
- bool ret = 0;
- /* check COREn IRQ */
- if (spm_read(SPM_WAKEUP_MISC) & (1 << (core_id)))
- ret = 1;
- /* check COREn FIQ */
- if (spm_read(SPM_WAKEUP_MISC) & (1 << (core_id + 8)))
- ret = 1;
- #if (MCDI_DVT_IPI)
- if (ret == 1)
- spm_idle_ver("spm_read(SPM_WAKEUP_MISC)=0x%x\n", spm_read(SPM_WAKEUP_MISC));
- #endif
- return ret;
- }
- bool spm_mcdi_can_enter(void)
- {
- bool ret = 1;
- /*check is MCDI kick */
- if ((SPM_MCDI_isKICK == 0) || ((spm_read(SPM_CPU_WAKEUP_EVENT) & 0x1) == 1)
- || ((spm_read(SPM_SW_RSV_3) & 0x1) == 1))
- ret = 0;
- #ifndef CONFIG_CPU_ISOLATION
- if (atomic_read(&is_in_hotplug) >= 1)
- ret = 0;
- #endif
- #if (MCDI_DVT_IPI)
- if (ret == 0) {
- spm_idle_ver("SPM_MCDI_isKICK=%d\n", SPM_MCDI_isKICK);
- spm_idle_ver("spm_read(SPM_CPU_WAKEUP_EVENT)=%d\n", spm_read(SPM_CPU_WAKEUP_EVENT));
- spm_idle_ver("spm_read(MCU_PWR_CON)=%d\n", spm_read(MCU_PWR_CON));
- }
- #endif
- return ret;
- }
- bool spm_mcdi_wfi(int core_id)
- {
- bool ret = 0;
- unsigned long flags;
- int dmnt_ret = 0;
- int mcdi_core_id = core_id;
- #if SPM_AEE_RR_REC
- spin_lock_irqsave(&__spm_lock, flags);
- *p_is_mcdi_wfi = (*p_is_mcdi_wfi | (1 << core_id));
- spin_unlock_irqrestore(&__spm_lock, flags);
- #endif
- if (spm_mcdi_can_enter() == 0) {
- #if SPM_AEE_RR_REC
- spin_lock_irqsave(&__spm_lock, flags);
- *p_is_mcdi_wfi = (*p_is_mcdi_wfi & ~(1 << core_id));
- spin_unlock_irqrestore(&__spm_lock, flags);
- #endif
- return ret;
- }
- if ((spm_read(SPM_SW_RSV_0) & (1 << mcdi_core_id)) == 0) {
- if (spm_is_cpu_irq_occur(mcdi_core_id) == 0) {
- /*core wfi_sel & cpu mask */
- spm_mcdi_wfi_sel_enter(core_id);
- /*sync core1~n local timer to XGPT */
- mcidle_before_wfi(core_id);
- dmnt_ret = mt_cpu_dormant_interruptible(CPU_MCDI_MODE);
- if (dmnt_ret == MT_CPU_DORMANT_RESET) {
- ret = 1;
- /*check if MCDI abort by unkonw IRQ */
- while ((spm_read(SPM_IRQ_STA) & (1 << (mcdi_core_id + 4))) == 0) {
- spin_lock_irqsave(&__spm_lock, flags);
- g_SPM_MCDI_Abnormal_WakeUp |= (1 << core_id);
- spin_unlock_irqrestore(&__spm_lock, flags);
- }
- } else if (dmnt_ret == MT_CPU_DORMANT_ABORT)
- ret = 0;
- /*clear core wfi_sel & cpu unmask */
- spm_mcdi_wfi_sel_leave(core_id);
- mcidle_after_wfi(core_id);
- spin_lock_irqsave(&__spm_lock, flags);
- /*Clear SPM SW IRQ */
- spm_write(SPM_SW_INT_CLEAR, (0x1 << core_id)); /* PCM_SWINT_3 */
- spin_unlock_irqrestore(&__spm_lock, flags);
- }
- } else if (spm_is_cpu_irq_occur(core_id) == 0) {
- /*core wfi_sel & cpu mask */
- spm_mcdi_wfi_sel_enter(core_id);
- /*sync core1~n local timer to XGPT */
- mcidle_before_wfi(core_id);
- wfi_with_sync();
- mcidle_after_wfi(core_id);
- /*clear core wfi_sel & cpu unmask */
- spm_mcdi_wfi_sel_leave(core_id);
- /*Clear SPM SW IRQ */
- spm_write(SPM_SW_INT_CLEAR, (0x1 << core_id)); /* PCM_SWINT_3 */
- ret = 1;
- }
- #if SPM_AEE_RR_REC
- spin_lock_irqsave(&__spm_lock, flags);
- *p_is_mcdi_wfi = (*p_is_mcdi_wfi & ~(1 << core_id));
- spin_unlock_irqrestore(&__spm_lock, flags);
- #endif
- return ret;
- }
- void spm_set_mcdi_pcm_ver(void)
- {
- CHIP_SW_VER ver = mt_get_chip_sw_ver();
- /* Get Different FW */
- }
- void __init spm_mcdi_init(void)
- {
- #if SPM_AEE_RR_REC
- p_is_mcdi_wfi = aee_rr_rec_mcdi_wfi();
- *p_is_mcdi_wfi = 0;
- #endif
- spm_set_mcdi_pcm_ver();
- }
- static void __exit spm_mcdi_exit(void)
- {
- spm_idle_ver("Exit SPM-MCDI\n\r");
- }
- #ifndef CONFIG_CPU_ISOLATION
- void spm_mcdi_wakeup_all_cores(void)
- {
- unsigned long flags;
- spin_lock_irqsave(&__spm_mcdi_lock, flags);
- if (SPM_MCDI_isKICK == 0) {
- spin_unlock_irqrestore(&__spm_mcdi_lock, flags);
- return;
- }
- /* trigger cpu wake up event */
- spm_mcdi_cpu_wake_up_event(1, 1);
- /* trigger cpu wake up event */
- spm_mcdi_cpu_wake_up_event(0, 0);
- spin_unlock_irqrestore(&__spm_mcdi_lock, flags);
- }
- #endif
- static void spm_mcdi_enable(enum spm_mcdi_lock_id id, int mcdi_en)
- {
- unsigned long flags;
- if (mcdi_en) {
- spin_lock_irqsave(&__spm_lock, flags);
- spm_mcdi_lock &= ~(1 << id);
- spin_unlock_irqrestore(&__spm_lock, flags);
- } else {
- spin_lock_irqsave(&__spm_lock, flags);
- spm_mcdi_lock |= (1 << id);
- spin_unlock_irqrestore(&__spm_lock, flags);
- }
- }
- static unsigned int spm_mcdi_is_disable(void)
- {
- return spm_mcdi_lock;
- }
- void spm_mcdi_switch_on_off(enum spm_mcdi_lock_id id, int mcdi_en)
- {
- spm_mcdi_enable(id, mcdi_en);
- if (mcdi_en) {
- if (spm_mcdi_is_disable())
- return;
- spm_go_to_mcdi(0, 0);
- } else
- spm_leave_MCDI();
- }
- MODULE_DESCRIPTION("SPM-MCDI Driver v0.1");
|