Beispiel #1
0
static void clock_module_disable(void)
{
	/* bit0: FSPI interface tri-state */
	IT83XX_SMFI_FLHCTRL3R |= (1 << 0);
	/* bit7: USB pad power-on disable */
	IT83XX_GCTRL_PMER2 &= ~(1 << 7);
	clock_disable_peripheral((CGC_OFFSET_EGPC | CGC_OFFSET_CIR), 0, 0);
	clock_disable_peripheral((CGC_OFFSET_SMBA | CGC_OFFSET_SMBB |
		CGC_OFFSET_SMBC | CGC_OFFSET_SMBD | CGC_OFFSET_SMBE |
		CGC_OFFSET_SMBF), 0, 0);
	clock_disable_peripheral((CGC_OFFSET_SSPI | CGC_OFFSET_PECI |
		CGC_OFFSET_USB), 0, 0);
}
Beispiel #2
0
static void adc_init(void)
{
	int i;

	/* Configure GPIOs */
	configure_gpio();

	/*
	 * Temporarily enable the PLL when turning on the clock to the ADC
	 * module, to work around chip errata (10.4).  No need to notify
	 * other modules; the PLL isn't enabled long enough to matter.
	 */
	clock_enable_pll(1, 0);

	/* Enable ADC0 module in run and sleep modes. */
	clock_enable_peripheral(CGC_OFFSET_ADC, 0x1,
			CGC_MODE_RUN | CGC_MODE_SLEEP);

	/*
	 * Use external voltage references (VREFA+, VREFA-) instead of
	 * VDDA and GNDA.
	 */
	LM4_ADC_ADCCTL = 0x01;

	/* Use internal oscillator */
	LM4_ADC_ADCCC = 0x1;

	/* Disable the PLL now that the ADC is using the internal oscillator */
	clock_enable_pll(0, 0);

	/* No tasks waiting yet */
	for (i = 0; i < LM4_ADC_SEQ_COUNT; i++)
		task_waiting_on_ss[i] = TASK_ID_INVALID;

	/* Enable IRQs */
	task_enable_irq(LM4_IRQ_ADC0_SS0);
	task_enable_irq(LM4_IRQ_ADC0_SS1);
	task_enable_irq(LM4_IRQ_ADC0_SS2);
	task_enable_irq(LM4_IRQ_ADC0_SS3);

	/* 2**6 = 64x oversampling */
	LM4_ADC_ADCSAC = 6;

	/* Initialize ADC sequencer */
	for (i = 0; i < ADC_CH_COUNT; ++i)
		adc_configure(adc_channels + i);

	/* Disable ADC0 module until it is needed to conserve power. */
	clock_disable_peripheral(CGC_OFFSET_ADC, 0x1,
			CGC_MODE_RUN | CGC_MODE_SLEEP);
}
Beispiel #3
0
int adc_read_channel(enum adc_channel ch)
{
	const struct adc_t *adc = adc_channels + ch;
	static uint32_t ch_busy_mask;
	static struct mutex adc_clock;
	int rv;

	/*
	 * TODO(crbug.com/314121): Generalize ADC reads such that any task can
	 * trigger a read of any channel.
	 */

	/*
	 * Enable ADC clock and set a bit in ch_busy_mask to signify that this
	 * channel is busy. Note, this function may be called from multiple
	 * tasks, but each channel may be read by only one task. If assert
	 * fails, then it means multiple tasks are trying to read same channel.
	 */
	mutex_lock(&adc_clock);
	ASSERT(!(ch_busy_mask & (1UL << ch)));
	clock_enable_peripheral(CGC_OFFSET_ADC, 0x1,
			CGC_MODE_RUN | CGC_MODE_SLEEP);
	ch_busy_mask |= (1UL << ch);
	mutex_unlock(&adc_clock);

	rv = flush_and_read(adc->sequencer);

	/*
	 * If no ADC channels are busy, then disable ADC clock to conserve
	 * power.
	 */
	mutex_lock(&adc_clock);
	ch_busy_mask &= ~(1UL << ch);
	if (!ch_busy_mask)
		clock_disable_peripheral(CGC_OFFSET_ADC, 0x1,
			CGC_MODE_RUN | CGC_MODE_SLEEP);
	mutex_unlock(&adc_clock);

	if (rv == ADC_READ_ERROR)
		return ADC_READ_ERROR;

	return rv * adc->factor_mul / adc->factor_div + adc->shift;
}