• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "platform_dumper.h"
22 #include "pwm_core.h"
23 
24 #define HDF_LOG_TAG pwm_hi35xx
25 
26 struct HiPwm {
27     struct PwmDev dev;
28     volatile unsigned char *base;
29     struct HiPwmRegs *reg;
30     struct PlatformDumper *dumper;
31     char *dumperName;
32     bool supportPolarity;
33 };
34 
PwmDumperCreate(struct HiPwm * hp)35 static int32_t PwmDumperCreate(struct HiPwm *hp)
36 {
37     struct PlatformDumper *dumper = NULL;
38     char *name = (char *)OsalMemCalloc(PWM_DUMPER_NAME_LEN);
39 
40     if (snprintf_s(name, PWM_DUMPER_NAME_LEN, PWM_DUMPER_NAME_LEN - 1, "%s%u",
41         PWM_DUMPER_NAME_PREFIX, hp->dev.num) < 0) {
42         HDF_LOGE("%s: snprintf_s name fail!", __func__);
43         OsalMemFree(name);
44         return HDF_ERR_IO;
45     }
46     dumper = PlatformDumperCreate(name);
47     if (dumper == NULL) {
48         HDF_LOGE("%s: get dumper for %s fail!", __func__, name);
49         OsalMemFree(name);
50         return HDF_ERR_IO;
51     }
52     hp->dumper = dumper;
53     hp->dumperName = name;
54 
55     return HDF_SUCCESS;
56 }
57 
PwmDumperDump(struct HiPwm * hp)58 static void PwmDumperDump(struct HiPwm *hp)
59 {
60     int32_t ret;
61     struct PlatformDumperData datas[] = {
62         {"PWM_CFG0", PLATFORM_DUMPER_REGISTERL, (void *)hp->base},
63         {"PWM_CFG1", PLATFORM_DUMPER_REGISTERL, (void *)(hp->base+ PWM_CFG1_SHIFT)},
64         {"PWM_CFG2", PLATFORM_DUMPER_REGISTERL, (void *)(hp->base + PWM_CFG2_SHIFT)},
65         {"PWM_CTRL", PLATFORM_DUMPER_REGISTERL, (void *)(hp->base + PWM_CTRL_SHIFT)},
66         {"PWM_STATE0", PLATFORM_DUMPER_REGISTERL, (void *)(hp->base + PWM_STATE0_SHIFT)},
67         {"PWM_STATE1", PLATFORM_DUMPER_REGISTERL, (void *)(hp->base + PWM_STATE1_SHIFT)},
68         {"PWM_STATE2", PLATFORM_DUMPER_REGISTERL, (void *)(hp->base + PWM_STATE2_SHIFT)},
69     };
70     if (hp->dumper == NULL) {
71         HDF_LOGE("%s: pwm dumper is NULL", __func__);
72         return;
73     }
74     ret = PlatformDumperAddDatas(hp->dumper, datas, sizeof(datas) / sizeof(struct PlatformDumperData));
75     if (ret != HDF_SUCCESS) {
76         return;
77     }
78     (void)PlatformDumperDump(hp->dumper);
79     (void)PlatformDumperClearDatas(hp->dumper);
80 }
81 
PwmDumperDestroy(struct HiPwm * hp)82 static inline void PwmDumperDestroy(struct HiPwm *hp)
83 {
84     PlatformDumperDestroy(hp->dumper);
85     OsalMemFree(hp->dumperName);
86 }
87 
HiPwmSetConfig(struct PwmDev * pwm,struct PwmConfig * config)88 int32_t HiPwmSetConfig(struct PwmDev *pwm, struct PwmConfig *config)
89 {
90     struct HiPwm *hp = (struct HiPwm *)pwm;
91     if (hp == NULL || hp->reg == NULL || config == NULL) {
92         HDF_LOGE("%s: hp reg or config is null", __func__);
93         return HDF_ERR_INVALID_PARAM;
94     }
95     if (config->polarity != PWM_NORMAL_POLARITY && config->polarity != PWM_INVERTED_POLARITY) {
96         HDF_LOGE("%s: polarity %hhu is invalid", __func__, config->polarity);
97         PwmDumperDump(hp);
98         return HDF_ERR_INVALID_PARAM;
99     }
100     if (config->period < PWM_MIN_PERIOD) {
101         HDF_LOGE("%s: period %u is not support, min period %d", __func__, config->period, PWM_MIN_PERIOD);
102         PwmDumperDump(hp);
103         return HDF_ERR_INVALID_PARAM;
104     }
105     if (config->duty < 1 || config->duty > config->period) {
106         HDF_LOGE("%s: duty %u is not support, duty must in [1, period = %u].",
107             __func__, config->duty, config->period);
108         PwmDumperDump(hp);
109         return HDF_ERR_INVALID_PARAM;
110     }
111     HiPwmDisable(hp->reg);
112     if (pwm->cfg.polarity != config->polarity && hp->supportPolarity) {
113         HiPwmSetPolarity(hp->reg, config->polarity);
114         HDF_LOGI("%s: [HiPwmSetPolarity] done, polarity: %hhu -> %hhu.", __func__, pwm->cfg.polarity, config->polarity);
115     }
116     if (pwm->cfg.period != config->period) {
117         HiPwmSetPeriod(hp->reg, config->period);
118         HDF_LOGI("%s: [HiPwmSetPeriod] done, period: %u -> %u", __func__, pwm->cfg.period, config->period);
119     }
120     if (pwm->cfg.duty != config->duty) {
121         HiPwmSetDuty(hp->reg, config->duty);
122         HDF_LOGI("%s: [HiPwmSetDuty] done, duty: %u -> %u", __func__, pwm->cfg.duty, config->duty);
123     }
124     if (config->status == PWM_ENABLE_STATUS) {
125         if (config->number == 0) {
126             HiPwmAlwaysOutput(hp->reg);
127             HDF_LOGI("%s: [HiPwmAlwaysOutput] done, then enable.", __func__);
128         } else {
129             HiPwmOutputNumberSquareWaves(hp->reg, config->number);
130             HDF_LOGI("%s: [HiPwmOutputNumberSquareWaves] done, then enable.", __func__);
131         }
132     }
133     HDF_LOGI("%s: set PwmConfig done: number %u, period %u, duty %u, polarity %hhu, enable %hhu.",
134         __func__, config->number, config->period, config->duty, config->polarity, config->status);
135     return HDF_SUCCESS;
136 }
137 
138 struct PwmMethod g_pwmOps = {
139     .setConfig = HiPwmSetConfig,
140 };
141 
HiPwmRemove(struct HiPwm * hp)142 static void HiPwmRemove(struct HiPwm *hp)
143 {
144     if (hp->base != NULL) {
145         OsalIoUnmap((void *)hp->base);
146     }
147     OsalMemFree(hp);
148 }
149 
HiPwmProbe(struct HiPwm * hp,struct HdfDeviceObject * obj)150 static int32_t HiPwmProbe(struct HiPwm *hp, struct HdfDeviceObject *obj)
151 {
152     uint32_t tmp;
153     int32_t ret;
154     struct DeviceResourceIface *iface = NULL;
155 
156     iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
157     if (iface == NULL || iface->GetUint32 == NULL) {
158         HDF_LOGE("%s: face is invalid", __func__);
159         return HDF_FAILURE;
160     }
161 
162     if (iface->GetUint32(obj->property, "num", &(hp->dev.num), 0) != HDF_SUCCESS) {
163         HDF_LOGE("%s: read num fail", __func__);
164         return HDF_FAILURE;
165     }
166 
167     if (iface->GetUint32(obj->property, "base", &tmp, 0) != HDF_SUCCESS) {
168         HDF_LOGE("%s: read base fail", __func__);
169         return HDF_FAILURE;
170     }
171 
172     hp->base = OsalIoRemap(tmp, sizeof(struct HiPwmRegs));
173     if (hp->base == NULL) {
174         HDF_LOGE("%s: OsalIoRemap fail", __func__);
175         return HDF_FAILURE;
176     }
177 
178     hp->reg = (struct HiPwmRegs *)hp->base;
179     hp->supportPolarity = true;
180     hp->dev.method = &g_pwmOps;
181     hp->dev.cfg.duty = PWM_DEFAULT_DUTY_CYCLE;
182     hp->dev.cfg.period = PWM_DEFAULT_PERIOD;
183     hp->dev.cfg.polarity = PWM_DEFAULT_POLARITY;
184     hp->dev.cfg.status = PWM_DISABLE_STATUS;
185     hp->dev.cfg.number = 0;
186     hp->dev.busy = false;
187     if (PwmDeviceAdd(obj, &(hp->dev)) != HDF_SUCCESS) {
188         OsalIoUnmap((void *)hp->base);
189         HDF_LOGE("%s: [PwmDeviceAdd] failed.", __func__);
190         return HDF_FAILURE;
191     }
192     ret = PwmDumperCreate(hp);
193     if (ret != HDF_SUCCESS) {
194         HDF_LOGE("%s: create dumper failed:%d", __func__, ret);
195         OsalIoUnmap((void *)hp->base);
196         return ret;
197     }
198     HDF_LOGI("%s: set PwmConfig: number %u, period %u, duty %u, polarity %hhu, enable %hhu.", __func__,
199         hp->dev.cfg.number, hp->dev.cfg.period, hp->dev.cfg.duty, hp->dev.cfg.polarity, hp->dev.cfg.status);
200     return HDF_SUCCESS;
201 }
202 
HdfPwmBind(struct HdfDeviceObject * obj)203 static int32_t HdfPwmBind(struct HdfDeviceObject *obj)
204 {
205     (void)obj;
206     return HDF_SUCCESS;
207 }
208 
HdfPwmInit(struct HdfDeviceObject * obj)209 static int32_t HdfPwmInit(struct HdfDeviceObject *obj)
210 {
211     int ret;
212     struct HiPwm *hp = NULL;
213 
214     if (obj == NULL) {
215         HDF_LOGE("%s: obj is null", __func__);
216         return HDF_ERR_INVALID_OBJECT;
217     }
218     hp = (struct HiPwm *)OsalMemCalloc(sizeof(*hp));
219     if (hp == NULL) {
220         HDF_LOGE("%s: OsalMemCalloc hp error", __func__);
221         return HDF_ERR_MALLOC_FAIL;
222     }
223 
224     ret = HiPwmProbe(hp, obj);
225     if (ret != HDF_SUCCESS) {
226         HDF_LOGE("%s: error probe, ret is %d", __func__, ret);
227         OsalMemFree(hp);
228     }
229     PwmDumperDump(hp);
230     HDF_LOGI("%s: pwm init success", __func__);
231     return ret;
232 }
233 
HdfPwmRelease(struct HdfDeviceObject * obj)234 static void HdfPwmRelease(struct HdfDeviceObject *obj)
235 {
236     struct HiPwm *hp = NULL;
237 
238     HDF_LOGI("%s: entry", __func__);
239     if (obj == NULL) {
240         HDF_LOGE("%s: obj is null", __func__);
241         return;
242     }
243     hp = (struct HiPwm *)obj->service;
244     if (hp == NULL) {
245         HDF_LOGE("%s: hp is null", __func__);
246         return;
247     }
248     PwmDumperDestroy(hp);
249     PwmDeviceRemove(obj, &(hp->dev));
250     HiPwmRemove(hp);
251 }
252 
253 struct HdfDriverEntry g_hdfPwm = {
254     .moduleVersion = 1,
255     .moduleName = "HDF_PLATFORM_PWM",
256     .Bind = HdfPwmBind,
257     .Init = HdfPwmInit,
258     .Release = HdfPwmRelease,
259 };
260 
261 HDF_INIT(g_hdfPwm);
262