void imx233_lradc_init(void) { arbiter_init(&channel_arbiter, HW_LRADC_NUM_CHANNELS); arbiter_init(&delay_arbiter, HW_LRADC_NUM_DELAYS); // enable block imx233_reset_block(&HW_LRADC_CTRL0); // disable ground ref __REG_CLR(HW_LRADC_CTRL0) = HW_LRADC_CTRL0__ONCHIP_GROUNDREF; // disable temperature sensors __REG_CLR(HW_LRADC_CTRL2) = HW_LRADC_CTRL2__TEMP_SENSOR_IENABLE0 | HW_LRADC_CTRL2__TEMP_SENSOR_IENABLE1; __REG_SET(HW_LRADC_CTRL2) = HW_LRADC_CTRL2__TEMPSENSE_PWD; // set frequency __REG_CLR(HW_LRADC_CTRL3) = HW_LRADC_CTRL3__CYCLE_TIME_BM; __REG_SET(HW_LRADC_CTRL3) = HW_LRADC_CTRL3__CYCLE_TIME__6MHz; // setup battery battery_chan = 7; imx233_lradc_reserve_channel(battery_chan); /* setup them for the simplest use: no accumulation, no division*/ imx233_lradc_setup_channel(battery_chan, false, false, 0, HW_LRADC_CHANNEL_BATTERY); /* setup delay channel for battery for automatic reading and scaling */ battery_delay_chan = 0; imx233_lradc_reserve_delay(battery_delay_chan); /* setup delay to trigger battery channel and retrigger itself. * The counter runs at 2KHz so a delay of 200 will trigger 10 * conversions per seconds */ imx233_lradc_setup_delay(battery_delay_chan, 1 << battery_chan, 1 << battery_delay_chan, 0, 200); imx233_lradc_kick_delay(battery_delay_chan); /* enable automatic conversion, use Li-Ion type battery */ imx233_lradc_setup_battery_conversion(true, HW_LRADC_CONVERSION__SCALE_FACTOR__LI_ION); }
void imx233_set_clock_divisor(enum imx233_clock_t clk, int div) { switch(clk) { case CLK_PIX: __REG_CLR(HW_CLKCTRL_PIX) = HW_CLKCTRL_PIX__DIV_BM; __REG_SET(HW_CLKCTRL_PIX) = div; while(HW_CLKCTRL_PIX & __CLK_BUSY); break; case CLK_SSP: __REG_CLR(HW_CLKCTRL_SSP) = HW_CLKCTRL_SSP__DIV_BM; __REG_SET(HW_CLKCTRL_SSP) = div; while(HW_CLKCTRL_SSP & __CLK_BUSY); break; case CLK_CPU: __REG_CLR(HW_CLKCTRL_CPU) = HW_CLKCTRL_CPU__DIV_CPU_BM; __REG_SET(HW_CLKCTRL_CPU) = div; while(HW_CLKCTRL_CPU & HW_CLKCTRL_CPU__BUSY_REF_CPU); break; case CLK_AHB: __REG_CLR(HW_CLKCTRL_HBUS) = HW_CLKCTRL_HBUS__DIV_BM; __REG_SET(HW_CLKCTRL_HBUS) = div; while(HW_CLKCTRL_HBUS & __CLK_BUSY); break; default: return; } }
static enum imx233_dcp_error_t imx233_dcp_job(int ch) { /* if IRQs are not enabled, don't enable channel interrupt and do some polling */ bool irq_enabled = irq_enabled(); /* enable channel, clear interrupt, enable interrupt */ imx233_icoll_enable_interrupt(INT_SRC_DCP, true); if(irq_enabled) __REG_SET(HW_DCP_CTRL) = HW_DCP_CTRL__CHANNEL_INTERRUPT_ENABLE(ch); __REG_CLR(HW_DCP_STAT) = HW_DCP_STAT__IRQ(ch); __REG_SET(HW_DCP_CHANNELCTRL) = HW_DCP_CHANNELCTRL__ENABLE_CHANNEL(ch); /* write back packet */ commit_discard_dcache_range(&channel_packet[ch], sizeof(struct imx233_dcp_packet_t)); /* write 1 to semaphore to run job */ HW_DCP_CHxCMDPTR(ch) = (uint32_t)PHYSICAL_ADDR(&channel_packet[ch]); HW_DCP_CHxSEMA(ch) = 1; /* wait completion */ if(irq_enabled) semaphore_wait(&channel_sema[ch], TIMEOUT_BLOCK); else while(__XTRACT_EX(HW_DCP_CHxSEMA(ch), HW_DCP_CHxSEMA__VALUE)) udelay(10); /* disable channel and interrupt */ __REG_CLR(HW_DCP_CTRL) = HW_DCP_CTRL__CHANNEL_INTERRUPT_ENABLE(ch); __REG_CLR(HW_DCP_CHANNELCTRL) = HW_DCP_CHANNELCTRL__ENABLE_CHANNEL(ch); /* read status */ return get_error_status(ch); }
void power_init(void) { /* setup vbusvalid parameters: set threshold to 4v and power up comparators */ __REG_CLR(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__VBUSVALID_TRSH_BM; __REG_SET(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__VBUSVALID_TRSH_4V | HW_POWER_5VCTRL__PWRUP_VBUS_CMPS; /* enable vbusvalid detection method for the dcdc (improves efficiency) */ __REG_SET(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__VBUSVALID_5VDETECT; /* clear vbusvalid irq and set correct polarity */ __REG_CLR(HW_POWER_CTRL) = HW_POWER_CTRL__VBUSVALID_IRQ; if(HW_POWER_STS & HW_POWER_STS__VBUSVALID) __REG_CLR(HW_POWER_CTRL) = HW_POWER_CTRL__POLARITY_VBUSVALID; else __REG_SET(HW_POWER_CTRL) = HW_POWER_CTRL__POLARITY_VBUSVALID; __REG_SET(HW_POWER_CTRL) = HW_POWER_CTRL__ENIRQ_VBUS_VALID; imx233_icoll_enable_interrupt(INT_SRC_VDD5V, true); /* setup linear regulator offsets to 25 mV below to prevent contention between * linear regulators and DCDC */ __FIELD_SET(HW_POWER_VDDDCTRL, LINREG_OFFSET, 2); __FIELD_SET(HW_POWER_VDDACTRL, LINREG_OFFSET, 2); __FIELD_SET(HW_POWER_VDDIOCTRL, LINREG_OFFSET, 2); /* enable a few bits controlling the DC-DC as recommended by Freescale */ __REG_SET(HW_POWER_LOOPCTRL) = HW_POWER_LOOPCTRL__TOGGLE_DIF | HW_POWER_LOOPCTRL__EN_CM_HYST; __FIELD_SET(HW_POWER_LOOPCTRL, EN_RCSCALE, HW_POWER_LOOPCTRL__EN_RCSCALE__2X); }
void imx233_lradc_setup_battery_conversion(bool automatic, unsigned long scale_factor) { __REG_CLR(HW_LRADC_CONVERSION) = HW_LRADC_CONVERSION__SCALE_FACTOR_BM; __REG_SET(HW_LRADC_CONVERSION) = scale_factor; if(automatic) __REG_SET(HW_LRADC_CONVERSION) = HW_LRADC_CONVERSION__AUTOMATIC; else __REG_CLR(HW_LRADC_CONVERSION) = HW_LRADC_CONVERSION__AUTOMATIC; }
void imx233_lcdif_dma_send(void *buf, unsigned width, unsigned height) { HW_LCDIF_CUR_BUF = (uint32_t)buf; HW_LCDIF_TRANSFER_COUNT = 0; HW_LCDIF_TRANSFER_COUNT = (height << 16) | width; __REG_CLR(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__RUN; __REG_SET(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__DATA_SELECT; __REG_SET(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__RUN; }
void imx233_lradc_setup_channel(int channel, bool div2, bool acc, int nr_samples, int src) { __REG_CLR(HW_LRADC_CHx(channel)) = HW_LRADC_CHx__NUM_SAMPLES_BM | HW_LRADC_CHx__ACCUMULATE; __REG_SET(HW_LRADC_CHx(channel)) = nr_samples << HW_LRADC_CHx__NUM_SAMPLES_BP | acc << HW_LRADC_CHx__ACCUMULATE; if(div2) __REG_SET(HW_LRADC_CTRL2) = HW_LRADC_CTRL2__DIVIDE_BY_TWO(channel); else __REG_CLR(HW_LRADC_CTRL2) = HW_LRADC_CTRL2__DIVIDE_BY_TWO(channel); __REG_CLR(HW_LRADC_CTRL4) = HW_LRADC_CTRL4__LRADCxSELECT_BM(channel); __REG_SET(HW_LRADC_CTRL4) = src << HW_LRADC_CTRL4__LRADCxSELECT_BP(channel); }
void powermgmt_init_target(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 */ __REG_SET(HW_POWER_BATTMONITOR) = HW_POWER_BATTMONITOR__ENBATADJ; /* make sure we are in a known state: disable charger and 4p2 */ __REG_SET(HW_POWER_CHARGE) = HW_POWER_CHARGE__PWD_BATTCHRG; __REG_CLR(HW_POWER_DCDC4P2) = HW_POWER_DCDC4P2__ENABLE_DCDC | HW_POWER_DCDC4P2__ENABLE_4P2; __REG_SET(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__PWD_CHARGE_4P2; charge_state = DISCHARGING; }
void imx233_enable_usb_phy(bool enable) { if(enable) { __REG_CLR(HW_USBPHY_CTRL) = __BLOCK_CLKGATE | __BLOCK_SFTRST; __REG_CLR(HW_USBPHY_PWD) = HW_USBPHY_PWD__ALL; } else { __REG_SET(HW_USBPHY_PWD) = HW_USBPHY_PWD__ALL; __REG_SET(HW_USBPHY_CTRL) = __BLOCK_CLKGATE | __BLOCK_SFTRST; } }
void imx233_lcdif_set_data_format(bool data_fmt_16, bool data_fmt_18, bool data_fmt_24) { if(data_fmt_16) __REG_SET(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__DATA_FORMAT_16_BIT; else __REG_CLR(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__DATA_FORMAT_16_BIT; if(data_fmt_18) __REG_SET(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__DATA_FORMAT_18_BIT; else __REG_CLR(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__DATA_FORMAT_18_BIT; if(data_fmt_24) __REG_SET(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__DATA_FORMAT_24_BIT; else __REG_CLR(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__DATA_FORMAT_24_BIT; }
void imx233_enable_usb_controller(bool enable) { if(enable) __REG_CLR(HW_DIGCTL_CTRL) = HW_DIGCTL_CTRL__USB_CLKGATE; else __REG_SET(HW_DIGCTL_CTRL) = HW_DIGCTL_CTRL__USB_CLKGATE; }
void imx233_softirq(int src, bool enable) { if(enable) __REG_SET(HW_ICOLL_INTERRUPT(src)) = HW_ICOLL_INTERRUPT__SOFTIRQ; else __REG_CLR(HW_ICOLL_INTERRUPT(src)) = HW_ICOLL_INTERRUPT__SOFTIRQ; }
void imx233_enable_interrupt(int src, bool enable) { if(enable) __REG_SET(HW_ICOLL_INTERRUPT(src)) = HW_ICOLL_INTERRUPT__ENABLE; else __REG_CLR(HW_ICOLL_INTERRUPT(src)) = HW_ICOLL_INTERRUPT__ENABLE; }
void imx233_enable_xtal_clock(enum imx233_xtal_clkt_t xtal_clk, bool enable) { if(enable) __REG_CLR(HW_CLKCTRL_XTAL) = xtal_clk; else __REG_SET(HW_CLKCTRL_XTAL) = xtal_clk; }
void imx233_enable_timrot_xtal_clk32k(bool enable) { if(enable) __REG_CLR(HW_CLKCTRL_XTAL) = HW_CLKCTRL_XTAL__TIMROT_CLK32K_GATE; else __REG_SET(HW_CLKCTRL_XTAL) = HW_CLKCTRL_XTAL__TIMROT_CLK32K_GATE; }
void imx233_lcdif_enable(bool enable) { if(enable) __REG_CLR(HW_LCDIF_CTRL) = __BLOCK_CLKGATE; else __REG_SET(HW_LCDIF_CTRL) = __BLOCK_CLKGATE; }
void imx233_lcdif_enable_bus_master(bool enable) { if(enable) __REG_SET(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__LCDIF_MASTER; else __REG_CLR(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__LCDIF_MASTER; }
void imx233_enable_usb_pll(bool enable) { if(enable) __REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS; else __REG_CLR(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS; }
void imx233_lradc_init(void) { mutex_init(&free_bm_mutex); semaphore_init(&free_bm_sema, HW_LRADC_NUM_CHANNELS, HW_LRADC_NUM_CHANNELS); free_bm = (1 << HW_LRADC_NUM_CHANNELS) - 1; // enable block imx233_reset_block(&HW_LRADC_CTRL0); // disable ground ref __REG_CLR(HW_LRADC_CTRL0) = HW_LRADC_CTRL0__ONCHIP_GROUNDREF; // disable temperature sensors __REG_CLR(HW_LRADC_CTRL2) = HW_LRADC_CTRL2__TEMP_SENSOR_IENABLE0 | HW_LRADC_CTRL2__TEMP_SENSOR_IENABLE1; __REG_SET(HW_LRADC_CTRL2) = HW_LRADC_CTRL2__TEMPSENSE_PWD; // set frequency __REG_CLR(HW_LRADC_CTRL3) = HW_LRADC_CTRL3__CYCLE_TIME_BM; __REG_SET(HW_LRADC_CTRL3) = HW_LRADC_CTRL3__CYCLE_TIME__6MHz; }
void imx233_audioin_close(void) { /* TODO mute */ /* Gate off ADC */ __REG_SET(HW_AUDIOIN_ANACLKCTRL) = HW_AUDIOIN_ANACLKCTRL__CLKGATE; /* will also gate off the module */ __REG_CLR(HW_AUDIOIN_CTRL) = HW_AUDIOIN_CTRL__RUN; }
void imx233_lradc_enable_channel_irq(int channel, bool enable) { if(enable) __REG_SET(HW_LRADC_CTRL1) = HW_LRADC_CTRL1__LRADCx_IRQ_EN(channel); else __REG_CLR(HW_LRADC_CTRL1) = HW_LRADC_CTRL1__LRADCx_IRQ_EN(channel); imx233_lradc_clear_channel_irq(channel); }
void imx233_lradc_init(void) { if (!g_f_is_initialised) { g_f_is_initialised = 1; // enable block imx233_reset_block(&HW_LRADC_CTRL0); // disable ground ref __REG_CLR(HW_LRADC_CTRL0) = HW_LRADC_CTRL0__ONCHIP_GROUNDREF; // disable temperature sensors __REG_CLR(HW_LRADC_CTRL2) = HW_LRADC_CTRL2__TEMP_SENSOR_IENABLE0 | HW_LRADC_CTRL2__TEMP_SENSOR_IENABLE1; __REG_SET(HW_LRADC_CTRL2) = HW_LRADC_CTRL2__TEMPSENSE_PWD; // set frequency __REG_CLR(HW_LRADC_CTRL3) = HW_LRADC_CTRL3__CYCLE_TIME_BM; __REG_SET(HW_LRADC_CTRL3) = HW_LRADC_CTRL3__CYCLE_TIME__6MHz; } }
void imx233_audioin_preinit(void) { /* Enable AUDIOIN block */ imx233_reset_block(&HW_AUDIOIN_CTRL); /* Enable ADC */ __REG_CLR(HW_AUDIOIN_ANACLKCTRL) = HW_AUDIOIN_ANACLKCTRL__CLKGATE; /* Set word-length to 16-bit */ __REG_SET(HW_AUDIOIN_CTRL) = HW_AUDIOIN_CTRL__WORD_LENGTH; }
/* set to 0 to disable current source */ static void imx233_lradc_set_temp_isrc(int sensor, int value) { if(sensor < 0 || sensor > 1) panicf("imx233_lradc_set_temp_isrc: invalid sensor"); unsigned mask = HW_LRADC_CTRL2__TEMP_ISRCx_BM(sensor); unsigned bp = HW_LRADC_CTRL2__TEMP_ISRCx_BP(sensor); unsigned en = HW_LRADC_CTRL2__TEMP_SENSOR_IENABLEx(sensor); __REG_CLR(HW_LRADC_CTRL2) = mask; __REG_SET(HW_LRADC_CTRL2) = value << bp; if(value != 0) { __REG_SET(HW_LRADC_CTRL2) = en; udelay(100); } else __REG_CLR(HW_LRADC_CTRL2) = en; }
void dma_clkgate_channel(unsigned chan, bool enable_clock) { if(APB_IS_APBX_CHANNEL(chan)) return; if(enable_clock) __REG_CLR(HW_APBH_CTRL0) = HW_APBH_CTRL0__CLKGATE_CHANNEL(APB_GET_DMA_CHANNEL(chan)); else __REG_SET(HW_APBH_CTRL0) = HW_APBH_CTRL0__CLKGATE_CHANNEL(APB_GET_DMA_CHANNEL(chan)); }
void imx233_power_set_charge_current(unsigned current) { __REG_CLR(HW_POWER_CHARGE) = HW_POWER_CHARGE__BATTCHRG_I_BM; /* 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; __REG_SET(HW_POWER_CHARGE) = g_charger_current_bits[i].bit; } }
void imx233_lcdif_pio_send(bool data_mode, unsigned len, uint32_t *buf) { unsigned max_xfer_size = 0xffff; if(len == 0) return; if(lcdif_word_length == HW_LCDIF_CTRL__WORD_LENGTH_16_BIT) max_xfer_size = 0x1fffe; imx233_lcdif_wait_ready(); unsigned msk = imx233_lcdif_enable_irqs(0); imx233_lcdif_enable_bus_master(false); do { unsigned burst = MIN(len, max_xfer_size); len -= burst; unsigned count = burst; if(lcdif_word_length != HW_LCDIF_CTRL__WORD_LENGTH_8_BIT) { if(burst & 1) burst++; count = burst / 2; } else count = burst; HW_LCDIF_TRANSFER_COUNT = 0; HW_LCDIF_TRANSFER_COUNT = 0x10000 | count; __REG_CLR(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__DATA_SELECT | HW_LCDIF_CTRL__RUN; if(data_mode) __REG_SET(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__DATA_SELECT; __REG_SET(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__RUN; burst = (burst + 3) / 4; while(burst-- > 0) { while(HW_LCDIF_STAT & HW_LCDIF_STAT__LFIFO_FULL); HW_LCDIF_DATA = *buf++; } while(HW_LCDIF_CTRL & HW_LCDIF_CTRL__RUN); }while(len > 0); imx233_lcdif_enable_bus_master(true); imx233_lcdif_enable_irqs(msk); }
void imx233_dcp_init(void) { /* Reset block */ imx233_reset_block(&HW_DCP_CTRL); /* Setup contexte pointer */ HW_DCP_CONTEXT = (uint32_t)PHYSICAL_ADDR(&dcp_context); /* Enable context switching and caching */ __REG_SET(HW_DCP_CTRL) = HW_DCP_CTRL__ENABLE_CONTEXT_CACHING | HW_DCP_CTRL__ENABLE_CONTEXT_SWITCHING; /* Check that there are sufficiently many channels */ if(__XTRACT(HW_DCP_CAPABILITY0, NUM_CHANNELS) != HW_DCP_NUM_CHANNELS) panicf("DCP has %lu channels but was configured to use %d !", __XTRACT(HW_DCP_CAPABILITY0, NUM_CHANNELS), HW_DCP_NUM_CHANNELS); /* Setup channel arbiter to use */ arbiter_init(&channel_arbiter, HW_DCP_NUM_CHANNELS); /* Merge channel0 interrupt */ __REG_SET(HW_DCP_CHANNELCTRL) = HW_DCP_CHANNELCTRL__CH0_IRQ_MERGED; /* setup semaphores */ for(int i = 0; i< HW_DCP_NUM_CHANNELS; i++) semaphore_init(&channel_sema[i], 1, 0); }
unsigned imx233_lcdif_enable_irqs(unsigned irq_bm) { unsigned old_msk = __XTRACT(HW_LCDIF_CTRL1, IRQ_EN); /* clear irq status */ __REG_CLR(HW_LCDIF_CTRL1) = irq_bm << HW_LCDIF_CTRL1__IRQ_BP; /* disable irqs */ __REG_CLR(HW_LCDIF_CTRL1) = HW_LCDIF_CTRL1__IRQ_EN_BM; /* enable irqs */ __REG_SET(HW_LCDIF_CTRL1) = irq_bm << HW_LCDIF_CTRL1__IRQ_EN_BP; return old_msk; }
void imx233_setup_pin_irq(int bank, int pin, bool enable_int, bool level, bool polarity, pin_irq_cb_t cb) { __REG_CLR(HW_PINCTRL_PIN2IRQ(bank)) = 1 << pin; __REG_CLR(HW_PINCTRL_IRQEN(bank)) = 1 << pin; __REG_CLR(HW_PINCTRL_IRQSTAT(bank))= 1 << pin; pin_cb[bank][pin] = cb; if(enable_int) { if(level) __REG_SET(HW_PINCTRL_IRQLEVEL(bank)) = 1 << pin; else __REG_CLR(HW_PINCTRL_IRQLEVEL(bank)) = 1 << pin; if(polarity) __REG_SET(HW_PINCTRL_IRQPOL(bank)) = 1 << pin; else __REG_CLR(HW_PINCTRL_IRQPOL(bank)) = 1 << pin; __REG_SET(HW_PINCTRL_PIN2IRQ(bank)) = 1 << pin; __REG_SET(HW_PINCTRL_IRQEN(bank)) = 1 << pin; imx233_enable_interrupt(INT_SRC_GPIO(bank), true); } }