blob: 11799ccd9b85806bb5426182ff63c892d833691b [file] [log] [blame]
Kévin Redon9a12d682018-07-08 13:21:16 +02001/* This program is free software; you can redistribute it and/or modify
2 * it under the terms of the GNU General Public License as published by
3 * the Free Software Foundation; either version 2 of the License, or
4 * (at your option) any later version.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 *
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
14 */
Harald Welte67322482017-02-04 14:43:41 +010015#include "board.h"
16#include "boardver_adc.h"
17
Harald Welte67322482017-02-04 14:43:41 +010018#define UV_PER_LSB ((3300 * 1000) / 4096)
Kévin Redonac0843a2018-07-11 09:23:33 +020019uint32_t adc2uv(uint16_t adc)
Harald Welte67322482017-02-04 14:43:41 +010020{
21 uint32_t uv = (uint32_t) adc * UV_PER_LSB;
22 return uv;
23}
24
25/***********************************************************************
26 * ADC for board version detection
27 ***********************************************************************/
28
29#ifdef PIN_VERSION_DET
30
31static int adc_sam3s_reva_errata = 0;
32
33static const Pin pin_version_det = PIN_VERSION_DET;
34
35/* Warning: Don't call this while other code (like the SIM VCC voltage
36 * reading) is running. The idea is you call this once during board
37 * startup and cache the result in a (global) variable if you need it
38 * later throughout the code */
39int get_board_version_adc(void)
40{
41 uint32_t chip_arch = CHIPID->CHIPID_CIDR & CHIPID_CIDR_ARCH_Msk;
42 uint32_t chip_ver = CHIPID->CHIPID_CIDR & CHIPID_CIDR_VERSION_Msk;
43 uint16_t sample;
44 uint32_t uv;
45
46 PIO_Configure(&pin_version_det, 1);
47
48 PMC_EnablePeripheral(ID_ADC);
49
50 ADC->ADC_CR |= ADC_CR_SWRST;
51 if (chip_ver == 0 &&
52 (chip_arch == CHIPID_CIDR_ARCH_SAM3SxA ||
53 chip_arch == CHIPID_CIDR_ARCH_SAM3SxB ||
54 chip_arch == CHIPID_CIDR_ARCH_SAM3SxC)) {
55 TRACE_INFO("Enabling Rev.A ADC Errata work-around\r\n");
56 adc_sam3s_reva_errata = 1;
57 }
58
59 if (adc_sam3s_reva_errata) {
60 /* Errata Work-Around to clear EOCx flags */
61 volatile uint32_t foo;
62 int i;
63 for (i = 0; i < 16; i++)
64 foo = ADC->ADC_CDR[i];
65 }
66
67 /* Initialize ADC for AD2, fADC=48/24=2MHz */
68 ADC->ADC_MR = ADC_MR_TRGEN_DIS | ADC_MR_LOWRES_BITS_12 |
69 ADC_MR_SLEEP_NORMAL | ADC_MR_FWUP_OFF |
70 ADC_MR_FREERUN_OFF | ADC_MR_PRESCAL(23) |
71 ADC_MR_STARTUP_SUT8 | ADC_MR_SETTLING(3) |
72 ADC_MR_ANACH_NONE | ADC_MR_TRACKTIM(4) |
73 ADC_MR_TRANSFER(1) | ADC_MR_USEQ_NUM_ORDER;
74 /* enable AD2 channel only */
75 ADC->ADC_CHER = ADC_CHER_CH2;
76
77 /* Make sure we don't use interrupts as that's what the SIM card
78 * VCC ADC code is using */
79 ADC->ADC_IER = 0;
80 NVIC_DisableIRQ(ADC_IRQn);
81
82 ADC->ADC_CR |= ADC_CR_START;
83
84 /* busy-wait, actually read the value */
85 do { } while (!(ADC->ADC_ISR & ADC_ISR_EOC2));
86 /* convert to voltage */
87 sample = ADC->ADC_CDR[2];
88 uv = adc2uv(sample);
Harald Weltec3941092018-08-26 09:53:13 +020089 TRACE_INFO("VERSION_DET ADC=%u => %lu uV\r\n", sample, uv);
Harald Welte67322482017-02-04 14:43:41 +010090
91 /* FIXME: convert to board version based on thresholds */
92
93 return 0;
94}
95
96#endif /* PIN_VERSION_DET */