1 /*
2  * Copyright (c) 2022 Chipsea Technologies (Shenzhen) Corp., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include <securec.h>
10 #include "osal_mem.h"
11 #include "osal_io.h"
12 #include "sensor_ppg_config.h"
13 
14 static struct PpgCfgData *g_ppgCfg = NULL;
15 
16 #define HDF_LOG_TAG    khdf_sensor_ppg_config_driver
17 
InitPpgCfgData()18 static int32_t InitPpgCfgData()
19 {
20     g_ppgCfg = (struct PpgCfgData *)OsalMemCalloc(sizeof(*g_ppgCfg));
21     if (g_ppgCfg == NULL) {
22         HDF_LOGE("%s: malloc failed!", __func__);
23         return HDF_FAILURE;
24     }
25     (void)memset_s(g_ppgCfg, sizeof(*g_ppgCfg), 0, sizeof(*g_ppgCfg));
26     return HDF_SUCCESS;
27 }
28 
GetPpgConfig(void)29 struct PpgCfgData *GetPpgConfig(void)
30 {
31     return g_ppgCfg;
32 }
33 
ParsePpgPinMuxConfig(struct DeviceResourceIface * parser,const struct DeviceResourceNode * node,struct PpgPinCfg * pinCfg)34 static int32_t ParsePpgPinMuxConfig(struct DeviceResourceIface *parser,
35     const struct DeviceResourceNode *node, struct PpgPinCfg *pinCfg)
36 {
37     int32_t ret;
38     int32_t num;
39     struct MultiUsePinSetCfg *mutiPinConfig = NULL;
40 
41     num = parser->GetElemNum(node, "multiUseSet");
42     if ((num <= 0) || (num > PPG_PIN_CONFIG_MAX_ITEM) || ((num % PPG_PIN_CFG_INDEX_MAX) != 0)) {
43         HDF_LOGW("%s: parser multiUseSet size overflow, ignore this config, num = %d", __func__, num);
44         return HDF_SUCCESS;
45     }
46 
47     if (pinCfg->multiUsePin == NULL) {
48         pinCfg->multiUsePin = (struct MultiUsePinSetCfg *)OsalMemCalloc(sizeof(uint32_t) * num);
49         if (pinCfg->multiUsePin == NULL) {
50             HDF_LOGE("%s: malloc ppg multiUsePin config item failed", __func__);
51             return HDF_ERR_MALLOC_FAIL;
52         }
53     }
54 
55     ret = parser->GetUint32Array(node, "multiUseSet", (uint32_t *)pinCfg->multiUsePin, num, 0);
56     if (ret != HDF_SUCCESS) {
57         HDF_LOGE("%s: parser multiUseSet reg array failed", __func__);
58         return HDF_FAILURE;
59     }
60 
61     for (uint32_t index = 0; index < (num / PPG_PIN_CFG_INDEX_MAX); ++index) {
62         mutiPinConfig = &pinCfg->multiUsePin[index];
63         ret = SetSensorPinMux(mutiPinConfig->regAddr, mutiPinConfig->regLen, mutiPinConfig->regValue);
64         if (ret != HDF_SUCCESS) {
65             HDF_LOGE("%s: SetSensorPinMux failed, index %d, reg=0x%x, len=%d, val=0x%x", __func__, index,
66                      mutiPinConfig->regAddr, mutiPinConfig->regLen, mutiPinConfig->regValue);
67             return HDF_FAILURE;
68         }
69     }
70 
71     return HDF_SUCCESS;
72 }
73 
ParsePpgGpiosConfig(struct DeviceResourceIface * parser,const struct DeviceResourceNode * node,struct PpgPinCfg * pinCfg)74 static int32_t ParsePpgGpiosConfig(struct DeviceResourceIface *parser,
75                                    const struct DeviceResourceNode *node, struct PpgPinCfg *pinCfg)
76 {
77     int32_t ret;
78     int32_t num;
79     struct GpiosPinSetCfg *gpioCfg = NULL;
80 
81     num = parser->GetElemNum(node, "gipos");
82     if ((num <= 0) || (num > PPG_PIN_CONFIG_MAX_ITEM) || ((num % PPG_GPIOS_INDEX_MAX) != 0)) {
83         HDF_LOGE("%s: parser gipos size overflow, ignore this config, num = %d", __func__, num);
84         return HDF_SUCCESS;
85     }
86 
87     if (pinCfg->gpios == NULL) {
88         pinCfg->gpios = (struct GpiosPinSetCfg *)OsalMemCalloc(sizeof(uint16_t) * num);
89         if (pinCfg->gpios == NULL) {
90             HDF_LOGE("%s: malloc ppg gipos config item failed", __func__);
91             return HDF_ERR_MALLOC_FAIL;
92         }
93     }
94 
95     ret = parser->GetUint16Array(node, "gipos", (uint16_t *)pinCfg->gpios, num, 0);
96     if (ret != HDF_SUCCESS) {
97         HDF_LOGE("%s: parser gipos reg array failed", __func__);
98         return HDF_FAILURE;
99     }
100 
101     pinCfg->gpioNum = 0;
102 
103     for (uint32_t index = 0; index < (num / PPG_GPIOS_INDEX_MAX); ++index) {
104         gpioCfg = &pinCfg->gpios[index];
105         ret = GpioSetDir(gpioCfg->gpioNo, gpioCfg->dirType);
106         if (ret != HDF_SUCCESS) {
107             HDF_LOGE("%s: GpioSetDir is error, ret = %d!", __func__, ret);
108             return HDF_FAILURE;
109         }
110 
111         if (pinCfg->gpios[index].gpioType == PPG_TYPE_GPIO) {
112             ret = GpioWrite(gpioCfg->gpioNo, gpioCfg->gpioValue);
113             if (ret != HDF_SUCCESS) {
114                 HDF_LOGE("%s: GpioWrite is error, ret = %d!", __func__, ret);
115                 return HDF_FAILURE;
116             }
117         }
118         pinCfg->gpioNum++;
119     }
120 
121     return HDF_SUCCESS;
122 }
123 
ParsePpgPinConfig(struct DeviceResourceIface * parser,const struct DeviceResourceNode * pinCfgNode,struct PpgPinCfg * config)124 int32_t ParsePpgPinConfig(struct DeviceResourceIface *parser,
125                           const struct DeviceResourceNode *pinCfgNode, struct PpgPinCfg *config)
126 {
127     int32_t ret;
128 
129     ret = ParsePpgPinMuxConfig(parser, pinCfgNode, config);
130     if (ret != HDF_SUCCESS) {
131         HDF_LOGE("%s: pin mux config failed!", __func__);
132         return HDF_FAILURE;
133     }
134 
135     ret = ParsePpgGpiosConfig(parser, pinCfgNode, config);
136     if (ret != HDF_SUCCESS) {
137         HDF_LOGE("%s: gpios config failed!", __func__);
138         return HDF_FAILURE;
139     }
140 
141     HDF_LOGI("%s: Parse and Set pin success!", __func__);
142     return HDF_SUCCESS;
143 }
144 
EnablePpgIrq(uint16_t pinIndex)145 int32_t EnablePpgIrq(uint16_t pinIndex)
146 {
147     struct PpgCfgData *config = GetPpgConfig();
148     struct GpiosPinSetCfg *gpio = NULL;
149     CHECK_NULL_PTR_RETURN_VALUE(config, HDF_ERR_INVALID_PARAM);
150     CHECK_NULL_PTR_RETURN_VALUE(config->pinCfg.gpios, HDF_ERR_INVALID_PARAM);
151 
152     for (uint16_t gpioIndex = 0; gpioIndex < config->pinCfg.gpioNum; gpioIndex++) {
153         gpio = &config->pinCfg.gpios[gpioIndex];
154         CHECK_NULL_PTR_RETURN_VALUE(gpio, HDF_ERR_INVALID_PARAM);
155         if ((gpio->gpioType == PPG_TYPE_IRQ) && (pinIndex == gpio->pinIndex)) {
156             if (GpioEnableIrq(gpio->gpioNo) != 0) {
157                 break;
158             }
159             return HDF_SUCCESS;
160         }
161     }
162     HDF_LOGE("%s: failed!", __func__);
163     return HDF_FAILURE;
164 }
165 
DisablePpgIrq(uint16_t pinIndex)166 int32_t DisablePpgIrq(uint16_t pinIndex)
167 {
168     struct PpgCfgData *config = GetPpgConfig();
169     struct GpiosPinSetCfg *gpio = NULL;
170     CHECK_NULL_PTR_RETURN_VALUE(config, HDF_ERR_INVALID_PARAM);
171     CHECK_NULL_PTR_RETURN_VALUE(config->pinCfg.gpios, HDF_ERR_INVALID_PARAM);
172 
173     for (uint16_t gpioIndex = 0; gpioIndex < config->pinCfg.gpioNum; gpioIndex++) {
174         gpio = &config->pinCfg.gpios[gpioIndex];
175         CHECK_NULL_PTR_RETURN_VALUE(gpio, HDF_ERR_INVALID_PARAM);
176         if ((gpio->gpioType == PPG_TYPE_IRQ) && (pinIndex == gpio->pinIndex)) {
177             if (GpioDisableIrq(gpio->gpioNo) != 0) {
178                 break;
179             }
180             return HDF_SUCCESS;
181         }
182     }
183     HDF_LOGE("%s: failed!", __func__);
184     return HDF_FAILURE;
185 }
186 
SetPpgIrq(uint16_t pinIndex,GpioIrqFunc irqFunc)187 int32_t SetPpgIrq(uint16_t pinIndex, GpioIrqFunc irqFunc)
188 {
189     struct PpgCfgData *config = GetPpgConfig();
190     struct GpiosPinSetCfg *gpio = NULL;
191     CHECK_NULL_PTR_RETURN_VALUE(config, HDF_ERR_INVALID_PARAM);
192     CHECK_NULL_PTR_RETURN_VALUE(irqFunc, HDF_ERR_INVALID_PARAM);
193     CHECK_NULL_PTR_RETURN_VALUE(config->pinCfg.gpios, HDF_ERR_INVALID_PARAM);
194 
195     for (uint16_t gpioIndex = 0; gpioIndex < config->pinCfg.gpioNum; gpioIndex++) {
196         gpio = &config->pinCfg.gpios[gpioIndex];
197         CHECK_NULL_PTR_RETURN_VALUE(gpio, HDF_ERR_INVALID_PARAM);
198         if ((gpio->pinIndex == pinIndex) && (gpio->gpioType == PPG_TYPE_IRQ)) {
199             if (GpioSetIrq(gpio->gpioNo, gpio->triggerMode, irqFunc, NULL) != 0) {
200                 break;
201             }
202             return HDF_SUCCESS;
203         }
204     }
205 
206     HDF_LOGE("%s: failed!", __func__);
207     return HDF_FAILURE;
208 }
209 
GetPinConfigData(const struct DeviceResourceNode * node,struct PpgPinCfg * pinCfg)210 static int32_t GetPinConfigData(const struct DeviceResourceNode *node, struct PpgPinCfg *pinCfg)
211 {
212     int32_t ret = HDF_FAILURE;
213     struct DeviceResourceIface *parser = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
214     CHECK_NULL_PTR_RETURN_VALUE(parser, HDF_ERR_INVALID_PARAM);
215 
216     const struct DeviceResourceNode *pinCfgNode = parser->GetChildNode(node, "ppgPinConfig");
217     if (pinCfgNode != NULL) {
218         ret = ParsePpgPinConfig(parser, pinCfgNode, pinCfg);
219     }
220 
221     HDF_LOGI("%s: Parse and Set pin ret = %d!", __func__, ret);
222     return ret;
223 }
224 
ReleasePpgCfgData(void)225 void ReleasePpgCfgData(void)
226 {
227     CHECK_NULL_PTR_RETURN(g_ppgCfg);
228 
229     if (g_ppgCfg->pinCfg.multiUsePin != NULL) {
230         OsalMemFree(g_ppgCfg->pinCfg.multiUsePin);
231     }
232 
233     if (g_ppgCfg->pinCfg.gpios != NULL) {
234         OsalMemFree(g_ppgCfg->pinCfg.gpios);
235     }
236 
237     OsalMemFree(g_ppgCfg);
238     g_ppgCfg = NULL;
239 }
240 
ParsePpgCfgData(const struct DeviceResourceNode * node,struct PpgCfgData ** cfgData)241 int32_t ParsePpgCfgData(const struct DeviceResourceNode *node, struct PpgCfgData **cfgData)
242 {
243     int32_t ret;
244 
245     if (g_ppgCfg != NULL) {
246         HDF_LOGI("%s: ppg config already parsed.", __func__);
247         return HDF_SUCCESS;
248     }
249 
250     ret = InitPpgCfgData();
251     if (ret != HDF_SUCCESS) {
252         HDF_LOGE("%s: Init ppg config failed.", __func__);
253         return HDF_FAILURE;
254     }
255 
256     ret = GetSensorBaseConfigData(node, &g_ppgCfg->sensorCfg);
257     if (ret != HDF_SUCCESS) {
258         HDF_LOGE("%s: get sensor base config failed.", __func__);
259         ReleasePpgCfgData();
260         return HDF_FAILURE;
261     }
262 
263     ret = GetPinConfigData(node, &g_ppgCfg->pinCfg);
264     if (ret != HDF_SUCCESS) {
265         HDF_LOGE("%s: get pin config failed.", __func__);
266         ReleasePpgCfgData();
267         return HDF_FAILURE;
268     }
269 
270     *cfgData = g_ppgCfg;
271     return HDF_SUCCESS;
272 }
273