From fdd3d90bd78fd753356d8aa3373e066141851a35 Mon Sep 17 00:00:00 2001 From: Randall Spangler Date: Mon, 29 Oct 2012 12:56:29 -0700 Subject: Clean up ADC module ADC config structs are now chip-specific; this saves code size (several hundred bytes on LM4, since no need for 24-entry ADC channel to GPIO mapping table). BUG=chrome-os-partner:15579 BRANCH=none TEST='adc' with system on and off; ChargerCurrent should be bigger when on. Change-Id: Ia88b3f043438bec049f2d2ad39fc42dcf86d9424 Signed-off-by: Randall Spangler Reviewed-on: https://gerrit.chromium.org/gerrit/36798 --- board/bds/board.c | 4 +- board/link/board.c | 8 ++-- board/spring/board.c | 6 +-- chip/lm4/adc.c | 117 ++++++++++++++++++++----------------------------- chip/lm4/lm4_adc.h | 26 ++++++----- chip/stm32/stm32_adc.h | 9 ++++ include/adc.h | 30 ++++++------- 7 files changed, 96 insertions(+), 104 deletions(-) diff --git a/board/bds/board.c b/board/bds/board.c index 04e3d56c67..ccbe69b38c 100644 --- a/board/bds/board.c +++ b/board/bds/board.c @@ -19,7 +19,7 @@ const struct adc_t adc_channels[ADC_CH_COUNT] = { * = -225 * ADC_VALUE / ADC_READ_MAX + 420.5 */ {"ECTemp", LM4_ADC_SEQ0, -225, ADC_READ_MAX, 420, - LM4_AIN_NONE, 0x0e /* TS0 | IE0 | END0 */}, + LM4_AIN_NONE, 0x0e /* TS0 | IE0 | END0 */, 0, 0}, /* Charger current is mapped from 0~4000mA to 0~1.6V. * And ADC maps 0~3.3V to ADC_READ_MAX. @@ -28,7 +28,7 @@ const struct adc_t adc_channels[ADC_CH_COUNT] = { * board, but that's good enough for debugging the ADC. */ {"BDSPot", LM4_ADC_SEQ1, 33 * 4000, ADC_READ_MAX * 16, 0, - LM4_AIN(0), 0x06 /* IE0 | END0 */}, + LM4_AIN(0), 0x06 /* IE0 | END0 */, LM4_GPIO_E, (1<<3)}, }; diff --git a/board/link/board.c b/board/link/board.c index 5f7fbf1106..e4fbb53423 100644 --- a/board/link/board.c +++ b/board/link/board.c @@ -5,8 +5,7 @@ /* EC for Link board configuration */ #include "adc.h" -#include "board.h" -#include "config.h" +#include "common.h" #include "gpio.h" #include "i2c.h" #include "lm4_adc.h" @@ -22,7 +21,6 @@ #define power_button_interrupt NULL #endif - /* GPIO signal list. Must match order from enum gpio_signal. */ const struct gpio_info gpio_list[GPIO_COUNT] = { /* Inputs with interrupt handlers are first for efficiency */ @@ -126,13 +124,13 @@ const struct adc_t adc_channels[ADC_CH_COUNT] = { * = -225 * ADC_VALUE / ADC_READ_MAX + 420.5 */ {"ECTemp", LM4_ADC_SEQ0, -225, ADC_READ_MAX, 420, - LM4_AIN_NONE, 0x0e /* TS0 | IE0 | END0 */}, + LM4_AIN_NONE, 0x0e /* TS0 | IE0 | END0 */, 0, 0}, /* Charger current is mapped from 0~4000mA to 0~1.6V. * And ADC maps 0~3.3V to ADC_READ_MAX. */ {"ChargerCurrent", LM4_ADC_SEQ1, 33 * 4000, ADC_READ_MAX * 16, 0, - LM4_AIN(11), 0x06 /* IE0 | END0 */}, + LM4_AIN(11), 0x06 /* IE0 | END0 */, LM4_GPIO_B, (1<<5)}, }; /* I2C ports */ diff --git a/board/spring/board.c b/board/spring/board.c index 5542f2354f..9316aaad52 100644 --- a/board/spring/board.c +++ b/board/spring/board.c @@ -99,11 +99,11 @@ const struct gpio_info gpio_list[GPIO_COUNT] = { /* ADC channels */ const struct adc_t adc_channels[ADC_CH_COUNT] = { /* Micro USB ID pin. Raw ADC value. */ - [ADC_CH_USB_ID] = {"USB_ID", 0, 1, 1, 0, STM32_AIN(5), 0}, + [ADC_CH_USB_ID] = {"USB_ID", 1, 1, 0, STM32_AIN(5)}, /* Micro USB D+ sense pin. Raw ADC value. */ - [ADC_CH_USB_DP_SNS] = {"USB_DP_SNS", 0, 1, 1, 0, STM32_AIN(2), 0}, + [ADC_CH_USB_DP_SNS] = {"USB_DP_SNS", 1, 1, 0, STM32_AIN(2)}, /* Micro USB D- sense pin. Raw ADC value. */ - [ADC_CH_USB_DN_SNS] = {"USB_DN_SNS", 0, 1, 1, 0, STM32_AIN(4), 0}, + [ADC_CH_USB_DN_SNS] = {"USB_DN_SNS", 1, 1, 0, STM32_AIN(4)}, }; void configure_board(void) diff --git a/chip/lm4/adc.c b/chip/lm4/adc.c index b2d3479eef..3bac9415c5 100644 --- a/chip/lm4/adc.c +++ b/chip/lm4/adc.c @@ -16,68 +16,44 @@ #include "timer.h" #include "util.h" -extern const struct adc_t adc_channels[ADC_CH_COUNT]; - static task_id_t task_waiting_on_ss[LM4_ADC_SEQ_COUNT]; -/* GPIO port and mask for AINs. */ -const uint32_t ain_port[24][2] = { - {LM4_GPIO_E, (1<<3)}, - {LM4_GPIO_E, (1<<2)}, - {LM4_GPIO_E, (1<<1)}, - {LM4_GPIO_E, (1<<0)}, - {LM4_GPIO_D, (1<<7)}, - {LM4_GPIO_D, (1<<6)}, - {LM4_GPIO_D, (1<<5)}, - {LM4_GPIO_D, (1<<4)}, - {LM4_GPIO_E, (1<<5)}, - {LM4_GPIO_E, (1<<4)}, - {LM4_GPIO_B, (1<<4)}, - {LM4_GPIO_B, (1<<5)}, - {LM4_GPIO_D, (1<<3)}, - {LM4_GPIO_D, (1<<2)}, - {LM4_GPIO_D, (1<<1)}, - {LM4_GPIO_D, (1<<0)}, - {LM4_GPIO_K, (1<<0)}, - {LM4_GPIO_K, (1<<1)}, - {LM4_GPIO_K, (1<<2)}, - {LM4_GPIO_K, (1<<3)}, - {LM4_GPIO_E, (1<<7)}, - {LM4_GPIO_E, (1<<6)}, - {LM4_GPIO_N, (1<<1)}, - {LM4_GPIO_N, (1<<0)}, -}; - - static void configure_gpio(void) { int i; /* Use analog function for AIN */ for (i = 0; i < ADC_CH_COUNT; ++i) { - int id = adc_channels[i].channel; - if (id != LM4_AIN_NONE) - gpio_set_alternate_function(ain_port[id][0], - ain_port[id][1], + if (adc_channels[i].gpio_mask) { + gpio_set_alternate_function(adc_channels[i].gpio_port, + adc_channels[i].gpio_mask, 1); + } } } - -int lm4_adc_flush_and_read(enum lm4_adc_sequencer seq) +/** + * Flush an ADC sequencer and initiate a read. + * + * @param seq Sequencer to read + * @return Raw ADC value. + */ +static int lm4_adc_flush_and_read(enum lm4_adc_sequencer seq) { - /* TODO: right now we have only a single channel so this is - * simple. When we have multiple channels, should we... + /* + * TODO: right now we have only a single channel so this is simple. + * When we have multiple channels, should we... * - * 1) Read them all using a timer interrupt, and then return - * the most recent value? This is lowest-latency for the - * caller, but won't return accurate data if read frequently. + * 1) Read them all using a timer interrupt, and then return the most + * recent value? This is lowest-latency for the caller, but won't + * return accurate data if read frequently. * - * 2) Reserve SS3 for reading a single value, and configure it - * on each read? Needs mutex if we could have multiple - * callers; doesn't matter if just used for debugging. + * 2) Reserve SS3 for reading a single value, and configure it on each + * read? Needs mutex if we could have multiple callers; doesn't matter + * if just used for debugging. * - * 3) Both? */ + * 3) Both? + */ volatile uint32_t scratch __attribute__((unused)); int event; @@ -85,8 +61,10 @@ int lm4_adc_flush_and_read(enum lm4_adc_sequencer seq) while (!(LM4_ADC_SSFSTAT(seq) & 0x100)) scratch = LM4_ADC_SSFIFO(seq); - /* TODO: This assumes we don't have multiple tasks accessing - * the same sequencer. Add mutex lock if needed. */ + /* + * This assumes we don't have multiple tasks accessing the same + * sequencer. Add mutex lock if needed. + */ task_waiting_on_ss[seq] = task_get_current(); /* Clear the interrupt status */ @@ -105,11 +83,18 @@ int lm4_adc_flush_and_read(enum lm4_adc_sequencer seq) return LM4_ADC_SSFIFO(seq); } - -int lm4_adc_configure(enum lm4_adc_sequencer seq, - int ain_id, - int ssctl) +/** + * Configure an ADC sequencer to be dedicated for an ADC input. + * + * @param seq Sequencer to configure + * @param ain_id ADC input to use + * @param ssctl Value for sampler sequencer control register + * + */ +static void lm4_adc_configure(const struct adc_t *adc) { + const enum lm4_adc_sequencer seq = adc->sequencer; + /* Configure sample sequencer */ LM4_ADC_ADCACTSS &= ~(0x01 << seq); @@ -117,22 +102,19 @@ int lm4_adc_configure(enum lm4_adc_sequencer seq, LM4_ADC_ADCEMUX = (LM4_ADC_ADCEMUX & ~(0xf << (seq * 4))) | 0x00; /* Sample internal temp sensor */ - if (ain_id != LM4_AIN_NONE) { - LM4_ADC_SSMUX(seq) = ain_id & 0xf; - LM4_ADC_SSEMUX(seq) = ain_id >> 4; - } else { + if (adc->channel == LM4_AIN_NONE) { LM4_ADC_SSMUX(seq) = 0x00; LM4_ADC_SSEMUX(seq) = 0x00; + } else { + LM4_ADC_SSMUX(seq) = adc->channel & 0xf; + LM4_ADC_SSEMUX(seq) = adc->channel >> 4; } - LM4_ADC_SSCTL(seq) = ssctl; + LM4_ADC_SSCTL(seq) = adc->flag; /* Enable sample sequencer */ LM4_ADC_ADCACTSS |= 0x01 << seq; - - return EC_SUCCESS; } - int adc_read_channel(enum adc_channel ch) { const struct adc_t *adc = adc_channels + ch; @@ -146,7 +128,9 @@ int adc_read_channel(enum adc_channel ch) /*****************************************************************************/ /* Interrupt handlers */ -/* Handles an interrupt on the specified sample sequencer. */ +/** + * Handle an interrupt on the specified sample sequencer. + */ static void handle_interrupt(int ss) { int id = task_waiting_on_ss[ss]; @@ -159,7 +143,6 @@ static void handle_interrupt(int ss) task_wake(id); } - static void ss0_interrupt(void) { handle_interrupt(0); } static void ss1_interrupt(void) { handle_interrupt(1); } static void ss2_interrupt(void) { handle_interrupt(2); } @@ -173,7 +156,7 @@ DECLARE_IRQ(LM4_IRQ_ADC0_SS3, ss3_interrupt, 2); /*****************************************************************************/ /* Console commands */ -#ifdef CONSOLE_COMMAND_ECTEMP +#ifdef CONFIG_CMD_ECTEMP static int command_ectemp(int argc, char **argv) { int t = adc_read_channel(ADC_CH_EC_TEMP); @@ -186,7 +169,6 @@ DECLARE_CONSOLE_COMMAND(ectemp, command_ectemp, NULL); #endif - static int command_adc(int argc, char **argv) { int i; @@ -208,7 +190,6 @@ DECLARE_CONSOLE_COMMAND(adc, command_adc, static void adc_init(void) { int i; - const struct adc_t *adc; /* Configure GPIOs */ configure_gpio(); @@ -248,9 +229,7 @@ static void adc_init(void) task_enable_irq(LM4_IRQ_ADC0_SS3); /* Initialize ADC sequencer */ - for (i = 0; i < ADC_CH_COUNT; ++i) { - adc = adc_channels + i; - lm4_adc_configure(adc->sequencer, adc->channel, adc->flag); - } + for (i = 0; i < ADC_CH_COUNT; ++i) + lm4_adc_configure(adc_channels + i); } DECLARE_HOOK(HOOK_INIT, adc_init, HOOK_PRIO_DEFAULT); diff --git a/chip/lm4/lm4_adc.h b/chip/lm4/lm4_adc.h index 98f5293646..69479ac265 100644 --- a/chip/lm4/lm4_adc.h +++ b/chip/lm4/lm4_adc.h @@ -14,11 +14,25 @@ enum lm4_adc_sequencer LM4_ADC_SEQ1, LM4_ADC_SEQ2, LM4_ADC_SEQ3, - LM4_ADC_SEQ_COUNT }; -/* Minimum and maximum values returned by lm4_adc_flush_and_read(). */ +/* Data structure to define ADC channels. */ +struct adc_t { + const char *name; + enum lm4_adc_sequencer sequencer; + int factor_mul; + int factor_div; + int shift; + int channel; + int flag; + uint32_t gpio_port; + uint8_t gpio_mask; +}; + +extern const struct adc_t adc_channels[ADC_CH_COUNT]; + +/* Minimum and maximum values returned by raw ADC read. */ #define ADC_READ_MIN 0 #define ADC_READ_MAX 4095 @@ -31,12 +45,4 @@ enum lm4_adc_sequencer /* Dummy value for "channel" in adc_t if we don't have an external channel. */ #define LM4_AIN_NONE (-1) -/* Flush an ADC sequencer and initiate a read. Return raw ADC value. */ -int lm4_adc_flush_and_read(enum lm4_adc_sequencer); - -/* Configure an ADC sequencer to be dedicated for an ADC input "ain_id". - * Value in "ssctl" field is passed to sampler sequencer control register. - */ -int lm4_adc_configure(enum lm4_adc_sequencer, int ain_id, int ssctl); - #endif /* __CROS_EC_LM4_ADC_H */ diff --git a/chip/stm32/stm32_adc.h b/chip/stm32/stm32_adc.h index 01e67c603b..d67459972c 100644 --- a/chip/stm32/stm32_adc.h +++ b/chip/stm32/stm32_adc.h @@ -8,6 +8,15 @@ #ifndef __CROS_EC_STM32_ADC_H #define __CROS_EC_STM32_ADC_H +/* Data structure to define ADC channels. */ +struct adc_t { + const char *name; + int factor_mul; + int factor_div; + int shift; + int channel; +}; + extern const struct adc_t adc_channels[ADC_CH_COUNT]; /* Minimum and maximum values returned by adc_read_channel(). */ diff --git a/include/adc.h b/include/adc.h index fe1296cc3b..646298ca76 100644 --- a/include/adc.h +++ b/include/adc.h @@ -9,24 +9,24 @@ #define __CROS_EC_ADC_H #include "common.h" -#include "board.h" -/* Data structure to define ADC channels. */ -struct adc_t -{ - const char* name; - int sequencer; - int factor_mul; - int factor_div; - int shift; - int channel; - int flag; -}; - -/* Read ADC channel. */ +/** + * Read an ADC channel. + * + * @param ch Channel to read + * + * @return The scaled ADC value, or ADC_READ_ERROR if error. + */ int adc_read_channel(enum adc_channel ch); -/* Read all ADC channels. Return non-zero on error. */ +/** + * Read all ADC channels. + * + * @param data Destination array for channel data; must be + * ADC_CH_COUNT elements long. + * + * @return EC_SUCCESS, or non-zero on error. + */ int adc_read_all_channels(int *data); #endif /* __CROS_EC_ADC_H */ -- cgit v1.2.1