summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx31/gigabeat-s/adc-gigabeat-s.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s/adc-gigabeat-s.c')
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/adc-gigabeat-s.c136
1 files changed, 136 insertions, 0 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/adc-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/adc-gigabeat-s.c
new file mode 100644
index 0000000000..52293228f8
--- /dev/null
+++ b/firmware/target/arm/imx31/gigabeat-s/adc-gigabeat-s.c
@@ -0,0 +1,136 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 by Michael Sevakis
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22#include "system.h"
23#include "mc13783.h"
24#include "adc.h"
25#include "adc-target.h"
26#include "kernel.h"
27
28/* Do this so we may read all channels in a single SPI message */
29static const unsigned char reg_array[4] =
30{
31 MC13783_ADC2,
32 MC13783_ADC2,
33 MC13783_ADC2,
34 MC13783_ADC2,
35};
36
37static uint32_t channels[2][4];
38static struct wakeup adc_wake;
39static struct mutex adc_mtx;
40static long last_adc_read[2]; /* One for each input group */
41
42/* Read 10-bit ADC channel */
43unsigned short adc_read(int channel)
44{
45 uint32_t data;
46 int input_select;
47
48 if ((unsigned)channel >= NUM_ADC_CHANNELS)
49 return ADC_READ_ERROR;
50
51 input_select = channel >> 3;
52
53 mutex_lock(&adc_mtx);
54
55 /* Limit the traffic through here */
56 if (current_tick != last_adc_read[input_select])
57 {
58 /* Keep enable, start conversion, increment from channel 0,
59 * increment from channel 4 */
60 uint32_t adc1 = MC13783_ADEN | MC13783_ASC |
61 (0 << MC13783_ADA1_POS) | (4 << MC13783_ADA2_POS);
62
63 if (input_select == 1)
64 adc1 |= MC13783_ADSEL; /* 2nd set of inputs */
65
66 /* Start conversion */
67 mc13783_write(MC13783_ADC1, adc1);
68
69 /* Wait for done signal */
70 wakeup_wait(&adc_wake, TIMEOUT_BLOCK);
71
72 /* Read all 8 channels that are converted - two channels in each
73 * word. */
74 mc13783_read_regset(reg_array, channels[input_select], 4);
75
76 last_adc_read[input_select] = current_tick;
77 }
78
79 data = channels[input_select][channel & 3];
80
81 mutex_unlock(&adc_mtx);
82
83 /* Channels 0-3/8-11 in ADD1, 4-7/12-15 in ADD2 */
84 return (channel & 4) ?
85 ((data & MC13783_ADD2) >> MC13783_ADD2_POS) :
86 ((data & MC13783_ADD1) >> MC13783_ADD1_POS);
87}
88
89bool adc_enable_channel(int channel, bool enable)
90{
91 uint32_t bit, mask;
92
93 switch (channel)
94 {
95 case ADC_CHARGER_CURRENT:
96 mask = MC13783_CHRGICON;
97 break;
98
99 case ADC_BATTERY_TEMP:
100 mask = MC13783_RTHEN;
101 break;
102
103 default:
104 return false;
105 }
106
107 bit = enable ? mask : 0;
108
109 return mc13783_write_masked(MC13783_ADC0, bit, mask)
110 != MC13783_DATA_ERROR;
111}
112
113/* Called by mc13783 interrupt thread when conversion is complete */
114void adc_done(void)
115{
116 wakeup_signal(&adc_wake);
117}
118
119void adc_init(void)
120{
121 wakeup_init(&adc_wake);
122 mutex_init(&adc_mtx);
123
124 /* Init so first reads get data */
125 last_adc_read[0] = last_adc_read[1] = current_tick-1;
126
127 /* Enable increment-by-read, turn off extra conversions. */
128 mc13783_write(MC13783_ADC0, MC13783_ADINC2 | MC13783_ADINC1);
129
130 /* Enable ADC, set multi-channel mode */
131 mc13783_write(MC13783_ADC1, MC13783_ADEN);
132
133 /* Enable ADCDONE event */
134 mc13783_write(MC13783_INTERRUPT_STATUS0, MC13783_ADCDONEI);
135 mc13783_enable_event(MC13783_ADCDONE_EVENT);
136}