1 /*
2  * Copyright (c) 2016-2017, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34  * By default disable both asserts and log for this module.
35  * This must be done before DebugP.h is included.
36  */
37 #ifndef DebugP_ASSERT_ENABLED
38 #define DebugP_ASSERT_ENABLED 0
39 #endif
40 #ifndef DebugP_LOG_ENABLED
41 #define DebugP_LOG_ENABLED 0
42 #endif
43 
44 #include <stdint.h>
45 
46 #include <ti/drivers/dpl/DebugP.h>
47 #include <ti/drivers/dpl/HwiP.h>
48 
49 #include <ti/drivers/adc/ADCCC32XX.h>
50 
51 #include <ti/devices/cc32xx/inc/hw_memmap.h>
52 #include <ti/devices/cc32xx/inc/hw_ocp_shared.h>
53 #include <ti/devices/cc32xx/inc/hw_types.h>
54 #include <ti/devices/cc32xx/driverlib/rom.h>
55 #include <ti/devices/cc32xx/driverlib/rom_map.h>
56 #include <ti/devices/cc32xx/driverlib/rom_patch.h>
57 #include <ti/devices/cc32xx/driverlib/adc.h>
58 #include <ti/devices/cc32xx/driverlib/pin.h>
59 
60 /* Pad configuration register defaults */
61 #define PAD_CONFIG_BASE (OCP_SHARED_BASE + OCP_SHARED_O_GPIO_PAD_CONFIG_0)
62 #define PAD_RESET_DRIVE PIN_STRENGTH_6MA
63 #define PAD_RESET_TYPE  PIN_TYPE_STD
64 #define PAD_RESET_STATE 0xC61
65 
66 #define PinConfigChannel(config) (((config) >> 8) & 0xff)
67 #define PinConfigPin(config) ((config) & 0xff)
68 
69 void ADCCC32XX_close(ADC_Handle handle);
70 int_fast16_t ADCCC32XX_control(ADC_Handle handle, uint_fast16_t cmd, void *arg);
71 int_fast16_t ADCCC32XX_convert(ADC_Handle handle, uint16_t *value);
72 uint32_t ADCCC32XX_convertToMicroVolts(ADC_Handle handle,
73     uint16_t adcValue);
74 void ADCCC32XX_init(ADC_Handle handle);
75 ADC_Handle ADCCC32XX_open(ADC_Handle handle, ADC_Params *params);
76 
77 /* ADC function table for ADCCC32XX implementation */
78 const ADC_FxnTable ADCCC32XX_fxnTable = {
79     ADCCC32XX_close,
80     ADCCC32XX_control,
81     ADCCC32XX_convert,
82     ADCCC32XX_convertToMicroVolts,
83     ADCCC32XX_init,
84     ADCCC32XX_open
85 };
86 
87 /* Internal ADC status structure */
88 static ADCCC32XX_State state = {
89     .baseAddr = ADC_BASE,
90     .numOpenChannels = 0
91 };
92 
93 /*
94  *  ======== ADCCC32XX_close ========
95  */
ADCCC32XX_close(ADC_Handle handle)96 void ADCCC32XX_close(ADC_Handle handle)
97 {
98     uintptr_t         key;
99     uint32_t          pin;
100     uint32_t          padRegister;
101     ADCCC32XX_Object *object = handle->object;
102     ADCCC32XX_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
103 
104     pin = PinConfigChannel(hwAttrs->adcPin);
105 
106     key = HwiP_disable();
107 
108     MAP_ADCChannelDisable(state.baseAddr, pin);
109     state.numOpenChannels--;
110 
111     if (state.numOpenChannels == 0) {
112         MAP_ADCDisable(state.baseAddr);
113     }
114 
115     HwiP_restore(key);
116 
117     /* Call PinConfigSet to de-isolate the input */
118     pin = PinConfigPin(hwAttrs->adcPin);
119     MAP_PinConfigSet(pin, PAD_RESET_DRIVE, PAD_RESET_TYPE);
120     /* Set reset state for the pad register */
121     padRegister = (PinToPadGet(pin)<<2) + PAD_CONFIG_BASE;
122     HWREG(padRegister) = PAD_RESET_STATE;
123 
124     object->isOpen = false;
125 
126     DebugP_log0("ADC: (%p) closed");
127 }
128 
129 /*
130  *  ======== ADCCC32XX_control ========
131  */
ADCCC32XX_control(ADC_Handle handle,uint_fast16_t cmd,void * arg)132 int_fast16_t ADCCC32XX_control(ADC_Handle handle, uint_fast16_t cmd, void *arg)
133 {
134     /* No implementation yet */
135     return (ADC_STATUS_UNDEFINEDCMD);
136 }
137 
138 /*
139  *  ======== ADCCC32XX_convert ========
140  */
ADCCC32XX_convert(ADC_Handle handle,uint16_t * value)141 int_fast16_t ADCCC32XX_convert(ADC_Handle handle, uint16_t *value)
142 {
143     uintptr_t                  key;
144     uint16_t                   adcSample = 0;
145     uint_fast16_t              adcChannel;
146     ADCCC32XX_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
147 
148     adcChannel = PinConfigChannel(hwAttrs->adcPin);
149     key = HwiP_disable();
150 
151     /* Wait until the FIFO is not empty */
152     while (MAP_ADCFIFOLvlGet(state.baseAddr, adcChannel) == 0) {
153         HwiP_restore(key);
154         key = HwiP_disable();
155     }
156 
157     adcSample = MAP_ADCFIFORead(ADC_BASE, adcChannel);
158 
159     HwiP_restore(key);
160 
161     /* Strip time stamp & reserve bits from ADC sample */
162     *value = ((adcSample >> 2) & 0x0FFF);
163 
164     return (ADC_STATUS_SUCCESS);
165 }
166 
167 /*
168  *  ======== ADCCC32XX_convertToMicroVolts ========
169  */
ADCCC32XX_convertToMicroVolts(ADC_Handle handle,uint16_t adcValue)170 uint32_t ADCCC32XX_convertToMicroVolts(ADC_Handle handle,
171     uint16_t adcValue)
172 {
173     /* Internal voltage reference is 1.467V (1467000 uV) */
174     return ((uint_fast32_t)(adcValue * (1467000.0 / 4095.0)));
175 }
176 
177 /*
178  *  ======== ADCCC32XX_init ========
179  */
ADCCC32XX_init(ADC_Handle handle)180 void ADCCC32XX_init(ADC_Handle handle)
181 {
182     /* Mark the object as available */
183     ((ADCCC32XX_Object *) handle->object)->isOpen = false;
184 }
185 
186 /*
187  *  ======== ADCCC32XX_open ========
188  */
ADCCC32XX_open(ADC_Handle handle,ADC_Params * params)189 ADC_Handle ADCCC32XX_open(ADC_Handle handle, ADC_Params *params)
190 {
191     uintptr_t                  key;
192     uint32_t                   pin;
193     ADCCC32XX_Object          *object = handle->object;
194     ADCCC32XX_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
195     uint32_t                   i;
196 
197     key = HwiP_disable();
198 
199     if (object->isOpen) {
200         HwiP_restore(key);
201 
202         DebugP_log1("ADC: (%p) already opened", (uintptr_t) handle);
203         return (NULL);
204     }
205 
206     object->isOpen = true;
207     state.numOpenChannels++;
208 
209     HwiP_restore(key);
210 
211     /* Configure pin as ADC input */
212     pin = PinConfigPin(hwAttrs->adcPin);
213     MAP_PinTypeADC(pin, PIN_MODE_255);
214 
215     /* Enable ADC Peripheral and ADC Channel */
216     pin = PinConfigChannel(hwAttrs->adcPin);
217     MAP_ADCEnable(state.baseAddr);
218     MAP_ADCChannelEnable(state.baseAddr, pin);
219 
220     /* Empty 5 samples from the FIFO */
221     for (i = 0; i < 5; i++) {
222         while (MAP_ADCFIFOLvlGet(state.baseAddr, pin) == 0){
223         }
224         MAP_ADCFIFORead(state.baseAddr, pin);
225     }
226 
227     DebugP_log1("ADC: (%p) instance opened.", (uintptr_t) handle);
228 
229     return (handle);
230 }
231