📄 pmicm.nc
字号:
/* $Id: PMICM.nc,v 1.7 2008/06/11 00:46:26 razvanm Exp $ *//* * Copyright (c) 2005 Arched Rock Corporation * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Arched Rock Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARCHED * ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. *//* * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By * downloading, copying, installing or using the software you agree to * this license. If you do not agree to this license, do not download, * install, copy or use the software. * * Intel Open Source License * * Copyright (c) 2002 Intel Corporation * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * Neither the name of the Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR ITS * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *//* * * Authors: Lama Nachman, Robert Adler */#define START_RADIO_LDO 1#define START_SENSOR_BOARD_LDO 1/* * VCC_MEM is connected to BUCK2 by default, make sure you have a board * that has the right resistor settings before disabling BUCK2 */#define DISABLE_BUCK2 0 //#include "trace.h"#include "Timer.h"#include "pmic.h"module PMICM { provides{ interface Init; interface PMIC; } uses interface Timer<TMilli> as chargeMonitorTimer; uses interface HplPXA27xGPIOPin as PMICGPIO; uses interface HplPXA27xI2C as PI2C; uses interface PlatformReset;}implementation {#include "pmic.h" bool gotReset; error_t readPMIC(uint8_t address, uint8_t *value, uint8_t numBytes){ //send the PMIC the address that we want to read if(numBytes > 0){ call PI2C.setIDBR(PMIC_SLAVE_ADDR<<1); call PI2C.setICR(call PI2C.getICR() | ICR_START); call PI2C.setICR(call PI2C.getICR() | ICR_TB); while(call PI2C.getICR() & ICR_TB); //actually send the address terminated with a STOP call PI2C.setIDBR(address); call PI2C.setICR(call PI2C.getICR() & ~ICR_START); call PI2C.setICR(call PI2C.getICR() | ICR_STOP); call PI2C.setICR(call PI2C.getICR() | ICR_TB); while(call PI2C.getICR() & ICR_TB); call PI2C.setICR(call PI2C.getICR() & ~ICR_STOP); //actually request the read of the data call PI2C.setIDBR(PMIC_SLAVE_ADDR<<1 | 1); call PI2C.setICR(call PI2C.getICR() | ICR_START); call PI2C.setICR(call PI2C.getICR() | ICR_TB); while(call PI2C.getICR() & ICR_TB); call PI2C.setICR(call PI2C.getICR() & ~ICR_START); //using Page Read Mode while (numBytes > 1){ call PI2C.setICR(call PI2C.getICR() | ICR_TB); while(call PI2C.getICR() & ICR_TB); *value = call PI2C.getIDBR(); value++; numBytes--; } call PI2C.setICR(call PI2C.getICR() | ICR_STOP); call PI2C.setICR(call PI2C.getICR() | ICR_ACKNAK); call PI2C.setICR(call PI2C.getICR() | ICR_TB); while(call PI2C.getICR() & ICR_TB); *value = call PI2C.getIDBR(); call PI2C.setICR(call PI2C.getICR() & ~ICR_STOP); call PI2C.setICR(call PI2C.getICR() & ~ICR_ACKNAK); return SUCCESS; } else{ return FAIL; } } error_t writePMIC(uint8_t address, uint8_t value){ call PI2C.setIDBR(PMIC_SLAVE_ADDR<<1); call PI2C.setICR(call PI2C.getICR() | ICR_START); call PI2C.setICR(call PI2C.getICR() | ICR_TB); while(call PI2C.getICR() & ICR_TB); PIDBR = address; call PI2C.setICR(call PI2C.getICR() & ~ICR_START); call PI2C.setICR(call PI2C.getICR() | ICR_TB); while(call PI2C.getICR() & ICR_TB); PIDBR = value; call PI2C.setICR(call PI2C.getICR() | ICR_STOP); call PI2C.setICR(call PI2C.getICR() | ICR_TB); while(call PI2C.getICR() & ICR_TB); call PI2C.setICR(call PI2C.getICR() & ~ICR_STOP); PICR &= ~ICR_STOP; return SUCCESS; } void startLDOs() { //uint8_t temp; uint8_t oldVal, newVal;#if START_SENSOR_BOARD_LDO // TODO : Need to move out of here to sensor board functions readPMIC(PMIC_A_REG_CONTROL_1, &oldVal, 1); newVal = oldVal | ARC1_LDO10_EN | ARC1_LDO11_EN; // sensor board writePMIC(PMIC_A_REG_CONTROL_1, newVal); readPMIC(PMIC_B_REG_CONTROL_2, &oldVal, 1); newVal = oldVal | BRC2_LDO10_EN | BRC2_LDO11_EN; writePMIC(PMIC_B_REG_CONTROL_2, newVal);#endif#if START_RADIO_LDO // TODO : Move to radio start readPMIC(PMIC_B_REG_CONTROL_1, &oldVal, 1); newVal = oldVal | BRC1_LDO5_EN; writePMIC(PMIC_B_REG_CONTROL_1, newVal);#endif#if DISABLE_BUCK2 // Disable BUCK2 if VCC_MEM is not configured to use BUCK2 readPMIC(PMIC_B_REG_CONTROL_1, &oldVal, 1); newVal = oldVal & ~BRC1_BUCK_EN; writePMIC(PMIC_B_REG_CONTROL_1, newVal);#endif#if 0 // Configure above LDOs, Radio and sensor board LDOs to turn off in sleep // TODO : Sleep setting doesn't work temp = BSC1_LDO1(1) | BSC1_LDO2(1) | BSC1_LDO3(1) | BSC1_LDO4(1); writePMIC(PMIC_B_SLEEP_CONTROL_1, temp); temp = BSC2_LDO5(1) | BSC2_LDO7(1) | BSC2_LDO8(1) | BSC2_LDO9(1); writePMIC(PMIC_B_SLEEP_CONTROL_2, temp); temp = BSC3_LDO12(1); writePMIC(PMIC_B_SLEEP_CONTROL_3, temp);#endif } error_t startPMICstuff() { //command result_t StdControl.start(){ XXX-pb //init unit uint8_t val[3]; //call PI2CInterrupt.enable(); XXX-pb } command error_t Init.init(){ uint8_t val[3]; PCFR |= PCFR_PI2C_EN; // Overrides GPIO settings on pins call PI2C.setICR(call PI2C.getICR() | (ICR_IUE | ICR_SCLE)); atomic{ gotReset=FALSE; } call PMICGPIO.setGAFRpin(0); call PMICGPIO.setGPDRbit(FALSE); call PMICGPIO.setGFERbit(TRUE); /* * Reset the watchdog, switch it to an interrupt, so we can disable it * Ignore SLEEP_N pin, enable H/W reset via button */ writePMIC(PMIC_SYS_CONTROL_A, SCA_RESET_WDOG | SCA_WDOG_ACTION | SCA_HWRES_EN); // Disable all interrupts from PMIC except for ONKEY button writePMIC(PMIC_IRQ_MASK_A, ~IMA_ONKEY_N); writePMIC(PMIC_IRQ_MASK_B, 0xFF); writePMIC(PMIC_IRQ_MASK_C, 0xFF); //read out the EVENT registers so that we can receive interrupts readPMIC(PMIC_EVENTS, val, 3); // Set default core voltage to 0.85 V#ifdef PXA27X_13M //P85 is not reliable, using P95 call PMIC.setCoreVoltage(B2R1_TRIM_P95_V);#else call PMIC.setCoreVoltage(B2R1_TRIM_1_25_V);#endif startLDOs(); return SUCCESS; } async event void PI2C.interruptI2C() { //PI2CInterrupt.fired(){ uint32_t status, update=0; status = call PI2C.getISR(); //PISR; if(status & ISR_ITE){ update |= ISR_ITE; //trace(DBG_USR1,"sent data"); } if(status & ISR_BED){ update |= ISR_BED; //trace(DBG_USR1,"bus error"); } call PI2C.setISAR(update); //PISR = update; } async event void PMICGPIO.interruptGPIOPin(){ uint8_t events[3]; bool localGotReset; //call PMICGPIO.call PMICInterrupt.clear(); XXX autocleard by GPIO module readPMIC(PMIC_EVENTS, events, 3); if(events[EVENTS_A_OFFSET] & EA_ONKEY_N){ atomic{ localGotReset = gotReset; } if(localGotReset==TRUE){ call PlatformReset.reset(); } else{ atomic{ gotReset=TRUE; } } } else{ //trace(DBG_USR1,"PMIC EVENTs =%#x %#x %#x\r\n",events[0], events[1], events[2]); } } /* * The Buck2 controls the core voltage, set to appropriate trim value */ command error_t PMIC.setCoreVoltage(uint8_t trimValue) { writePMIC(PMIC_BUCK2_REG1, (trimValue & B2R1_TRIM_MASK) | B2R1_GO); return SUCCESS; } command error_t PMIC.shutDownLDOs() { uint8_t temp; uint8_t oldVal, newVal; /* * Shut down all LDOs that are not controlled by the sleep mode * Note, we assume here the LDO10 & LDO11 (sensor board) will be off * Should be moved to sensor board control */ // LDO1, LDO4, LDO6, LDO7, LDO8, LDO9, LDO10, LDO 11, LDO13, LDO14 readPMIC(PMIC_A_REG_CONTROL_1, &oldVal, 1); newVal = oldVal & ~ARC1_LDO13_EN & ~ARC1_LDO14_EN; newVal = newVal & ~ARC1_LDO10_EN & ~ARC1_LDO11_EN; // sensor board writePMIC(PMIC_A_REG_CONTROL_1, newVal); readPMIC(PMIC_B_REG_CONTROL_1, &oldVal, 1); newVal = oldVal & ~BRC1_LDO1_EN & ~BRC1_LDO4_EN & ~BRC1_LDO5_EN & ~BRC1_LDO6_EN & ~BRC1_LDO7_EN; writePMIC(PMIC_B_REG_CONTROL_1, newVal); readPMIC(PMIC_B_REG_CONTROL_2, &oldVal, 1); newVal = oldVal & ~BRC2_LDO8_EN & ~BRC2_LDO9_EN & ~BRC2_LDO10_EN & ~BRC2_LDO11_EN & ~BRC2_LDO14_EN & ~BRC2_SIMCP_EN; writePMIC(PMIC_B_REG_CONTROL_2, newVal); return SUCCESS; } error_t getPMICADCVal(uint8_t channel, uint8_t *val){ uint8_t oldval; error_t rval; //read out the old value so that we can reset at the end rval = readPMIC(PMIC_ADC_MAN_CONTROL, &oldval,1); if (rval == SUCCESS) { rval = writePMIC(PMIC_ADC_MAN_CONTROL, PMIC_AMC_ADCMUX(channel) | PMIC_AMC_MAN_CONV | PMIC_AMC_LDO_INT_Enable); } if (rval == SUCCESS) { rval = readPMIC(PMIC_MAN_RES,val,1); } if (rval == SUCCESS) { //reset to old state rval = writePMIC(PMIC_ADC_MAN_CONTROL, oldval); } return rval; } command error_t PMIC.getBatteryVoltage(uint8_t *val){ //for now, let's use the manual conversion mode return getPMICADCVal(0, val); } command error_t PMIC.chargingStatus(uint8_t *vBat, uint8_t *vChg, uint8_t *iChg){ getPMICADCVal(0, vBat); getPMICADCVal(2, vChg); getPMICADCVal(1, iChg); return SUCCESS; } command error_t PMIC.enableAutoCharging(bool enable){ return SUCCESS; } command error_t PMIC.enableManualCharging(bool enable){ //just turn on or off the LED for now!! uint8_t val; if(enable){ //want to turn on the charger getPMICADCVal(2, &val); //if charger is present due some stuff...75 should be 4.65V or so if(val > 75 ) { //trace(DBG_USR1,"Charger Voltage is %.3fV...enabling charger...\r\n", ((val*6) * .01035)); //write the total timeout to be 8 hours writePMIC(PMIC_TCTR_CONTROL,8); //enable the charger at 100mA and 4.35V writePMIC(PMIC_CHARGE_CONTROL,PMIC_CC_CHARGE_ENABLE | PMIC_CC_ISET(1) | PMIC_CC_VSET(7)); //turn on the LED writePMIC(PMIC_LED1_CONTROL,0x80); //start a timer to monitor our progress every 5 minutes! call chargeMonitorTimer.startPeriodic(300000); } else{ //trace(DBG_USR1,"Charger Voltage is %.3fV...charger not enabled\r\n", ((val*6) * .01035)); } } else{ //turn off the charger and the LED call PMIC.getBatteryVoltage(&val); //trace(DBG_USR1,"Disabling Charger...Battery Voltage is %.3fV\r\n", (val * .01035) + 2.65); //disable everything that we enabled writePMIC(PMIC_TCTR_CONTROL,0); writePMIC(PMIC_CHARGE_CONTROL,0); writePMIC(PMIC_LED1_CONTROL,0x00); } return SUCCESS; } event void chargeMonitorTimer.fired(){ uint8_t val; call PMIC.getBatteryVoltage(&val); //stop when vBat>4V if(val>130){ call PMIC.enableManualCharging(FALSE); call chargeMonitorTimer.stop(); } return; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -