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 %u 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 HDF_LOGI("%s: [HiPwmDisable] done.", __func__);
54 if (pwm->cfg.polarity != config->polarity && hp->supportPolarity) {
55 HiPwmSetPolarity(hp->reg, config->polarity);
56 HDF_LOGI("%s: [HiPwmSetPolarity] done, polarity: %u -> %u.", __func__, pwm->cfg.polarity, config->polarity);
57 }
58 if (pwm->cfg.period != config->period) {
59 HiPwmSetPeriod(hp->reg, config->period);
60 HDF_LOGI("%s: [HiPwmSetPeriod] done, period: %u -> %u", __func__, pwm->cfg.period, config->period);
61 }
62 if (pwm->cfg.duty != config->duty) {
63 HiPwmSetDuty(hp->reg, config->duty);
64 HDF_LOGI("%s: [HiPwmSetDuty] done, duty: %u -> %u", __func__, pwm->cfg.duty, config->duty);
65 }
66 if (config->status == PWM_ENABLE_STATUS) {
67 if (config->number == 0) {
68 HiPwmAlwaysOutput(hp->reg);
69 HDF_LOGI("%s: [HiPwmAlwaysOutput] done, then enable.", __func__);
70 } else {
71 HiPwmOutputNumberSquareWaves(hp->reg, config->number);
72 HDF_LOGI("%s: [HiPwmOutputNumberSquareWaves] done, then enable.", __func__);
73 }
74 }
75 HDF_LOGI("%s: set PwmConfig done: number %u, period %u, duty %u, polarity %u, enable %u.",
76 __func__, config->number, config->period, config->duty, config->polarity, config->status);
77 HDF_LOGI("%s: success.", __func__);
78 return HDF_SUCCESS;
79 }
80
81 struct PwmMethod g_pwmOps = {
82 .setConfig = HiPwmSetConfig,
83 };
84
HiPwmRemove(struct HiPwm * hp)85 static void HiPwmRemove(struct HiPwm *hp)
86 {
87 if (hp->base != NULL) {
88 OsalIoUnmap((void *)hp->base);
89 }
90 OsalMemFree(hp);
91 }
92
HiPwmProbe(struct HiPwm * hp,struct HdfDeviceObject * obj)93 static int32_t HiPwmProbe(struct HiPwm *hp, struct HdfDeviceObject *obj)
94 {
95 uint32_t tmp;
96 struct DeviceResourceIface *iface = NULL;
97
98 iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
99 if (iface == NULL || iface->GetUint32 == NULL) {
100 HDF_LOGE("%s: face is invalid", __func__);
101 return HDF_FAILURE;
102 }
103
104 if (iface->GetUint32(obj->property, "num", &(hp->dev.num), 0) != HDF_SUCCESS) {
105 HDF_LOGE("%s: read num fail", __func__);
106 return HDF_FAILURE;
107 }
108
109 if (iface->GetUint32(obj->property, "base", &tmp, 0) != HDF_SUCCESS) {
110 HDF_LOGE("%s: read base fail", __func__);
111 return HDF_FAILURE;
112 }
113
114 hp->base = OsalIoRemap(tmp, sizeof(struct HiPwmRegs));
115 if (hp->base == NULL) {
116 HDF_LOGE("%s: OsalIoRemap fail", __func__);
117 return HDF_FAILURE;
118 }
119
120 hp->reg = (struct HiPwmRegs *)hp->base;
121 hp->supportPolarity = true;
122 hp->dev.method = &g_pwmOps;
123 hp->dev.cfg.duty = PWM_DEFAULT_DUTY_CYCLE;
124 hp->dev.cfg.period = PWM_DEFAULT_PERIOD;
125 hp->dev.cfg.polarity = PWM_DEFAULT_POLARITY;
126 hp->dev.cfg.status = PWM_DISABLE_STATUS;
127 hp->dev.cfg.number = 0;
128 hp->dev.busy = false;
129 if (PwmDeviceAdd(obj, &(hp->dev)) != HDF_SUCCESS) {
130 OsalIoUnmap((void *)hp->base);
131 HDF_LOGE("%s: [PwmDeviceAdd] failed.", __func__);
132 return HDF_FAILURE;
133 }
134 HDF_LOGI("%s: set PwmConfig: number %u, period %u, duty %u, polarity %u, enable %u.", __func__,
135 hp->dev.cfg.number, hp->dev.cfg.period, hp->dev.cfg.duty, hp->dev.cfg.polarity, hp->dev.cfg.status);
136 HDF_LOGI("%s: success.", __func__);
137
138 return HDF_SUCCESS;
139 }
140
HdfPwmBind(struct HdfDeviceObject * obj)141 static int32_t HdfPwmBind(struct HdfDeviceObject *obj)
142 {
143 (void)obj;
144 return HDF_SUCCESS;
145 }
146
HdfPwmInit(struct HdfDeviceObject * obj)147 static int32_t HdfPwmInit(struct HdfDeviceObject *obj)
148 {
149 int ret;
150 struct HiPwm *hp = NULL;
151
152 HDF_LOGI("%s: entry", __func__);
153 if (obj == NULL) {
154 HDF_LOGE("%s: obj is null", __func__);
155 return HDF_ERR_INVALID_OBJECT;
156 }
157 hp = (struct HiPwm *)OsalMemCalloc(sizeof(*hp));
158 if (hp == NULL) {
159 HDF_LOGE("%s: OsalMemCalloc hp error", __func__);
160 return HDF_ERR_MALLOC_FAIL;
161 }
162
163 ret = HiPwmProbe(hp, obj);
164 if (ret != HDF_SUCCESS) {
165 HDF_LOGE("%s: error probe, ret is %d", __func__, ret);
166 OsalMemFree(hp);
167 }
168 return ret;
169 }
170
HdfPwmRelease(struct HdfDeviceObject * obj)171 static void HdfPwmRelease(struct HdfDeviceObject *obj)
172 {
173 struct HiPwm *hp = NULL;
174
175 HDF_LOGI("%s: entry", __func__);
176 if (obj == NULL) {
177 HDF_LOGE("%s: obj is null", __func__);
178 return;
179 }
180 hp = (struct HiPwm *)obj->service;
181 if (hp == NULL) {
182 HDF_LOGE("%s: hp is null", __func__);
183 return;
184 }
185 PwmDeviceRemove(obj, &(hp->dev));
186 HiPwmRemove(hp);
187 }
188
189 struct HdfDriverEntry g_hdfPwm = {
190 .moduleVersion = 1,
191 .moduleName = "HDF_PLATFORM_PWM",
192 .Bind = HdfPwmBind,
193 .Init = HdfPwmInit,
194 .Release = HdfPwmRelease,
195 };
196
197 HDF_INIT(g_hdfPwm);
198