/* * ======== PowerMSP432_updateFreqs ======== */ void PowerMSP432_updateFreqs(PowerMSP432_Freqs *freqs) { Types_FreqHz cpuFreq; cpuFreq.hi = 0; cpuFreq.lo = freqs->MCLK; BIOS_setCpuFreq(&cpuFreq); ClockFreqs_setFrequency(ClockFreqs_Clock_ACLK, freqs->ACLK); ClockFreqs_setFrequency(ClockFreqs_Clock_SMCLK, freqs->SMCLK); ClockFreqs_setFrequency(ClockFreqs_Clock_HSMCLK, freqs->HSMCLK); }
/* * ======== Power_changeSetpoint ======== * Initiate a change to the F/V setpoint of the CPU, or the peripheral domain. * */ Power_Status Power_changeSetpoint(Power_Domain domain, UInt newSetpoint, UInt notifyTimeout) { PSCL_Status statusPSCL = PSCL_CANNOT_CHANGE_SETPOINT; Power_Status status = Power_SOK; Power_Status statusNotifyCPU = Power_SOK; Power_Status statusNotifyPER = Power_SOK; Bool notifyCPU = FALSE; Bool notifyPER = FALSE; UInt willChange = FALSE; Bool proceed = FALSE; Types_FreqHz cpuFreq; UInt previousSPPER; UInt previousSP; UInt disallowed; PSCL_ClkID clk; UInt frequency; UInt voltage; UInt maskSP; UInt taskKey; UInt swiKey; UInt key; /* make sure V/F scaling is supported */ if (!ti_sysbios_family_c674_Power_enableScaling) { status = Power_ENOTIMPLEMENTED; } /* check to make sure V/F scaling initialized OK */ else if (Power_module->PSCLinitOK == FALSE) { status = Power_EINITFAILURE; } /* check that domain ID is valid */ else if ((domain != Power_CPU) && (domain != Power_PER)) { status = Power_EINVALIDVALUE; } /* check if setpoint ID is out of range for the specified domain ID */ else if (((domain == Power_CPU) && (newSetpoint > (Power_module->numSPCPU - 1))) || ((domain == Power_PER) && (newSetpoint > (Power_module->numSPPER - 1)))) { status = Power_EOUTOFRANGE; } else { /* convert requested setpoint into a mask bit */ maskSP = 1 << newSetpoint; /* go atomic */ key = Hwi_disable(); /* now check the requested SP against disallowed SP constraints */ if (domain == Power_CPU) { disallowed = maskSP & Power_module->disallowedSetpointsCPU; } else { disallowed = maskSP & Power_module->disallowedSetpointsPER; } /* if the SP is *not* disallowed, check and set the 'busy' flag */ if (disallowed == 0) { if (Power_module->busy == FALSE) { Power_module->busy = TRUE; proceed = TRUE; } else { status = Power_EBUSY; } } else { status = Power_ENOTSUPPORTED; } /* end ATOMIC */ Hwi_restore(key); if (proceed == TRUE) { /* determine PSCL clock ID */ clk = (PSCL_ClkID) domain == Power_CPU ? PSCL_CPU_CLK : PSCL_PER_CLK; /* disable Task scheduling; allow Swi & Hwi for completion */ taskKey = Task_disable(); /* set flag for domain to be notified for SP change */ if (domain == Power_CPU) { notifyCPU = TRUE; } else { notifyPER = TRUE; } /* if voltage scaling enabled, call to PSCL to see if this setpoint change will result in a voltage change; if yes, then must notify for other clk domain too, as there will be a voltage scale even though that clk frequency isn't changing */ if (Power_module->currentConfig.scaleVoltage == TRUE) { PSCL_queryWillChangeVoltage(clk, newSetpoint, &willChange); if (willChange == TRUE) { if (domain == Power_CPU) { notifyPER = TRUE; } else { notifyCPU = TRUE; } } } /* now send any pre-notifications for CPU domain */ if (notifyCPU == TRUE) { /* set nextSP to indicate the pending setpoint */ if (domain == Power_CPU) { Power_module->nextSP = newSetpoint; /* yes, new setpoint */ previousSP = Power_module->currentSetpointCPU; } else { /* not new CPU setpoint */ Power_module->nextSP = Power_module->currentSetpointCPU; previousSP = Power_module->currentSetpointCPU; } /* notify clients registered for pre CPU SP notification */ statusNotifyCPU = Power_notify(Power_PENDING_CPU_SETPOINTCHANGE, notifyTimeout, Power_SigType_INTERNAL, NULL, NULL); } /* now send any pre-notifications for PER domain */ if ((statusNotifyCPU == Power_SOK) && (notifyPER == TRUE)) { /* set nextSPPER to indicate the pending setpoint */ if (domain == Power_CPU) { /* not new PER SP */ Power_module->nextSPPER = Power_module->currentSetpointPER; previousSPPER = Power_module->currentSetpointPER; } else { Power_module->nextSPPER = newSetpoint; /* yes, new PER SP */ previousSPPER = Power_module->currentSetpointPER; } /* notify clients registered for pre PER SP notification */ statusNotifyPER = Power_notify(Power_PENDING_PER_SETPOINTCHANGE, notifyTimeout, Power_SigType_INTERNAL, NULL, NULL); } /* if all 'pre' notifications succeeded... do the scaling op */ if ((statusNotifyCPU == Power_SOK) && (statusNotifyPER == Power_SOK)) { swiKey = Swi_disable(); /* call to PSCL to change the setpoint */ statusPSCL = PSCL_changeSetpoint(clk, newSetpoint, Power_module->currentConfig.scaleVoltage, Power_module->currentConfig.waitForVoltageScale,NULL,NULL); Swi_restore(swiKey); } /* if scaling operation successful... */ if (statusPSCL == PSCL_OK) { /* update previous and current SP globals */ if (notifyCPU == TRUE) { Power_module->currentSetpointCPU = Power_module->nextSP; Power_module->previousSP = previousSP; } if (notifyPER == TRUE) { Power_module->currentSetpointPER = Power_module->nextSPPER; Power_module->previousSPPER = previousSPPER; } /* if scaled the CPU frequency... tell BIOS about it */ if (domain == Power_CPU) { Power_getSetpointInfo(Power_CPU, newSetpoint, &frequency, &voltage); cpuFreq.lo = frequency * 1000; /* convert kHz to Hz */ cpuFreq.hi = 0; BIOS_setCpuFreq(&cpuFreq); } /* now notify post-notification clients */ if (notifyCPU == TRUE) { /* notify clients registered of post CPU SP change */ statusNotifyCPU = Power_notify(Power_DONE_CPU_SETPOINTCHANGE, notifyTimeout, Power_SigType_INTERNAL, NULL, NULL); } if ((statusNotifyCPU == Power_SOK) && (notifyPER == TRUE)) { /* notify clients registered of post PER SP change */ statusNotifyPER = Power_notify(Power_DONE_PER_SETPOINTCHANGE, notifyTimeout, Power_SigType_INTERNAL, NULL, NULL); } } /* done, so clear Power busy flag */ Power_module->busy = FALSE; /* resume Tasking */ Task_restore(taskKey); /* figure out return code */ if (statusPSCL == PSCL_INVALID_SETPOINT) { status = Power_EOUTOFRANGE; /* invalid SP according to PSCL */ } else if ((statusNotifyCPU == Power_ETIMEOUT) || (statusNotifyPER == Power_ETIMEOUT) ) { status = Power_ETIMEOUT; /* notification timeout */ } else if ((status != Power_SOK) || (statusPSCL != PSCL_OK)) { status = Power_EFAIL; /* convert to 'general failure' */ } } } return (status); }