Will Robertson | 590501c | 2007-09-21 15:51:53 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * $Id$ |
| 9 | * |
Michael Sevakis | b12c69b | 2008-04-13 20:03:08 +0000 | [diff] [blame] | 10 | * Copyright (C) 2008 by Michael Sevakis |
Will Robertson | 590501c | 2007-09-21 15:51:53 +0000 | [diff] [blame] | 11 | * |
Daniel Stenberg | 2acc0ac | 2008-06-28 18:10:04 +0000 | [diff] [blame^] | 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. |
Will Robertson | 590501c | 2007-09-21 15:51:53 +0000 | [diff] [blame] | 16 | * |
| 17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 18 | * KIND, either express or implied. |
| 19 | * |
| 20 | ****************************************************************************/ |
Michael Sevakis | b12c69b | 2008-04-13 20:03:08 +0000 | [diff] [blame] | 21 | #include "config.h" |
| 22 | #include "system.h" |
| 23 | #include "mc13783.h" |
Will Robertson | 590501c | 2007-09-21 15:51:53 +0000 | [diff] [blame] | 24 | #include "adc-target.h" |
| 25 | #include "kernel.h" |
| 26 | |
Michael Sevakis | b12c69b | 2008-04-13 20:03:08 +0000 | [diff] [blame] | 27 | /* Do this so we may read all channels in a single SPI message */ |
Michael Sevakis | 25ebc85 | 2008-04-14 04:22:47 +0000 | [diff] [blame] | 28 | static const unsigned char reg_array[4] = |
Michael Sevakis | b12c69b | 2008-04-13 20:03:08 +0000 | [diff] [blame] | 29 | { |
| 30 | MC13783_ADC2, |
| 31 | MC13783_ADC2, |
| 32 | MC13783_ADC2, |
| 33 | MC13783_ADC2, |
Michael Sevakis | b12c69b | 2008-04-13 20:03:08 +0000 | [diff] [blame] | 34 | }; |
| 35 | |
Michael Sevakis | 25ebc85 | 2008-04-14 04:22:47 +0000 | [diff] [blame] | 36 | static uint32_t channels[2][4]; |
Michael Sevakis | b12c69b | 2008-04-13 20:03:08 +0000 | [diff] [blame] | 37 | static struct wakeup adc_wake; |
| 38 | static struct mutex adc_mtx; |
| 39 | static long last_adc_read[2]; /* One for each input group */ |
| 40 | |
| 41 | /* Read 10-bit ADC channel */ |
| 42 | unsigned short adc_read(int channel) |
| 43 | { |
| 44 | uint32_t data; |
| 45 | int input_select; |
| 46 | |
| 47 | if ((unsigned)channel >= NUM_ADC_CHANNELS) |
| 48 | return ADC_READ_ERROR; |
| 49 | |
Michael Sevakis | b12c69b | 2008-04-13 20:03:08 +0000 | [diff] [blame] | 50 | input_select = channel >> 3; |
| 51 | |
Michael Sevakis | 25ebc85 | 2008-04-14 04:22:47 +0000 | [diff] [blame] | 52 | mutex_lock(&adc_mtx); |
| 53 | |
Michael Sevakis | b12c69b | 2008-04-13 20:03:08 +0000 | [diff] [blame] | 54 | /* Limit the traffic through here */ |
Michael Sevakis | 0257547 | 2008-04-14 06:52:38 +0000 | [diff] [blame] | 55 | if (current_tick != last_adc_read[input_select]) |
Michael Sevakis | b12c69b | 2008-04-13 20:03:08 +0000 | [diff] [blame] | 56 | { |
| 57 | /* Keep enable, start conversion, increment from channel 0, |
| 58 | * increment from channel 4 */ |
| 59 | uint32_t adc1 = MC13783_ADEN | MC13783_ASC | MC13783_ADA1w(0) | |
| 60 | MC13783_ADA2w(4); |
| 61 | |
| 62 | if (input_select == 1) |
| 63 | adc1 |= MC13783_ADSEL; /* 2nd set of inputs */ |
| 64 | |
| 65 | /* Start conversion */ |
| 66 | mc13783_write(MC13783_ADC1, adc1); |
| 67 | |
| 68 | /* Wait for done signal */ |
| 69 | wakeup_wait(&adc_wake, TIMEOUT_BLOCK); |
| 70 | |
| 71 | /* Read all 8 channels that are converted - two channels in each |
| 72 | * word. */ |
Michael Sevakis | 25ebc85 | 2008-04-14 04:22:47 +0000 | [diff] [blame] | 73 | mc13783_read_regset(reg_array, channels[input_select], 4); |
Michael Sevakis | b12c69b | 2008-04-13 20:03:08 +0000 | [diff] [blame] | 74 | |
| 75 | last_adc_read[input_select] = current_tick; |
| 76 | } |
| 77 | |
Michael Sevakis | 054c728 | 2008-04-27 22:35:24 +0000 | [diff] [blame] | 78 | data = channels[input_select][channel & 3]; |
Michael Sevakis | b12c69b | 2008-04-13 20:03:08 +0000 | [diff] [blame] | 79 | |
| 80 | mutex_unlock(&adc_mtx); |
| 81 | |
Michael Sevakis | a9c20f5 | 2008-05-21 08:42:11 +0000 | [diff] [blame] | 82 | /* Channels 0-3/8-11 in ADD1, 4-7/12-15 in ADD2 */ |
Michael Sevakis | 054c728 | 2008-04-27 22:35:24 +0000 | [diff] [blame] | 83 | return (channel & 4) ? MC13783_ADD2r(data) : MC13783_ADD1r(data); |
Michael Sevakis | b12c69b | 2008-04-13 20:03:08 +0000 | [diff] [blame] | 84 | } |
| 85 | |
Michael Sevakis | a9c20f5 | 2008-05-21 08:42:11 +0000 | [diff] [blame] | 86 | /* Called by mc13783 interrupt thread when conversion is complete */ |
Michael Sevakis | b12c69b | 2008-04-13 20:03:08 +0000 | [diff] [blame] | 87 | void adc_done(void) |
| 88 | { |
| 89 | wakeup_signal(&adc_wake); |
| 90 | } |
Will Robertson | 590501c | 2007-09-21 15:51:53 +0000 | [diff] [blame] | 91 | |
| 92 | void adc_init(void) |
| 93 | { |
Michael Sevakis | b12c69b | 2008-04-13 20:03:08 +0000 | [diff] [blame] | 94 | wakeup_init(&adc_wake); |
| 95 | mutex_init(&adc_mtx); |
Will Robertson | 590501c | 2007-09-21 15:51:53 +0000 | [diff] [blame] | 96 | |
Michael Sevakis | b12c69b | 2008-04-13 20:03:08 +0000 | [diff] [blame] | 97 | /* Init so first reads get data */ |
| 98 | last_adc_read[0] = last_adc_read[1] = current_tick-1; |
Will Robertson | 590501c | 2007-09-21 15:51:53 +0000 | [diff] [blame] | 99 | |
Michael Sevakis | 054c728 | 2008-04-27 22:35:24 +0000 | [diff] [blame] | 100 | /* Enable increment-by-read, thermistor, charge current */ |
Michael Sevakis | b12c69b | 2008-04-13 20:03:08 +0000 | [diff] [blame] | 101 | mc13783_write(MC13783_ADC0, MC13783_ADINC2 | MC13783_ADINC1 | |
Michael Sevakis | 054c728 | 2008-04-27 22:35:24 +0000 | [diff] [blame] | 102 | MC13783_RTHEN | MC13783_CHRGICON); |
Michael Sevakis | b12c69b | 2008-04-13 20:03:08 +0000 | [diff] [blame] | 103 | /* Enable ADC, set multi-channel mode */ |
| 104 | mc13783_write(MC13783_ADC1, MC13783_ADEN); |
Michael Sevakis | a9c20f5 | 2008-05-21 08:42:11 +0000 | [diff] [blame] | 105 | |
| 106 | /* Enable ADCDONE event */ |
| 107 | mc13783_write(MC13783_INTERRUPT_STATUS0, MC13783_ADCDONEI); |
| 108 | mc13783_enable_event(MC13783_ADCDONE_EVENT); |
Will Robertson | 590501c | 2007-09-21 15:51:53 +0000 | [diff] [blame] | 109 | } |