OrangePi3 LTS PWM的使用
kernel版本:orange-pi-5.10-media
根据使用手册,26pin中的pwm0默认是不开启的,需要开机后修改/boot/orangepiEnv.txt,在其中添加overlays=pwm字样,才可以启用。
如果不添加字样,如何默认开启pwm0 呢,修改dts配置文件。
pwm0对应的管脚pd22,在pinctrl默认将pmux配置成了uart2。
1、修改pinctrl节点,注释掉uart的pinctrl配置
// uart2_rts_cts_pins: uart2-rts-cts-pins {
// pins = "PD21", "PD22";
// function = "uart2";
// };
2、添加pwm0的pinctrl配置
pwm0_pin: pwm0-pin {
pins = "PD22";
function = "pwm";
};
3、修改驱动使用的节点
驱动文件
/**
* dts config
*
* sys_fans{
compatible = "max, fans";
pwms = <&pwm 0 1000000 1>;
};
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_device.h>
#include <linux/err.h>
#include <linux/pwm.h>
#include <linux/printk.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/delay.h>
#include <linux/kthread.h>
#include "../type.h"
#include "pwm_test.h"
static ssize_t name_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
return sprintf(buf, "%s\n", DRIVER_NAME);
}
static DEVICE_ATTR(name, 0444, name_show,NULL);
static struct attribute *attrs[] = {
&dev_attr_name.attr,
NULL, /* need to NULL terminate the list of attributes */
};
static struct attribute_group attr_group = {
.attrs = attrs,
};
static int dts_parse(struct platform_device *pdev)
{
int ret = 0;
struct device_node * node;
const char *str;
max_pwms_driver * max_pwms = (max_pwms_driver *)platform_get_drvdata(pdev);
struct pwm_state pstate;
node = pdev->dev.of_node;
if (!node)
{
max_error("failed to find node for %s\n",DEVICE_NAME);
return -ENODEV;
}
max_pwms->pwm = devm_of_pwm_get(&pdev->dev, pdev->dev.of_node, NULL);
if (IS_ERR(max_pwms->pwm))
{
dev_err(&pdev->dev, "Could not get PWM\n");
}
else
{
max_info("devm_of_pwm_get pwm success\n");
}
// pwm_init_state( max_pwms->pwm, &pstate);
// pr_info("pstate->period===%d\n",pstate.period);
// pr_info("pstate->duty_cycle===%d\n",pstate.duty_cycle);
// pr_info("pstate->polarity===%d\n",pstate.polarity);
max_info("devm_of_pwm_get pwm success\n");
pwm_config(max_pwms->pwm, 500000, 1000000);
//pwm_set_polarity(max_pwms->pwm, PWM_POLARITY_INVERSED);
pwm_enable(max_pwms->pwm);
return 0;
error:
return -EINVAL;
}
static int max_pwm_probe(struct platform_device *pdev)
{
int ret = 0;
struct class *pwms_class;
max_pwms_driver *max_pwms;
max_pwms = kzalloc(sizeof(max_pwms_driver), GFP_KERNEL);
if (!max_pwms) {
max_error("kzalloc max_pwms error\n");
return -ENOMEM;
}
mutex_init(&max_pwms->mutex);
platform_set_drvdata(pdev, max_pwms);
ret = dts_parse(pdev);
if (ret){
max_error("dts parse error\n");
goto malloc_error;
}
pwms_class = class_create(THIS_MODULE, DRIVER_NAME);
if (IS_ERR(pwms_class)) {
ret= PTR_ERR(pwms_class);
max_error("pwms_class: class create failed\n");
goto malloc_error;
}
max_pwms->dev = device_create(pwms_class,
&pdev->dev, 0, NULL, DEVICE_NAME);
if (unlikely(IS_ERR(max_pwms->dev))) {
ret = PTR_ERR(max_pwms->dev);
max_pwms->dev = NULL;
goto destory_class;
}
ret = sysfs_create_group(&max_pwms->dev->kobj, &attr_group);
if(ret){
max_error("sysfs_create_group in leds driver\n");
goto destory_device;
}
dev_set_drvdata(max_pwms->dev,max_pwms);
max_info("max_pwm_probe success \n");
return 0;
destory_device:
device_destroy(pwms_class,0);
destory_class:
class_destroy(pwms_class);
malloc_error:
kfree(max_pwms);
return -ENODEV;
}
static int max_pwm_remove(struct platform_device *pdev)
{
max_pwms_driver * max_pwms = (max_pwms_driver *)platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
kfree(max_pwms);
return 0;
}
static const struct of_device_id max_pwm_dt_match[] = {
{
.compatible = "max, fans",
},
{},
};
static struct platform_driver pwm_driver = {
.driver = {
.name = DEVICE_NAME,
.owner = THIS_MODULE,
.of_match_table = max_pwm_dt_match,
},
.probe = max_pwm_probe,
.remove = max_pwm_remove,
};
static int __init orange_pwm_init(void)
{
if (platform_driver_register(&pwm_driver)) {
max_error("failed to register driver\n");
return -ENODEV;
}
max_info("orange_pwm_init:module init\n");
return 0;
}
static void __exit orange_pwm_exit(void)
{
max_info("orange_pwm_exit module exit\n");
}
module_init(orange_pwm_init);
module_exit(orange_pwm_exit);
MODULE_DESCRIPTION("Max Pwm Test Driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("738270732@qq.com");
.h文件
#ifndef __PWM_TEST_H__
#define __PWM_TEST_H__
#define DRIVER_NAME "max_pwm"
#define DEVICE_NAME "pwms"
typedef struct pwm_driver
{
struct mutex mutex;
struct device *dev;
struct pwm_device *pwm;
unsigned int period;
unsigned int enable;
unsigned int duty;
}max_pwms_driver;
#endif