• 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 "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