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_lcdif_wait_fifo(void) { #if IMX233_SUBTARGET >= 3700 while(BF_RD(LCDIF_STAT, TXFIFO_FULL)); #else while(!BF_RD(LCDIF_CTRL, FIFO_STATUS)); #endif }
static inline int __attribute__((always_inline)) read_pswitch(void) { #if IMX233_SUBTARGET >= 3700 return BF_RD(POWER_STS, PSWITCH); #else return BF_RD(DIGCTL_STATUS, PSWITCH); #endif }
bool imx233_power_usb_detect(void) { #ifdef USE_VBUSVALID return BF_RD(POWER_STS, VBUSVALID); #else return BF_RD(POWER_STS, VDD5V_GT_VDDIO); #endif }
void imx233_power_init(void) { #if IMX233_SUBTARGET >= 3700 BF_CLR(POWER_MINPWR, HALF_FETS); #endif /* setup vbusvalid parameters: set threshold to 4v and power up comparators */ BF_CS(POWER_5VCTRL, VBUSVALID_TRSH(1)); #if IMX233_SUBTARGET >= 3780 BF_SET(POWER_5VCTRL, PWRUP_VBUS_CMPS); #else BF_SET(POWER_5VCTRL, OTG_PWRUP_CMPS); #endif /* enable vbusvalid detection method for the dcdc (improves efficiency) */ BF_SET(POWER_5VCTRL, VBUSVALID_5VDETECT); /* disable shutdown on 5V fail */ BF_CLR(POWER_5VCTRL, PWDN_5VBRNOUT); #ifdef USE_VBUSVALID /* make sure VBUSVALID is unlocked */ BF_CLR(POWER_DEBUG, VBUSVALIDPIOLOCK); /* clear vbusvalid irq and set correct polarity */ BF_CLR(POWER_CTRL, VBUSVALID_IRQ); if(BF_RD(POWER_STS, VBUSVALID)) BF_CLR(POWER_CTRL, POLARITY_VBUSVALID); else BF_SET(POWER_CTRL, POLARITY_VBUSVALID); BF_SET(POWER_CTRL, ENIRQ_VBUS_VALID); /* make sure old detection way is not enabled */ BF_CLR(POWER_CTRL, ENIRQ_VDD5V_GT_VDDIO); #else BF_CLR(POWER_CTRL, VDD5V_GT_VDDIO_IRQ); if(BF_RD(POWER_STS, VDD5V_GT_VDDIO)) BF_CLR(POWER_CTRL, POLARITY_VDD5V_GT_VDDIO); else BF_SET(POWER_CTRL, POLARITY_VDD5V_GT_VDDIO); BF_SET(POWER_CTRL, ENIRQ_VDD5V_GT_VDDIO); /* make the vbusvalid detection way is not enabled */ #if IMX233_SUBTARGET >= 3700 BF_CLR(POWER_CTRL, ENIRQ_VBUS_VALID); #endif #endif /* the VDD5V IRQ is shared by several sources, disable them */ #if IMX233_SUBTARGET >= 3700 BF_CLR(POWER_CTRL, ENIRQ_PSWITCH); BF_CLR(POWER_CTRL, ENIRQ_DC_OK); #if IMX233_SUBTARGET < 3780 BF_CLR(POWER_CTRL, ENIRQ_LINREG_OK); #endif /* IMX233_SUBTARGET < 3780 */ #endif /* IMX233_SUBTARGET >= 3700 */ imx233_icoll_enable_interrupt(INT_SRC_VDD5V, true); }
void INT_LCDIF_ERROR(void) { if(BF_RD(LCDIF_CTRL1, CUR_FRAME_DONE_IRQ)) { if(g_cur_frame_cb) g_cur_frame_cb(); BF_CLR(LCDIF_CTRL1, CUR_FRAME_DONE_IRQ); } if(BF_RD(LCDIF_CTRL1, VSYNC_EDGE_IRQ)) { if(g_vsync_edge_cb) g_vsync_edge_cb(); BF_CLR(LCDIF_CTRL1, VSYNC_EDGE_IRQ); } }
int button_read_device(void) { int btn = 0; if(BF_RD(POWER_STS, PSWITCH) == 1) btn |= BUTTON_POWER; return imx233_button_lradc_read(btn); }
//////////////////////////////////////////////////////////////////////////////// //! See hw_power.h for details. //////////////////////////////////////////////////////////////////////////////// void hw_power_ClearVbusValidInterrupt(void) { while( BF_RD(POWER_CTRL, VBUSVALID_IRQ) != 0 ) { BF_CLR(POWER_CTRL, VBUSVALID_IRQ); } }
static inline int __attribute__((always_inline)) read_lradc(int src) { BF_CLR(LRADC_CTRL1, LRADCx_IRQ(src)); BF_SETV(LRADC_CTRL0, SCHEDULE, 1 << src); while(!BF_RD(LRADC_CTRL1, LRADCx_IRQ(src))); return BF_RDn(LRADC_CHn, src, VALUE); }
//////////////////////////////////////////////////////////////////////////////// //! See hw_power.h for details. //////////////////////////////////////////////////////////////////////////////// uint16_t hw_power_GetBatteryChargeCurrentThreshold(void) { uint16_t u16Threshold; u16Threshold = BF_RD(POWER_CHARGE, STOP_ILIMIT); return hw_power_ConvertSettingToCurrent(u16Threshold); }
//////////////////////////////////////////////////////////////////////////////// //! See hw_power.h for details. //////////////////////////////////////////////////////////////////////////////// void hw_power_ClearVdd5vDroopInterrupt(void) { while( BF_RD(POWER_CTRL, VDD5V_DROOP_IRQ) != 0 ) { BF_CLR(POWER_CTRL, VDD5V_DROOP_IRQ); } }
//////////////////////////////////////////////////////////////////////////////// //! See hw_power.h for details. //////////////////////////////////////////////////////////////////////////////// uint16_t hw_power_GetMaxBatteryChargeCurrent(void) { uint8_t u8Bits; // Get the raw data from register u8Bits = BF_RD(POWER_CHARGE, BATTCHRG_I); // Translate raw data to current (in mA) and return it return hw_power_ConvertSettingToCurrent(u8Bits); }
/* clear RTC ALARM wakeup or AUTORESTART bits here. */ void PowerPrep_ClearAutoRestart( void ) { HW_RTC_CTRL_CLR( BM_ICOLL_CTRL_SFTRST ); while( HW_RTC_CTRL.B.SFTRST == 1 ); HW_RTC_CTRL_CLR( BM_ICOLL_CTRL_CLKGATE ); while( HW_RTC_CTRL.B.CLKGATE == 1 ); /* Due to the hardware design bug of mx28 EVK-A * we need to set the AUTO_RESTART bit. */ if(HW_RTC_PERSISTENT0.B.AUTO_RESTART==0) { while(BF_RD( RTC_STAT, NEW_REGS)); HW_RTC_PERSISTENT0.B.AUTO_RESTART = 1; BF_SET(RTC_CTRL, FORCE_UPDATE); BF_CLR(RTC_CTRL, FORCE_UPDATE); while(BF_RD( RTC_STAT, NEW_REGS)); while(BF_RD( RTC_STAT, STALE_REGS)); } }
enum imx233_i2c_error_t imx233_i2c_end(unsigned timeout) { if(i2c_nr_stages == 0) return I2C_ERROR; i2c_stage[i2c_nr_stages - 1].dma.cmd |= BM_APB_CHx_CMD_SEMAPHORE | BM_APB_CHx_CMD_IRQONCMPLT; BF_CLR(I2C_CTRL1, ALL_IRQ); imx233_dma_reset_channel(APB_I2C); imx233_icoll_enable_interrupt(INT_SRC_I2C_DMA, true); imx233_icoll_enable_interrupt(INT_SRC_I2C_ERROR, true); imx233_dma_enable_channel_interrupt(APB_I2C, true); imx233_dma_start_command(APB_I2C, &i2c_stage[0].dma); enum imx233_i2c_error_t ret; if(semaphore_wait(&i2c_sema, timeout) == OBJ_WAIT_TIMEDOUT) { imx233_dma_reset_channel(APB_I2C); imx233_i2c_reset(); ret = I2C_TIMEOUT; } else if(BF_RD(I2C_CTRL1, MASTER_LOSS_IRQ)) ret = I2C_MASTER_LOSS; else if(BF_RD(I2C_CTRL1, NO_SLAVE_ACK_IRQ)) { /* the core doesn't like this error, this is a workaround to prevent lock up */ #if IMX233_SUBTARGET >= 3780 BF_SET(I2C_CTRL1, CLR_GOT_A_NAK); #endif imx233_dma_reset_channel(APB_I2C); imx233_i2c_reset(); ret = I2C_NO_SLAVE_ACK; } else if(BF_RD(I2C_CTRL1, EARLY_TERM_IRQ)) ret = I2C_SLAVE_NAK; else ret = imx233_i2c_finalize(); /* sleep */ BF_SET(I2C_CTRL0, CLKGATE); mutex_unlock(&i2c_mutex); return ret; }
//////////////////////////////////////////////////////////////////////////////// //! See hw_power.h for details. //////////////////////////////////////////////////////////////////////////////// uint16_t hw_power_SetBatteryChargeCurrentThreshold(uint16_t u16Threshold) { uint16_t u16OldSetting; uint16_t u16NewSetting; uint16_t u16ToggleMask; //-------------------------------------------------------------------------- // See hw_power_SetMaxBatteryChargeCurrent for an explanation of why we're // using the toggle register here. // // Since this function doesn't have any major hardware effect, we could use // the usual macros for writing to this bit field. But, for the sake of // parallel construction and any potentially odd effects on the status bit, // we use the toggle register in the same way as ddi_bc_hwSetMaxCurrent. //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- // The threshold hardware can't express as large a range as the max // current setting, but we can use the same functions as long as we add an // extra check here. // // Thresholds larger than 180mA can't be expressed. //-------------------------------------------------------------------------- if (u16Threshold > 180) u16Threshold = 180; //////////////////////////////////////// // Create the mask //////////////////////////////////////// // Get the old setting. u16OldSetting = BF_RD(POWER_CHARGE, STOP_ILIMIT); // Convert the new threshold into a setting. u16NewSetting = hw_power_ConvertCurrentToSetting(u16Threshold); // Compute the toggle mask. u16ToggleMask = u16OldSetting ^ u16NewSetting; // Shift to the correct bit position u16ToggleMask = BF_POWER_CHARGE_STOP_ILIMIT(u16ToggleMask); ///////////////////////////////////////// // Write to the register ///////////////////////////////////////// // Write to the toggle register. HW_POWER_CHARGE_TOG(u16ToggleMask); // Tell the caller what current we're set at now. return(hw_power_ConvertSettingToCurrent(u16NewSetting)); }
bool gpmi_is_dma_active(uint32_t chipSelect) { uint32_t u32Sema; reg32_t r32ChipDmaNumber = (NAND0_APBH_CH); //+chipSelect); uint32_t u32Run; u32Sema = HW_APBH_CHn_SEMA_RD(r32ChipDmaNumber) & BM_APBH_CHn_SEMA_PHORE; u32Run = BF_RD(GPMI_CTRL0, RUN); // A nonzero value for either of these means a DMA is running. return ( u32Sema | u32Run ); }
/** * Context functions */ static inline enum context_t get_context(void) { #if IMX233_SUBTARGET >= 3780 /* On the imx233 it's easy because we know the power up source */ unsigned pwrup_src = BF_RD(POWER_STS, PWRUP_SOURCE); if(pwrup_src & (1 << 5)) return CONTEXT_USB; else if(pwrup_src & (1 << 4)) return CONTEXT_RTC; else return CONTEXT_NORMAL; #else /* On the other targets, we need to poke a few more registers */ #endif }
//////////////////////////////////////////////////////////////////////////////// //! See hw_power.h for details. //////////////////////////////////////////////////////////////////////////////// bool hw_power_EnablePswitchInterrupt(bool bEnable) { bool bPrev = BF_RD(POWER_CTRL, ENIRQ_PSWITCH); if(bEnable) { BF_SET(POWER_CTRL, ENIRQ_PSWITCH); } else { BF_CLR(POWER_CTRL, ENIRQ_PSWITCH); } return bPrev; }
//////////////////////////////////////////////////////////////////////////////// //! See hw_power.h for details. //////////////////////////////////////////////////////////////////////////////// bool hw_power_EnableVdd5vGtVddioInterrupt(bool bEnable) { bool bPrev = BF_RD(POWER_CTRL, ENIRQ_VDD5V_GT_VDDIO); if(bEnable) { BF_SET(POWER_CTRL, ENIRQ_VDD5V_GT_VDDIO); } else { BF_CLR(POWER_CTRL, ENIRQ_VDD5V_GT_VDDIO); } return bPrev; }
//////////////////////////////////////////////////////////////////////////////// //! See hw_power.h for details. //////////////////////////////////////////////////////////////////////////////// bool hw_power_EnableVbusValidInterrupt(bool bEnable) { bool bPrev = BF_RD(POWER_CTRL, ENIRQ_VBUS_VALID); if(bEnable) { BF_SET(POWER_CTRL, ENIRQ_VBUS_VALID); } else { BF_CLR(POWER_CTRL, ENIRQ_VBUS_VALID); } return bPrev; }
//////////////////////////////////////////////////////////////////////////////// //! See hw_power.h for details. //////////////////////////////////////////////////////////////////////////////// bool hw_power_EnableVdddBrownoutInterrupt(bool bEnable) { bool bPrev = BF_RD(POWER_CTRL, ENIRQ_VDDD_BO); if(bEnable) { BF_SET(POWER_CTRL, ENIRQ_VDDD_BO); } else { BF_CLR(POWER_CTRL, ENIRQ_VDDD_BO); } return bPrev; }
//////////////////////////////////////////////////////////////////////////////// //! See hw_power.h for details. //////////////////////////////////////////////////////////////////////////////// bool hw_power_EnableBatteryBrownoutInterrupt(bool bEnable) { bool bPrev = BF_RD(POWER_CTRL, ENIRQBATT_BO); if(bEnable) { BF_SET(POWER_CTRL, ENIRQBATT_BO); } else { BF_CLR(POWER_CTRL, ENIRQBATT_BO); } return bPrev; }
void lcd_enable(bool enable) { if(lcd_active() == enable) return; lcd_set_active(enable); if(lcd_active()) { // enable spi spi_enable(true); // reset imx233_lcdif_reset_lcd(true); imx233_lcdif_reset_lcd(false); mdelay(1); imx233_lcdif_reset_lcd(true); mdelay(1); // "power" on lcd_power(true); // setup registers lcd_power_seq(); lcd_init_seq(); lcd_display_on_seq(); imx233_dma_reset_channel(APB_LCDIF); imx233_dma_start_command(APB_LCDIF, &lcdif_dma[0].dma); } else { // power down lcd_display_off_seq(); lcd_power(false); // stop lcdif BF_CLR(LCDIF_CTRL, DOTCLK_MODE); /* stmp37xx errata: clearing DOTCLK_MODE won't clear RUN: wait until * fifo is empty and then clear manually */ while(!BF_RD(LCDIF_STAT, TXFIFO_EMPTY)); BF_CLR(LCDIF_CTRL, RUN); // disable spi spi_enable(false); } }
//////////////////////////////////////////////////////////////////////////////// //! See hw_power.h for details. //////////////////////////////////////////////////////////////////////////////// bool hw_power_EnableVdd5vDroopInterrupt(bool bEnable) { bool bPrev = false; bPrev = BF_RD(POWER_CTRL, ENIRQ_VDD5V_DROOP); if(bEnable) { BF_SET(POWER_CTRL, ENIRQ_VDD5V_DROOP); } else { BF_CLR(POWER_CTRL, ENIRQ_VDD5V_DROOP); } return bPrev; }
//////////////////////////////////////////////////////////////////////////////// //! See hw_power.h for details. //////////////////////////////////////////////////////////////////////////////// bool hw_power_Enable4p2BrownoutInterrupt(bool bEnable) { bool bPrev = false; bPrev = BF_RD(POWER_CTRL, ENIRQ_DCDC4P2_BO); if(bEnable) { BF_SET(POWER_CTRL, ENIRQ_DCDC4P2_BO); } else { BF_CLR(POWER_CTRL, ENIRQ_DCDC4P2_BO); } return bPrev; }
//////////////////////////////////////////////////////////////////////////////// //! See hw_lradc.h for details. //////////////////////////////////////////////////////////////////////////////// bool hw_lradc_GetInterruptFlag(hw_lradc_Channel_t eChannel) { bool bRtn; // Returns LRADC interrupt flag switch (eChannel) { case LRADC_CH0: bRtn = BF_RD(LRADC_CTRL1, LRADC0_IRQ); break; case LRADC_CH1: bRtn = BF_RD(LRADC_CTRL1, LRADC1_IRQ); break; case LRADC_CH2: bRtn = BF_RD(LRADC_CTRL1, LRADC2_IRQ); break; case LRADC_CH3: bRtn = BF_RD(LRADC_CTRL1, LRADC3_IRQ); break; case LRADC_CH4: bRtn = BF_RD(LRADC_CTRL1, LRADC4_IRQ); break; case LRADC_CH5: bRtn = BF_RD(LRADC_CTRL1, LRADC5_IRQ); break; case LRADC_CH6: bRtn = BF_RD(LRADC_CTRL1, LRADC6_IRQ); break; case LRADC_CH7: bRtn = BF_RD(LRADC_CTRL1, LRADC7_IRQ); break; default: bRtn = 0; break; } return bRtn; }
//////////////////////////////////////////////////////////////////////////////// //! See hw_lradc.h for details. //////////////////////////////////////////////////////////////////////////////// bool hw_lradc_GetChannelPresent(hw_lradc_Channel_t eChannel) { bool bRtn; // Read a bit field of HW_LRADC_STATUS register switch (eChannel) { case LRADC_CH0: bRtn = BF_RD(LRADC_STATUS, CHANNEL0_PRESENT); break; case LRADC_CH1: bRtn = BF_RD(LRADC_STATUS, CHANNEL1_PRESENT); break; case LRADC_CH2: bRtn = BF_RD(LRADC_STATUS, CHANNEL2_PRESENT); break; case LRADC_CH3: bRtn = BF_RD(LRADC_STATUS, CHANNEL3_PRESENT); break; case LRADC_CH4: bRtn = BF_RD(LRADC_STATUS, CHANNEL4_PRESENT); break; case LRADC_CH5: bRtn = BF_RD(LRADC_STATUS, CHANNEL5_PRESENT); break; case LRADC_CH6: bRtn = BF_RD(LRADC_STATUS, CHANNEL6_PRESENT); break; case LRADC_CH7: bRtn = BF_RD(LRADC_STATUS, CHANNEL7_PRESENT); break; default: bRtn = 0; break; } return bRtn; }
void imx233_lcdif_pio_send(bool data_mode, unsigned len, void *buf) { imx233_lcdif_wait_ready(); if(len == 0) return; #if IMX233_SUBTARGET >= 3780 imx233_lcdif_enable_bus_master(false); #endif if(data_mode) BF_SET(LCDIF_CTRL, DATA_SELECT); else BF_CLR(LCDIF_CTRL, DATA_SELECT); switch(BF_RD(LCDIF_CTRL, WORD_LENGTH)) { case BV_LCDIF_CTRL_WORD_LENGTH__8_BIT: pio_send(len, 1, buf); break; case BV_LCDIF_CTRL_WORD_LENGTH__16_BIT: pio_send(len, 2, buf); break; #if IMX233_SUBTARGET >= 3780 case BV_LCDIF_CTRL_WORD_LENGTH__18_BIT: pio_send(len, 4, buf); break; #endif default: panicf("Don't know how to handle this word length"); } }
//////////////////////////////////////////////////////////////////////////////// //! See hw_power.h for details. //////////////////////////////////////////////////////////////////////////////// uint16_t hw_power_SetMaxBatteryChargeCurrent(uint16_t u16Current) { uint16_t u16OldSetting; uint16_t u16NewSetting; uint16_t u16ToggleMask; if(u16Current > 780) u16Current = 780; // Get the old setting. u16OldSetting = BF_RD(POWER_CHARGE, BATTCHRG_I); // Convert the new threshold into a setting. u16NewSetting = hw_power_ConvertCurrentToSetting(u16Current); // Compute the toggle mask. u16ToggleMask = u16OldSetting ^ u16NewSetting; // Write to the toggle register. HW_POWER_CHARGE_TOG(u16ToggleMask << BP_POWER_CHARGE_BATTCHRG_I); // Tell the caller what current we're set at now. return(hw_power_ConvertSettingToCurrent(u16NewSetting)); }
bool charging_state(void) { return BF_RD(POWER_STS, CHRGSTS); }