1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
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 "pwm_hi35xx.h"
17 #include "device_resource_if.h"
18 #include "hdf_log.h"
19 #include "osal_io.h"
20 #include "osal_mem.h"
21 #include "pwm_core.h"
22
23 #define HDF_LOG_TAG pwm_hi35xx
24
25 struct HiPwm {
26 struct PwmDev dev;
27 volatile unsigned char *base;
28 struct HiPwmRegs *reg;
29 bool supportPolarity;
30 };
31
HiPwmSetConfig(struct PwmDev * pwm,struct PwmConfig * config)32 int32_t HiPwmSetConfig(struct PwmDev *pwm, struct PwmConfig *config)
33 {
34 struct HiPwm *hp = (struct HiPwm *)pwm;
35 if (hp == NULL || hp->reg == NULL || config == NULL) {
36 HDF_LOGE("%s: hp reg or config is null", __func__);
37 return HDF_ERR_INVALID_PARAM;
38 }
39 if (config->polarity != PWM_NORMAL_POLARITY && config->polarity != PWM_INVERTED_POLARITY) {
40 HDF_LOGE("%s: polarity %hhu is invalid", __func__, config->polarity);
41 return HDF_ERR_INVALID_PARAM;
42 }
43 if (config->period < PWM_MIN_PERIOD) {
44 HDF_LOGE("%s: period %u is not support, min period %d", __func__, config->period, PWM_MIN_PERIOD);
45 return HDF_ERR_INVALID_PARAM;
46 }
47 if (config->duty < 1 || config->duty > config->period) {
48 HDF_LOGE("%s: duty %u is not support, duty must in [1, period = %u].",
49 __func__, config->duty, config->period);
50 return HDF_ERR_INVALID_PARAM;
51 }
52 HiPwmDisable(hp->reg);
53 if (pwm->cfg.polarity != config->polarity && hp->supportPolarity) {
54 HiPwmSetPolarity(hp->reg, config->polarity);
55 HDF_LOGI("%s: [HiPwmSetPolarity] done, polarity: %hhu -> %hhu.", __func__, pwm->cfg.polarity, config->polarity);
56 }
57 if (pwm->cfg.period != config->period) {
58 HiPwmSetPeriod(hp->reg, config->period);
59 HDF_LOGI("%s: [HiPwmSetPeriod] done, period: %u -> %u", __func__, pwm->cfg.period, config->period);
60 }
61 if (pwm->cfg.duty != config->duty) {
62 HiPwmSetDuty(hp->reg, config->duty);
63 HDF_LOGI("%s: [HiPwmSetDuty] done, duty: %u -> %u", __func__, pwm->cfg.duty, config->duty);
64 }
65 if (config->status == PWM_ENABLE_STATUS) {
66 if (config->number == 0) {
67 HiPwmAlwaysOutput(hp->reg);
68 HDF_LOGI("%s: [HiPwmAlwaysOutput] done, then enable.", __func__);
69 } else {
70 HiPwmOutputNumberSquareWaves(hp->reg, config->number);
71 HDF_LOGI("%s: [HiPwmOutputNumberSquareWaves] done, then enable.", __func__);
72 }
73 }
74 HDF_LOGI("%s: set PwmConfig done: number %u, period %u, duty %u, polarity %hhu, enable %hhu.",
75 __func__, config->number, config->period, config->duty, config->polarity, config->status);
76 return HDF_SUCCESS;
77 }
78
79 struct PwmMethod g_pwmOps = {
80 .setConfig = HiPwmSetConfig,
81 };
82
HiPwmRemove(struct HiPwm * hp)83 static void HiPwmRemove(struct HiPwm *hp)
84 {
85 if (hp->base != NULL) {
86 OsalIoUnmap((void *)hp->base);
87 }
88 OsalMemFree(hp);
89 }
90
HiPwmProbe(struct HiPwm * hp,struct HdfDeviceObject * obj)91 static int32_t HiPwmProbe(struct HiPwm *hp, struct HdfDeviceObject *obj)
92 {
93 uint32_t tmp;
94 struct DeviceResourceIface *iface = NULL;
95
96 iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
97 if (iface == NULL || iface->GetUint32 == NULL) {
98 HDF_LOGE("%s: face is invalid", __func__);
99 return HDF_FAILURE;
100 }
101
102 if (iface->GetUint32(obj->property, "num", &(hp->dev.num), 0) != HDF_SUCCESS) {
103 HDF_LOGE("%s: read num fail", __func__);
104 return HDF_FAILURE;
105 }
106
107 if (iface->GetUint32(obj->property, "base", &tmp, 0) != HDF_SUCCESS) {
108 HDF_LOGE("%s: read base fail", __func__);
109 return HDF_FAILURE;
110 }
111
112 hp->base = OsalIoRemap(tmp, sizeof(struct HiPwmRegs));
113 if (hp->base == NULL) {
114 HDF_LOGE("%s: OsalIoRemap fail", __func__);
115 return HDF_FAILURE;
116 }
117
118 hp->reg = (struct HiPwmRegs *)hp->base;
119 hp->supportPolarity = true;
120 hp->dev.method = &g_pwmOps;
121 hp->dev.cfg.duty = PWM_DEFAULT_DUTY_CYCLE;
122 hp->dev.cfg.period = PWM_DEFAULT_PERIOD;
123 hp->dev.cfg.polarity = PWM_DEFAULT_POLARITY;
124 hp->dev.cfg.status = PWM_DISABLE_STATUS;
125 hp->dev.cfg.number = 0;
126 hp->dev.busy = false;
127 if (PwmDeviceAdd(obj, &(hp->dev)) != HDF_SUCCESS) {
128 OsalIoUnmap((void *)hp->base);
129 HDF_LOGE("%s: [PwmDeviceAdd] failed.", __func__);
130 return HDF_FAILURE;
131 }
132 HDF_LOGI("%s: set PwmConfig: number %u, period %u, duty %u, polarity %hhu, enable %hhu.", __func__,
133 hp->dev.cfg.number, hp->dev.cfg.period, hp->dev.cfg.duty, hp->dev.cfg.polarity, hp->dev.cfg.status);
134 return HDF_SUCCESS;
135 }
136
HdfPwmBind(struct HdfDeviceObject * obj)137 static int32_t HdfPwmBind(struct HdfDeviceObject *obj)
138 {
139 (void)obj;
140 return HDF_SUCCESS;
141 }
142
HdfPwmInit(struct HdfDeviceObject * obj)143 static int32_t HdfPwmInit(struct HdfDeviceObject *obj)
144 {
145 int ret;
146 struct HiPwm *hp = NULL;
147
148 if (obj == NULL) {
149 HDF_LOGE("%s: obj is null", __func__);
150 return HDF_ERR_INVALID_OBJECT;
151 }
152 hp = (struct HiPwm *)OsalMemCalloc(sizeof(*hp));
153 if (hp == NULL) {
154 HDF_LOGE("%s: OsalMemCalloc hp error", __func__);
155 return HDF_ERR_MALLOC_FAIL;
156 }
157
158 ret = HiPwmProbe(hp, obj);
159 if (ret != HDF_SUCCESS) {
160 HDF_LOGE("%s: error probe, ret is %d", __func__, ret);
161 OsalMemFree(hp);
162 }
163 HDF_LOGI("%s: pwm init success", __func__);
164 return ret;
165 }
166
HdfPwmRelease(struct HdfDeviceObject * obj)167 static void HdfPwmRelease(struct HdfDeviceObject *obj)
168 {
169 struct HiPwm *hp = NULL;
170
171 HDF_LOGI("%s: entry", __func__);
172 if (obj == NULL) {
173 HDF_LOGE("%s: obj is null", __func__);
174 return;
175 }
176 hp = (struct HiPwm *)obj->service;
177 if (hp == NULL) {
178 HDF_LOGE("%s: hp is null", __func__);
179 return;
180 }
181 PwmDeviceRemove(obj, &(hp->dev));
182 HiPwmRemove(hp);
183 }
184
185 struct HdfDriverEntry g_hdfPwm = {
186 .moduleVersion = 1,
187 .moduleName = "HDF_PLATFORM_PWM",
188 .Bind = HdfPwmBind,
189 .Init = HdfPwmInit,
190 .Release = HdfPwmRelease,
191 };
192
193 HDF_INIT(g_hdfPwm);
194