1 /*
2 * Copyright (c) 2022 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "stm32mp1_adc.h"
17 #include "device_resource_if.h"
18 #include "hdf_device_desc.h"
19 #include "hdf_log.h"
20 #include "osal_io.h"
21 #include "osal_mem.h"
22 #include "osal_time.h"
23 #include "stm32mp1xx.h"
24 #include "stm32mp1xx_hal_conf.h"
25
26 #define HDF_LOG_TAG stm32mp1_adc
27
Mp1xxAdcPinInit(struct Mp1xxAdcDevice * stm32mp1)28 static void Mp1xxAdcPinInit(struct Mp1xxAdcDevice *stm32mp1)
29 {
30 uint32_t i;
31 uint32_t value;
32 volatile unsigned char *gpioBase;
33 volatile unsigned char *comBase;
34
35 gpioBase = OsalIoRemap(MP1XX_GPIO_BASE + MP1XX_GPIO_MODE_REG_OFFSET,
36 MP1XX_GPIO_GROUP_NUMBER * MP1XX_GPIO_GROUP_SIZE);
37 for (i = 0; i < MP1XX_ADC_CHANNEL_COUNT_MAX; i++) {
38 if (stm32mp1->validChannel[i] == 0 || stm32mp1->pins[i * MP1_ADC_PIN_DATA_WIDTH] >= MP1XX_GPIO_GROUP_NUMBER) {
39 continue;
40 }
41
42 value = OSAL_READL(gpioBase);
43 value |= (MP1XX_GPIO_ANALOG_MODE_MASK << MP1XX_GPIO_REG_PIN_SHIFT);
44 OSAL_WRITEL(value, MP1XX_GPIO_BASE + MP1XX_GPIO_MODE_REG_OFFSET);
45
46 RCC->MC_AHB4ENSETR |= 0x1U << stm32mp1->pins[i * MP1_ADC_PIN_DATA_WIDTH];
47 }
48 RCC->PLL4CR |= 0x1U;
49 comBase = OsalIoRemap(MP1XX_ADC_COMMON_REG_BASE, MP1XX_ADC_COMMON_REG_SIZE);
50 OSAL_WRITEL(MP1XX_ADC_CKMODE_SEL, comBase + MP1XX_ADC_CCR_OFFSET);
51 if (stm32mp1->devNum == MP1XX_ADC_DEVICE_2) {
52 value = stm32mp1->validChannel[MP1XX_ADC_VDDCORE_CHANNEL] & 0x1U; // VddCore
53 OSAL_WRITEL(value, stm32mp1->regBase + MP1XX_ADC_OR_OFFSET);
54 value = stm32mp1->validChannel[MP1XX_ADC_VREF_CHANNEL] & 0x1U; // Vref
55 value |= (stm32mp1->validChannel[MP1XX_ADC_TSEN_CHANNEL] & 0x1U) << MP1XX_ADC_VREF_SHIFT; // Tsen
56 value |= (stm32mp1->validChannel[MP1XX_ADC_VBAT_CHANNEL] & 0x1U) << MP1XX_ADC_VBAT_SHIFT; // Vbat
57 OSAL_WRITEL(value, comBase + MP1XX_ADC_CCR_OFFSET);
58 }
59 }
60
Mp1xxAdcReset(struct Mp1xxAdcDevice * stm32mp1)61 static inline void Mp1xxAdcReset(struct Mp1xxAdcDevice *stm32mp1)
62 {
63 (void)stm32mp1;
64 }
65
Mp1xxAdcSetConfig(struct Mp1xxAdcDevice * stm32mp1)66 static inline void Mp1xxAdcSetConfig(struct Mp1xxAdcDevice *stm32mp1)
67 {
68 uint32_t value;
69
70 value = 0x1U << MP1XX_ADC_JQDIS_SHIFT;
71 OSAL_WRITEL(value, stm32mp1->regBase + MP1XX_ADC_CFGR_OFFSET);
72 }
73
Mp1xxAdcSetSampleTime(struct Mp1xxAdcDevice * stm32mp1)74 static inline void Mp1xxAdcSetSampleTime(struct Mp1xxAdcDevice *stm32mp1)
75 {
76 uint32_t sampleTime;
77 uint32_t i;
78
79 sampleTime = 0;
80 for (i = 0; i < MP1XX_CHANNLE_NUM_PER_REG; i++) {
81 sampleTime |= (stm32mp1->sampleTime & MP1XX_SAMPLE_TIME_MASK) << (i * MP1XX_SAMPLE_TIME_BITS);
82 }
83 OSAL_WRITEL(sampleTime, stm32mp1->regBase + MP1XX_ADC_SMPR1_OFFSET);
84 OSAL_WRITEL(sampleTime, stm32mp1->regBase + MP1XX_ADC_SMPR2_OFFSET);
85 }
86
Mp1xxAdcCalibration(struct Mp1xxAdcDevice * stm32mp1)87 static void Mp1xxAdcCalibration(struct Mp1xxAdcDevice *stm32mp1)
88 {
89 uint32_t value;
90 uint32_t delay = 0;
91
92 OSAL_WRITEL(0, stm32mp1->regBase + MP1XX_ADC_CR_OFFSET);
93 OSAL_WRITEL(MP1XX_ADC_REGULATOR_EN, stm32mp1->regBase + MP1XX_ADC_CR_OFFSET);
94 while (1) {
95 value = OSAL_READL(stm32mp1->regBase + MP1XX_ADC_ISR_OFFSET);
96 if (((value >> MP1XX_ADC_REGULATOR_RDY_SHIFT) & 0x1U) == 1 || delay > MP1XX_ADC_CAL_TIME_OUT) {
97 break;
98 }
99 OsalMDelay(1);
100 delay++;
101 }
102 delay = 0;
103 value = OSAL_READL(stm32mp1->regBase + MP1XX_ADC_CR_OFFSET);
104 value |= 0x1U << MP1XX_ADC_ADCAL_SHIFT;
105 OSAL_WRITEL(value, stm32mp1->regBase + MP1XX_ADC_CR_OFFSET);
106 while (1) {
107 value = OSAL_READL(stm32mp1->regBase + MP1XX_ADC_CR_OFFSET);
108 if (((value >> MP1XX_ADC_ADCAL_SHIFT) & 0x1U) == 0 || delay > MP1XX_ADC_CAL_TIME_OUT) {
109 break;
110 }
111 OsalMDelay(1);
112 delay++;
113 }
114 }
115
Mp1xxAdcClkEnable(struct Mp1xxAdcDevice * stm32mp1)116 static inline void Mp1xxAdcClkEnable(struct Mp1xxAdcDevice *stm32mp1)
117 {
118 (void)stm32mp1;
119 static bool hasInit = false;
120 if (hasInit == true) {
121 return;
122 }
123
124 __HAL_RCC_ADC12_CLK_ENABLE();
125 hasInit = true;
126 }
127
Mp1xxAdcEnable(struct Mp1xxAdcDevice * stm32mp1)128 static inline void Mp1xxAdcEnable(struct Mp1xxAdcDevice *stm32mp1)
129 {
130 uint32_t value = 0;
131
132 value = OSAL_READL(stm32mp1->regBase + MP1XX_ADC_CR_OFFSET);
133 OSAL_WRITEL((value | 1), stm32mp1->regBase + MP1XX_ADC_CR_OFFSET);
134 }
135
Mp1xxAdcDeviceInit(struct Mp1xxAdcDevice * stm32mp1)136 static inline void Mp1xxAdcDeviceInit(struct Mp1xxAdcDevice *stm32mp1)
137 {
138 if (!stm32mp1->adcEnable) {
139 return;
140 }
141 Mp1xxAdcClkEnable(stm32mp1);
142 Mp1xxAdcPinInit(stm32mp1);
143 Mp1xxAdcCalibration(stm32mp1);
144 Mp1xxAdcReset(stm32mp1);
145 Mp1xxAdcSetConfig(stm32mp1);
146 Mp1xxAdcSetSampleTime(stm32mp1);
147 Mp1xxAdcEnable(stm32mp1);
148 }
149
Mp1xxAdcStart(struct Mp1xxAdcDevice * stm32mp1)150 static inline void Mp1xxAdcStart(struct Mp1xxAdcDevice *stm32mp1)
151 {
152 uint32_t value;
153
154 value = OSAL_READL(stm32mp1->regBase + MP1XX_ADC_CR_OFFSET);
155
156 value |= 0x1U << MP1XX_ADC_ADSTART_SHIFT;
157 value |= MP1XX_ADC_ENABLE;
158 OSAL_WRITEL(value, stm32mp1->regBase + MP1XX_ADC_CR_OFFSET);
159 }
160
Mp1xxAdcOpen(struct AdcDevice * device)161 static int32_t Mp1xxAdcOpen(struct AdcDevice *device)
162 {
163 struct Mp1xxAdcDevice *stm32mp1 = NULL;
164
165 if (device == NULL) {
166 HDF_LOGE("%s: device is NULL!", __func__);
167 return HDF_ERR_INVALID_OBJECT;
168 }
169
170 stm32mp1 = (struct Mp1xxAdcDevice *)device;
171 if (!stm32mp1->adcEnable) {
172 HDF_LOGE("%s: ADC %u is disabled!", __func__, stm32mp1->devNum);
173 return HDF_ERR_NOT_SUPPORT;
174 }
175
176 Mp1xxAdcStart(stm32mp1);
177 return HDF_SUCCESS;
178 }
179
Mp1xxAdcClose(struct AdcDevice * device)180 static int32_t Mp1xxAdcClose(struct AdcDevice *device)
181 {
182 (void)device;
183 return HDF_SUCCESS;
184 }
185
Mp1xxAdcSetSequence(struct Mp1xxAdcDevice * stm32mp1,uint32_t channel)186 static inline void Mp1xxAdcSetSequence(struct Mp1xxAdcDevice *stm32mp1, uint32_t channel)
187 {
188 uint32_t value;
189
190 if (channel >= MP1XX_ADC_CHANNEL_COUNT_MAX) {
191 return;
192 }
193 value = channel << MP1XX_ADC_SQ1_SHIFT;
194 OSAL_WRITEL(value, stm32mp1->regBase + MP1XX_ADC_SQR1_OFFSET);
195
196 value = 0x1U << channel;
197 OSAL_WRITEL(value, stm32mp1->regBase + MP1XX_ADC_PCSEL_OFFSET);
198 }
199
Mp1xxAdcRead(struct AdcDevice * device,uint32_t channel,uint32_t * val)200 static int32_t Mp1xxAdcRead(struct AdcDevice *device, uint32_t channel, uint32_t *val)
201 {
202 uint32_t value;
203 uint32_t delay = 0;
204 struct Mp1xxAdcDevice *stm32mp1 = NULL;
205
206 if (device == NULL || val == NULL) {
207 HDF_LOGE("%s: device or val is NULL!", __func__);
208 return HDF_ERR_INVALID_OBJECT;
209 }
210
211 if (channel >= MP1XX_ADC_CHANNEL_COUNT_MAX) {
212 HDF_LOGE("%s: invalid channel: %u!", __func__, channel);
213 return HDF_ERR_INVALID_PARAM;
214 }
215
216 stm32mp1 = (struct Mp1xxAdcDevice *)device;
217 if (!stm32mp1->adcEnable) {
218 HDF_LOGE("%s: ADC %u is disabled!", __func__, stm32mp1->devNum);
219 return HDF_ERR_NOT_SUPPORT;
220 }
221
222 Mp1xxAdcSetSequence(stm32mp1, channel);
223 Mp1xxAdcStart(stm32mp1);
224 while (true) {
225 value = OSAL_READL(stm32mp1->regBase + MP1XX_ADC_ISR_OFFSET);
226 if ((value & MP1XX_ADC_EOC_MASK) != 0 || delay > MP1XX_ADC_CONV_TIME_OUT) {
227 OSAL_WRITEL(value, stm32mp1->regBase + MP1XX_ADC_ISR_OFFSET);
228 break;
229 }
230 OsalUDelay(1);
231 delay++;
232 }
233
234 value = OSAL_READL(stm32mp1->regBase + MP1XX_ADC_DR_OFFSET);
235 *val = value >> (MP1XX_ADC_DATA_WIDTH_MAX - stm32mp1->dataWidth);
236
237 return HDF_SUCCESS;
238 }
239
240 static const struct AdcMethod g_method = {
241 .start = Mp1xxAdcOpen,
242 .stop = Mp1xxAdcClose,
243 .read = Mp1xxAdcRead,
244 };
245
Mp1xxAdcReadDrs(struct Mp1xxAdcDevice * stm32mp1,const struct DeviceResourceNode * node)246 static int32_t Mp1xxAdcReadDrs(struct Mp1xxAdcDevice *stm32mp1, const struct DeviceResourceNode *node)
247 {
248 int32_t ret;
249 struct DeviceResourceIface *drsOps = NULL;
250
251 drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
252 if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetUint8Array == NULL || drsOps->GetBool == NULL) {
253 HDF_LOGE("%s: invalid drs ops", __func__);
254 return HDF_ERR_NOT_SUPPORT;
255 }
256
257 ret = drsOps->GetUint32(node, "reg_pbase", &stm32mp1->regBasePhy, 0);
258 if (ret != HDF_SUCCESS) {
259 HDF_LOGE("%s: read regBasePhy failed", __func__);
260 return ret;
261 }
262
263 ret = drsOps->GetUint32(node, "reg_size", &stm32mp1->regSize, 0);
264 if (ret != HDF_SUCCESS) {
265 HDF_LOGE("%s: read regSize failed", __func__);
266 return ret;
267 }
268
269 ret = drsOps->GetUint32(node, "dev_num", &stm32mp1->devNum, 0);
270 if (ret != HDF_SUCCESS) {
271 HDF_LOGE("%s: read devNum failed", __func__);
272 return ret;
273 }
274
275 ret = drsOps->GetUint8Array(node, "channel_enable", stm32mp1->validChannel, MP1XX_ADC_CHANNEL_COUNT_MAX, 0);
276 if (ret != HDF_SUCCESS) {
277 HDF_LOGE("%s: read validChannel failed", __func__);
278 return ret;
279 }
280
281 ret = drsOps->GetUint32(node, "sample_time", &stm32mp1->sampleTime, 0);
282 if (ret != HDF_SUCCESS) {
283 HDF_LOGE("%s: read sampleTime failed", __func__);
284 return ret;
285 }
286
287 ret = drsOps->GetUint32(node, "data_width", &stm32mp1->dataWidth, 0);
288 if (ret != HDF_SUCCESS) {
289 HDF_LOGE("%s: read dataWidth failed", __func__);
290 return ret;
291 }
292
293 stm32mp1->adcEnable = drsOps->GetBool(node, "adc_enable");
294
295 ret = drsOps->GetUint8Array(node, "pins", stm32mp1->pins, MP1XX_ADC_CHANNEL_COUNT_MAX, 0);
296 if (ret != HDF_SUCCESS) {
297 HDF_LOGE("%s: read pin failed", __func__);
298 return ret;
299 }
300
301 return HDF_SUCCESS;
302 }
303
Mp1xxAdcParseInit(struct HdfDeviceObject * device,struct DeviceResourceNode * node)304 static int32_t Mp1xxAdcParseInit(struct HdfDeviceObject *device, struct DeviceResourceNode *node)
305 {
306 int32_t ret;
307 struct Mp1xxAdcDevice *stm32mp1 = NULL;
308 (void)device;
309
310 stm32mp1 = (struct Mp1xxAdcDevice *)OsalMemCalloc(sizeof(*stm32mp1));
311 if (stm32mp1 == NULL) {
312 HDF_LOGE("%s: alloc stm32mp1 failed", __func__);
313 return HDF_ERR_MALLOC_FAIL;
314 }
315
316 ret = Mp1xxAdcReadDrs(stm32mp1, node);
317 if (ret != HDF_SUCCESS) {
318 HDF_LOGE("%s: read drs failed:%d", __func__, ret);
319 goto ERR;
320 }
321
322 stm32mp1->regBase = OsalIoRemap(stm32mp1->regBasePhy, stm32mp1->regSize);
323 if (stm32mp1->regBase == NULL) {
324 HDF_LOGE("%s: remap regbase failed", __func__);
325 ret = HDF_ERR_IO;
326 goto ERR;
327 }
328
329 Mp1xxAdcDeviceInit(stm32mp1);
330 stm32mp1->device.priv = (void *)node;
331 stm32mp1->device.devNum = stm32mp1->devNum;
332 stm32mp1->device.ops = &g_method;
333 ret = AdcDeviceAdd(&stm32mp1->device);
334 if (ret != HDF_SUCCESS) {
335 HDF_LOGE("%s: add adc device:%u failed", __func__, stm32mp1->devNum);
336 goto ERR;
337 }
338 return HDF_SUCCESS;
339
340 ERR:
341 if (stm32mp1 != NULL) {
342 if (stm32mp1->regBase != NULL) {
343 OsalIoUnmap((void *)stm32mp1->regBase);
344 stm32mp1->regBase = NULL;
345 }
346 AdcDeviceRemove(&stm32mp1->device);
347 OsalMemFree(stm32mp1);
348 }
349 return ret;
350 }
351
Mp1xxAdcInit(struct HdfDeviceObject * device)352 static int32_t Mp1xxAdcInit(struct HdfDeviceObject *device)
353 {
354 int32_t ret;
355 struct DeviceResourceNode *childNode = NULL;
356
357 HDF_LOGI("%s: Enter", __func__);
358 if (device == NULL || device->property == NULL) {
359 HDF_LOGE("%s: device or property is null", __func__);
360 return HDF_ERR_INVALID_OBJECT;
361 }
362
363 ret = HDF_SUCCESS;
364 DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode)
365 {
366 ret = Mp1xxAdcParseInit(device, childNode);
367 if (ret != HDF_SUCCESS) {
368 break;
369 }
370 }
371 return ret;
372 }
373
Mp1xxAdcRemoveByNode(const struct DeviceResourceNode * node)374 static void Mp1xxAdcRemoveByNode(const struct DeviceResourceNode *node)
375 {
376 int32_t ret;
377 int32_t devNum;
378 struct AdcDevice *device = NULL;
379 struct Mp1xxAdcDevice *stm32mp1 = NULL;
380 struct DeviceResourceIface *drsOps = NULL;
381
382 drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
383 if (drsOps == NULL || drsOps->GetUint32 == NULL) {
384 HDF_LOGE("%s: invalid drs ops", __func__);
385 return;
386 }
387
388 ret = drsOps->GetUint32(node, "devNum", (uint32_t *)&devNum, 0);
389 if (ret != HDF_SUCCESS) {
390 HDF_LOGE("%s: read devNum failed", __func__);
391 return;
392 }
393
394 device = AdcDeviceGet(devNum);
395 if (device != NULL && device->priv == node) {
396 AdcDevicePut(device);
397 AdcDeviceRemove(device);
398 stm32mp1 = (struct Mp1xxAdcDevice *)device;
399 OsalIoUnmap((void *)stm32mp1->regBase);
400 OsalMemFree(stm32mp1);
401 }
402 return;
403 }
404
Mp1xxAdcRelease(struct HdfDeviceObject * device)405 static void Mp1xxAdcRelease(struct HdfDeviceObject *device)
406 {
407 const struct DeviceResourceNode *childNode = NULL;
408
409 HDF_LOGI("%s: enter", __func__);
410 if (device == NULL || device->property == NULL) {
411 HDF_LOGE("%s: device or property is null", __func__);
412 return;
413 }
414 DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode)
415 {
416 Mp1xxAdcRemoveByNode(childNode);
417 }
418 }
419
420 static struct HdfDriverEntry g_stm32mp1AdcDriverEntry = {
421 .moduleVersion = 1,
422 .Init = Mp1xxAdcInit,
423 .Release = Mp1xxAdcRelease,
424 .moduleName = "stm32mp157_adc_driver",
425 };
426 HDF_INIT(g_stm32mp1AdcDriverEntry);
427