blob: a8fe8c156016feb211b092a133029f5c4cc8756c [file] [log] [blame]
Barry Wardell18cfe432006-08-20 23:05:47 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Barry Wardell
11 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000012 * 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.
Barry Wardell18cfe432006-08-20 23:05:47 +000016 *
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 "cpu.h"
23#include "system.h"
24#include "kernel.h"
25#include "thread.h"
26#include "adc.h"
27
Barry Wardelle367b052006-08-22 20:17:09 +000028static unsigned short adcdata[NUM_ADC_CHANNELS];
29
Barry Wardell1d1a17c2007-10-16 10:48:16 +000030/* Scan ADC so that adcdata[channel] gets updated. */
Barry Wardell18cfe432006-08-20 23:05:47 +000031unsigned short adc_scan(int channel)
32{
Barry Wardelle367b052006-08-22 20:17:09 +000033 unsigned int adc_data_1;
34 unsigned int adc_data_2;
35
Barry Wardell1d1a17c2007-10-16 10:48:16 +000036 /* Start conversion */
Barry Wardelle367b052006-08-22 20:17:09 +000037 ADC_ADDR |= 0x80000000;
Barry Wardell1d1a17c2007-10-16 10:48:16 +000038
39 /* Wait for conversion to complete */
40 while((ADC_STATUS & (0x40<<8*channel))==0);
41
42 /* Stop conversion */
43 ADC_ADDR &=~ 0x80000000;
44
Barry Wardelle367b052006-08-22 20:17:09 +000045 /* ADC_DATA_1 and ADC_DATA_2 are both four bytes, one byte per channel.
46 For each channel, ADC_DATA_1 stores the 8-bit msb, ADC_DATA_2 stores the
47 2-bit lsb (in bits 0 and 1). Each channel is 10 bits total. */
48 adc_data_1 = ((ADC_DATA_1 >> (8*channel)) & 0xff);
49 adc_data_2 = ((ADC_DATA_2 >> (8*channel+6)) & 0x3);
50
51 adcdata[channel] = (adc_data_1<<2 | adc_data_2);
52
Barry Wardell1d1a17c2007-10-16 10:48:16 +000053 /* ADC values read low if PLL is enabled */
54 if(PLL_CONTROL & 0x80000000){
55 adcdata[channel] += 0x14;
56 if(adcdata[channel] > 0x400)
57 adcdata[channel] = 0x400;
58 }
59
Barry Wardelle367b052006-08-22 20:17:09 +000060 return adcdata[channel];
Barry Wardell18cfe432006-08-20 23:05:47 +000061}
62
Barry Wardelle367b052006-08-22 20:17:09 +000063/* Read 10-bit channel data */
Barry Wardell18cfe432006-08-20 23:05:47 +000064unsigned short adc_read(int channel)
65{
Barry Wardelle367b052006-08-22 20:17:09 +000066 return adcdata[channel];
67}
68
69static int adc_counter;
70
71static void adc_tick(void)
72{
73 if(++adc_counter == HZ)
74 {
75 adc_counter = 0;
Robert Kuklaa615aab2008-01-12 20:36:45 +000076 adc_scan(0);
77 adc_scan(1);
78 adc_scan(2);
79 adc_scan(3);
Barry Wardelle367b052006-08-22 20:17:09 +000080 }
Barry Wardell18cfe432006-08-20 23:05:47 +000081}
82
Barry Wardell1d1a17c2007-10-16 10:48:16 +000083/* Figured out from how the OF does things */
Barry Wardell18cfe432006-08-20 23:05:47 +000084void adc_init(void)
85{
Barry Wardell1d1a17c2007-10-16 10:48:16 +000086 ADC_INIT |= 1;
87 ADC_INIT |= 0x40000000;
88 udelay(100);
Barry Wardelle367b052006-08-22 20:17:09 +000089
Barry Wardell1d1a17c2007-10-16 10:48:16 +000090 /* Reset ADC */
91 DEV_RS2 |= 0x20;
92 udelay(100);
93
94 DEV_RS2 &=~ 0x20;
95 udelay(100);
96
97 /* Enable ADC */
98 DEV_EN2 |= 0x20;
99 udelay(100);
100
101 ADC_CLOCK_SRC |= 0x3;
102 udelay(100);
103
104 ADC_ADDR |= 0x40;
105 ADC_ADDR |= 0x20000000;
106 udelay(100);
107
108 ADC_INIT;
109 ADC_INIT = 0;
110 udelay(100);
111
112 ADC_STATUS = 0;
113
114 /* Enable channel 0 (battery) */
115 DEV_INIT1 &=~0x3;
116 ADC_ADDR |= 0x1000000;
117 ADC_STATUS |= 0x20;
118
Robert Kuklaa615aab2008-01-12 20:36:45 +0000119 /* Enable channel 1 (unknown) */
Barry Wardell1d1a17c2007-10-16 10:48:16 +0000120 DEV_INIT1 &=~30;
121 ADC_ADDR |= 0x2000000;
122 ADC_STATUS |= 0x2000;
123
Robert Kuklac7559752008-02-10 16:06:01 +0000124#if defined (IRIVER_H10) || defined(IRIVER_H10_5GB) || defined(MROBE_100)
Robert Kuklaa615aab2008-01-12 20:36:45 +0000125 /* Enable channel 2 (H10:remote) */
Barry Wardell1d1a17c2007-10-16 10:48:16 +0000126 DEV_INIT1 &=~0x300;
127 DEV_INIT1 |= 0x100;
128 ADC_ADDR |= 0x4000000;
129 ADC_STATUS |= 0x200000;
130
Robert Kuklaa615aab2008-01-12 20:36:45 +0000131 /* Enable channel 3 (H10:scroll pad) */
Barry Wardell1d1a17c2007-10-16 10:48:16 +0000132 DEV_INIT1 &=~0x3000;
133 DEV_INIT1 |= 0x1000;
134 ADC_ADDR |= 0x8000000;
135 ADC_STATUS |= 0x20000000;
Michael Giacomelli054447f2008-02-10 05:39:20 +0000136#endif
Barry Wardell5a79b4e2006-09-23 17:47:54 +0000137
138 /* Force a scan of all channels to get initial values */
Robert Kuklaa615aab2008-01-12 20:36:45 +0000139 adc_scan(0);
140 adc_scan(1);
141 adc_scan(2);
142 adc_scan(3);
Barry Wardell8d2711b2006-11-11 01:18:57 +0000143
Barry Wardelle367b052006-08-22 20:17:09 +0000144 tick_add_task(adc_tick);
Barry Wardell18cfe432006-08-20 23:05:47 +0000145}