• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Bestechnic (Shanghai) Co., Ltd. All rights reserved.
3  *
4  * This file 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 "pwm_bes.h"
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include "hdf_device_desc.h"
13 #include "hal_trace.h"
14 #include "hal_timer.h"
15 #include "pwm_core.h"
16 #include "hdf_log.h"
17 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
18 #include "hcs_macro.h"
19 #include "hdf_config_macro.h"
20 #else
21 #include "device_resource_if.h"
22 #endif
23 
24 #if defined (LOSCFG_SOC_SERIES_BES2700)
25 #define PWM_MAX_FUNCTION 4
26 #elif defined (LOSCFG_SOC_SERIES_BES2600)
27 #include "hal_iomux.h"
28 #define PWM_MAX_FUNCTION 8
29 #endif
30 
31 #define UNTIL_NAN0SECONDS 1000000000
32 #define PERCENT 100
33 #define DEC_TEN 10
34 #define PIN_GROUP_NUM 8
35 
36 static uint32_t g_pwmFunction[PWM_MAX_FUNCTION] = {
37     HAL_IOMUX_FUNC_PWM0,
38     HAL_IOMUX_FUNC_PWM1,
39     HAL_IOMUX_FUNC_PWM2,
40     HAL_IOMUX_FUNC_PWM3,
41 #if defined (LOSCFG_SOC_SERIES_BES2600)
42     HAL_IOMUX_FUNC_PWM4,
43     HAL_IOMUX_FUNC_PWM5,
44     HAL_IOMUX_FUNC_PWM6,
45     HAL_IOMUX_FUNC_PWM7,
46 #endif
47 };
48 
49 static int32_t PwmDevSetConfig(struct PwmDev *pwm, struct PwmConfig *config);
50 static int32_t PwmDevOpen(struct PwmDev *pwm);
51 static int32_t PwmDevClose(struct PwmDev *pwm);
52 
53 struct PwmMethod g_pwmmethod = {
54     .setConfig = PwmDevSetConfig,
55     .open = PwmDevOpen,
56     .close = PwmDevClose,
57 };
58 
InitPwmDevice(const struct PwmDev * host)59 static int InitPwmDevice(const struct PwmDev *host)
60 {
61     struct PwmDevice *pwmDevice = NULL;
62     struct PwmResource *resource = NULL;
63 
64     if (host == NULL || host->priv == NULL) {
65         HDF_LOGE("%s: invalid parameter\r\n", __func__);
66         return HDF_ERR_INVALID_PARAM;
67     }
68     pwmDevice = (struct PwmDevice *)host->priv;
69     resource = &pwmDevice->resource;
70     if (resource == NULL) {
71         HDF_LOGE("resource is NULL\r\n");
72         return HDF_ERR_INVALID_OBJECT;
73     }
74 
75     struct HAL_IOMUX_PIN_FUNCTION_MAP pinMuxPwm[] = {
76         {0, 0, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_NOPULL},
77     };
78 
79     pinMuxPwm->pin = resource->pwmPin;
80     pinMuxPwm->function = g_pwmFunction[resource->pwmId];
81 
82     hal_iomux_init(pinMuxPwm, ARRAY_SIZE(pinMuxPwm));
83 
84     return HDF_SUCCESS;
85 }
86 
87 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
88 #define PWM_FIND_CONFIG(node, name, resource) \
89     do { \
90         if (strcmp(HCS_PROP(node, match_attr), name) == 0) { \
91             tempPin = HCS_PROP(node, pwmPin); \
92             resource->pwmPin = ((tempPin / DEC_TEN) * PIN_GROUP_NUM) + (tempPin % DEC_TEN); \
93             resource->pwmId = HCS_PROP(node, pwmId); \
94             result = HDF_SUCCESS; \
95             break; \
96         } \
97     } while (0)
98 #define PLATFORM_PWM_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), pwm_config)
GetPwmDeviceResource(struct PwmDevice * device,const char * deviceMatchAttr)99 static uint32_t GetPwmDeviceResource(struct PwmDevice *device, const char *deviceMatchAttr)
100 {
101     int32_t result = HDF_FAILURE;
102     struct PwmResource *resource = NULL;
103     if (device == NULL || deviceMatchAttr == NULL) {
104         HDF_LOGE("%s: device or deviceMatchAttr is NULL", __func__);
105         return HDF_ERR_INVALID_PARAM;
106     }
107     resource = &device->resource;
108 #if HCS_NODE_EXISTS(PLATFORM_PWM_CONFIG)
109     HCS_FOREACH_CHILD_VARGS(PLATFORM_PWM_CONFIG, PWM_FIND_CONFIG, deviceMatchAttr, resource);
110 #endif
111     if (result != HDF_SUCCESS) {
112         HDF_LOGE("resourceNode %s is NULL\r\n", deviceMatchAttr);
113     }
114     return result;
115 }
116 #else
GetPwmDeviceResource(struct PwmDevice * device,const struct DeviceResourceNode * resourceNode)117 static uint32_t GetPwmDeviceResource(
118     struct PwmDevice *device, const struct DeviceResourceNode *resourceNode)
119 {
120     uint32_t tempPin = 0;
121     struct DeviceResourceIface *dri = NULL;
122     struct PwmResource *resource = NULL;
123     if (device == NULL || resourceNode == NULL) {
124         HDF_LOGE("resource or device is NULL\r\n");
125         return HDF_ERR_INVALID_PARAM;
126     }
127 
128     resource = &device->resource;
129     if (resource == NULL) {
130         HDF_LOGE("resource is NULL\r\n");
131         return HDF_ERR_INVALID_OBJECT;
132     }
133 
134     dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
135     if (dri == NULL || dri->GetUint32 == NULL) {
136         HDF_LOGE("DeviceResourceIface is invalid\r\n");
137         return HDF_ERR_INVALID_PARAM;
138     }
139 
140     if (dri->GetUint32(resourceNode, "pwmPin", &tempPin, 0) != HDF_SUCCESS) {
141         HDF_LOGE("read pwmPin fail\r\n");
142         return HDF_FAILURE;
143     }
144     resource->pwmPin = ((tempPin / DEC_TEN) * PIN_GROUP_NUM) + (tempPin % DEC_TEN);
145 
146     if (dri->GetUint32(resourceNode, "pwmId", &resource->pwmId, 0) != HDF_SUCCESS) {
147         HDF_LOGE("read pwmId fail\r\n");
148         return HDF_FAILURE;
149     }
150 
151     return HDF_SUCCESS;
152 }
153 #endif
AttachPwmDevice(struct PwmDev * host,const struct HdfDeviceObject * device)154 static int32_t AttachPwmDevice(struct PwmDev *host, const struct HdfDeviceObject *device)
155 {
156     int32_t ret;
157     struct PwmDevice *pwmDevice = NULL;
158 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
159     if (device == NULL || host == NULL) {
160 #else
161     if (device == NULL || device->property == NULL || host == NULL) {
162 #endif
163         HDF_LOGE("%s: param is NULL\r\n", __func__);
164         return HDF_ERR_INVALID_PARAM;
165     }
166 
167     pwmDevice = (struct PwmDevice *)OsalMemAlloc(sizeof(struct PwmDevice));
168     if (pwmDevice == NULL) {
169         HDF_LOGE("%s: OsalMemAlloc pwmDevice error\r\n", __func__);
170         return HDF_ERR_MALLOC_FAIL;
171     }
172 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
173     ret = GetPwmDeviceResource(pwmDevice, device->deviceMatchAttr);
174 #else
175     ret = GetPwmDeviceResource(pwmDevice, device->property);
176 #endif
177     if (ret != HDF_SUCCESS) {
178         (void)OsalMemFree(pwmDevice);
179         return HDF_FAILURE;
180     }
181 
182     host->priv = pwmDevice;
183     host->num = pwmDevice->resource.pwmId;
184 
185     return InitPwmDevice(host);
186 }
187 /* HdfDriverEntry method definitions */
188 static int32_t PwmDriverBind(struct HdfDeviceObject *device);
189 static int32_t PwmDriverInit(struct HdfDeviceObject *device);
190 static void PwmDriverRelease(struct HdfDeviceObject *device);
191 
192 /* HdfDriverEntry definitions */
193 struct HdfDriverEntry g_pwmDriverEntry = {
194     .moduleVersion = 1,
195     .moduleName = "BES_PWM_MODULE_HDF",
196     .Bind = PwmDriverBind,
197     .Init = PwmDriverInit,
198     .Release = PwmDriverRelease,
199 };
200 
201 // Initialize HdfDriverEntry
202 HDF_INIT(g_pwmDriverEntry);
203 
204 static int32_t PwmDriverBind(struct HdfDeviceObject *device)
205 {
206     static struct PwmDev devService;
207 
208     if (device == NULL) {
209         HDF_LOGE("hdfDevice object is null!\r\n");
210         return HDF_FAILURE;
211     }
212 
213     device->service = &devService.service;
214     devService.device = device;
215     HDF_LOGI("Enter %s\r\n", __func__);
216 
217     return HDF_SUCCESS;
218 }
219 
220 static int32_t PwmDriverInit(struct HdfDeviceObject *device)
221 {
222     int32_t ret;
223     struct PwmDev *host = NULL;
224 
225     if (device == NULL) {
226         HDF_LOGE("%s: device is NULL\r\n", __func__);
227         return HDF_ERR_INVALID_OBJECT;
228     }
229 
230     HDF_LOGI("Enter %s:\r\n", __func__);
231 
232     host = (struct PwmDev *)device->service;
233     if (host == NULL) {
234         HDF_LOGE("%s: host is NULL\r\n", __func__);
235         return HDF_ERR_MALLOC_FAIL;
236     }
237 
238     ret = AttachPwmDevice(host, device);
239     if (ret != HDF_SUCCESS) {
240         HDF_LOGE("%s:attach error\r\n", __func__);
241         return HDF_DEV_ERR_ATTACHDEV_FAIL;
242     }
243 
244     host->method = &g_pwmmethod;
245     ret = PwmDeviceAdd(device, host);
246     if (ret != HDF_SUCCESS) {
247         PwmDeviceRemove(device, host);
248         OsalMemFree(host->device);
249         return HDF_DEV_ERR_NO_DEVICE;
250     }
251 
252     HDF_LOGI("PwmDriverInit success!\r\n");
253     return HDF_SUCCESS;
254 }
255 
256 static void PwmDriverRelease(struct HdfDeviceObject *device)
257 {
258     struct PwmDev *host = NULL;
259 
260     if (device == NULL || device->service == NULL) {
261         HDF_LOGE("device is null\r\n");
262         return;
263     }
264 
265     host = (struct PwmDev *)device->service;
266     if (host->device != NULL) {
267         host->method = NULL;
268         OsalMemFree(host->device);
269         host->device = NULL;
270         host = NULL;
271     }
272 
273     device->service = NULL;
274     HDF_LOGI("PwmDriverRelease finish!!\r\n");
275     return;
276 }
277 
278 static int32_t PwmDevSetConfig(struct PwmDev *pwm, struct PwmConfig *config)
279 {
280     struct PwmDevice *prvPwm = NULL;
281     struct HAL_PWM_CFG_T *pwmCfg = NULL;
282     enum HAL_PWM_ID_T pwmId;
283 
284     if (pwm == NULL || config == NULL || (config->period > UNTIL_NAN0SECONDS)) {
285         HDF_LOGE("%s\r\n", __FUNCTION__);
286         return HDF_FAILURE;
287     }
288 
289     prvPwm = (struct PwmDevice *)PwmGetPriv(pwm);
290     if (prvPwm == NULL) {
291         return HDF_FAILURE;
292     }
293     pwmCfg = &prvPwm->pwmCfg;
294     pwmCfg->freq = UNTIL_NAN0SECONDS / config->period;
295     pwmCfg->ratio = config->duty * PERCENT / config->period;
296     pwmCfg->inv = false;
297     pwmCfg->sleep_on = false;
298 
299     pwmId = prvPwm->resource.pwmId;
300 
301     if (config->status == PWM_ENABLE_STATUS) {
302         hal_pwm_enable(pwmId, pwmCfg);
303     } else {
304         hal_pwm_disable(pwmId);
305     }
306 
307     return HDF_SUCCESS;
308 }
309 
310 static int32_t PwmDevOpen(struct PwmDev *pwm)
311 {
312     if (pwm == NULL) {
313         HDF_LOGE("%s\r\n", __FUNCTION__);
314         return HDF_ERR_INVALID_PARAM;
315     }
316 
317     return HDF_SUCCESS;
318 }
319 
320 static int32_t PwmDevClose(struct PwmDev *pwm)
321 {
322     struct PwmDevice *prvPwm = NULL;
323     enum HAL_PWM_ID_T pwmId = 0;
324 
325     if (pwm == NULL) {
326         HDF_LOGE("%s\r\n", __FUNCTION__);
327         return HDF_ERR_INVALID_PARAM;
328     }
329 
330     prvPwm = (struct PwmDevice *)PwmGetPriv(pwm);
331     if (prvPwm == NULL) {
332         HDF_LOGE("%s\r\n", __FUNCTION__);
333         return HDF_DEV_ERR_NO_DEVICE;
334     }
335 
336     pwmId = prvPwm->resource.pwmId;
337 
338     hal_pwm_disable(pwmId);
339 
340     return HDF_SUCCESS;
341 }
342