void INT_VDD5V(void) { #ifdef USE_VBUSVALID if(BF_RD(POWER_CTRL, VBUSVALID_IRQ)) { if(BF_RD(POWER_STS, VBUSVALID)) usb_insert_int(); else usb_remove_int(); /* reverse polarity */ BF_WR(POWER_CTRL_TOG, POLARITY_VBUSVALID(1)); /* clear int */ BF_CLR(POWER_CTRL, VBUSVALID_IRQ); } #else if(BF_RD(POWER_CTRL, VDD5V_GT_VDDIO_IRQ)) { if(BF_RD(POWER_STS, VDD5V_GT_VDDIO)) usb_insert_int(); else usb_remove_int(); /* reverse polarity */ BF_WR(POWER_CTRL_TOG, POLARITY_VDD5V_GT_VDDIO(1)); /* clear int */ BF_CLR(POWER_CTRL, VDD5V_GT_VDDIO_IRQ); } #endif }
void imx233_power_set_stop_current(unsigned current) { #if IMX233_SUBTARGET >= 3700 BF_CLR(POWER_CHARGE, STOP_ILIMIT); #else BF_CLR(POWER_BATTCHRG, STOP_ILIMIT); #endif /* find closest current GREATHER THAN OR EQUAL TO the expected current */ unsigned sum = 0; for(unsigned i = 0; i < ARRAYLEN(g_charger_stop_current_bits); i++) sum += g_charger_stop_current_bits[i].current; for(unsigned i = 0; i < ARRAYLEN(g_charger_stop_current_bits); i++) { sum -= g_charger_stop_current_bits[i].current; if(current > sum) { current -= g_charger_stop_current_bits[i].current; #if IMX233_SUBTARGET >= 3700 BF_WR(POWER_CHARGE_SET, STOP_ILIMIT(g_charger_stop_current_bits[i].bit)); #else BF_WR(POWER_BATTCHRG_SET, STOP_ILIMIT(g_charger_stop_current_bits[i].bit)); #endif } } }
void imx233_lcdif_set_data_swizzle(unsigned swizzle) { #if IMX233_SUBTARGET >= 3780 BF_WR(LCDIF_CTRL, INPUT_DATA_SWIZZLE, swizzle); #else BF_WR(LCDIF_CTRL, DATA_SWIZZLE, swizzle); #endif }
//////////////////////////////////////////////////////////////////////////////// //! See hw_lradc.h for details. //////////////////////////////////////////////////////////////////////////////// void hw_lradc_AssignChannel( hw_lradc_Channel_t eVirtualChannel, hw_lradc_Channel_t ePhysicalChannel ) { // Maps the physical channel to virtual channel switch ( eVirtualChannel ) { case LRADC_CH0: BF_WR( LRADC_CTRL4, LRADC0SELECT, ePhysicalChannel ); break; case LRADC_CH1: BF_WR( LRADC_CTRL4, LRADC1SELECT, ePhysicalChannel ); break; case LRADC_CH2: BF_WR( LRADC_CTRL4, LRADC2SELECT, ePhysicalChannel ); break; case LRADC_CH3: BF_WR( LRADC_CTRL4, LRADC3SELECT, ePhysicalChannel ); break; case LRADC_CH4: BF_WR( LRADC_CTRL4, LRADC4SELECT, ePhysicalChannel ); break; case LRADC_CH5: BF_WR( LRADC_CTRL4, LRADC5SELECT, ePhysicalChannel ); break; case LRADC_CH6: BF_WR( LRADC_CTRL4, LRADC6SELECT, ePhysicalChannel ); break; case LRADC_CH7: BF_WR( LRADC_CTRL4, LRADC7SELECT, ePhysicalChannel ); break; default: break; } }
void imx233_audioout_preinit(void) { /* Enable AUDIOOUT block */ imx233_reset_block(&HW_AUDIOOUT_CTRL); /* Enable digital filter clock */ imx233_clkctrl_enable(CLK_FILT, true); /* Enable DAC */ BF_CLR(AUDIOOUT_ANACLKCTRL, CLKGATE); /* Set capless mode */ #if IMX233_AUDIO_COUPLING_MODE == ACM_CAP BF_SET(AUDIOOUT_PWRDN, CAPLESS); #else BF_CLR(AUDIOOUT_PWRDN, CAPLESS); #endif /* Set word-length to 16-bit */ BF_SET(AUDIOOUT_CTRL, WORD_LENGTH); /* Power up DAC */ BF_CLR(AUDIOOUT_PWRDN, DAC); /* Hold HP to ground to avoid pop, then release and power up HP */ BF_SET(AUDIOOUT_ANACTRL, HP_HOLD_GND); BF_CLR(AUDIOOUT_PWRDN, HEADPHONE); /* Set HP mode to AB */ BF_SET(AUDIOOUT_ANACTRL, HP_CLASSAB); /* change bias to -50% */ BF_WR(AUDIOOUT_TEST, HP_I1_ADJ, 1); BF_WR(AUDIOOUT_REFCTRL, BIAS_CTRL, 1); #if IMX233_SUBTARGET >= 3700 BF_SET(AUDIOOUT_REFCTRL, RAISE_REF); #endif BF_SET(AUDIOOUT_REFCTRL, XTAL_BGR_BIAS); /* Stop holding to ground */ BF_CLR(AUDIOOUT_ANACTRL, HP_HOLD_GND); /* Set dmawait count to 31 (see errata, workaround random stop) */ BF_WR(AUDIOOUT_CTRL, DMAWAIT_COUNT, 31); /* start converting audio */ BF_SET(AUDIOOUT_CTRL, RUN); /* unmute DAC */ HW_AUDIOOUT_DACVOLUME_CLR = BM_OR2(AUDIOOUT_DACVOLUME, MUTE_LEFT, MUTE_RIGHT); /* send a few samples to avoid pop */ HW_AUDIOOUT_DATA = 0; HW_AUDIOOUT_DATA = 0; HW_AUDIOOUT_DATA = 0; HW_AUDIOOUT_DATA = 0; }
//////////////////////////////////////////////////////////////////////////////// //! See hw_lradc.h for details. //////////////////////////////////////////////////////////////////////////////// RtStatus_t hw_lradc_EnableBatteryMeasurement( hw_lradc_DelayTrigger_t eTrigger, uint16_t u16SamplingInterval) { hw_lradc_Channel_t eChannel = BATTERY_VOLTAGE_CH; // // Check if the lradc channel is present in this product // if( hw_lradc_GetChannelPresent(eChannel) == 0 ) return (ERROR_HW_LRADC_CH_NOT_PRESENT); // Disable the channel interrupt hw_lradc_EnableInterrupt(eChannel, FALSE); hw_lradc_ClearInterruptFlag(eChannel); // Configure the battery conversion register BF_WR(LRADC_CONVERSION, SCALE_FACTOR, 2); // Enable the automatic update mode of BATT_VALUE field in HW_POWER_MONITOR BF_SET(LRADC_CONVERSION, AUTOMATIC); hw_lradc_ConfigureChannel( eChannel, //Lradc channel FALSE, //DIVIDE_BY_TWO FALSE, //ACCUMULATE 0); //NUM_SAMPLES // schedule a conversion before the setting up of the delay channel // so the user can have a good value right after the function returns hw_lradc_ScheduleChannel(eChannel); // Setup the trigger loop forever, hw_lradc_SetDelayTrigger( eTrigger, // Trigger Index (1 << eChannel), // Lradc channels (1 << eTrigger), // Restart the triggers 0, // No loop count u16SamplingInterval); // 0.5*N msec on 2khz // Clear the accumulator & NUM_SAMPLES HW_LRADC_CHn_CLR(eChannel, 0xFFFFFFFF); // Kick off the LRADC battery measurement hw_lradc_SetDelayTriggerKick(eTrigger, TRUE); /* Wait for first measurement of battery. Should occur in 13 LRADC clock * cycles from the time of channel kickoff. Also add some wait time for * copy to the power supply BATT_VAL field to occur. */ hw_digctl_MicrosecondWait(10); return SUCCESS; }
//////////////////////////////////////////////////////////////////////////////// //! See hw_power.h for details. //////////////////////////////////////////////////////////////////////////////// void hw_power_SetBatteryMonitorVoltage(uint16_t u16BattVolt) { uint16_t u16BattValue; // Adjust for 8-mV LSB resolution u16BattValue = u16BattVolt/BATT_VAL_FIELD_RESOL; // Write to register BF_WR(POWER_BATTMONITOR, BATT_VAL, u16BattValue); }
void imx233_power_set_charge_current(unsigned current) { #if IMX233_SUBTARGET >= 3700 BF_CLR(POWER_CHARGE, BATTCHRG_I); #else BF_CLR(POWER_BATTCHRG, BATTCHRG_I); #endif /* find closest current LOWER THAN OR EQUAL TO the expected current */ for(unsigned i = 0; i < ARRAYLEN(g_charger_current_bits); i++) if(current >= g_charger_current_bits[i].current) { current -= g_charger_current_bits[i].current; #if IMX233_SUBTARGET >= 3700 BF_WR(POWER_CHARGE_SET, BATTCHRG_I(g_charger_current_bits[i].bit)); #else BF_WR(POWER_BATTCHRG_SET, BATTCHRG_I(g_charger_current_bits[i].bit)); #endif } }
void imx233_powermgmt_init(void) { imx233_power_set_charge_current(IMX233_CHARGE_CURRENT); imx233_power_set_stop_current(IMX233_STOP_CURRENT); #if IMX233_SUBTARGET >= 3700 /* assume that adc_init was called and battery monitoring via LRADC setup */ BF_WR(POWER_BATTMONITOR, EN_BATADJ(1)); /* setup linear regulator offsets to 25 mV below to prevent contention between * linear regulators and DCDC */ BF_WR(POWER_VDDDCTRL, LINREG_OFFSET(2)); BF_WR(POWER_VDDACTRL, LINREG_OFFSET(2)); BF_WR(POWER_VDDIOCTRL, LINREG_OFFSET(2)); /* enable a few bits controlling the DC-DC as recommended by Freescale */ BF_SET(POWER_LOOPCTRL, TOGGLE_DIF); BF_SET(POWER_LOOPCTRL, EN_CM_HYST); BF_CS(POWER_LOOPCTRL, EN_RCSCALE(1)); #else BF_SET(POWER_5VCTRL, LINREG_OFFSET); #endif }
//////////////////////////////////////////////////////////////////////////////// //! See hw_lradc.h for details. //////////////////////////////////////////////////////////////////////////////// void hw_lradc_Init(bool bEnableOnChipGroundRef, hw_lradc_ClockFreq_t eFreq) { if( bHwLradcInitialized == true ) { return; } // Clear the Soft Reset for normal operation BF_CLR(LRADC_CTRL0, SFTRST); // Clear the Clock Gate for normal operation BF_CLR(LRADC_CTRL0, CLKGATE); // use bitfield clear macro // Set on-chip ground ref if(bEnableOnChipGroundRef) { // Enable the onchip ground ref of LRADC conversions BF_SET( LRADC_CTRL0, ONCHIP_GROUNDREF); } else { // Disable the onchip ground ref of LRADC conversions BF_CLR( LRADC_CTRL0, ONCHIP_GROUNDREF); } // Set LRADC conversion clock frequency BF_WR(LRADC_CTRL3, CYCLE_TIME, eFreq); // Make sure the LRADC channel-6 selected for VDDIO BF_WR(LRADC_CTRL4, LRADC6SELECT, VDDIO_VOLTAGE_CH); // Make sure the LRADC channel-7 selected for Battery BF_WR(LRADC_CTRL4, LRADC7SELECT, BATTERY_VOLTAGE_CH); bHwLradcInitialized = true; }
// bbp = bytes per pixel static void pio_send(unsigned len, unsigned bpp, uint8_t *buf) { /* WARNING: the imx233 has a limitation on count wrt to byte packing, the * count must be a multiple of 2 with maximum packing when word-length is * 16-bit! * On the other hand, 8-bit word length doesn't seem to have any limitations, * for example one can send 3 bytes with a packing format of 0xf * WARNING for this function to work properly with any swizzle, we have to * make sure we pack as many 32-bits as possible even when the data is not * word-aligned */ imx233_lcdif_set_byte_packing_format(0xf); /* compute shift between buf and next word-aligned pointer */ int shift = 0; uint32_t temp_buf = 0; int count = len * bpp; // number of bytes while(0x3 & (intptr_t)buf) { temp_buf = temp_buf | *buf++ << shift; shift += 8; count--; } /* starting from now, all read are 32-bit */ uint32_t *wbuf = (void *)buf; #if IMX233_SUBTARGET >= 3780 HW_LCDIF_TRANSFER_COUNT = BF_OR2(LCDIF_TRANSFER_COUNT, V_COUNT(1), H_COUNT(len)); #else BF_WR(LCDIF_CTRL, COUNT, len); #endif BF_SET(LCDIF_CTRL, RUN); while(count > 0) { uint32_t val = *wbuf++; imx233_lcdif_wait_fifo(); HW_LCDIF_DATA = temp_buf | val << shift; if(shift != 0) temp_buf = val >> (32 - shift); count -= 4; } /* send remaining bytes if any */ if(shift != 0) { imx233_lcdif_wait_fifo(); HW_LCDIF_DATA = temp_buf; } imx233_lcdif_wait_ready(); }
void imx233_powermgmt_init(void) { imx233_power_set_charge_current(IMX233_CHARGE_CURRENT); imx233_power_set_stop_current(IMX233_STOP_CURRENT); /* assume that adc_init was called and battery monitoring via LRADC setup */ BF_WR(POWER_BATTMONITOR, EN_BATADJ, 1); #if IMX233_SUBTARGET >= 3700 /* setup linear regulator offsets to 25 mV below to prevent contention between * linear regulators and DCDC */ BF_WR(POWER_VDDDCTRL, LINREG_OFFSET, 2); BF_WR(POWER_VDDACTRL, LINREG_OFFSET, 2); BF_WR(POWER_VDDIOCTRL, LINREG_OFFSET, 2); /* enable DCDC (more efficient) */ BF_SET(POWER_5VCTRL, ENABLE_DCDC); BF_CLR(POWER_5VCTRL, DCDC_XFER); #else BF_SET(POWER_5VCTRL, LINREG_OFFSET); BF_SET(POWER_5VCTRL, EN_DCDC1); BF_SET(POWER_5VCTRL, EN_DCDC2); #endif #if IMX233_SUBTARGET >= 3780 /* enable a few bits controlling the DC-DC as recommended by Freescale */ BF_SET(POWER_LOOPCTRL, TOGGLE_DIF); BF_SET(POWER_LOOPCTRL, EN_CM_HYST); BF_CLR(POWER_LOOPCTRL, EN_RCSCALE); BF_SETV(POWER_LOOPCTRL, EN_RCSCALE, 1); /* adjust arbitration between 4.2 and battery */ BF_WR(POWER_DCDC4P2, CMPTRIP, 0); /* 85% */ BF_WR(POWER_DCDC4P2, DROPOUT_CTRL, 0xe); /* select greater, 200 mV drop */ /* make sure we are in a known state: disable charger and 4p2 */ BF_SET(POWER_CHARGE, PWD_BATTCHRG); BF_WR(POWER_DCDC4P2, ENABLE_DCDC, 0); BF_WR(POWER_DCDC4P2, ENABLE_4P2, 0); BF_SET(POWER_5VCTRL, PWD_CHARGE_4P2); #endif }
//////////////////////////////////////////////////////////////////////////////// //! \brief //! //! \return //////////////////////////////////////////////////////////////////////////////// int PowerPrep_ConfigurePowerSource( void ) { int iReturnValue = SUCCESS; /* initialize DCDC operating parameters */ hw_power_Init(); #ifdef NO_DCDC_BATT_SOURCE /* device configured for no source to DCDC_BATT input (5V only power * source). This boot option doesn't waste time looking for a good * battery. Battery powered operation and automatic voltage * measurements are disabled. */ // set bit 11 of PERSISTENT1 HW_RTC_PERSISTENT1_SET(0x800); // clear bit 12 PERSISTENT1 HW_RTC_PERSISTENT1_CLR(0x1000); bBatteryReady = false; bBatteryGood = false; printf("\r\nConfigured for 5v only power source.\ Battery powered operation disabled.\r\n"); /* Disable automatic battery voltage measurements which seem unnecessary * for this configuration. */ BF_SET(POWER_BATTMONITOR,EN_BATADJ); BF_CLR(LRADC_CONVERSION, AUTOMATIC); BF_WR(POWER_BATTMONITOR, BATT_VAL,525); //4200/8 HW_POWER_BATTMONITOR.B.BRWNOUT_LVL = BATTERY_BRWNOUT_BITFIELD_VALUE; iReturnValue = PowerPrep_5vBoot(); #ifndef MXS_VBUS_CURRENT_DRAW PowerPrep_CPUClock2PLL(); #endif #elif defined(NO_VDD5V_SOURCE) printf("\r\nConfigured for DCDC_BATT only power source.\r\n"); #ifdef mx28 /* We only care about the DCDC_BATT source in this configuration */ BF_SET(POWER_BATTMONITOR,PWDN_BATTBRNOUT_5VDETECT_ENABLE); #endif // clear bit 11 PERSISTENT1 HW_RTC_PERSISTENT1_CLR(0x800); // set bit 12 PERSISTENT1 HW_RTC_PERSISTENT1_SET(0x1000); /* since the DCDC_BATT input is our only source, we'll assume * it is good and attempt to boot. If your device has uses * this configuration but has a external DCDC_BATT source * that takes time to ramp, you could add a voltage check * and wait here until voltage reaches near the final level to * avoid trigger a battery brownout when the voltage is too * low. */ bBatteryReady = true; /* bBatteryGood is not used for this configuration */ /* bBatteryGood = don't care */ /*Boot from DCDC_BATT source*/ iReturnValue = PowerPrep_BattBoot(); PowerPrep_CPUClock2PLL(); /* raise battery brownout level to programmed value. */ PowerPrep_InitBattBo(); /* Configured to not use a VDD5V source */ HW_POWER_5VCTRL_SET(BM_POWER_5VCTRL_ILIMIT_EQ_ZERO); #else //clear bit 11 and 12 of PERSISTENT1 HW_RTC_PERSISTENT1_CLR(0x1800); /* check if Battery Voltage is high enough for full * power operation. */ bBatteryReady = PowerPrep_IsBatteryReady(); if(!IsVdd5vGtVddio()) { /* this option allows for fast booting without * the unecessary delay required for proper * battery detection when booting from 5v. */ /* battery voltage is present and 5v is not connected, * assume valid battery voltage source is present. Battery * brownout protection will take care of supply protection * if battery becomes invalid in the future */ bBatteryGood = true; printf("\r\nboot from battery. 5v input not detected\r\n"); /*Boot from battery*/ iReturnValue = PowerPrep_BattBoot(); PowerPrep_CPUClock2PLL(); } else { /* 5v input detected, boot from 5V. */ bBatteryGood = PowerPrep_IsBatteryGood(); if(!bBatteryGood) { BF_CLR(LRADC_CONVERSION, AUTOMATIC); BF_WR(POWER_BATTMONITOR, BATT_VAL,0); printf("\r\nNo battery or bad battery\ detected!!!.Disabling battery\ voltage measurements./r/n"); } iReturnValue = PowerPrep_5vBoot(); #ifndef MXS_VBUS_CURRENT_DRAW PowerPrep_CPUClock2PLL(); #endif /* MXS_VBUS_CURRENT_DRAW */ }
//////////////////////////////////////////////////////////////////////////////// //! \brief //! //! \return //////////////////////////////////////////////////////////////////////////////// int PowerPrep_ConfigurePowerSource( void ) { int iReturnValue = SUCCESS; /* initialize DCDC operating parameters */ hw_power_Init(); #ifdef NO_BATTERY_VOLTAGE_SOURCE /* device configured for "no battery" operation (5V only power source). This boot * option doesn't waste time looking for a good battery. Battery powered * operation and automatic voltage measurements are disabled. */ bBatteryReady = false; bBatteryGood = false; printf("\r\nConfigured for 5v only power source.\ Battery powered operation disabled.\r\n"); /* disable automatic battery voltage measurements */ BF_CLR(LRADC_CONVERSION, AUTOMATIC); BF_WR(POWER_BATTMONITOR, BATT_VAL,0); iReturnValue = PowerPrep_5vBoot(); #ifndef MXS_VBUS_CURRENT_DRAW PowerPrep_CPUClock2PLL(); #endif #else /* check if Battery Voltage is high enough for full * power operation. */ bBatteryReady = PowerPrep_IsBatteryReady(); if(!IsVdd5vGtVddio()) { /* this option allows for fast booting without * the unecessary delay required for proper * battery detection when booting from 5v. */ /* battery voltage is present and 5v is not connected, * assume valid battery voltage source is present. Battery * brownout protection will take care of supply protection * if battery becomes invalid in the future */ bBatteryGood = true; printf("\r\nboot from battery. 5v input not detected\r\n"); /*Boot from battery*/ iReturnValue = PowerPrep_BattBoot(); PowerPrep_CPUClock2PLL(); } else { /* 5v input detected. Now we need to determine if a * valid battery source is present to decide which * power source to use during bootup. */ bBatteryGood = PowerPrep_IsBatteryGood(); if(!bBatteryReady) { if(bBatteryGood) /* control arrives here if the battery voltage source * appears to be chargeable but the voltage is current * too low to use as a reliable battery voltage source. */ printf("\r\nChargeable battery detected but\ the voltage is too low for battery\ powered operation.Booting from 5V\ power source.\r\n"); else { BF_CLR(LRADC_CONVERSION, AUTOMATIC); BF_WR(POWER_BATTMONITOR, BATT_VAL,0); printf("\r\nNo battery or bad battery\ detected!!!.Disabling battery\ voltage measurements./r/n"); } iReturnValue = PowerPrep_5vBoot(); #ifndef MXS_VBUS_CURRENT_DRAW PowerPrep_CPUClock2PLL(); #endif /* MXS_VBUS_CURRENT_DRAW */ } else { printf("\r\n5v source detected.Valid battery\ voltage detected.Booting from battery\ voltage source.\r\n"); /*Boot from battery*/ iReturnValue = PowerPrep_BattBoot(); PowerPrep_CPUClock2PLL(); } }
void charging_algorithm_step(void) { #if IMX233_SUBTARGET >= 3700 bool is_5v_present = usb_detect() == USB_INSERTED; /* initial state & 5v -> battery transition */ if(!is_5v_present && charge_state != DISCHARGING) { logf("pwrmgmt: * -> discharging"); logf("pwrmgmt: disable charger and 4p2"); charge_state = DISCHARGING; /* 5V has been lost: disable 4p2 power rail */ BF_SET(POWER_CHARGE, PWD_BATTCHRG); #if IMX233_SUBTARGET >= 3780 BF_WR(POWER_DCDC4P2, ENABLE_DCDC(0)); BF_WR(POWER_DCDC4P2, ENABLE_4P2(0)); BF_WR(POWER_5VCTRL, CHARGE_4P2_ILIMIT(0)); BF_SET(POWER_5VCTRL, PWD_CHARGE_4P2); #endif } /* battery -> 5v transition */ else if(is_5v_present && charge_state == DISCHARGING) { logf("pwrmgmt: discharging -> trickle"); logf("pwrmgmt: begin charging 4p2"); #if IMX233_SUBTARGET >= 3780 /* 5V has been detected: prepare 4.2V power rail for activation * WARNING we can reach this situation when starting after Freescale bootloader * or after RoLo in a state where the DCDC is running. In this case, * we must *NOT* disable it or this will shutdown the device. This procedure * is safe: it will never disable the DCDC and will not reduce the charge * limit on the 4P2 rail. */ BF_WR(POWER_DCDC4P2, ENABLE_4P2(1)); BF_SET(POWER_CHARGE, ENABLE_LOAD); BF_WR(POWER_5VCTRL, CHARGE_4P2_ILIMIT(0)); /* start by drawing 0mA */ BF_CLR(POWER_5VCTRL, PWD_CHARGE_4P2);// FIXME: manual error ? BF_WR(POWER_DCDC4P2, ENABLE_DCDC(1)); /* the tick task will take care of slowly ramping up the current in the rail * every 10ms (since it runs at HZ and HZ=100) */ #endif charge_state = TRICKLE; } /* trickle -> charging transition */ else if(charge_state == TRICKLE) { #if IMX233_SUBTARGET >= 3780 /* If 4.2V current limit has not reached 780mA, don't do anything, the * DPC is still running */ /* If we've reached the maximum, take action */ if(BF_RD(POWER_5VCTRL, CHARGE_4P2_ILIMIT) == MAX_4P2_ILIMIT) #endif { logf("pwrmgmt: enable dcdc and charger"); logf("pwrmgmt: trickle -> charging"); #if IMX233_SUBTARGET >= 3780 /* adjust arbitration between 4.2 and battery */ BF_WR(POWER_DCDC4P2, CMPTRIP(0)); /* 85% */ BF_WR(POWER_DCDC4P2, DROPOUT_CTRL(0xe)); /* select greater, 200 mV drop */ #endif /* switch to DCDC */ BF_CLR(POWER_5VCTRL, DCDC_XFER); BF_SET(POWER_5VCTRL, ENABLE_DCDC); /* enable battery charging */ BF_CLR(POWER_CHARGE, PWD_BATTCHRG); charge_state = CHARGING; timeout_charging = current_tick + IMX233_CHARGING_TIMEOUT; } } /* charging -> error transition */ else if(charge_state == CHARGING && TIME_AFTER(current_tick, timeout_charging)) { /* we have charged for a too long time, declare charger broken */ logf("pwrmgmt: charging timeout exceeded!"); logf("pwrmgmt: charging -> error"); /* stop charging, note that we leave the 4.2 rail active so that the DCDC * keep drawing current from the 4.2 only and leave the battery untouched */ BF_SET(POWER_CHARGE, PWD_BATTCHRG); /* goto error state */ charge_state = CHARGE_STATE_ERROR; } /* charging -> topoff transition */ else if(charge_state == CHARGING && !BF_RD(POWER_STS, CHRGSTS)) { logf("pwrmgmt: topping off"); logf("pwrmgmt: charging -> topoff"); charge_state = TOPOFF; timeout_topping_off = current_tick + IMX233_TOPOFF_TIMEOUT; } /* topoff -> disabled transition */ else if(charge_state == TOPOFF && TIME_AFTER(current_tick, timeout_topping_off)) { logf("pwrmgmt: charging finished"); logf("pwrmgmt: topoff -> disabled"); /* stop charging, note that we leave the 4.2 rail active so that the DCDC * keep drawing current from the 4.2 only and leave the battery untouched */ BF_SET(POWER_CHARGE, PWD_BATTCHRG); charge_state = CHARGE_STATE_DISABLED; } #endif }
void imx233_lcdif_enable_sync_signals(bool en) { BF_WR(LCDIF_VDCTRL3, SYNC_SIGNALS_ON, en); }
void imx233_lcdif_set_byte_packing_format(unsigned byte_packing) { BF_WR(LCDIF_CTRL1, BYTE_PACKING_FORMAT, byte_packing); }
//////////////////////////////////////////////////////////////////////////////// //! See hw_power.h for details. //////////////////////////////////////////////////////////////////////////////// void hw_power_SetBatteryBrownoutCode( uint16_t BoRegCode ) { BF_WR(POWER_BATTMONITOR, BRWNOUT_LVL, BoRegCode ); }
//////////////////////////////////////////////////////////////////////////////// //! See hw_power.h for details. //////////////////////////////////////////////////////////////////////////////// RtStatus_t hw_power_Init(void) { RtStatus_t rtn = SUCCESS; //-------------------------------------------------------------------------- // Make the clock registers accessible by ungating power block //-------------------------------------------------------------------------- BF_CLR(POWER_CTRL, CLKGATE); //-------------------------------------------------------------------------- // Improve efficieny and reduce transient ripple //-------------------------------------------------------------------------- { //---------------------------------------------------------------------- // Change stepping voltage only after the diff control loop // has toggled as well. //---------------------------------------------------------------------- BF_SET(POWER_LOOPCTRL, TOGGLE_DIF); //---------------------------------------------------------------------- // Enable the commom mode and differential mode hysterisis //---------------------------------------------------------------------- BF_SET(POWER_LOOPCTRL, EN_CM_HYST); BF_SET(POWER_LOOPCTRL, EN_DF_HYST); //---------------------------------------------------------------------- // To run with a lower battery voltage, adjust the duty // cycle positive limit //---------------------------------------------------------------------- BF_WR(POWER_DCLIMITS, POSLIMIT_BUCK, 0x30); } //-------------------------------------------------------------------------- // Finally enable the battery adjust //-------------------------------------------------------------------------- BF_SET(POWER_BATTMONITOR,EN_BATADJ); //---------------------------------------------------------------------- // Increase the RCSCALE_THRESHOLD //---------------------------------------------------------------------- BF_SET(POWER_LOOPCTRL, RCSCALE_THRESH); //---------------------------------------------------------------------- // Increase the RCSCALE level for quick DCDC response to dynamic load //---------------------------------------------------------------------- hw_power_EnableRcScale(HW_POWER_RCSCALE_8X_INCR); hw_power_EnableHalfFets(FALSE); hw_power_EnableDoubleFets(TRUE); //-------------------------------------------------------------------------- // Initialize the variables we use in hw_power driver. //-------------------------------------------------------------------------- if( bMasterFlagsInitialized == false ) { // Initialize the brownout variables and synchronize these with the // master brownout register. bEnableMaster5vBrownout = HW_POWER_5VCTRL.B.PWDN_5VBRNOUT; bEnableMasterBattBrownout = HW_POWER_BATTMONITOR.B.PWDN_BATTBRNOUT; // Initialize the 4p2 and charger variables. Both the local and the // master have to be true for the variable to be true. bEnableMaster4p2 = HW_POWER_DCDC4P2.B.ENABLE_4P2 && !HW_POWER_5VCTRL.B.PWD_CHARGE_4P2; bEnableMasterCharge = !HW_POWER_CHARGE.B.PWD_BATTCHRG && !HW_POWER_5VCTRL.B.PWD_CHARGE_4P2; bMasterFlagsInitialized = true; } /* Enable 5V to battery source handoff on detection of 5V * disconnection. Get the DCDC control loop ready for * action. Leaving DCDC_XFER set causes problems with 4p2 * operation and has other issues so we only leave * it on long enough to prepare the DCDC control loop */ HW_POWER_5VCTRL_SET(BM_POWER_5VCTRL_DCDC_XFER); hw_digctl_MicrosecondWait(30); HW_POWER_5VCTRL_CLR(BM_POWER_5VCTRL_DCDC_XFER); return rtn; }
void charging_algorithm_step(void) { #if IMX233_SUBTARGET >= 3780 bool is_5v_present = usb_detect() == USB_INSERTED; /* initial state & 5v -> battery transition */ if(!is_5v_present && charge_state != DISCHARGING) { logf("pwrmgmt: * -> discharging"); logf("pwrmgmt: disable charger and 4p2"); /* 5V has been lost: disable 4p2 power rail */ BF_SET(POWER_CHARGE, PWD_BATTCHRG); BF_WR(POWER_DCDC4P2, ENABLE_DCDC, 0); BF_WR(POWER_DCDC4P2, ENABLE_4P2, 0); BF_SET(POWER_5VCTRL, PWD_CHARGE_4P2); charge_state = DISCHARGING; } /* battery -> 5v transition */ else if(is_5v_present && charge_state == DISCHARGING) { logf("pwrmgmt: discharging -> trickle"); logf("pwrmgmt: begin charging 4p2"); /* 5V has been detected: prepare 4.2V power rail for activation */ BF_WR(POWER_DCDC4P2, ENABLE_4P2, 1); BF_SET(POWER_CHARGE, ENABLE_LOAD); BF_WR(POWER_5VCTRL, CHARGE_4P2_ILIMIT, 1); BF_CLR(POWER_5VCTRL, PWD_CHARGE_4P2);// FIXME: manual error ? BF_WR(POWER_DCDC4P2, ENABLE_DCDC, 1); timeout_4p2_ilimit_increase = current_tick + HZ / 100; charge_state = TRICKLE; } else if(charge_state == TRICKLE && TIME_AFTER(current_tick, timeout_4p2_ilimit_increase)) { /* if 4.2V current limit has not reached 780mA, increase it slowly to * charge the 4.2V capacitance */ if(BF_RD(POWER_5VCTRL, CHARGE_4P2_ILIMIT) != 0x3f) { //logf("pwrmgmt: incr 4.2 ilimit"); HW_POWER_5VCTRL += BF_POWER_5VCTRL_CHARGE_4P2_ILIMIT(1); timeout_4p2_ilimit_increase = current_tick + HZ / 100; } /* we've reached the maximum, take action */ else { logf("pwrmgmt: enable dcdc and charger"); logf("pwrmgmt: trickle -> charging"); BF_CLR(POWER_5VCTRL, DCDC_XFER); BF_SET(POWER_5VCTRL, ENABLE_DCDC); /* enable battery charging */ BF_CLR(POWER_CHARGE, PWD_BATTCHRG); charge_state = CHARGING; timeout_charging = current_tick + IMX233_CHARGING_TIMEOUT; } } else if(charge_state == CHARGING && TIME_AFTER(current_tick, timeout_charging)) { /* we have charged for a too long time, declare charger broken */ logf("pwrmgmt: charging timeout exceeded!"); logf("pwrmgmt: charging -> error"); /* stop charging */ BF_SET(POWER_5VCTRL, PWD_CHARGE_4P2); /* goto error state */ charge_state = CHARGE_STATE_ERROR; } else if(charge_state == CHARGING && !BF_RD(POWER_STS, CHRGSTS)) { logf("pwrmgmt: topping off"); logf("pwrmgmt: charging -> topoff"); charge_state = TOPOFF; timeout_topping_off = current_tick + IMX233_TOPOFF_TIMEOUT; } else if(charge_state == TOPOFF && TIME_AFTER(current_tick, timeout_topping_off)) { logf("pwrmgmt: charging finished"); logf("pwrmgmt: topoff -> disabled"); /* stop charging */ BF_SET(POWER_CHARGE, PWD_BATTCHRG); charge_state = CHARGE_STATE_DISABLED; } #endif }