高通平台添加设备驱动流程

高通平台添加驱动如下: 

----------- kernel/msm-3.18/arch/arm/boot/dts/qcom/msm-pmi8950.dtsi -----------
index a714654..d6c2c57 100644
@@ -192,7 +192,13 @@
             mpp@a300 {
                 reg = <0xa300 0x100>;
                 qcom,pin-num = <4>;
-                status = "disabled";
+                //status = "disabled";
+                qcom,mode = <1>;
+                qcom,invert = <0>;
+                qcom,src-sel = <5>; // notice: mpp4 need config DTETS2
+                qcom,pull = <1>;
+                qcom,vin-sel = <3>;
+                qcom,master-en = <1>;
             };
         };
 
@@ -410,6 +416,16 @@
             reg = <0xa100 0x100>;
             label = "mpp";
         };
+
+        pwm-beeper@a300 {
+            compatible = "ckt-pwm-beeper";
+            label = "mpp";
+            reg = <0xa300 0x100>;
+            pwms = <&pmi8950_pwm 0 0>;
+            //pinctrl-names = "default";
+            //pinctrl-0 = <&pwm0_pin>;
+            status = "okay";
+        };
     };
 
     qcom,pmi8950@3 {
@@ -419,13 +435,21 @@
         #size-cells = <1>;
 
         pmi8950_pwm: pwm@b000 {
-            status = "disabled";
+            //status = "disabled";
+            status = "okay";
             compatible = "qcom,qpnp-pwm";
             reg = <0xb000 0x100>;
             reg-names = "qpnp-lpg-channel-base";
             qcom,channel-id = <0>;
             qcom,supported-sizes = <6>, <9>;
+            qcom,period = <4000000>;
             #pwm-cells = <2>;
+            qcom,dtest-line = <2>; // notice: pwm need config DTETS2
+            qcom,dtest-output = <2>;
+            qcom,pwm {
+                qcom,duty = <2000000>; //PWM duty time in microseconds
+                 label = "pwm"; 
+            };
         };
 
         labibb: qpnp-labibb-regulator {

--------- kernel/msm-3.18/arch/arm64/configs/msmcortex-perf_defconfig ---------
index f5249bc..87d96b8 100755
@@ -596,6 +596,7 @@ CONFIG_SPDM_SCM=y
 CONFIG_DEVFREQ_SPDM=y
 CONFIG_PWM=y
 CONFIG_PWM_QPNP=y
+CONFIG_INPUT_CKT_PWM_BEEPER=y
 CONFIG_ARM_GIC_PANIC_HANDLER=y
 CONFIG_ARM_GIC_V3_ACL=y
 CONFIG_CORESIGHT=y

------------ kernel/msm-3.18/arch/arm64/configs/msmcortex_defconfig ------------
index 4b4a396..a4eaaa2 100755
@@ -623,6 +623,8 @@ CONFIG_SPDM_SCM=y
 CONFIG_DEVFREQ_SPDM=y
 CONFIG_PWM=y
 CONFIG_PWM_QPNP=y
+#Evan add
+CONFIG_INPUT_CKT_PWM_BEEPER=y
 CONFIG_ARM_GIC_PANIC_HANDLER=y
 CONFIG_ARM_GIC_V3_ACL=y
 CONFIG_CORESIGHT=y

------------------ kernel/msm-3.18/drivers/input/misc/Kconfig ------------------
index 4069df1..7e75ce5 100644
@@ -558,6 +558,17 @@ config INPUT_PWM_BEEPER
       To compile this driver as a module, choose M here: the module will be
       called pwm-beeper.
 
+config INPUT_CKT_PWM_BEEPER
+    tristate "CKT PWM beeper support"
+    depends on PWM
+    help
+      Say Y here to get support for PWM based beeper devices.
+
+      If unsure, say N.
+
+      To compile this driver as a module, choose M here: the module will be
+      called ckt-pwm-beeper.
+
 config INPUT_GPIO_ROTARY_ENCODER
     tristate "Rotary encoders connected to GPIO pins"
     depends on GPIOLIB

----------------- kernel/msm-3.18/drivers/input/misc/Makefile -----------------
index 1456a01..1efb67d 100644
@@ -57,6 +57,7 @@ obj-$(CONFIG_INPUT_PM8XXX_VIBRATOR)    += pm8xxx-vibrator.o
 obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY)    += pmic8xxx-pwrkey.o
 obj-$(CONFIG_INPUT_POWERMATE)        += powermate.o
 obj-$(CONFIG_INPUT_PWM_BEEPER)        += pwm-beeper.o
+obj-$(CONFIG_INPUT_CKT_PWM_BEEPER)    += ckt-pwm-beeper.o
 obj-$(CONFIG_INPUT_RB532_BUTTON)    += rb532_button.o
 obj-$(CONFIG_INPUT_RETU_PWRBUTTON)    += retu-pwrbutton.o
 obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER)    += rotary_encoder.o

