a test code to implement and test LP1768 power control mode

Dependencies:   mbed

This code implemented some LP1768 power mode : Sleep(), DeepSleep(), PowerDown(), DeepPowerDown(), BOGD_PowerDown(). It also has a test code to test these power modes and wakeup using watch dog. The wakeup part is based on Erik's code but add implementation for LP1768. As LP1768 has debug enabled in default, it cannot be waked up in DeepSleep mode. Therefore this code use WDC reset to wake up the chips from deep sleep. The test code also allow test the power under two clock frequency (96 MHz and 48MHz). Inspired by Paul and Michael Wang, I also tested the power reduction by power off PHY. The analysis could be found in http://mbed.org/users/steniu01/notebook/lp1768-power-mode-implementation-and-measurement-/#

PowerControl/EthernetPowerControl.cpp

Committer:
steniu01
Date:
2014-08-02
Revision:
2:15d9501bf5b3
Parent:
1:571258908570

File content as of revision 2:15d9501bf5b3:

#include "EthernetPowerControl.h"

void write_PHY (unsigned int PhyReg, unsigned short Value) {
   /* Write a data 'Value' to PHY register 'PhyReg'. */
   unsigned int tout;
   /* Hardware MII Management for LPC176x devices. */
   LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
   LPC_EMAC->MWTD = Value;

   /* Wait utill operation completed */
   for (tout = 0; tout < MII_WR_TOUT; tout++) {
      if ((LPC_EMAC->MIND & MIND_BUSY) == 0) {
         break;
      }
   }
}

unsigned short read_PHY (unsigned int PhyReg) {
   /* Read a PHY register 'PhyReg'. */
   unsigned int tout, val;

   LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
   LPC_EMAC->MCMD = MCMD_READ;

   /* Wait until operation completed */
   for (tout = 0; tout < MII_RD_TOUT; tout++) {
      if ((LPC_EMAC->MIND & MIND_BUSY) == 0) {
         break;
      }
   }
   LPC_EMAC->MCMD = 0;
   val = LPC_EMAC->MRDD;
   
   return (val);
}

void EMAC_Init()
{
  unsigned int tout,regv;
  /* Power Up the EMAC controller. */
  Peripheral_PowerUp(LPC1768_PCONP_PCENET);
  
  LPC_PINCON->PINSEL2 = 0x50150105;
  LPC_PINCON->PINSEL3 &= ~0x0000000F;
  LPC_PINCON->PINSEL3 |= 0x00000005;

  /* Reset all EMAC internal modules. */
  LPC_EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX |
             MAC1_SIM_RES | MAC1_SOFT_RES;
  LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES;

  /* A short delay after reset. */
  for (tout = 100; tout; tout--);

  /* Initialize MAC control registers. */
  LPC_EMAC->MAC1 = MAC1_PASS_ALL;
  LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;
  LPC_EMAC->MAXF = ETH_MAX_FLEN;
  LPC_EMAC->CLRT = CLRT_DEF;
  LPC_EMAC->IPGR = IPGR_DEF;

  /* Enable Reduced MII interface. */
  LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM;

  /* Reset Reduced MII Logic. */
  LPC_EMAC->SUPP = SUPP_RES_RMII;
  for (tout = 100; tout; tout--);
  LPC_EMAC->SUPP = 0;

  /* Put the DP83848C in reset mode */
  write_PHY (PHY_REG_BMCR, 0x8000);

  /* Wait for hardware reset to end. */
  for (tout = 0; tout < 0x100000; tout++) {
    regv = read_PHY (PHY_REG_BMCR);
    if (!(regv & 0x8000)) {
      /* Reset complete */
      break;
    }
  }
}


void PHY_PowerDown()
{
    if (!Peripheral_GetStatus(LPC1768_PCONP_PCENET))
        EMAC_Init(); //init EMAC if it is not already init'd
    
    unsigned int regv;
    regv = read_PHY(PHY_REG_BMCR);
    write_PHY(PHY_REG_BMCR, regv | (1 << PHY_REG_BMCR_POWERDOWN));
    regv = read_PHY(PHY_REG_BMCR);
    
    //shouldn't need the EMAC now.
    Peripheral_PowerDown(LPC1768_PCONP_PCENET);
    
    //and turn off the PHY OSC
     LPC_GPIO1->FIODIR |= 0x8000000;
     LPC_GPIO1->FIOCLR = 0x8000000;
}

void PHY_PowerUp()
{   
    if (!Peripheral_GetStatus(LPC1768_PCONP_PCENET))
        EMAC_Init(); //init EMAC if it is not already init'd
        
    LPC_GPIO1->FIODIR |= 0x8000000;
    LPC_GPIO1->FIOSET = 0x8000000;
    
    //wait for osc to be stable
    wait_ms(200);
    
    unsigned int regv;
    regv = read_PHY(PHY_REG_BMCR);
    write_PHY(PHY_REG_BMCR, regv & ~(1 << PHY_REG_BMCR_POWERDOWN));
    regv = read_PHY(PHY_REG_BMCR);
}

void PHY_EnergyDetect_Enable()
{
    if (!Peripheral_GetStatus(LPC1768_PCONP_PCENET))
        EMAC_Init(); //init EMAC if it is not already init'd
        
    unsigned int regv;
    regv = read_PHY(PHY_REG_EDCR);
    write_PHY(PHY_REG_BMCR, regv | (1 << PHY_REG_EDCR_ENABLE));
    regv = read_PHY(PHY_REG_EDCR);   
}

void PHY_EnergyDetect_Disable()
{
    if (!Peripheral_GetStatus(LPC1768_PCONP_PCENET))
        EMAC_Init(); //init EMAC if it is not already init'd
    unsigned int regv;
    regv = read_PHY(PHY_REG_EDCR);
    write_PHY(PHY_REG_BMCR, regv & ~(1 << PHY_REG_EDCR_ENABLE));
    regv = read_PHY(PHY_REG_EDCR);   
}