• 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(struct PwmDev * host)59 static int InitPwmDevice(struct PwmDev *host)
60 {
61     struct PwmDevice *pwmDevice = NULL;
62     struct PwmResource *resource = NULL;
63     if (host == NULL || host->priv == NULL) {
64         HDF_LOGE("%s: invalid parameter\r\n", __func__);
65         return HDF_ERR_INVALID_PARAM;
66     }
67     pwmDevice = (struct PwmDevice *)host->priv;
68     if (pwmDevice == NULL) {
69         HDF_LOGE("pwmDevice is NULL\r\n");
70         return HDF_DEV_ERR_NO_DEVICE;
71     }
72 
73     resource = &pwmDevice->resource;
74     if (resource == NULL) {
75         HDF_LOGE("resource is NULL\r\n");
76         return HDF_ERR_INVALID_OBJECT;
77     }
78 
79     struct HAL_IOMUX_PIN_FUNCTION_MAP pinMuxPwm[] = {
80         {0, 0, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_NOPULL},
81     };
82 
83     pinMuxPwm->pin = resource->pwmPin;
84     pinMuxPwm->function = g_pwmFunction[resource->pwmId];
85 
86     hal_iomux_init(pinMuxPwm, ARRAY_SIZE(pinMuxPwm));
87 
88     return HDF_SUCCESS;
89 }
90 
GetPwmDeviceResource(struct PwmDevice * device,const struct DeviceResourceNode * resourceNode)91 static uint32_t GetPwmDeviceResource(struct PwmDevice *device, const struct DeviceResourceNode *resourceNode)
92 {
93     uint32_t tempPin = 0;
94     struct DeviceResourceIface *dri = NULL;
95     struct PwmResource *resource = NULL;
96     if (device == NULL || resourceNode == NULL) {
97         HDF_LOGE("resource or device is NULL\r\n");
98         return HDF_ERR_INVALID_PARAM;
99     }
100 
101     resource = &device->resource;
102     if (resource == NULL) {
103         HDF_LOGE("resource is NULL\r\n");
104         return HDF_ERR_INVALID_OBJECT;
105     }
106 
107     dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
108     if (dri == NULL || dri->GetUint32 == NULL) {
109         HDF_LOGE("DeviceResourceIface is invalid\r\n");
110         return HDF_ERR_INVALID_PARAM;
111     }
112 
113     if (dri->GetUint32(resourceNode, "pwmPin", &tempPin, 0) != HDF_SUCCESS) {
114         HDF_LOGE("read pwmPin fail\r\n");
115         return HDF_FAILURE;
116     }
117     resource->pwmPin = ((tempPin / DEC_TEN) * PIN_GROUP_NUM) + (tempPin % DEC_TEN);
118 
119     if (dri->GetUint32(resourceNode, "pwmId", &resource->pwmId, 0) != HDF_SUCCESS) {
120         HDF_LOGE("read pwmId fail\r\n");
121         return HDF_FAILURE;
122     }
123 
124     return HDF_SUCCESS;
125 }
126 
AttachPwmDevice(struct PwmDev * host,struct HdfDeviceObject * device)127 static int32_t AttachPwmDevice(struct PwmDev *host, struct HdfDeviceObject *device)
128 {
129     int32_t ret;
130     struct PwmDevice *pwmDevice = NULL;
131 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
132     if (device == NULL || host == NULL) {
133 #else
134     if (device == NULL || device->property == NULL || host == NULL) {
135 #endif
136         HDF_LOGE("%s: param is NULL\r\n", __func__);
137         return HDF_ERR_INVALID_PARAM;
138     }
139 
140     pwmDevice = (struct PwmDevice *)OsalMemAlloc(sizeof(struct PwmDevice));
141     if (pwmDevice == NULL) {
142         HDF_LOGE("%s: OsalMemAlloc pwmDevice error\r\n", __func__);
143         return HDF_ERR_MALLOC_FAIL;
144     }
145 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
146     ret = GetPwmDeviceResource(pwmDevice, device->deviceMatchAttr);
147 #else
148     ret = GetPwmDeviceResource(pwmDevice, device->property);
149 #endif
150     if (ret != HDF_SUCCESS) {
151         (void)OsalMemFree(pwmDevice);
152         return HDF_FAILURE;
153     }
154 
155     host->priv = pwmDevice;
156     host->num = pwmDevice->resource.pwmId;
157 
158     return InitPwmDevice(host);
159 }
160 /* HdfDriverEntry method definitions */
161 static int32_t PwmDriverBind(struct HdfDeviceObject *device);
162 static int32_t PwmDriverInit(struct HdfDeviceObject *device);
163 static void PwmDriverRelease(struct HdfDeviceObject *device);
164 
165 /* HdfDriverEntry definitions */
166 struct HdfDriverEntry g_pwmDriverEntry = {
167     .moduleVersion = 1,
168     .moduleName = "BES_PWM_MODULE_HDF",
169     .Bind = PwmDriverBind,
170     .Init = PwmDriverInit,
171     .Release = PwmDriverRelease,
172 };
173 
174 // Initialize HdfDriverEntry
175 HDF_INIT(g_pwmDriverEntry);
176 
177 static int32_t PwmDriverBind(struct HdfDeviceObject *device)
178 {
179     static struct PwmDev devService;
180 
181     if (device == NULL) {
182         HDF_LOGE("hdfDevice object is null!\r\n");
183         return HDF_FAILURE;
184     }
185 
186     device->service = &devService.service;
187     devService.device = device;
188     HDF_LOGI("Enter %s\r\n", __func__);
189 
190     return HDF_SUCCESS;
191 }
192 
193 static int32_t PwmDriverInit(struct HdfDeviceObject *device)
194 {
195     int32_t ret;
196     struct PwmDev *host = NULL;
197 
198     if (device == NULL) {
199         HDF_LOGE("%s: device is NULL\r\n", __func__);
200         return HDF_ERR_INVALID_OBJECT;
201     }
202 
203     HDF_LOGI("Enter %s:\r\n", __func__);
204 
205     host = (struct PwmDev *)device->service;
206     if (host == NULL) {
207         HDF_LOGE("%s: host is NULL\r\n", __func__);
208         return HDF_ERR_MALLOC_FAIL;
209     }
210 
211     ret = AttachPwmDevice(host, device);
212     if (ret != HDF_SUCCESS) {
213         HDF_LOGE("%s:attach error\r\n", __func__);
214         return HDF_DEV_ERR_ATTACHDEV_FAIL;
215     }
216 
217     host->method = &g_pwmmethod;
218     ret = PwmDeviceAdd(device, host);
219     if (ret != HDF_SUCCESS) {
220         PwmDeviceRemove(device, host);
221         OsalMemFree(host->device);
222         return HDF_DEV_ERR_NO_DEVICE;
223     }
224 
225     HDF_LOGI("PwmDriverInit success!\r\n");
226     return HDF_SUCCESS;
227 }
228 
229 static void PwmDriverRelease(struct HdfDeviceObject *device)
230 {
231     struct PwmDev *host = NULL;
232 
233     if (device == NULL || device->service == NULL) {
234         HDF_LOGE("device is null\r\n");
235         return;
236     }
237 
238     host = (struct PwmDev *)device->service;
239     if (host != NULL && host->device != NULL) {
240         host->method = NULL;
241         OsalMemFree(host->device);
242         host->device = NULL;
243         host = NULL;
244     }
245 
246     device->service = NULL;
247     HDF_LOGI("PwmDriverRelease finish!!\r\n");
248     return;
249 }
250 
251 static int32_t PwmDevSetConfig(struct PwmDev *pwm, struct PwmConfig *config)
252 {
253     struct PwmDevice *prvPwm = NULL;
254     struct HAL_PWM_CFG_T *pwmCfg = NULL;
255     enum HAL_PWM_ID_T pwmId;
256 
257     if (pwm == NULL || config == NULL || (config->period > UNTIL_NAN0SECONDS)) {
258         HDF_LOGE("%s\r\n", __FUNCTION__);
259         return HDF_FAILURE;
260     }
261 
262     prvPwm = (struct PwmDevice *)PwmGetPriv(pwm);
263     if (prvPwm == NULL) {
264         return HDF_FAILURE;
265     }
266     pwmCfg = &prvPwm->pwmCfg;
267     pwmCfg->freq = UNTIL_NAN0SECONDS / config->period;
268     pwmCfg->ratio = config->duty * PERCENT / config->period;
269     pwmCfg->inv = false;
270     pwmCfg->sleep_on = false;
271 
272     pwmId = prvPwm->resource.pwmId;
273 
274     if (config->status == PWM_ENABLE_STATUS) {
275         hal_pwm_enable(pwmId, pwmCfg);
276     } else {
277         hal_pwm_disable(pwmId);
278     }
279 
280     return HDF_SUCCESS;
281 }
282 
283 static int32_t PwmDevOpen(struct PwmDev *pwm)
284 {
285     if (pwm == NULL) {
286         HDF_LOGE("%s\r\n", __FUNCTION__);
287         return HDF_ERR_INVALID_PARAM;
288     }
289 
290     return HDF_SUCCESS;
291 }
292 
293 static int32_t PwmDevClose(struct PwmDev *pwm)
294 {
295     struct PwmDevice *prvPwm = NULL;
296     enum HAL_PWM_ID_T pwmId = 0;
297 
298     if (pwm == NULL) {
299         HDF_LOGE("%s\r\n", __FUNCTION__);
300         return HDF_ERR_INVALID_PARAM;
301     }
302 
303     prvPwm = (struct PwmDevice *)PwmGetPriv(pwm);
304     if (prvPwm == NULL) {
305         HDF_LOGE("%s\r\n", __FUNCTION__);
306         return HDF_DEV_ERR_NO_DEVICE;
307     }
308 
309     pwmId = prvPwm->resource.pwmId;
310 
311     hal_pwm_disable(pwmId);
312 
313     return HDF_SUCCESS;
314 }
315