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