11bd4fe43Sopenharmony_ci/* 21bd4fe43Sopenharmony_ci * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. 31bd4fe43Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 41bd4fe43Sopenharmony_ci * you may not use this file except in compliance with the License. 51bd4fe43Sopenharmony_ci * You may obtain a copy of the License at 61bd4fe43Sopenharmony_ci * 71bd4fe43Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 81bd4fe43Sopenharmony_ci * 91bd4fe43Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 101bd4fe43Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 111bd4fe43Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 121bd4fe43Sopenharmony_ci * See the License for the specific language governing permissions and 131bd4fe43Sopenharmony_ci * limitations under the License. 141bd4fe43Sopenharmony_ci */ 151bd4fe43Sopenharmony_ci 161bd4fe43Sopenharmony_ci#include "pwm_hi35xx.h" 171bd4fe43Sopenharmony_ci#include "device_resource_if.h" 181bd4fe43Sopenharmony_ci#include "hdf_log.h" 191bd4fe43Sopenharmony_ci#include "osal_io.h" 201bd4fe43Sopenharmony_ci#include "osal_mem.h" 211bd4fe43Sopenharmony_ci#include "platform_dumper.h" 221bd4fe43Sopenharmony_ci#include "pwm_core.h" 231bd4fe43Sopenharmony_ci 241bd4fe43Sopenharmony_ci#define HDF_LOG_TAG pwm_hi35xx 251bd4fe43Sopenharmony_ci 261bd4fe43Sopenharmony_cistruct HiPwm { 271bd4fe43Sopenharmony_ci struct PwmDev dev; 281bd4fe43Sopenharmony_ci volatile unsigned char *base; 291bd4fe43Sopenharmony_ci struct HiPwmRegs *reg; 301bd4fe43Sopenharmony_ci struct PlatformDumper *dumper; 311bd4fe43Sopenharmony_ci char *dumperName; 321bd4fe43Sopenharmony_ci bool supportPolarity; 331bd4fe43Sopenharmony_ci}; 341bd4fe43Sopenharmony_ci 351bd4fe43Sopenharmony_cistatic int32_t PwmDumperCreate(struct HiPwm *hp) 361bd4fe43Sopenharmony_ci{ 371bd4fe43Sopenharmony_ci struct PlatformDumper *dumper = NULL; 381bd4fe43Sopenharmony_ci char *name = (char *)OsalMemCalloc(PWM_DUMPER_NAME_LEN); 391bd4fe43Sopenharmony_ci 401bd4fe43Sopenharmony_ci if (snprintf_s(name, PWM_DUMPER_NAME_LEN, PWM_DUMPER_NAME_LEN - 1, "%s%u", 411bd4fe43Sopenharmony_ci PWM_DUMPER_NAME_PREFIX, hp->dev.num) < 0) { 421bd4fe43Sopenharmony_ci HDF_LOGE("%s: snprintf_s name fail!", __func__); 431bd4fe43Sopenharmony_ci OsalMemFree(name); 441bd4fe43Sopenharmony_ci return HDF_ERR_IO; 451bd4fe43Sopenharmony_ci } 461bd4fe43Sopenharmony_ci dumper = PlatformDumperCreate(name); 471bd4fe43Sopenharmony_ci if (dumper == NULL) { 481bd4fe43Sopenharmony_ci HDF_LOGE("%s: get dumper for %s fail!", __func__, name); 491bd4fe43Sopenharmony_ci OsalMemFree(name); 501bd4fe43Sopenharmony_ci return HDF_ERR_IO; 511bd4fe43Sopenharmony_ci } 521bd4fe43Sopenharmony_ci hp->dumper = dumper; 531bd4fe43Sopenharmony_ci hp->dumperName = name; 541bd4fe43Sopenharmony_ci 551bd4fe43Sopenharmony_ci return HDF_SUCCESS; 561bd4fe43Sopenharmony_ci} 571bd4fe43Sopenharmony_ci 581bd4fe43Sopenharmony_cistatic void PwmDumperDump(struct HiPwm *hp) 591bd4fe43Sopenharmony_ci{ 601bd4fe43Sopenharmony_ci int32_t ret; 611bd4fe43Sopenharmony_ci struct PlatformDumperData datas[] = { 621bd4fe43Sopenharmony_ci {"PWM_CFG0", PLATFORM_DUMPER_REGISTERL, (void *)hp->base}, 631bd4fe43Sopenharmony_ci {"PWM_CFG1", PLATFORM_DUMPER_REGISTERL, (void *)(hp->base+ PWM_CFG1_SHIFT)}, 641bd4fe43Sopenharmony_ci {"PWM_CFG2", PLATFORM_DUMPER_REGISTERL, (void *)(hp->base + PWM_CFG2_SHIFT)}, 651bd4fe43Sopenharmony_ci {"PWM_CTRL", PLATFORM_DUMPER_REGISTERL, (void *)(hp->base + PWM_CTRL_SHIFT)}, 661bd4fe43Sopenharmony_ci {"PWM_STATE0", PLATFORM_DUMPER_REGISTERL, (void *)(hp->base + PWM_STATE0_SHIFT)}, 671bd4fe43Sopenharmony_ci {"PWM_STATE1", PLATFORM_DUMPER_REGISTERL, (void *)(hp->base + PWM_STATE1_SHIFT)}, 681bd4fe43Sopenharmony_ci {"PWM_STATE2", PLATFORM_DUMPER_REGISTERL, (void *)(hp->base + PWM_STATE2_SHIFT)}, 691bd4fe43Sopenharmony_ci }; 701bd4fe43Sopenharmony_ci if (hp->dumper == NULL) { 711bd4fe43Sopenharmony_ci HDF_LOGE("%s: pwm dumper is NULL", __func__); 721bd4fe43Sopenharmony_ci return; 731bd4fe43Sopenharmony_ci } 741bd4fe43Sopenharmony_ci ret = PlatformDumperAddDatas(hp->dumper, datas, sizeof(datas) / sizeof(struct PlatformDumperData)); 751bd4fe43Sopenharmony_ci if (ret != HDF_SUCCESS) { 761bd4fe43Sopenharmony_ci return; 771bd4fe43Sopenharmony_ci } 781bd4fe43Sopenharmony_ci (void)PlatformDumperDump(hp->dumper); 791bd4fe43Sopenharmony_ci (void)PlatformDumperClearDatas(hp->dumper); 801bd4fe43Sopenharmony_ci} 811bd4fe43Sopenharmony_ci 821bd4fe43Sopenharmony_cistatic inline void PwmDumperDestroy(struct HiPwm *hp) 831bd4fe43Sopenharmony_ci{ 841bd4fe43Sopenharmony_ci PlatformDumperDestroy(hp->dumper); 851bd4fe43Sopenharmony_ci OsalMemFree(hp->dumperName); 861bd4fe43Sopenharmony_ci} 871bd4fe43Sopenharmony_ci 881bd4fe43Sopenharmony_ciint32_t HiPwmSetConfig(struct PwmDev *pwm, struct PwmConfig *config) 891bd4fe43Sopenharmony_ci{ 901bd4fe43Sopenharmony_ci struct HiPwm *hp = (struct HiPwm *)pwm; 911bd4fe43Sopenharmony_ci if (hp == NULL || hp->reg == NULL || config == NULL) { 921bd4fe43Sopenharmony_ci HDF_LOGE("%s: hp reg or config is null", __func__); 931bd4fe43Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 941bd4fe43Sopenharmony_ci } 951bd4fe43Sopenharmony_ci if (config->polarity != PWM_NORMAL_POLARITY && config->polarity != PWM_INVERTED_POLARITY) { 961bd4fe43Sopenharmony_ci HDF_LOGE("%s: polarity %hhu is invalid", __func__, config->polarity); 971bd4fe43Sopenharmony_ci PwmDumperDump(hp); 981bd4fe43Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 991bd4fe43Sopenharmony_ci } 1001bd4fe43Sopenharmony_ci if (config->period < PWM_MIN_PERIOD) { 1011bd4fe43Sopenharmony_ci HDF_LOGE("%s: period %u is not support, min period %d", __func__, config->period, PWM_MIN_PERIOD); 1021bd4fe43Sopenharmony_ci PwmDumperDump(hp); 1031bd4fe43Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 1041bd4fe43Sopenharmony_ci } 1051bd4fe43Sopenharmony_ci if (config->duty < 1 || config->duty > config->period) { 1061bd4fe43Sopenharmony_ci HDF_LOGE("%s: duty %u is not support, duty must in [1, period = %u].", 1071bd4fe43Sopenharmony_ci __func__, config->duty, config->period); 1081bd4fe43Sopenharmony_ci PwmDumperDump(hp); 1091bd4fe43Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 1101bd4fe43Sopenharmony_ci } 1111bd4fe43Sopenharmony_ci HiPwmDisable(hp->reg); 1121bd4fe43Sopenharmony_ci if (pwm->cfg.polarity != config->polarity && hp->supportPolarity) { 1131bd4fe43Sopenharmony_ci HiPwmSetPolarity(hp->reg, config->polarity); 1141bd4fe43Sopenharmony_ci HDF_LOGI("%s: [HiPwmSetPolarity] done, polarity: %hhu -> %hhu.", __func__, pwm->cfg.polarity, config->polarity); 1151bd4fe43Sopenharmony_ci } 1161bd4fe43Sopenharmony_ci if (pwm->cfg.period != config->period) { 1171bd4fe43Sopenharmony_ci HiPwmSetPeriod(hp->reg, config->period); 1181bd4fe43Sopenharmony_ci HDF_LOGI("%s: [HiPwmSetPeriod] done, period: %u -> %u", __func__, pwm->cfg.period, config->period); 1191bd4fe43Sopenharmony_ci } 1201bd4fe43Sopenharmony_ci if (pwm->cfg.duty != config->duty) { 1211bd4fe43Sopenharmony_ci HiPwmSetDuty(hp->reg, config->duty); 1221bd4fe43Sopenharmony_ci HDF_LOGI("%s: [HiPwmSetDuty] done, duty: %u -> %u", __func__, pwm->cfg.duty, config->duty); 1231bd4fe43Sopenharmony_ci } 1241bd4fe43Sopenharmony_ci if (config->status == PWM_ENABLE_STATUS) { 1251bd4fe43Sopenharmony_ci if (config->number == 0) { 1261bd4fe43Sopenharmony_ci HiPwmAlwaysOutput(hp->reg); 1271bd4fe43Sopenharmony_ci HDF_LOGI("%s: [HiPwmAlwaysOutput] done, then enable.", __func__); 1281bd4fe43Sopenharmony_ci } else { 1291bd4fe43Sopenharmony_ci HiPwmOutputNumberSquareWaves(hp->reg, config->number); 1301bd4fe43Sopenharmony_ci HDF_LOGI("%s: [HiPwmOutputNumberSquareWaves] done, then enable.", __func__); 1311bd4fe43Sopenharmony_ci } 1321bd4fe43Sopenharmony_ci } 1331bd4fe43Sopenharmony_ci HDF_LOGI("%s: set PwmConfig done: number %u, period %u, duty %u, polarity %hhu, enable %hhu.", 1341bd4fe43Sopenharmony_ci __func__, config->number, config->period, config->duty, config->polarity, config->status); 1351bd4fe43Sopenharmony_ci return HDF_SUCCESS; 1361bd4fe43Sopenharmony_ci} 1371bd4fe43Sopenharmony_ci 1381bd4fe43Sopenharmony_cistruct PwmMethod g_pwmOps = { 1391bd4fe43Sopenharmony_ci .setConfig = HiPwmSetConfig, 1401bd4fe43Sopenharmony_ci}; 1411bd4fe43Sopenharmony_ci 1421bd4fe43Sopenharmony_cistatic void HiPwmRemove(struct HiPwm *hp) 1431bd4fe43Sopenharmony_ci{ 1441bd4fe43Sopenharmony_ci if (hp->base != NULL) { 1451bd4fe43Sopenharmony_ci OsalIoUnmap((void *)hp->base); 1461bd4fe43Sopenharmony_ci } 1471bd4fe43Sopenharmony_ci OsalMemFree(hp); 1481bd4fe43Sopenharmony_ci} 1491bd4fe43Sopenharmony_ci 1501bd4fe43Sopenharmony_cistatic int32_t HiPwmProbe(struct HiPwm *hp, struct HdfDeviceObject *obj) 1511bd4fe43Sopenharmony_ci{ 1521bd4fe43Sopenharmony_ci uint32_t tmp; 1531bd4fe43Sopenharmony_ci int32_t ret; 1541bd4fe43Sopenharmony_ci struct DeviceResourceIface *iface = NULL; 1551bd4fe43Sopenharmony_ci 1561bd4fe43Sopenharmony_ci iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); 1571bd4fe43Sopenharmony_ci if (iface == NULL || iface->GetUint32 == NULL) { 1581bd4fe43Sopenharmony_ci HDF_LOGE("%s: face is invalid", __func__); 1591bd4fe43Sopenharmony_ci return HDF_FAILURE; 1601bd4fe43Sopenharmony_ci } 1611bd4fe43Sopenharmony_ci 1621bd4fe43Sopenharmony_ci if (iface->GetUint32(obj->property, "num", &(hp->dev.num), 0) != HDF_SUCCESS) { 1631bd4fe43Sopenharmony_ci HDF_LOGE("%s: read num fail", __func__); 1641bd4fe43Sopenharmony_ci return HDF_FAILURE; 1651bd4fe43Sopenharmony_ci } 1661bd4fe43Sopenharmony_ci 1671bd4fe43Sopenharmony_ci if (iface->GetUint32(obj->property, "base", &tmp, 0) != HDF_SUCCESS) { 1681bd4fe43Sopenharmony_ci HDF_LOGE("%s: read base fail", __func__); 1691bd4fe43Sopenharmony_ci return HDF_FAILURE; 1701bd4fe43Sopenharmony_ci } 1711bd4fe43Sopenharmony_ci 1721bd4fe43Sopenharmony_ci hp->base = OsalIoRemap(tmp, sizeof(struct HiPwmRegs)); 1731bd4fe43Sopenharmony_ci if (hp->base == NULL) { 1741bd4fe43Sopenharmony_ci HDF_LOGE("%s: OsalIoRemap fail", __func__); 1751bd4fe43Sopenharmony_ci return HDF_FAILURE; 1761bd4fe43Sopenharmony_ci } 1771bd4fe43Sopenharmony_ci 1781bd4fe43Sopenharmony_ci hp->reg = (struct HiPwmRegs *)hp->base; 1791bd4fe43Sopenharmony_ci hp->supportPolarity = true; 1801bd4fe43Sopenharmony_ci hp->dev.method = &g_pwmOps; 1811bd4fe43Sopenharmony_ci hp->dev.cfg.duty = PWM_DEFAULT_DUTY_CYCLE; 1821bd4fe43Sopenharmony_ci hp->dev.cfg.period = PWM_DEFAULT_PERIOD; 1831bd4fe43Sopenharmony_ci hp->dev.cfg.polarity = PWM_DEFAULT_POLARITY; 1841bd4fe43Sopenharmony_ci hp->dev.cfg.status = PWM_DISABLE_STATUS; 1851bd4fe43Sopenharmony_ci hp->dev.cfg.number = 0; 1861bd4fe43Sopenharmony_ci hp->dev.busy = false; 1871bd4fe43Sopenharmony_ci if (PwmDeviceAdd(obj, &(hp->dev)) != HDF_SUCCESS) { 1881bd4fe43Sopenharmony_ci OsalIoUnmap((void *)hp->base); 1891bd4fe43Sopenharmony_ci HDF_LOGE("%s: [PwmDeviceAdd] failed.", __func__); 1901bd4fe43Sopenharmony_ci return HDF_FAILURE; 1911bd4fe43Sopenharmony_ci } 1921bd4fe43Sopenharmony_ci ret = PwmDumperCreate(hp); 1931bd4fe43Sopenharmony_ci if (ret != HDF_SUCCESS) { 1941bd4fe43Sopenharmony_ci HDF_LOGE("%s: create dumper failed:%d", __func__, ret); 1951bd4fe43Sopenharmony_ci OsalIoUnmap((void *)hp->base); 1961bd4fe43Sopenharmony_ci return ret; 1971bd4fe43Sopenharmony_ci } 1981bd4fe43Sopenharmony_ci HDF_LOGI("%s: set PwmConfig: number %u, period %u, duty %u, polarity %hhu, enable %hhu.", __func__, 1991bd4fe43Sopenharmony_ci hp->dev.cfg.number, hp->dev.cfg.period, hp->dev.cfg.duty, hp->dev.cfg.polarity, hp->dev.cfg.status); 2001bd4fe43Sopenharmony_ci return HDF_SUCCESS; 2011bd4fe43Sopenharmony_ci} 2021bd4fe43Sopenharmony_ci 2031bd4fe43Sopenharmony_cistatic int32_t HdfPwmBind(struct HdfDeviceObject *obj) 2041bd4fe43Sopenharmony_ci{ 2051bd4fe43Sopenharmony_ci (void)obj; 2061bd4fe43Sopenharmony_ci return HDF_SUCCESS; 2071bd4fe43Sopenharmony_ci} 2081bd4fe43Sopenharmony_ci 2091bd4fe43Sopenharmony_cistatic int32_t HdfPwmInit(struct HdfDeviceObject *obj) 2101bd4fe43Sopenharmony_ci{ 2111bd4fe43Sopenharmony_ci int ret; 2121bd4fe43Sopenharmony_ci struct HiPwm *hp = NULL; 2131bd4fe43Sopenharmony_ci 2141bd4fe43Sopenharmony_ci if (obj == NULL) { 2151bd4fe43Sopenharmony_ci HDF_LOGE("%s: obj is null", __func__); 2161bd4fe43Sopenharmony_ci return HDF_ERR_INVALID_OBJECT; 2171bd4fe43Sopenharmony_ci } 2181bd4fe43Sopenharmony_ci hp = (struct HiPwm *)OsalMemCalloc(sizeof(*hp)); 2191bd4fe43Sopenharmony_ci if (hp == NULL) { 2201bd4fe43Sopenharmony_ci HDF_LOGE("%s: OsalMemCalloc hp error", __func__); 2211bd4fe43Sopenharmony_ci return HDF_ERR_MALLOC_FAIL; 2221bd4fe43Sopenharmony_ci } 2231bd4fe43Sopenharmony_ci 2241bd4fe43Sopenharmony_ci ret = HiPwmProbe(hp, obj); 2251bd4fe43Sopenharmony_ci if (ret != HDF_SUCCESS) { 2261bd4fe43Sopenharmony_ci HDF_LOGE("%s: error probe, ret is %d", __func__, ret); 2271bd4fe43Sopenharmony_ci OsalMemFree(hp); 2281bd4fe43Sopenharmony_ci } 2291bd4fe43Sopenharmony_ci PwmDumperDump(hp); 2301bd4fe43Sopenharmony_ci HDF_LOGI("%s: pwm init success", __func__); 2311bd4fe43Sopenharmony_ci return ret; 2321bd4fe43Sopenharmony_ci} 2331bd4fe43Sopenharmony_ci 2341bd4fe43Sopenharmony_cistatic void HdfPwmRelease(struct HdfDeviceObject *obj) 2351bd4fe43Sopenharmony_ci{ 2361bd4fe43Sopenharmony_ci struct HiPwm *hp = NULL; 2371bd4fe43Sopenharmony_ci 2381bd4fe43Sopenharmony_ci HDF_LOGI("%s: entry", __func__); 2391bd4fe43Sopenharmony_ci if (obj == NULL) { 2401bd4fe43Sopenharmony_ci HDF_LOGE("%s: obj is null", __func__); 2411bd4fe43Sopenharmony_ci return; 2421bd4fe43Sopenharmony_ci } 2431bd4fe43Sopenharmony_ci hp = (struct HiPwm *)obj->service; 2441bd4fe43Sopenharmony_ci if (hp == NULL) { 2451bd4fe43Sopenharmony_ci HDF_LOGE("%s: hp is null", __func__); 2461bd4fe43Sopenharmony_ci return; 2471bd4fe43Sopenharmony_ci } 2481bd4fe43Sopenharmony_ci PwmDumperDestroy(hp); 2491bd4fe43Sopenharmony_ci PwmDeviceRemove(obj, &(hp->dev)); 2501bd4fe43Sopenharmony_ci HiPwmRemove(hp); 2511bd4fe43Sopenharmony_ci} 2521bd4fe43Sopenharmony_ci 2531bd4fe43Sopenharmony_cistruct HdfDriverEntry g_hdfPwm = { 2541bd4fe43Sopenharmony_ci .moduleVersion = 1, 2551bd4fe43Sopenharmony_ci .moduleName = "HDF_PLATFORM_PWM", 2561bd4fe43Sopenharmony_ci .Bind = HdfPwmBind, 2571bd4fe43Sopenharmony_ci .Init = HdfPwmInit, 2581bd4fe43Sopenharmony_ci .Release = HdfPwmRelease, 2591bd4fe43Sopenharmony_ci}; 2601bd4fe43Sopenharmony_ci 2611bd4fe43Sopenharmony_ciHDF_INIT(g_hdfPwm); 262