summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2013-06-16 20:59:36 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2013-06-17 00:29:25 +0200
commitf4fdf1ffe2189dafd1ebbbbf50f1a4626364ead3 (patch)
tree03a43c6fd5d20fd9354e34903840f7d7baffa117
parent239219ee70aa02a324fb94b6e463781c5c77beea (diff)
downloadrockbox-f4fdf1ffe2189dafd1ebbbbf50f1a4626364ead3.tar.gz
rockbox-f4fdf1ffe2189dafd1ebbbbf50f1a4626364ead3.zip
imx233: fix lradc/adc for stmp3600 and stmp3700
The lradc architecture of the stmp3600 is rather different: only channels 6 and 7 have configurable source and we need to take care when allocating channels so that we can actually measure the right channel! Delegate die temperature sensing to the power block on stmp3600. Change-Id: I0860eb4ea98240facc3d4a19d61684eca5f630cc
-rw-r--r--firmware/target/arm/imx233/adc-imx233.c19
-rw-r--r--firmware/target/arm/imx233/adc-imx233.h2
-rw-r--r--firmware/target/arm/imx233/lradc-imx233.c57
-rw-r--r--firmware/target/arm/imx233/lradc-imx233.h11
-rw-r--r--firmware/target/arm/imx233/touchscreen-imx233.c2
5 files changed, 83 insertions, 8 deletions
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 @@
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22#include "adc-imx233.h" 22#include "adc-imx233.h"
23#include "power-imx233.h"
23 24
24void adc_init(void) 25void adc_init(void)
25{ 26{
@@ -35,7 +36,7 @@ static short adc_read_physical_ex(int virt)
35 36
36static short adc_read_physical(int src, bool div2) 37static short adc_read_physical(int src, bool div2)
37{ 38{
38 int virt = imx233_lradc_acquire_channel(TIMEOUT_BLOCK); 39 int virt = imx233_lradc_acquire_channel(src, TIMEOUT_BLOCK);
39 // divide by two for wider ranger 40 // divide by two for wider ranger
40 imx233_lradc_setup_channel(virt, div2, false, 0, src); 41 imx233_lradc_setup_channel(virt, div2, false, 0, src);
41 int val = adc_read_physical_ex(virt); 42 int val = adc_read_physical_ex(virt);
@@ -52,14 +53,17 @@ static short adc_read_virtual(int c)
52 case IMX233_ADC_VDDIO: 53 case IMX233_ADC_VDDIO:
53 /* VddIO pin has a builtin 2:1 divide */ 54 /* VddIO pin has a builtin 2:1 divide */
54 return adc_read_physical(LRADC_SRC_VDDIO, false); 55 return adc_read_physical(LRADC_SRC_VDDIO, false);
56#if IMX233_SUBTARGET >= 3700
55 case IMX233_ADC_VDD5V: 57 case IMX233_ADC_VDD5V:
56 /* Vdd5V pin has a builtin 4:1 divide */ 58 /* Vdd5V pin has a builtin 4:1 divide */
57 return adc_read_physical(LRADC_SRC_5V, false) * 2; 59 return adc_read_physical(LRADC_SRC_5V, false) * 2;
60#endif
58 case IMX233_ADC_DIE_TEMP: 61 case IMX233_ADC_DIE_TEMP:
59 { 62 {
63#if IMX233_SUBTARGET >= 3700
60 // don't block on second channel otherwise we might deadlock ! 64 // don't block on second channel otherwise we might deadlock !
61 int nmos_chan = imx233_lradc_acquire_channel(TIMEOUT_BLOCK); 65 int nmos_chan = imx233_lradc_acquire_channel(LRADC_SRC_NMOS_THIN, TIMEOUT_BLOCK);
62 int pmos_chan = imx233_lradc_acquire_channel(TIMEOUT_NOBLOCK); 66 int pmos_chan = imx233_lradc_acquire_channel(LRADC_SRC_PMOS_THIN, TIMEOUT_NOBLOCK);
63 int val = 0; 67 int val = 0;
64 if(pmos_chan >= 0) 68 if(pmos_chan >= 0)
65 { 69 {
@@ -67,12 +71,19 @@ static short adc_read_virtual(int c)
67 imx233_lradc_release_channel(pmos_chan); 71 imx233_lradc_release_channel(pmos_chan);
68 } 72 }
69 imx233_lradc_release_channel(nmos_chan); 73 imx233_lradc_release_channel(nmos_chan);
74#else
75 int min, max, val;
76 if(imx233_power_sense_die_temperature(&min, &max) < 0)
77 val = -1;
78 else
79 val = (max + min) / 2;
80#endif
70 return val; 81 return val;
71 } 82 }
72#ifdef IMX233_BATT_TEMP_SENSOR 83#ifdef IMX233_BATT_TEMP_SENSOR
73 case IMX233_ADC_BATT_TEMP: 84 case IMX233_ADC_BATT_TEMP:
74 { 85 {
75 int virt = imx233_lradc_acquire_channel(TIMEOUT_BLOCK); 86 int virt = imx233_lradc_acquire_channel(IMX233_BATT_TEMP_SENSOR, TIMEOUT_BLOCK);
76 int val = imx233_lradc_sense_ext_temperature(virt, IMX233_BATT_TEMP_SENSOR); 87 int val = imx233_lradc_sense_ext_temperature(virt, IMX233_BATT_TEMP_SENSOR);
77 imx233_lradc_release_channel(virt); 88 imx233_lradc_release_channel(virt);
78 return val; 89 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 @@
31#define IMX233_ADC_BATTERY -1 /* Battery voltage (mV) */ 31#define IMX233_ADC_BATTERY -1 /* Battery voltage (mV) */
32#define IMX233_ADC_DIE_TEMP -2 /* Die temperature (°C) */ 32#define IMX233_ADC_DIE_TEMP -2 /* Die temperature (°C) */
33#define IMX233_ADC_VDDIO -3 /* VddIO voltage (mV) */ 33#define IMX233_ADC_VDDIO -3 /* VddIO voltage (mV) */
34#if IMX233_SUBTARGET >= 3700
34#define IMX233_ADC_VDD5V -4 /* Vdd5V voltage (mV) */ 35#define IMX233_ADC_VDD5V -4 /* Vdd5V voltage (mV) */
36#endif
35#ifdef IMX233_BATT_TEMP_SENSOR 37#ifdef IMX233_BATT_TEMP_SENSOR
36#define IMX233_ADC_BATT_TEMP -5 /* Battery temperature (°C) */ 38#define IMX233_ADC_BATT_TEMP -5 /* Battery temperature (°C) */
37#endif 39#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 @@
25#include "stdlib.h" 25#include "stdlib.h"
26 26
27/* channels */ 27/* channels */
28#if IMX233_SUBTARGET >= 3700
28static struct channel_arbiter_t channel_arbiter; 29static struct channel_arbiter_t channel_arbiter;
30#else
31static struct semaphore channel_sema[LRADC_NUM_CHANNELS];
32#endif
29/* delay channels */ 33/* delay channels */
30static struct channel_arbiter_t delay_arbiter; 34static struct channel_arbiter_t delay_arbiter;
31/* battery is very special, dedicate a channel and a delay to it */ 35/* battery is very special, dedicate a channel and a delay to it */
@@ -44,6 +48,7 @@ void INT_LRADC_CH(int chan)
44{ 48{
45 if(irq_cb[chan]) 49 if(irq_cb[chan])
46 irq_cb[chan](chan); 50 irq_cb[chan](chan);
51 imx233_lradc_clear_channel_irq(chan);
47} 52}
48 53
49define_cb(0) 54define_cb(0)
@@ -58,6 +63,7 @@ define_cb(7)
58void imx233_lradc_set_channel_irq_callback(int channel, lradc_irq_fn_t cb) 63void imx233_lradc_set_channel_irq_callback(int channel, lradc_irq_fn_t cb)
59{ 64{
60 irq_cb[channel] = cb; 65 irq_cb[channel] = cb;
66 imx233_icoll_enable_interrupt(INT_SRC_LRADC_CHx(channel), cb != NULL);
61} 67}
62 68
63void imx233_lradc_setup_channel(int channel, bool div2, bool acc, int nr_samples, int src) 69void 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
68 BF_SETV(LRADC_CTRL2, DIVIDE_BY_TWO, 1 << channel); 74 BF_SETV(LRADC_CTRL2, DIVIDE_BY_TWO, 1 << channel);
69 else 75 else
70 BF_CLRV(LRADC_CTRL2, DIVIDE_BY_TWO, 1 << channel); 76 BF_CLRV(LRADC_CTRL2, DIVIDE_BY_TWO, 1 << channel);
77#if IMX233_SUBTARGET >= 3700
71 HW_LRADC_CTRL4_CLR = BM_LRADC_CTRL4_LRADCxSELECT(channel); 78 HW_LRADC_CTRL4_CLR = BM_LRADC_CTRL4_LRADCxSELECT(channel);
72 HW_LRADC_CTRL4_SET = src << BP_LRADC_CTRL4_LRADCxSELECT(channel); 79 HW_LRADC_CTRL4_SET = src << BP_LRADC_CTRL4_LRADCxSELECT(channel);
80#else
81 if(channel == 6)
82 {
83 BF_CLR(LRADC_CTRL2, LRADC6SELECT);
84 BF_SETV(LRADC_CTRL2, LRADC6SELECT, src);
85 }
86 else if(channel == 7)
87 {
88 BF_CLR(LRADC_CTRL2, LRADC7SELECT);
89 BF_SETV(LRADC_CTRL2, LRADC7SELECT, src);
90 }
91 else if(channel != src)
92 panicf("cannot configure channel %d for source %d", channel, src);
93#endif
73} 94}
74 95
75void imx233_lradc_setup_delay(int dchan, int trigger_lradc, int trigger_delays, 96void imx233_lradc_setup_delay(int dchan, int trigger_lradc, int trigger_delays,
@@ -126,8 +147,10 @@ void imx233_lradc_clear_channel(int channel)
126 BF_CLRn(LRADC_CHn, channel, VALUE); 147 BF_CLRn(LRADC_CHn, channel, VALUE);
127} 148}
128 149
129int imx233_lradc_acquire_channel(int timeout) 150#if IMX233_SUBTARGET >= 3700
151int imx233_lradc_acquire_channel(int src, int timeout)
130{ 152{
153 (void) src;
131 return arbiter_acquire(&channel_arbiter, timeout); 154 return arbiter_acquire(&channel_arbiter, timeout);
132} 155}
133 156
@@ -140,6 +163,26 @@ void imx233_lradc_reserve_channel(int channel)
140{ 163{
141 return arbiter_reserve(&channel_arbiter, channel); 164 return arbiter_reserve(&channel_arbiter, channel);
142} 165}
166#else
167int imx233_lradc_acquire_channel(int src, int timeout)
168{
169 int channel = src <= LRADC_SRC_BATTERY ? src : 6;
170 if(semaphore_wait(&channel_sema[channel], timeout) == OBJ_WAIT_TIMEDOUT)
171 return -1;
172 return channel;
173}
174
175void imx233_lradc_release_channel(int chan)
176{
177 semaphore_release(&channel_sema[chan]);
178}
179
180void imx233_lradc_reserve_channel(int channel)
181{
182 if(imx233_lradc_acquire_channel(channel, 0) == -1)
183 panicf("Cannot reserve a used channel");
184}
185#endif
143 186
144int imx233_lradc_acquire_delay(int timeout) 187int imx233_lradc_acquire_delay(int timeout)
145{ 188{
@@ -156,6 +199,7 @@ void imx233_lradc_reserve_delay(int channel)
156 return arbiter_reserve(&delay_arbiter, channel); 199 return arbiter_reserve(&delay_arbiter, channel);
157} 200}
158 201
202#if IMX233_SUBTARGET >= 3700
159int imx233_lradc_sense_die_temperature(int nmos_chan, int pmos_chan) 203int imx233_lradc_sense_die_temperature(int nmos_chan, int pmos_chan)
160{ 204{
161 imx233_lradc_setup_channel(nmos_chan, false, false, 0, LRADC_SRC_NMOS_THIN); 205 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)
177 // return diff * 1.012 / 4 221 // return diff * 1.012 / 4
178 return (diff * 1012) / 4000; 222 return (diff * 1012) / 4000;
179} 223}
224#endif
180 225
181/* set to 0 to disable current source */ 226/* set to 0 to disable current source */
182static void imx233_lradc_set_temp_isrc(int sensor, int value) 227static void imx233_lradc_set_temp_isrc(int sensor, int value)
@@ -278,7 +323,15 @@ bool imx233_lradc_read_touch_detect(void)
278 323
279void imx233_lradc_init(void) 324void imx233_lradc_init(void)
280{ 325{
326 /* On STMP3700+, any channel can measure any source but on STMP3600 only
327 * channels 6 and 7 can measure all sources. Channel 7 being dedicated to
328 * battery, only channel 6 is available for free use */
329#if IMX233_SUBTARGET >= 3700
281 arbiter_init(&channel_arbiter, LRADC_NUM_CHANNELS); 330 arbiter_init(&channel_arbiter, LRADC_NUM_CHANNELS);
331#else
332 for(int i = 0; i < LRADC_NUM_CHANNELS; i++)
333 semaphore_init(&channel_sema[i], 1, 1);
334#endif
282 arbiter_init(&delay_arbiter, LRADC_NUM_DELAYS); 335 arbiter_init(&delay_arbiter, LRADC_NUM_DELAYS);
283 // enable block 336 // enable block
284 imx233_reset_block(&HW_LRADC_CTRL0); 337 imx233_reset_block(&HW_LRADC_CTRL0);
@@ -287,7 +340,9 @@ void imx233_lradc_init(void)
287 // disable temperature sensors 340 // disable temperature sensors
288 BF_CLR(LRADC_CTRL2, TEMP_SENSOR_IENABLE0); 341 BF_CLR(LRADC_CTRL2, TEMP_SENSOR_IENABLE0);
289 BF_CLR(LRADC_CTRL2, TEMP_SENSOR_IENABLE1); 342 BF_CLR(LRADC_CTRL2, TEMP_SENSOR_IENABLE1);
343#if IMX233_SUBTARGET >= 3700
290 BF_SET(LRADC_CTRL2, TEMPSENSE_PWD); 344 BF_SET(LRADC_CTRL2, TEMPSENSE_PWD);
345#endif
291 // set frequency 346 // set frequency
292 BF_CLR(LRADC_CTRL3, CYCLE_TIME); 347 BF_CLR(LRADC_CTRL3, CYCLE_TIME);
293 BF_SETV(LRADC_CTRL3, CYCLE_TIME_V, 6MHZ); 348 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 @@
55#define LRADC_SRC_NMOS_THICK LRADC_SRC(10) 55#define LRADC_SRC_NMOS_THICK LRADC_SRC(10)
56#define LRADC_SRC_PMOS_THICK LRADC_SRC(11) 56#define LRADC_SRC_PMOS_THICK LRADC_SRC(11)
57#define LRADC_SRC_PMOS_THICK LRADC_SRC(11) 57#define LRADC_SRC_PMOS_THICK LRADC_SRC(11)
58#if IMX233_SUBTARGET >= 3700
58#define LRADC_SRC_USB_DP LRADC_SRC(12) 59#define LRADC_SRC_USB_DP LRADC_SRC(12)
59#define LRADC_SRC_USB_DN LRADC_SRC(13) 60#define LRADC_SRC_USB_DN LRADC_SRC(13)
60#define LRADC_SRC_VBG LRADC_SRC(14) 61#define LRADC_SRC_VBG LRADC_SRC(14)
61#define LRADC_SRC_5V LRADC_SRC(15) 62#define LRADC_SRC_5V LRADC_SRC(15)
63#endif
62 64
63/* frequency of the delay counter */ 65/* frequency of the delay counter */
64#define LRADC_DELAY_FREQ 2000 66#define LRADC_DELAY_FREQ 2000
@@ -72,14 +74,17 @@ void imx233_lradc_setup_delay(int dchan, int trigger_lradc, int trigger_delays,
72void imx233_lradc_clear_channel_irq(int channel); 74void imx233_lradc_clear_channel_irq(int channel);
73bool imx233_lradc_read_channel_irq(int channel); 75bool imx233_lradc_read_channel_irq(int channel);
74void imx233_lradc_enable_channel_irq(int channel, bool enable); 76void imx233_lradc_enable_channel_irq(int channel, bool enable);
77/* a non-null cb will enable the icoll interrupt, a null one will disable it
78 * NOTE the channel irq is automatically cleared */
75void imx233_lradc_set_channel_irq_callback(int channel, lradc_irq_fn_t cb); 79void imx233_lradc_set_channel_irq_callback(int channel, lradc_irq_fn_t cb);
76void imx233_lradc_kick_channel(int channel); 80void imx233_lradc_kick_channel(int channel);
77void imx233_lradc_kick_delay(int dchan); 81void imx233_lradc_kick_delay(int dchan);
78void imx233_lradc_wait_channel(int channel); 82void imx233_lradc_wait_channel(int channel);
79int imx233_lradc_read_channel(int channel); 83int imx233_lradc_read_channel(int channel);
80void imx233_lradc_clear_channel(int channel); 84void imx233_lradc_clear_channel(int channel);
81// acquire a virtual channel, returns -1 on timeout, channel otherwise */ 85/* acquire a channel, returns -1 on timeout, channel otherwise
82int imx233_lradc_acquire_channel(int timeout); 86 * the returned channel is garanteed to be able measure source src */
87int imx233_lradc_acquire_channel(int src, int timeout);
83void imx233_lradc_release_channel(int chan); 88void imx233_lradc_release_channel(int chan);
84// doesn't check that channel is in use! 89// doesn't check that channel is in use!
85void imx233_lradc_reserve_channel(int channel); 90void imx233_lradc_reserve_channel(int channel);
@@ -96,9 +101,11 @@ void imx233_lradc_enable_touch_detect_irq(bool enable);
96void imx233_lradc_clear_touch_detect_irq(void); 101void imx233_lradc_clear_touch_detect_irq(void);
97bool imx233_lradc_read_touch_detect(void); 102bool imx233_lradc_read_touch_detect(void);
98 103
104#if IMX233_SUBTARGET >= 3700
99/* enable sensing and return temperature in kelvin, 105/* enable sensing and return temperature in kelvin,
100 * channels needs not to be configured */ 106 * channels needs not to be configured */
101int imx233_lradc_sense_die_temperature(int nmos_chan, int pmos_chan); 107int imx233_lradc_sense_die_temperature(int nmos_chan, int pmos_chan);
108#endif
102/* return *raw* external temperature, might need some transformation 109/* return *raw* external temperature, might need some transformation
103 * channel needs not to be configured */ 110 * channel needs not to be configured */
104int imx233_lradc_sense_ext_temperature(int chan, int sensor); 111int 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)
167 167
168void imx233_touchscreen_init(void) 168void imx233_touchscreen_init(void)
169{ 169{
170 touch_chan = imx233_lradc_acquire_channel(TIMEOUT_NOBLOCK); 170 touch_chan = imx233_lradc_acquire_channel(LRADC_SRC_XPLUS, TIMEOUT_NOBLOCK);
171 touch_delay = imx233_lradc_acquire_delay(TIMEOUT_NOBLOCK); 171 touch_delay = imx233_lradc_acquire_delay(TIMEOUT_NOBLOCK);
172 if(touch_chan < 0 || touch_delay < 0) 172 if(touch_chan < 0 || touch_delay < 0)
173 panicf("Cannot acquire channel and delays for touchscreen measurement"); 173 panicf("Cannot acquire channel and delays for touchscreen measurement");