summaryrefslogtreecommitdiffstats
path: root/firmware/target/arm/imx233/lradc-imx233.c
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2012-03-17 17:39:27 +0100
committerAmaury Pouly <amaury.pouly@gmail.com>2012-03-17 17:42:49 +0100
commite5b5041583e389e6866b210683a09c97a10077d3 (patch)
tree256bc4b1f0fbccce21295afbda907988be78f3bb /firmware/target/arm/imx233/lradc-imx233.c
parent7676dae3e0f279d4b193f1c9abf8977c8f52e5d2 (diff)
downloadrockbox-e5b5041583e389e6866b210683a09c97a10077d3.tar.gz
rockbox-e5b5041583e389e6866b210683a09c97a10077d3.tar.bz2
rockbox-e5b5041583e389e6866b210683a09c97a10077d3.zip
imx233/fuze+: rework lradc/adc code, add external temperature sensing(battery)
Rework code to be more useful: - move battery channel init to lradc - always init lradc from system (previously from adc) - don't reserve channels for vddio, nmos or pmos - implement external temperature sensing using current source - use this for battery sensing on the Fuze+ (calibration needed) Change-Id: I5f9a24b9243db7d1e6bdb16b84bc891e61d0c318
Diffstat (limited to 'firmware/target/arm/imx233/lradc-imx233.c')
-rw-r--r--firmware/target/arm/imx233/lradc-imx233.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/firmware/target/arm/imx233/lradc-imx233.c b/firmware/target/arm/imx233/lradc-imx233.c
index 432d1c1035..4d309b0875 100644
--- a/firmware/target/arm/imx233/lradc-imx233.c
+++ b/firmware/target/arm/imx233/lradc-imx233.c
@@ -27,6 +27,9 @@
static struct channel_arbiter_t channel_arbiter;
/* delay channels */
static struct channel_arbiter_t delay_arbiter;
+/* battery is very special, dedicate a channel and a delay to it */
+static int battery_chan;
+static int battery_delay_chan;
void imx233_lradc_setup_channel(int channel, bool div2, bool acc, int nr_samples, int src)
{
@@ -111,6 +114,8 @@ void imx233_lradc_reserve_delay(int channel)
int imx233_lradc_sense_die_temperature(int nmos_chan, int pmos_chan)
{
+ imx233_lradc_setup_channel(nmos_chan, false, false, 0, HW_LRADC_CHANNEL_NMOS_THIN);
+ imx233_lradc_setup_channel(pmos_chan, false, false, 0, HW_LRADC_CHANNEL_PMOS_THIN);
// mux sensors
__REG_CLR(HW_LRADC_CTRL2) = HW_LRADC_CTRL2__TEMPSENSE_PWD;
imx233_lradc_clear_channel(nmos_chan);
@@ -129,6 +134,60 @@ int imx233_lradc_sense_die_temperature(int nmos_chan, int pmos_chan)
return (diff * 1012) / 4000;
}
+/* 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;
+}
+
+int imx233_lradc_sense_ext_temperature(int chan, int sensor)
+{
+#define EXT_TEMP_ACC_COUNT 5
+ /* setup channel */
+ imx233_lradc_setup_channel(chan, false, false, 0, sensor);
+ /* set current source to 300µA */
+ imx233_lradc_set_temp_isrc(sensor, HW_LRADC_CTRL2__TEMP_ISRC__300uA);
+ /* read value and accumulate */
+ int a = 0;
+ for(int i = 0; i < EXT_TEMP_ACC_COUNT; i++)
+ {
+ imx233_lradc_clear_channel(chan);
+ imx233_lradc_kick_channel(chan);
+ imx233_lradc_wait_channel(chan);
+ a += imx233_lradc_read_channel(chan);
+ }
+ /* setup channel for small accumulation */
+ /* set current source to 20µA */
+ imx233_lradc_set_temp_isrc(sensor, HW_LRADC_CTRL2__TEMP_ISRC__20uA);
+ /* read value */
+ int b = 0;
+ for(int i = 0; i < EXT_TEMP_ACC_COUNT; i++)
+ {
+ imx233_lradc_clear_channel(chan);
+ imx233_lradc_kick_channel(chan);
+ imx233_lradc_wait_channel(chan);
+ b += imx233_lradc_read_channel(chan);
+ }
+ /* disable sensor current */
+ imx233_lradc_set_temp_isrc(sensor, HW_LRADC_CTRL2__TEMP_ISRC__0uA);
+
+ return (b - a) / EXT_TEMP_ACC_COUNT;
+}
+
void imx233_lradc_setup_battery_conversion(bool automatic, unsigned long scale_factor)
{
__REG_CLR(HW_LRADC_CONVERSION) = HW_LRADC_CONVERSION__SCALE_FACTOR_BM;
@@ -159,4 +218,20 @@ void imx233_lradc_init(void)
// 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);
}