i.MX31/Gigabeat S: Implement frequency and voltage scaling-- 1.6V for 528MHz, and...
[kugel-rb.git] / firmware / target / arm / imx31 / gigabeat-s / adc-gigabeat-s.c
blob52293228f8abf2555b543c15dfe8e8c7ed271d4f
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2008 by Michael Sevakis
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
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"
28 /* Do this so we may read all channels in a single SPI message */
29 static const unsigned char reg_array[4] =
31 MC13783_ADC2,
32 MC13783_ADC2,
33 MC13783_ADC2,
34 MC13783_ADC2,
37 static uint32_t channels[2][4];
38 static struct wakeup adc_wake;
39 static struct mutex adc_mtx;
40 static long last_adc_read[2]; /* One for each input group */
42 /* Read 10-bit ADC channel */
43 unsigned short adc_read(int channel)
45 uint32_t data;
46 int input_select;
48 if ((unsigned)channel >= NUM_ADC_CHANNELS)
49 return ADC_READ_ERROR;
51 input_select = channel >> 3;
53 mutex_lock(&adc_mtx);
55 /* Limit the traffic through here */
56 if (current_tick != last_adc_read[input_select])
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);
63 if (input_select == 1)
64 adc1 |= MC13783_ADSEL; /* 2nd set of inputs */
66 /* Start conversion */
67 mc13783_write(MC13783_ADC1, adc1);
69 /* Wait for done signal */
70 wakeup_wait(&adc_wake, TIMEOUT_BLOCK);
72 /* Read all 8 channels that are converted - two channels in each
73 * word. */
74 mc13783_read_regset(reg_array, channels[input_select], 4);
76 last_adc_read[input_select] = current_tick;
79 data = channels[input_select][channel & 3];
81 mutex_unlock(&adc_mtx);
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);
89 bool adc_enable_channel(int channel, bool enable)
91 uint32_t bit, mask;
93 switch (channel)
95 case ADC_CHARGER_CURRENT:
96 mask = MC13783_CHRGICON;
97 break;
99 case ADC_BATTERY_TEMP:
100 mask = MC13783_RTHEN;
101 break;
103 default:
104 return false;
107 bit = enable ? mask : 0;
109 return mc13783_write_masked(MC13783_ADC0, bit, mask)
110 != MC13783_DATA_ERROR;
113 /* Called by mc13783 interrupt thread when conversion is complete */
114 void adc_done(void)
116 wakeup_signal(&adc_wake);
119 void adc_init(void)
121 wakeup_init(&adc_wake);
122 mutex_init(&adc_mtx);
124 /* Init so first reads get data */
125 last_adc_read[0] = last_adc_read[1] = current_tick-1;
127 /* Enable increment-by-read, turn off extra conversions. */
128 mc13783_write(MC13783_ADC0, MC13783_ADINC2 | MC13783_ADINC1);
130 /* Enable ADC, set multi-channel mode */
131 mc13783_write(MC13783_ADC1, MC13783_ADEN);
133 /* Enable ADCDONE event */
134 mc13783_write(MC13783_INTERRUPT_STATUS0, MC13783_ADCDONEI);
135 mc13783_enable_event(MC13783_ADCDONE_EVENT);