------------- kernel/msm-3.18/drivers/input/misc/ckt-pwm-beeper.c -------------
new file mode 100644
index 0000000..1d82031
@@ -0,0 +1,285 @@
+/*
+ *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ *  PWM beeper driver
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under  the terms of the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/slab.h>
+#include <linux/spmi.h>
+
+struct pwm_beeper {
+    struct input_dev *input;
+    struct pwm_device *pwm;
+    unsigned long period;
+    struct class *beeper_class;
+};
+
+static struct pwm_beeper *beeper;
+
+#define HZ_TO_NANOSECONDS(x) (1000000000UL/(x))
+#define BEEPER_DEF_HZ   4000
+
+static ssize_t beeper_bell(struct class *class,
+            struct class_attribute *attr,
+            const char *buf, size_t count)
+{
+    ssize_t ret = -EINVAL;
+    int value,period;
+
+    pr_debug("%s\n",__func__);
+    ret = kstrtoint(buf, 10, &value);
+    if (ret)
+        return ret;
+    
+    if (value == 0) {
+        pwm_config(beeper->pwm, 0, 0);
+        pwm_disable(beeper->pwm);
+        beeper->period = 0;
+    } else {
+        period = HZ_TO_NANOSECONDS(BEEPER_DEF_HZ);
+        ret = pwm_config(beeper->pwm, period / 2, period);
+        if (ret)
+            return ret;
+        ret = pwm_enable(beeper->pwm);
+        if (ret)
+            return ret;
+        beeper->period = period;
+    }
+    
+    return count;
+}
+
+static ssize_t beeper_tone(struct class *class,
+            struct class_attribute *attr,
+            const char *buf, size_t count)
+{
+
+    ssize_t ret = -EINVAL;
+    int value,period;
+
+    pr_debug("%s\n",__func__);
+    ret = kstrtoint(buf, 10, &value);
+    if (ret)
+        return ret;
+    if (value == 0) {
+        pwm_config(beeper->pwm, 0, 0);
+        pwm_disable(beeper->pwm);
+        beeper->period = 0;
+    } else {
+        period = HZ_TO_NANOSECONDS(value);
+        ret = pwm_config(beeper->pwm, period / 2, period);
+        if (ret)
+            return ret;
+        ret = pwm_enable(beeper->pwm);
+        if (ret)
+            return ret;
+        beeper->period = period;
+    }
+
+    return count;
+}
+
+static CLASS_ATTR(bell, 0644, NULL, beeper_bell);
+static CLASS_ATTR(tone, 0644, NULL, beeper_tone);
+
+
+static int pwm_beeper_event(struct input_dev *input,
+                unsigned int type, unsigned int code, int value)
+{
+    int ret = 0;
+    struct pwm_beeper *beeper = input_get_drvdata(input);
+    unsigned long period;
+    pr_debug("%s:code=%d,value=%d\n",__func__,code,value);
+    if (type != EV_SND || value < 0)
+        return -EINVAL;
+
+    switch (code) {
+    case SND_BELL:
+        value = value ? 1000 : 0;
+        break;
+    case SND_TONE:
+        break;
+    default:
+        return -EINVAL;
+    }
+
+    if (value == 0) {
+        pwm_config(beeper->pwm, 0, 0);
+        pwm_disable(beeper->pwm);
+        beeper->period = 0;
+    } else {
+        period = HZ_TO_NANOSECONDS(value);
+        ret = pwm_config(beeper->pwm, period / 2, period);
+        if (ret)
+            return ret;
+        ret = pwm_enable(beeper->pwm);
+        if (ret)
+            return ret;
+        beeper->period = period;
+    }
+
+    return 0;
+}
+
+static int pwm_beeper_probe(struct spmi_device *spmi)
+{
+    struct device_node *node;
+    int error;
+
+    node = spmi->dev.of_node;
+    if (node == NULL)
+        return -ENODEV;
+    
+    beeper = kzalloc(sizeof(*beeper), GFP_KERNEL);
+    if (!beeper)
+        return -ENOMEM;
+
+    beeper->pwm = of_pwm_get(node, NULL);
+    if (IS_ERR(beeper->pwm)) {
+        pr_err("%s: Error, pwm device\n",__func__);
+        beeper->pwm = NULL;
+        goto err_free;
+    }
+
+    beeper->input = input_allocate_device();
+    if (!beeper->input) {
+        dev_err(&spmi->dev, "Failed to allocate input device\n");
+        error = -ENOMEM;
+        goto err_pwm_free;
+    }
+    beeper->input->dev.parent = &spmi->dev;
+
+    beeper->input->name = "pwm-beeper";
+    beeper->input->phys = "pwm/input0";
+    beeper->input->id.bustype = BUS_HOST;
+    beeper->input->id.vendor = 0x001f;
+    beeper->input->id.product = 0x0001;
+    beeper->input->id.version = 0x0100;
+
+    beeper->input->evbit[0] = BIT(EV_SND);
+    beeper->input->sndbit[0] = BIT(SND_TONE) | BIT(SND_BELL);
+
+    beeper->input->event = pwm_beeper_event;
+
+    input_set_drvdata(beeper->input, beeper);
+
+    error = input_register_device(beeper->input);
+    if (error) {
+        dev_err(&spmi->dev, "Failed to register input device: %d\n", error);
+        goto err_input_free;
+    }
+
+    beeper->beeper_class= class_create(THIS_MODULE, "beeper");
+    if (IS_ERR(beeper->beeper_class))
+        return PTR_ERR(beeper->beeper_class);
+    error = class_create_file(beeper->beeper_class, &class_attr_bell);
+    error = class_create_file(beeper->beeper_class, &class_attr_tone);
+
+    dev_set_drvdata(&spmi->dev, beeper);
+
+    return 0;
+
+err_input_free:
+    input_free_device(beeper->input);
+err_pwm_free:
+    pwm_free(beeper->pwm);
+err_free:
+    kfree(beeper);
+
+    return error;
+}
+
+static int pwm_beeper_remove(struct spmi_device *spmi)
+{
+    //struct pwm_beeper *beeper = dev_get_drvdata(&spmi->dev);
+    class_remove_file(beeper->beeper_class, &class_attr_bell);
+    class_remove_file(beeper->beeper_class, &class_attr_tone);
+    class_destroy(beeper->beeper_class);
+        
+    input_unregister_device(beeper->input);
+
+    pwm_disable(beeper->pwm);
+    pwm_free(beeper->pwm);
+
+    kfree(beeper);
+
+    return 0;
+}
+
+#if 0 //#ifdef CONFIG_PM_SLEEP
+static int pwm_beeper_suspend(struct spmi_device *spmi)
+{
+    //struct pwm_beeper *beeper = dev_get_drvdata(&spmi->dev);
+
+    if (beeper->period)
+        pwm_disable(beeper->pwm);
+
+    return 0;
+}
+
+static int pwm_beeper_resume(struct spmi_device *spmi)
+{
+    //struct pwm_beeper *beeper = dev_get_drvdata(&spmi->dev);
+
+    if (beeper->period) {
+        pwm_config(beeper->pwm, beeper->period / 2, beeper->period);
+        pwm_enable(beeper->pwm);
+    }
+
+    return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(pwm_beeper_pm_ops,
+             pwm_beeper_suspend, pwm_beeper_resume);
+#endif
+
+#ifdef CONFIG_OF
+static const struct of_device_id pwm_beeper_match[] = {
+    { .compatible = "ckt-pwm-beeper", },
+    { },
+};
+#endif
+
+static struct spmi_driver pwm_beeper_driver = {
+    .probe    = pwm_beeper_probe,
+    .remove = pwm_beeper_remove,
+    .driver = {
+        .name    = "pwm-beeper",
+        .owner    = THIS_MODULE,
+        //.pm    = PWM_BEEPER_PM_OPS,
+        .of_match_table = of_match_ptr(pwm_beeper_match),
+    },
+};
+
+static int __init pwm_beeper_init(void)
+{
+    return spmi_driver_register(&pwm_beeper_driver);
+}
+module_init(pwm_beeper_init);
+
+static void __exit pwm_beeper_exit(void)
+{
+    spmi_driver_unregister(&pwm_beeper_driver);
+}
+module_exit(pwm_beeper_exit);
+
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("PWM beeper driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pwm-beeper");

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/855478.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

力扣每日一题(2024-6-18)2288. 价格减免

本文章是对官方题解的补充说明 原题链接&#xff1a;2288. 价格减免 思路 由题目中的“单词之间用单个空格分隔”和 “如果单词的形式为美元符号后跟着一个非负实数&#xff0c;那么这个单词就表示一个 价格 。” 可知&#xff1a; 首先要通过 ‘space’把原字符串进行切分&…

PHP 标准建议psr

PSR-1: Basic Coding Standard&#xff08;基础编码标准&#xff09; PSR-1 定义了PHP代码文件的基本编写规范&#xff0c;它关注的是代码文件的结构和一些通用的编程约定&#xff0c;主要包括&#xff1a; 文件命名&#xff1a;PHP文件必须以.php为后缀。PHP标签&#xff1a…

智慧校园的构建要素是什么

在当今数字时代&#xff0c;智慧校园的构建已成为教育界的热门话题。随着技术的不断进步&#xff0c;学校不再只是传统的教学场所&#xff0c;而是一个充满智能化和创新的环境。那么&#xff0c;智慧校园的构建要素究竟是什么呢&#xff1f; 基础设施建设 高速、稳定的网络覆…

Vue的computed大致细节

computed computed具体实现流程computer的执行顺序 computed 具体实现流程 computer内部首先是标准化参数然后调用runner函数进行依赖收集设置dirty为true创建副作用函数&#xff0c;具体如下 const runner effect(getter,{//延迟执行lazy:true,//标记为computed effect 用…

pygame游戏开发

Pygame游戏开发 pygame简介 模块库请参考&#xff1a;pygame官方文档 pygame可以用作游戏开发&#xff0c;但在商业游戏中真正的开发工具却不是pygame。使用pygame开发游戏周期长。 安装pygame 在pycharm中安装第三方库pygame&#xff1a; 在计算机中安装pygame&#xf…

ElasticSearch学习篇13_《检索技术核心20讲》进阶篇之LSM树

背景 学习极客实践课程《检索技术核心20讲》https://time.geekbang.org/column/article/215243&#xff0c;文档形式记录笔记。 内容 磁盘和内存数据读取特点 工业界中数据量往往很庞大&#xff0c;比如数据无法全部加载进内存&#xff0c;无法支持索引的高效实时更新&…

Nature Electronics|微器件在柔性基底上的高密度集成(可穿戴电子/界面调控/电子皮肤/柔性电子)

2024年4月22日,韩国首尔大学Yongtaek Hong和美国斯坦福大学Byeongmoon Lee团队,在《Nature Electronics》上发布了一篇题为“A site-selective integration strategy for microdevices on conformable substrates”的论文。论文内容如下: 一、 摘要 微器件可以被集成在柔性…

【GD32F303红枫派使用手册】第十九节

19.1 实验内容 通过本实验主要学习以下内容&#xff1a; SPI简介 GD32F303 SPI简介 SPI NOR FLASH——GD25Q32ESIGR简介 使用GD32F303 SPI接口实现对GD25Q32ESIGR的读写操作 19.2 实验原理 19.2.1 SPI简介 SPI&#xff08;Serial Peripheral interface&#xff09;&…

Django期末重点

思维导图 一、Djanog框架基础 MVT设计模式&#xff08;model模型【操作数据库】、template模板【页面展示】、view视图【处理请求和调用模型模板】&#xff09; 二、Django项目框架搭建 创建项目骨架 django-admin startproject 项目名启动服务 &#xff08;1&#xff09;p…

STM32(七)———TIM定时器(基本and通用)

文章目录 前言一、通用定时器TIM简介1.STM32F10X系列总共最多有八个定时器&#xff1a;2.三种STM32定时器的区别&#xff1a;3.STM32 的通用定时器功能&#xff1a;4.计数器模式 二、基本定时器1.基本定时器的结构框图2.定时时间的计算3.定时器的结构体和库函数 总结 前言 一个…

C#——文件读取BufferedStream类详情

文件读取BufferedStream类 BufferedStream字节流临时存储 缓存区是内存中字节块&#xff0c;用于缓存数据&#xff0c;减少对操作系统调用失败的次数&#xff0c;缓存区可以提升数据 用法: // 创建一个缓存区对象 参数是stream对象&#xff0c;指定字节临时存储的路径 Buffe…

如何利用机器学习算法进行数据分析和挖掘,数据优化、预处理、特征提取等老板吩咐的工作

在利用机器学习算法进行数据分析和挖掘时&#xff0c;数据优化、预处理和特征提取是非常重要的步骤。 1. 数据收集 收集相关数据&#xff0c;这是整个过程的起点和基础。数据可以来自多个来源&#xff0c;如数据库、API、网络爬虫等。 2. 数据预处理 数据预处理是保证数据质…

如何实现ElementUI动态表头?

可能看到这个标题,有些小伙伴会有些疑惑,动态表头是个什么东西,怎么没听说过? 其实动态表头在企业的项目中用途还是非常广泛的,比如erp系统什么的 那么动态表头是什么呢?说简单点就是让ElementUI的Table表格可以实现自定义表头展示+表头拖拽排序的一个功能 这个东西我…

<Rust><iced>基于rust使用iced构建GUI实例:如何将svg格式转为ico格式图片?

前言 本专栏是Rust实例应用。 环境配置 平台:windows 软件:vscode 语言:rust 库:iced、iced_aw 概述 本文是专栏第4篇实例,依旧是一个图像格式转换程序,基于rust的svg库resvg、图像处理库image以及文件处理库rfd。 流程是先用resvg获取svg图片的数据并将其转为png数据…

20.Dcoker跨宿主机容器通信之overlay

Dcoker跨宿主机容器通信之overlay http://www.cnblogs.com/CloudMan6/p/7270551.html 环境准备&#xff0c;三台机器&#xff0c;主机名为docker01&#xff08;192.168.111.11&#xff09;、docker02&#xff08;192.168.111.12&#xff09;、docker03&#xff08;192.168.111…

电子竞赛5——作息时间控制器

一 . 题目要求 用单片机制作作息时间控制器&#xff1b;用四位数码管显示实时时钟&#xff08;时、分&#xff0c;24小时制、12小时制&#xff09;&#xff0c;有秒闪&#xff0c;小时十位有零消隐&#xff1b;可用数字键或、-键校时&#xff08;可快速、-&#xff09;被校位&…

【ARMv8/ARMv9 硬件加速系列 4 -- 加解密 Cryptographic Extension 介绍】

文章目录 ARMv8.0 Cryptographic ExtensionFEAT_AESFEAT_PMULLFEAT_SHA1FEAT_SHA256ARMv8.2 扩展FEAT_SHA512FEAT_SHA3FEAT_SM3FEAT_SM4ARMv8.0 Cryptographic Extension ARMv8.0引入了加密扩展(Cryptographic Extension),旨在加速加密和解密操作。这一扩展通过新增专用指令…

redis雪崩问题怎么解决

Redis雪崩问题通常发生在大量缓存同时过期&#xff0c;导致所有请求直接打到数据库上&#xff0c;从而可能压垮数据库。解决这一问题的关键在于分散缓存失效时间&#xff0c;避免集中失效。此外&#xff0c;还可以通过限流、降级、预热等策略来进一步缓解压力。 下面是一个综合…

C++代码编写风格:Header-Only与声明实现分离的选择

C代码编写风格&#xff1a;Header-Only与声明实现分离的选择 最近看到一些小伙伴问到了几个比较有趣的问题&#xff0c;这里总结一下&#xff0c;这些都是实际面试中出现过的问题&#xff0c;看看你知道多少&#xff0c;考察一下底子。 面试问题1&#xff1a;你通常编写代码的风…

JAVA云HIS医院管理系统源码 云HIS系统的应用场景

JAVA云HIS医院管理系统源码 云HIS系统的应用场景 云HIS是针对中小医疗健康机构推出的一套基于云端的诊所云HIS服务平台&#xff0c;包括内部管理系统、临床辅助决策系统、体检系统、客户管理与服务系统、健康管理系统、知识管理系统、医患沟通系统、线上营销系统、其他外部系…