diff --git a/firmware/target/arm/imx233/adc-imx233.c b/firmware/target/arm/imx233/adc-imx233.c index 9b5af82d5d..a6025cfde9 100644 --- a/firmware/target/arm/imx233/adc-imx233.c +++ b/firmware/target/arm/imx233/adc-imx233.c @@ -20,6 +20,7 @@ ****************************************************************************/ #include "adc-imx233.h" +#include "power-imx233.h" void adc_init(void) { @@ -35,7 +36,7 @@ static short adc_read_physical_ex(int virt) static short adc_read_physical(int src, bool div2) { - int virt = imx233_lradc_acquire_channel(TIMEOUT_BLOCK); + int virt = imx233_lradc_acquire_channel(src, TIMEOUT_BLOCK); // divide by two for wider ranger imx233_lradc_setup_channel(virt, div2, false, 0, src); int val = adc_read_physical_ex(virt); @@ -52,14 +53,17 @@ static short adc_read_virtual(int c) case IMX233_ADC_VDDIO: /* VddIO pin has a builtin 2:1 divide */ return adc_read_physical(LRADC_SRC_VDDIO, false); +#if IMX233_SUBTARGET >= 3700 case IMX233_ADC_VDD5V: /* Vdd5V pin has a builtin 4:1 divide */ return adc_read_physical(LRADC_SRC_5V, false) * 2; +#endif case IMX233_ADC_DIE_TEMP: { +#if IMX233_SUBTARGET >= 3700 // don't block on second channel otherwise we might deadlock ! - int nmos_chan = imx233_lradc_acquire_channel(TIMEOUT_BLOCK); - int pmos_chan = imx233_lradc_acquire_channel(TIMEOUT_NOBLOCK); + int nmos_chan = imx233_lradc_acquire_channel(LRADC_SRC_NMOS_THIN, TIMEOUT_BLOCK); + int pmos_chan = imx233_lradc_acquire_channel(LRADC_SRC_PMOS_THIN, TIMEOUT_NOBLOCK); int val = 0; if(pmos_chan >= 0) { @@ -67,12 +71,19 @@ static short adc_read_virtual(int c) imx233_lradc_release_channel(pmos_chan); } imx233_lradc_release_channel(nmos_chan); +#else + int min, max, val; + if(imx233_power_sense_die_temperature(&min, &max) < 0) + val = -1; + else + val = (max + min) / 2; +#endif return val; } #ifdef IMX233_BATT_TEMP_SENSOR case IMX233_ADC_BATT_TEMP: { - int virt = imx233_lradc_acquire_channel(TIMEOUT_BLOCK); + int virt = imx233_lradc_acquire_channel(IMX233_BATT_TEMP_SENSOR, TIMEOUT_BLOCK); int val = imx233_lradc_sense_ext_temperature(virt, IMX233_BATT_TEMP_SENSOR); imx233_lradc_release_channel(virt); return val; diff --git a/firmware/target/arm/imx233/adc-imx233.h b/firmware/target/arm/imx233/adc-imx233.h index 09fd7eb013..f833e17be0 100644 --- a/firmware/target/arm/imx233/adc-imx233.h +++ b/firmware/target/arm/imx233/adc-imx233.h @@ -31,7 +31,9 @@ #define IMX233_ADC_BATTERY -1 /* Battery voltage (mV) */ #define IMX233_ADC_DIE_TEMP -2 /* Die temperature (°C) */ #define IMX233_ADC_VDDIO -3 /* VddIO voltage (mV) */ +#if IMX233_SUBTARGET >= 3700 #define IMX233_ADC_VDD5V -4 /* Vdd5V voltage (mV) */ +#endif #ifdef IMX233_BATT_TEMP_SENSOR #define IMX233_ADC_BATT_TEMP -5 /* Battery temperature (°C) */ #endif diff --git a/firmware/target/arm/imx233/lradc-imx233.c b/firmware/target/arm/imx233/lradc-imx233.c index 4fe05f36f7..d95a002663 100644 --- a/firmware/target/arm/imx233/lradc-imx233.c +++ b/firmware/target/arm/imx233/lradc-imx233.c @@ -25,7 +25,11 @@ #include "stdlib.h" /* channels */ +#if IMX233_SUBTARGET >= 3700 static struct channel_arbiter_t channel_arbiter; +#else +static struct semaphore channel_sema[LRADC_NUM_CHANNELS]; +#endif /* delay channels */ static struct channel_arbiter_t delay_arbiter; /* battery is very special, dedicate a channel and a delay to it */ @@ -44,6 +48,7 @@ void INT_LRADC_CH(int chan) { if(irq_cb[chan]) irq_cb[chan](chan); + imx233_lradc_clear_channel_irq(chan); } define_cb(0) @@ -58,6 +63,7 @@ define_cb(7) void imx233_lradc_set_channel_irq_callback(int channel, lradc_irq_fn_t cb) { irq_cb[channel] = cb; + imx233_icoll_enable_interrupt(INT_SRC_LRADC_CHx(channel), cb != NULL); } void imx233_lradc_setup_channel(int channel, bool div2, bool acc, int nr_samples, int src) @@ -68,8 +74,23 @@ void imx233_lradc_setup_channel(int channel, bool div2, bool acc, int nr_samples BF_SETV(LRADC_CTRL2, DIVIDE_BY_TWO, 1 << channel); else BF_CLRV(LRADC_CTRL2, DIVIDE_BY_TWO, 1 << channel); +#if IMX233_SUBTARGET >= 3700 HW_LRADC_CTRL4_CLR = BM_LRADC_CTRL4_LRADCxSELECT(channel); HW_LRADC_CTRL4_SET = src << BP_LRADC_CTRL4_LRADCxSELECT(channel); +#else + if(channel == 6) + { + BF_CLR(LRADC_CTRL2, LRADC6SELECT); + BF_SETV(LRADC_CTRL2, LRADC6SELECT, src); + } + else if(channel == 7) + { + BF_CLR(LRADC_CTRL2, LRADC7SELECT); + BF_SETV(LRADC_CTRL2, LRADC7SELECT, src); + } + else if(channel != src) + panicf("cannot configure channel %d for source %d", channel, src); +#endif } void imx233_lradc_setup_delay(int dchan, int trigger_lradc, int trigger_delays, @@ -126,8 +147,10 @@ void imx233_lradc_clear_channel(int channel) BF_CLRn(LRADC_CHn, channel, VALUE); } -int imx233_lradc_acquire_channel(int timeout) +#if IMX233_SUBTARGET >= 3700 +int imx233_lradc_acquire_channel(int src, int timeout) { + (void) src; return arbiter_acquire(&channel_arbiter, timeout); } @@ -140,6 +163,26 @@ void imx233_lradc_reserve_channel(int channel) { return arbiter_reserve(&channel_arbiter, channel); } +#else +int imx233_lradc_acquire_channel(int src, int timeout) +{ + int channel = src <= LRADC_SRC_BATTERY ? src : 6; + if(semaphore_wait(&channel_sema[channel], timeout) == OBJ_WAIT_TIMEDOUT) + return -1; + return channel; +} + +void imx233_lradc_release_channel(int chan) +{ + semaphore_release(&channel_sema[chan]); +} + +void imx233_lradc_reserve_channel(int channel) +{ + if(imx233_lradc_acquire_channel(channel, 0) == -1) + panicf("Cannot reserve a used channel"); +} +#endif int imx233_lradc_acquire_delay(int timeout) { @@ -156,6 +199,7 @@ void imx233_lradc_reserve_delay(int channel) return arbiter_reserve(&delay_arbiter, channel); } +#if IMX233_SUBTARGET >= 3700 int imx233_lradc_sense_die_temperature(int nmos_chan, int pmos_chan) { imx233_lradc_setup_channel(nmos_chan, false, false, 0, LRADC_SRC_NMOS_THIN); @@ -177,6 +221,7 @@ int imx233_lradc_sense_die_temperature(int nmos_chan, int pmos_chan) // return diff * 1.012 / 4 return (diff * 1012) / 4000; } +#endif /* set to 0 to disable current source */ static void imx233_lradc_set_temp_isrc(int sensor, int value) @@ -278,7 +323,15 @@ bool imx233_lradc_read_touch_detect(void) void imx233_lradc_init(void) { + /* On STMP3700+, any channel can measure any source but on STMP3600 only + * channels 6 and 7 can measure all sources. Channel 7 being dedicated to + * battery, only channel 6 is available for free use */ +#if IMX233_SUBTARGET >= 3700 arbiter_init(&channel_arbiter, LRADC_NUM_CHANNELS); +#else + for(int i = 0; i < LRADC_NUM_CHANNELS; i++) + semaphore_init(&channel_sema[i], 1, 1); +#endif arbiter_init(&delay_arbiter, LRADC_NUM_DELAYS); // enable block imx233_reset_block(&HW_LRADC_CTRL0); @@ -287,7 +340,9 @@ void imx233_lradc_init(void) // disable temperature sensors BF_CLR(LRADC_CTRL2, TEMP_SENSOR_IENABLE0); BF_CLR(LRADC_CTRL2, TEMP_SENSOR_IENABLE1); +#if IMX233_SUBTARGET >= 3700 BF_SET(LRADC_CTRL2, TEMPSENSE_PWD); +#endif // set frequency BF_CLR(LRADC_CTRL3, CYCLE_TIME); BF_SETV(LRADC_CTRL3, CYCLE_TIME_V, 6MHZ); diff --git a/firmware/target/arm/imx233/lradc-imx233.h b/firmware/target/arm/imx233/lradc-imx233.h index d1529f4266..f274db3520 100644 --- a/firmware/target/arm/imx233/lradc-imx233.h +++ b/firmware/target/arm/imx233/lradc-imx233.h @@ -55,10 +55,12 @@ #define LRADC_SRC_NMOS_THICK LRADC_SRC(10) #define LRADC_SRC_PMOS_THICK LRADC_SRC(11) #define LRADC_SRC_PMOS_THICK LRADC_SRC(11) +#if IMX233_SUBTARGET >= 3700 #define LRADC_SRC_USB_DP LRADC_SRC(12) #define LRADC_SRC_USB_DN LRADC_SRC(13) #define LRADC_SRC_VBG LRADC_SRC(14) #define LRADC_SRC_5V LRADC_SRC(15) +#endif /* frequency of the delay counter */ #define LRADC_DELAY_FREQ 2000 @@ -72,14 +74,17 @@ void imx233_lradc_setup_delay(int dchan, int trigger_lradc, int trigger_delays, void imx233_lradc_clear_channel_irq(int channel); bool imx233_lradc_read_channel_irq(int channel); void imx233_lradc_enable_channel_irq(int channel, bool enable); +/* a non-null cb will enable the icoll interrupt, a null one will disable it + * NOTE the channel irq is automatically cleared */ void imx233_lradc_set_channel_irq_callback(int channel, lradc_irq_fn_t cb); void imx233_lradc_kick_channel(int channel); void imx233_lradc_kick_delay(int dchan); void imx233_lradc_wait_channel(int channel); int imx233_lradc_read_channel(int channel); void imx233_lradc_clear_channel(int channel); -// acquire a virtual channel, returns -1 on timeout, channel otherwise */ -int imx233_lradc_acquire_channel(int timeout); +/* acquire a channel, returns -1 on timeout, channel otherwise + * the returned channel is garanteed to be able measure source src */ +int imx233_lradc_acquire_channel(int src, int timeout); void imx233_lradc_release_channel(int chan); // doesn't check that channel is in use! void imx233_lradc_reserve_channel(int channel); @@ -96,9 +101,11 @@ void imx233_lradc_enable_touch_detect_irq(bool enable); void imx233_lradc_clear_touch_detect_irq(void); bool imx233_lradc_read_touch_detect(void); +#if IMX233_SUBTARGET >= 3700 /* enable sensing and return temperature in kelvin, * channels needs not to be configured */ int imx233_lradc_sense_die_temperature(int nmos_chan, int pmos_chan); +#endif /* return *raw* external temperature, might need some transformation * channel needs not to be configured */ int imx233_lradc_sense_ext_temperature(int chan, int sensor); diff --git a/firmware/target/arm/imx233/touchscreen-imx233.c b/firmware/target/arm/imx233/touchscreen-imx233.c index 4f35110df7..e76d7a49e3 100644 --- a/firmware/target/arm/imx233/touchscreen-imx233.c +++ b/firmware/target/arm/imx233/touchscreen-imx233.c @@ -167,7 +167,7 @@ static void touch_channel_irq(int chan) void imx233_touchscreen_init(void) { - touch_chan = imx233_lradc_acquire_channel(TIMEOUT_NOBLOCK); + touch_chan = imx233_lradc_acquire_channel(LRADC_SRC_XPLUS, TIMEOUT_NOBLOCK); touch_delay = imx233_lradc_acquire_delay(TIMEOUT_NOBLOCK); if(touch_chan < 0 || touch_delay < 0) panicf("Cannot acquire channel and delays for touchscreen measurement");