summaryrefslogtreecommitdiff
path: root/firmware/target/arm
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm')
-rw-r--r--firmware/target/arm/imx31/debug-imx31.c26
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/adc-imx31.c103
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/adc-target.h29
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c40
4 files changed, 145 insertions, 53 deletions
diff --git a/firmware/target/arm/imx31/debug-imx31.c b/firmware/target/arm/imx31/debug-imx31.c
index 7f1c9166d6..94df64b6d7 100644
--- a/firmware/target/arm/imx31/debug-imx31.c
+++ b/firmware/target/arm/imx31/debug-imx31.c
@@ -25,6 +25,7 @@
25#include "font.h" 25#include "font.h"
26#include "debug-target.h" 26#include "debug-target.h"
27#include "mc13783.h" 27#include "mc13783.h"
28#include "adc.h"
28 29
29bool __dbg_hw_info(void) 30bool __dbg_hw_info(void)
30{ 31{
@@ -47,11 +48,6 @@ bool __dbg_ports(void)
47 MC13783_RTC_ALARM, 48 MC13783_RTC_ALARM,
48 MC13783_RTC_DAY, 49 MC13783_RTC_DAY,
49 MC13783_RTC_DAY_ALARM, 50 MC13783_RTC_DAY_ALARM,
50 MC13783_ADC0,
51 MC13783_ADC1,
52 MC13783_ADC2,
53 MC13783_ADC3,
54 MC13783_ADC4,
55 }; 51 };
56 52
57 static const char *pmic_regnames[ARRAYLEN(pmic_regset)] = 53 static const char *pmic_regnames[ARRAYLEN(pmic_regset)] =
@@ -64,11 +60,6 @@ bool __dbg_ports(void)
64 "RTC Alarm ", 60 "RTC Alarm ",
65 "RTC Day ", 61 "RTC Day ",
66 "RTC Day Al", 62 "RTC Day Al",
67 "ADC0 ",
68 "ADC1 ",
69 "ADC2 ",
70 "ADC3 ",
71 "ADC4 ",
72 }; 63 };
73 64
74 uint32_t pmic_regs[ARRAYLEN(pmic_regset)]; 65 uint32_t pmic_regs[ARRAYLEN(pmic_regset)];
@@ -132,6 +123,21 @@ bool __dbg_ports(void)
132 lcd_puts(0, line++, buf); 123 lcd_puts(0, line++, buf);
133 } 124 }
134 125
126 line++;
127
128 lcd_puts(0, line++, "ADC"); line++;
129
130 for (i = 0; i < NUM_ADC_CHANNELS; i += 4)
131 {
132 snprintf(buf, sizeof(buf),
133 "CH%02d:%04u CH%02d:%04u CH%02d:%04u CH%02d:%04u",
134 i+0, adc_read(i+0),
135 i+1, adc_read(i+1),
136 i+2, adc_read(i+2),
137 i+3, adc_read(i+3));
138 lcd_puts(0, line++, buf);
139 }
140
135 lcd_update(); 141 lcd_update();
136 if (button_get_w_tmo(HZ/10) == (DEBUG_CANCEL|BUTTON_REL)) 142 if (button_get_w_tmo(HZ/10) == (DEBUG_CANCEL|BUTTON_REL))
137 return false; 143 return false;
diff --git a/firmware/target/arm/imx31/gigabeat-s/adc-imx31.c b/firmware/target/arm/imx31/gigabeat-s/adc-imx31.c
index 1fd2247ef1..b1b79a7989 100644
--- a/firmware/target/arm/imx31/gigabeat-s/adc-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/adc-imx31.c
@@ -7,7 +7,7 @@
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2006 by Wade Brown 10 * Copyright (C) 2008 by Michael Sevakis
11 * 11 *
12 * All files in this archive are subject to the GNU General Public License. 12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement. 13 * See the file COPYING in the source tree root for full license agreement.
@@ -16,37 +16,96 @@
16 * KIND, either express or implied. 16 * KIND, either express or implied.
17 * 17 *
18 ****************************************************************************/ 18 ****************************************************************************/
19#include "cpu.h" 19#include "config.h"
20#include "system.h"
21#include "mc13783.h"
20#include "adc-target.h" 22#include "adc-target.h"
21#include "kernel.h" 23#include "kernel.h"
22 24
23/* prototypes */ 25/* Do this so we may read all channels in a single SPI message */
24static unsigned short __adc_read(int channel); 26static const unsigned char reg_array[NUM_ADC_CHANNELS/2] =
25static void adc_tick(void);
26
27void adc_init(void)
28{ 27{
29} 28 MC13783_ADC2,
29 MC13783_ADC2,
30 MC13783_ADC2,
31 MC13783_ADC2,
32 MC13783_ADC2,
33 MC13783_ADC2,
34 MC13783_ADC2,
35 MC13783_ADC2,
36};
30 37
31/* Called to get the recent ADC reading */ 38static uint32_t channels[2][NUM_ADC_CHANNELS/2];
32inline unsigned short adc_read(int channel) 39static struct wakeup adc_wake;
40static struct mutex adc_mtx;
41static long last_adc_read[2]; /* One for each input group */
42
43/* Read 10-bit ADC channel */
44unsigned short adc_read(int channel)
33{ 45{
34 (void)channel; 46 uint32_t data;
35 return 0; 47 int input_select;
48
49 if ((unsigned)channel >= NUM_ADC_CHANNELS)
50 return ADC_READ_ERROR;
51
52 mutex_lock(&adc_mtx);
53
54 input_select = channel >> 3;
55
56 /* Limit the traffic through here */
57 if (TIME_AFTER(current_tick, last_adc_read[input_select]))
58 {
59 /* Keep enable, start conversion, increment from channel 0,
60 * increment from channel 4 */
61 uint32_t adc1 = MC13783_ADEN | MC13783_ASC | MC13783_ADA1w(0) |
62 MC13783_ADA2w(4);
63
64 if (input_select == 1)
65 adc1 |= MC13783_ADSEL; /* 2nd set of inputs */
66
67 /* Start conversion */
68 mc13783_write(MC13783_ADC1, adc1);
69
70 /* Wait for done signal */
71 wakeup_wait(&adc_wake, TIMEOUT_BLOCK);
72
73 /* Read all 8 channels that are converted - two channels in each
74 * word. */
75 mc13783_read_regset(reg_array, channels[input_select],
76 NUM_ADC_CHANNELS/2);
77
78 last_adc_read[input_select] = current_tick;
79 }
80
81 data = channels[input_select][channel & 7];
82
83 mutex_unlock(&adc_mtx);
84
85 /* Extract the bitfield depending on even or odd channel number */
86 return (channel & 1) ? MC13783_ADD2r(data) : MC13783_ADD1r(data);
36} 87}
37 88
38/** 89/* Called when conversion is complete */
39 * Read the ADC by polling 90void adc_done(void)
40 * @param channel The ADC channel to read
41 * @return 10bit reading from ADC channel or ADC_READ_ERROR if timeout
42 */
43static unsigned short __adc_read(int channel)
44{ 91{
45 (void)channel; 92 wakeup_signal(&adc_wake);
46 return 0;
47} 93}
48 94
49/* add this to the tick so that the ADC converts are done in the background */ 95void adc_init(void)
50static void adc_tick(void)
51{ 96{
97 wakeup_init(&adc_wake);
98 mutex_init(&adc_mtx);
99
100 /* Init so first reads get data */
101 last_adc_read[0] = last_adc_read[1] = current_tick-1;
102
103 /* Enable increment-by-read, thermistor */
104 mc13783_write(MC13783_ADC0, MC13783_ADINC2 | MC13783_ADINC1 |
105 MC13783_RTHEN);
106 /* Enable ADC, set multi-channel mode */
107 mc13783_write(MC13783_ADC1, MC13783_ADEN);
108 /* Enable the ADCDONE interrupt - notifications are dispatched by
109 * event handler. */
110 mc13783_clear(MC13783_INTERRUPT_MASK0, MC13783_ADCDONE);
52} 111}
diff --git a/firmware/target/arm/imx31/gigabeat-s/adc-target.h b/firmware/target/arm/imx31/gigabeat-s/adc-target.h
index 8d2beaf320..6b066b0b59 100644
--- a/firmware/target/arm/imx31/gigabeat-s/adc-target.h
+++ b/firmware/target/arm/imx31/gigabeat-s/adc-target.h
@@ -20,18 +20,29 @@
20#define _ADC_TARGET_H_ 20#define _ADC_TARGET_H_
21 21
22/* only two channels used by the Gigabeat */ 22/* only two channels used by the Gigabeat */
23#define NUM_ADC_CHANNELS 2 23#define NUM_ADC_CHANNELS 16
24
25#define ADC_BATTERY 0
26#define ADC_UNKNOWN_1 1
27#define ADC_UNKNOWN_2 2
28#define ADC_UNKNOWN_3 3
29#define ADC_UNKNOWN_4 4
30#define ADC_UNKNOWN_5 5
31#define ADC_UNKNOWN_6 6
32#define ADC_UNKNOWN_7 7
33#define ADC_HPREMOTE 8
34#define ADC_UNKNOWN_9 9
35#define ADC_UNKNOWN_10 10
36#define ADC_UNKNOWN_11 11
37#define ADC_UNKNOWN_12 12
38#define ADC_UNKNOWN_13 13
39#define ADC_UNKNOWN_14 14
40#define ADC_UNKNOWN_15 15
24 41
25#define ADC_BATTERY 0
26#define ADC_HPREMOTE 1
27#define ADC_UNKNOWN_3 2
28#define ADC_UNKNOWN_4 3
29#define ADC_UNKNOWN_5 4
30#define ADC_UNKNOWN_6 5
31#define ADC_UNKNOWN_7 6
32#define ADC_UNKNOWN_8 7
33 42
34#define ADC_UNREG_POWER ADC_BATTERY /* For compatibility */ 43#define ADC_UNREG_POWER ADC_BATTERY /* For compatibility */
35#define ADC_READ_ERROR 0xFFFF 44#define ADC_READ_ERROR 0xFFFF
36 45
46void adc_done(void);
47
37#endif 48#endif
diff --git a/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c b/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c
index fdb214a33d..d62df92ac5 100644
--- a/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c
@@ -26,6 +26,7 @@
26 26
27#include "power-imx31.h" 27#include "power-imx31.h"
28#include "button-target.h" 28#include "button-target.h"
29#include "adc-target.h"
29 30
30/* This is all based on communicating with the MC13783 PMU which is on 31/* This is all based on communicating with the MC13783 PMU which is on
31 * CSPI2 with the chip select at 0. The LCD controller resides on 32 * CSPI2 with the chip select at 0. The LCD controller resides on
@@ -64,17 +65,21 @@ static __attribute__((noreturn)) void mc13783_interrupt_thread(void)
64 65
65 gpio_enable_event(MC13783_GPIO_NUM, MC13783_EVENT_ID); 66 gpio_enable_event(MC13783_GPIO_NUM, MC13783_EVENT_ID);
66 67
67 /* Check initial states */ 68 /* Check initial states for events with a sense bit */
68 value = mc13783_read(MC13783_INTERRUPT_SENSE0); 69 value = mc13783_read(MC13783_INTERRUPT_SENSE0);
69 set_charger_inserted(value & MC13783_CHGDET); 70 set_charger_inserted(value & MC13783_CHGDET);
70 71
71 value = mc13783_read(MC13783_INTERRUPT_SENSE1); 72 value = mc13783_read(MC13783_INTERRUPT_SENSE1);
72 button_power_set_state((value & MC13783_ON1B) == 0); 73 button_power_set_state((value & MC13783_ONOFD1) == 0);
73 set_headphones_inserted((value & MC13783_ON2B) == 0); 74 set_headphones_inserted((value & MC13783_ONOFD2) == 0);
74 75
75 /* Enable desired PMIC interrupts */ 76 pending[0] = pending[1] = 0xffffff;
77 mc13783_write_regset(status_regs, pending, 2);
78
79 /* Enable desired PMIC interrupts - some are unmasked in the drivers that
80 * handle a specific task */
76 mc13783_clear(MC13783_INTERRUPT_MASK0, MC13783_CHGDET); 81 mc13783_clear(MC13783_INTERRUPT_MASK0, MC13783_CHGDET);
77 mc13783_clear(MC13783_INTERRUPT_MASK1, MC13783_ON1B | MC13783_ON2B); 82 mc13783_clear(MC13783_INTERRUPT_MASK1, MC13783_ONOFD1 | MC13783_ONOFD2);
78 83
79 while (1) 84 while (1)
80 { 85 {
@@ -83,10 +88,16 @@ static __attribute__((noreturn)) void mc13783_interrupt_thread(void)
83 mc13783_read_regset(status_regs, pending, 2); 88 mc13783_read_regset(status_regs, pending, 2);
84 mc13783_write_regset(status_regs, pending, 2); 89 mc13783_write_regset(status_regs, pending, 2);
85 90
86
87 if (pending[0]) 91 if (pending[0])
88 { 92 {
89 /* Handle ...PENDING0 */ 93 /* Handle ...PENDING0 */
94
95 /* Handle interrupts without a sense bit */
96 if (pending[0] & MC13783_ADCDONE)
97 adc_done();
98
99 /* Handle interrupts that have a sense bit that needs to
100 * be checked */
90 if (pending[0] & MC13783_CHGDET) 101 if (pending[0] & MC13783_CHGDET)
91 { 102 {
92 value = mc13783_read(MC13783_INTERRUPT_SENSE0); 103 value = mc13783_read(MC13783_INTERRUPT_SENSE0);
@@ -96,19 +107,24 @@ static __attribute__((noreturn)) void mc13783_interrupt_thread(void)
96 } 107 }
97 } 108 }
98 109
99
100 if (pending[1]) 110 if (pending[1])
101 { 111 {
102 /* Handle ...PENDING1 */ 112 /* Handle ...PENDING1 */
103 if (pending[1] & (MC13783_ON1B | MC13783_ON2B)) 113
114 /* Handle interrupts without a sense bit */
115 /* ... */
116
117 /* Handle interrupts that have a sense bit that needs to
118 * be checked */
119 if (pending[1] & (MC13783_ONOFD1 | MC13783_ONOFD2))
104 { 120 {
105 value = mc13783_read(MC13783_INTERRUPT_SENSE1); 121 value = mc13783_read(MC13783_INTERRUPT_SENSE1);
106 122
107 if (pending[1] & MC13783_ON1B) 123 if (pending[1] & MC13783_ONOFD1)
108 button_power_set_state((value & MC13783_ON1B) == 0); 124 button_power_set_state((value & MC13783_ONOFD1) == 0);
109 125
110 if (pending[1] & MC13783_ON2B) 126 if (pending[1] & MC13783_ONOFD2)
111 set_headphones_inserted((value & MC13783_ON2B) == 0); 127 set_headphones_inserted((value & MC13783_ONOFD2) == 0);
112 } 128 }
113 } 129 }
114 } 130 }