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); }
struct imx233_timrot_info_t imx233_timrot_get_info(unsigned timer_nr) { struct imx233_timrot_info_t info; memset(&info, 0, sizeof(info)); info.src = BF_RDn(TIMROT_TIMCTRLn, timer_nr, SELECT); info.prescale = BF_RDn(TIMROT_TIMCTRLn, timer_nr, PRESCALE); info.reload = BF_RDn(TIMROT_TIMCTRLn, timer_nr, RELOAD); info.polarity = BF_RDn(TIMROT_TIMCTRLn, timer_nr, POLARITY); info.fixed_count = BF_RDn(TIMROT_TIMCOUNTn, timer_nr, FIXED_COUNT); info.run_count = BF_RDn(TIMROT_TIMCOUNTn, timer_nr, RUNNING_COUNT); return info; }
struct imx233_pwm_info_t imx233_pwm_get_info(int channel) { #define ENTRY(mode, name, val) [BV_PWM_PERIODn_##mode##_STATE__##name] = val static char active_state[] = { ENTRY(ACTIVE, 0, '0'), ENTRY(ACTIVE, 1, '1'), ENTRY(ACTIVE, HI_Z, 'Z') }; static char inactive_state[] = { ENTRY(INACTIVE, 0, '0'), ENTRY(INACTIVE, 1, '1'), ENTRY(INACTIVE, HI_Z, 'Z') }; #undef ENTRY struct imx233_pwm_info_t info; memset(&info, 0, sizeof(info)); info.enabled = imx233_pwm_is_enabled(channel); info.cdiv = pwm_cdiv_table[BF_RDn(PWM_PERIODn, channel, CDIV)]; info.period = BF_RDn(PWM_PERIODn, channel, PERIOD) + 1; info.active = BF_RDn(PWM_ACTIVEn, channel, ACTIVE); info.inactive = BF_RDn(PWM_ACTIVEn, channel, INACTIVE); info.active_state = active_state[BF_RDn(PWM_PERIODn, channel, ACTIVE_STATE)]; info.inactive_state = inactive_state[BF_RDn(PWM_PERIODn, channel, INACTIVE_STATE)]; return info; }
int gpmi_wait_for_dma(uint32_t u32usec, uint32_t chipSelect) { reg32_t r32ChipDmaNumber = NAND0_APBH_CH; // + chipSelect; bool bTimedOut = FALSE; int rtStatus = SUCCESS; #if 1 //def RTOS_THREADX // Wait for the IRQ to unlock the spinlock. int lockResult = spinlock_lock(&g_gpmi.dmaInfo.irqSpinlock, u32usec); // Note that, in the RTOS_THREADX case, SEMA.PHORE register can easily be nonzero if the CPU is running fast. // (The DMA engine can trigger the ISR at the end of the DMA, before decrementing // the SEMA.PHORE count, thus creating a race condition that lets us find a // nonzero SEMA.PHORE value here.) // // Since SEMA.PHORE can still be nonzero, we cannot use it as // evidence of timeout. We have to rely on the RTOS timeout indicator. bTimedOut = (lockResult != 0); //( TX_SUCCESS != retCode_tx_semaphore ); #else // RTOS_THREADX not defined // Poll for DMA completion. { uint64_t u64StartTime; // Microsecond read - always read at start of transaction so that if // ThreadX times out, that time is included in the overall timeout time. u64StartTime = g_gpmi.dmaInfo.uStartDMATime; // End of DMA chain will decrement the hardware semaphore. Poll the hardware semaphore for // DMA completion. do { i32Sema = HW_APBH_CHn_SEMA_RD(r32ChipDmaNumber) & BM_APBH_CHn_SEMA_PHORE; } while ((i32Sema != 0) && ( (hw_profile_GetMicroseconds() - u64StartTime) < u32usec)); } // Re-read the hardware semaphore in case a higher-priority thread caused the timeout between semaphore // and timeout test. i32Sema = HW_APBH_CHn_SEMA_RD(r32ChipDmaNumber) & BM_APBH_CHn_SEMA_PHORE; bTimedOut = (0 != i32Sema); #endif // ifdef RTOS_THREADX // // If timeout: return error, // else: return BAR field from last DMA command // if ( bTimedOut ) { // The DMA has not completed within the alotted time. // // Clean up. //! @todo Since we don't know exactly what caused the timeout, it //! could be beneficial to also reset the GPMI block here. //! Note, however, that soft-resetting the GPMI block changes //! its register settings. Thus, it would also be necessary to //! re-initialize the GPMI settings completely. Otherwise the //! GPMI may not work. // abort dma by resetting channel // BW_APBH_CHANNEL_CTRL_RESET_CHANNEL(1 << r32ChipDmaNumber); // // // Wait for the reset to complete // while ( HW_APBH_CHANNEL_CTRL.B.RESET_CHANNEL & (0x1 << r32ChipDmaNumber) ) // { // ; // } // // // // // Okay, this is important. // // When we read from the NAND using GPMI with ECC, // // there will be an ECC interrupt upon completion of the ECC correction. // // Thereafter, these actions must happen in sequence: // // 1. ECC status must be read. // // 2. ECC ISR must be reenabled. // // 3. ECC-completion must be cleared, which frees the ECC // // block to process the next data. // // The status must be read before the ECC-completion is cleared, or // // the next ECC cycle will overwrite the status. In the case of a // // successful DMA and ECC, the code that reads the ECC status // // also performs steps 2 and 3. // // // // Q: What happens if the DMA times-out for some reason? // // A: Somebody may have to clean-up by using steps 2 and 3. // // That somebody is us. // // // // // If there was an ECC-completion expected... // if (kNandGpmiDmaWaitMask_Ecc & g_gpmi.dmaInfo.u16DmaWaitMask) // { // // ...then we have to clear the ECC-completion and the ECC circuit. // // // It is not necessary to reset the BCH block after an "uncorrectable" error. // // In fact, due to a 378x chip bug it is not possible to reset the // // BCH block after it has been used to transfer data. // // // Clear the ECC-completion. // gpmi_clear_ecc_isr_enable( ); // } rtStatus = ERROR_DDI_NAND_GPMI_DMA_TIMEOUT; } else { // The DMA descriptor chain was set up with the alternate meaning // of the BAR register. Rather than containing an // address at this point, it contains a return-code that indicates whether // the "success" or "failure" part of the chain executed last. // So, here we get that return code. rtStatus = (int)BF_RDn(APBH_CHn_BAR, r32ChipDmaNumber, ADDRESS); } return rtStatus; }
//////////////////////////////////////////////////////////////////////////////// //! See hw_lradc.h for details. //////////////////////////////////////////////////////////////////////////////// bool hw_lradc_GetToggleFlag(hw_lradc_Channel_t eChannel) { // Return the TOGGLE flag of a LRADC channel return ((bool)(BF_RDn(LRADC_CHn, eChannel, TOGGLE))); }