void spm_sodi_init(void) { #if SPM_USE_TWAM_DEBUG unsigned long flags; struct twam_sig twamsig = { .sig0 = 10, /* disp_req */ .sig1 = 23, /* self-refresh */ .sig2 = 25, /* md2_srcclkena */ .sig3 = 21, /* md2_apsrc_req_mux */ }; #endif #if defined (CONFIG_OF) struct device_node *node; struct resource r; /* mcucfg */ node = of_find_compatible_node(NULL, NULL, MCUCFG_NODE); if (!node) { spm_err("error: cannot find node " MCUCFG_NODE); BUG(); } if (of_address_to_resource(node, 0, &r)) { spm_err("error: cannot get phys addr" MCUCFG_NODE); BUG(); } mcucfg_phys_base = r.start; mcucfg_base = (unsigned long)of_iomap(node, 0); if(!mcucfg_base) { spm_err("error: cannot iomap " MCUCFG_NODE); BUG(); } printk("mcucfg_base = 0x%u\n", (unsigned int)mcucfg_base); #endif #if SPM_AEE_RR_REC spm_sodi_aee_init(); #endif #if SPM_USE_TWAM_DEBUG #if 0 spin_lock_irqsave(&__spm_lock, flags); spm_write(SPM_AP_STANBY_CON, spm_read(SPM_AP_STANBY_CON) | ASC_MD_DDR_EN_SEL); spin_unlock_irqrestore(&__spm_lock, flags); #endif spm_twam_register_handler(twam_handler); spm_twam_enable_monitor(&twamsig, false,SPM_TWAM_MONITOR_TICK); #endif } MODULE_DESCRIPTION("SPM-SODI Driver v0.1");
/************************************** * Init and IRQ Function **************************************/ static irqreturn_t spm_irq0_handler(int irq, void *dev_id) { u32 isr; unsigned long flags; struct twam_sig twamsig; spin_lock_irqsave(&__spm_lock, flags); /* get ISR status */ isr = spm_read(SPM_SLEEP_ISR_STATUS); if (isr & ISRS_TWAM) { twamsig.sig0 = spm_read(SPM_SLEEP_TWAM_STATUS0); twamsig.sig1 = spm_read(SPM_SLEEP_TWAM_STATUS1); twamsig.sig2 = spm_read(SPM_SLEEP_TWAM_STATUS2); twamsig.sig3 = spm_read(SPM_SLEEP_TWAM_STATUS3); } /* clean ISR status */ spm_write(SPM_SLEEP_ISR_MASK, spm_read(SPM_SLEEP_ISR_MASK) | ISRM_ALL_EXC_TWAM); spm_write(SPM_SLEEP_ISR_STATUS, isr); if (isr & ISRS_TWAM) udelay(100); /* need 3T TWAM clock (32K/26M) */ spm_write(SPM_PCM_SW_INT_CLEAR, PCM_SW_INT0); spin_unlock_irqrestore(&__spm_lock, flags); if ((isr & ISRS_TWAM) && spm_twam_handler) spm_twam_handler(&twamsig); if (isr & (ISRS_SW_INT0 | ISRS_PCM_RETURN)) spm_err("IRQ0 HANDLER SHOULD NOT BE EXECUTED (0x%x)\n", isr); return IRQ_HANDLED; }
int spm_fs_init(void) { int r; /* create /sys/power/spm/xxx */ r = sysfs_create_group(power_kobj, &spm_attr_group); if (r) spm_err("FAILED TO CREATE /sys/power/spm (%d)\n", r); return r; }
int spm_set_vcore_dvs_voltage(unsigned int opp) { u8 f26m_req, apsrc_req; u32 target_sta, req; int timeout, r = 0; bool not_existed, not_support; unsigned long flags; if (opp == OPPI_PERF_ULTRA) { f26m_req = 1; apsrc_req = 1; target_sta = VCORE_STA_UHPM; } else if (opp == OPPI_PERF) { f26m_req = 1; apsrc_req = 0; target_sta = VCORE_STA_HPM; } else if (opp == OPPI_LOW_PWR) { f26m_req = 0; apsrc_req = 0; target_sta = VCORE_STA_LPM; } else { return -EINVAL; } spin_lock_irqsave(&__spm_lock, flags); not_existed = is_fw_not_existed(); not_support = is_fw_not_support_uhpm(); if (not_existed || (opp == OPPI_PERF_ULTRA && not_support)) { __go_to_vcore_dvfs(SPM_VCORE_DVFS_EN, f26m_req, apsrc_req); } else { req = spm_read(SPM_PCM_SRC_REQ) & ~(SR_PCM_F26M_REQ | SR_PCM_APSRC_REQ); spm_write(SPM_PCM_SRC_REQ, req | (f26m_req << 1) | apsrc_req); } if (opp < OPPI_LOW_PWR) { /* normal FW fetch time + 1.15->1.05->1.15->1.25V transition time */ timeout = 2 * __spm_vcore_dvfs.pcmdesc->size + 3 * PER_OPP_DVS_US; r = wait_pcm_complete_dvs(get_vcore_sta() == target_sta, timeout); if (r >= 0) { /* DVS pass */ r = 0; } else { spm_err("[VcoreFS] OPP: %u (%u)(%u)\n", opp, not_existed, not_support); spm_dump_vcore_dvs_regs(NULL); BUG(); } } spin_unlock_irqrestore(&__spm_lock, flags); return r; }
static irqreturn_t spm_irq_aux_handler(u32 irq_id) { u32 isr; unsigned long flags; spin_lock_irqsave(&__spm_lock, flags); isr = spm_read(SPM_SLEEP_ISR_STATUS); spm_write(SPM_PCM_SW_INT_CLEAR, (1U << irq_id)); spin_unlock_irqrestore(&__spm_lock, flags); spm_err("IRQ%u HANDLER SHOULD NOT BE EXECUTED (0x%x)\n", irq_id, isr); return IRQ_HANDLED; }
char *spm_dump_vcore_dvs_regs(char *p) { if (p) { p += sprintf(p, "SLEEP_DVFS_STA: 0x%x\n", spm_read(SPM_SLEEP_DVFS_STA)); p += sprintf(p, "PCM_SRC_REQ : 0x%x\n", spm_read(SPM_PCM_SRC_REQ)); p += sprintf(p, "PCM_REG13_DATA: 0x%x\n", spm_read(SPM_PCM_REG13_DATA)); p += sprintf(p, "PCM_REG12_MASK: 0x%x\n", spm_read(SPM_PCM_REG12_MASK)); p += sprintf(p, "PCM_REG12_DATA: 0x%x\n", spm_read(SPM_PCM_REG12_DATA)); p += sprintf(p, "AP_STANBY_CON : 0x%x\n", spm_read(SPM_AP_STANBY_CON)); p += sprintf(p, "PCM_FSM_STA : 0x%x\n", spm_read(SPM_PCM_FSM_STA)); } else { spm_err("[VcoreFS] SLEEP_DVFS_STA: 0x%x\n", spm_read(SPM_SLEEP_DVFS_STA)); spm_err("[VcoreFS] PCM_SRC_REQ : 0x%x\n", spm_read(SPM_PCM_SRC_REQ)); spm_err("[VcoreFS] PCM_REG13_DATA: 0x%x\n", spm_read(SPM_PCM_REG13_DATA)); spm_err("[VcoreFS] PCM_REG12_MASK: 0x%x\n", spm_read(SPM_PCM_REG12_MASK)); spm_err("[VcoreFS] PCM_REG12_DATA: 0x%x\n", spm_read(SPM_PCM_REG12_DATA)); spm_err("[VcoreFS] AP_STANBY_CON : 0x%x\n", spm_read(SPM_AP_STANBY_CON)); spm_err("[VcoreFS] PCM_FSM_STA : 0x%x\n", spm_read(SPM_PCM_FSM_STA)); } return p; }
char *spm_dump_vcore_dvs_regs(char *p) { if (p) { p += sprintf(p, "SLEEP_DVFS_STA: 0x%x\n", spm_read(SPM_SLEEP_DVFS_STA)); p += sprintf(p, "PCM_SRC_REQ : 0x%x\n", spm_read(SPM_PCM_SRC_REQ)); p += sprintf(p, "PCM_REG13_DATA: 0x%x\n", spm_read(SPM_PCM_REG13_DATA)); p += sprintf(p, "PCM_REG12_DATA: 0x%x\n", spm_read(SPM_PCM_REG12_DATA)); p += sprintf(p, "PCM_REG12_MASK: 0x%x\n", spm_read(SPM_PCM_REG12_MASK)); p += sprintf(p, "AP_STANBY_CON : 0x%x\n", spm_read(SPM_AP_STANBY_CON)); p += sprintf(p, "PCM_IM_PTR : 0x%x (%u)\n", spm_read(SPM_PCM_IM_PTR), spm_read(SPM_PCM_IM_LEN)); p += sprintf(p, "PCM_REG6_DATA : 0x%x\n", spm_read(SPM_PCM_REG6_DATA)); p += sprintf(p, "PCM_REG11_DATA: 0x%x\n", spm_read(SPM_PCM_REG11_DATA)); } else { spm_err("[VcoreFS] SLEEP_DVFS_STA: 0x%x\n", spm_read(SPM_SLEEP_DVFS_STA)); spm_err("[VcoreFS] PCM_SRC_REQ : 0x%x\n", spm_read(SPM_PCM_SRC_REQ)); spm_err("[VcoreFS] PCM_REG13_DATA: 0x%x\n", spm_read(SPM_PCM_REG13_DATA)); spm_err("[VcoreFS] PCM_REG12_DATA: 0x%x\n", spm_read(SPM_PCM_REG12_DATA)); spm_err("[VcoreFS] PCM_REG12_MASK: 0x%x\n", spm_read(SPM_PCM_REG12_MASK)); spm_err("[VcoreFS] AP_STANBY_CON : 0x%x\n", spm_read(SPM_AP_STANBY_CON)); spm_err("[VcoreFS] PCM_IM_PTR : 0x%x (%u)\n", spm_read(SPM_PCM_IM_PTR), spm_read(SPM_PCM_IM_LEN)); spm_err("[VcoreFS] PCM_REG6_DATA : 0x%x\n", spm_read(SPM_PCM_REG6_DATA)); spm_err("[VcoreFS] PCM_REG11_DATA: 0x%x\n", spm_read(SPM_PCM_REG11_DATA)); spm_err("[VcoreFS] PCM_REG0_DATA : 0x%x\n", spm_read(SPM_PCM_REG0_DATA)); spm_err("[VcoreFS] PCM_REG1_DATA : 0x%x\n", spm_read(SPM_PCM_REG1_DATA)); spm_err("[VcoreFS] PCM_REG2_DATA : 0x%x\n", spm_read(SPM_PCM_REG2_DATA)); spm_err("[VcoreFS] PCM_REG3_DATA : 0x%x\n", spm_read(SPM_PCM_REG3_DATA)); spm_err("[VcoreFS] PCM_REG4_DATA : 0x%x\n", spm_read(SPM_PCM_REG4_DATA)); spm_err("[VcoreFS] PCM_REG5_DATA : 0x%x\n", spm_read(SPM_PCM_REG5_DATA)); spm_err("[VcoreFS] PCM_REG7_DATA : 0x%x\n", spm_read(SPM_PCM_REG7_DATA)); spm_err("[VcoreFS] PCM_REG8_DATA : 0x%x\n", spm_read(SPM_PCM_REG8_DATA)); spm_err("[VcoreFS] PCM_REG9_DATA : 0x%x\n", spm_read(SPM_PCM_REG9_DATA)); spm_err("[VcoreFS] PCM_REG10_DATA: 0x%x\n", spm_read(SPM_PCM_REG10_DATA)); spm_err("[VcoreFS] PCM_REG14_DATA: 0x%x\n", spm_read(SPM_PCM_REG14_DATA)); spm_err("[VcoreFS] PCM_REG15_DATA: %u\n" , spm_read(SPM_PCM_REG15_DATA)); } return p; }