rk3399配寄存器形式控制pwm

版权声明:转载请说明出处 https://blog.csdn.net/qq_33166886/article/details/85164824

具体的寄存器配法,就去看一下手册吧 

#include<linux/pwm.h>
#include <linux/moduleparam.h>
#include <linux/stat.h>
#include <linux/kernel.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/module.h> 
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/clk.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/platform_device.h>
#include <linux/slab.h>

#define GPIO_LOW 0
#define GPIO_HIGH 1


#define PWM_REG_CNTR                    0x00  /* Counter Register */
#define PWM_REG_HPR		                  0x04  /* Period Register */
#define PWM_REG_LPR                     0x08  /* Duty Cycle Register */
#define PWM_REG_CTRL                    0x0c  /* Control Register */
/*REG_CTRL bits definitions*/
#define PWM_ENABLE			            (1 << 0)
#define PWM_DISABLE			            (0 << 0)
/*operation mode*/
#define PWM_MODE_ONESHOT			     (0x00 << 1)
#define PWM_MODE_CONTINUMOUS 	     (0x01 << 1)
#define PWM_MODE_CAPTURE		        (0x02 << 1)

int major;
int gpio;
static struct class *cls;
static struct clk *pwm_clk;
void __iomem *base;
static int pwm_open(struct inode *inode, struct file *file)
{
	printk(KERN_EMERG "%s-%d: enter\n",__FUNCTION__,__LINE__);
	
	return 0;	
}
static ssize_t pwm_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
	int val,ret;
	ret = copy_from_user(&val, buf, count);
	printk(KERN_INFO "val:%d\n",val);
	if(val>100){
		printk(KERN_INFO "error\n");
		return -1;
	}
	val = 100000 - (val * 1000);
	writel_relaxed(val,base + PWM_REG_LPR);
	return 0;
}
static struct file_operations pwm_fops = {
    .owner  =   THIS_MODULE,   
    .open   =   pwm_open,  
    .write  =	pwm_write,
};
static int pwm_probe(struct platform_device *pdev)
{
	struct resource *r;
//	struct device_node *node = pdev->dev.of_node;
	int ret;
	int val;
	int pwm_freq_nstime;
//	int pwm_id;
	int pwm_freq;

	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!r) {
		dev_err(&pdev->dev, "no memory resources defined\n");
		return -ENODEV;
	}
	
	base = devm_ioremap_resource(&pdev->dev, r);
	if (IS_ERR(base))
		return PTR_ERR(base);
	
	pwm_clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(pwm_clk)) {
		ret = PTR_ERR(pwm_clk);
		if (ret != -EPROBE_DEFER)
			dev_err(&pdev->dev, "Can't get bus clk: %d\n", ret);
		return ret;
	}
	ret = clk_prepare_enable(pwm_clk);
	if (ret) {
		dev_err(&pdev->dev, "Can't enable bus clk: %d\n", ret);
		return ret;
	}
//	of_property_read_u32(node, "pwm_id", &pwm_id);

	val = readl_relaxed(base + PWM_REG_CTRL);
	val = (val & 0xFFFFFFFE) | PWM_DISABLE;
	writel_relaxed(val, base + PWM_REG_CTRL);
	val = readl_relaxed(base + PWM_REG_CTRL);
	val = (val & 0xFFFFFFF9) | PWM_MODE_CONTINUMOUS;
	writel_relaxed(val, base + PWM_REG_CTRL);
	val = readl_relaxed(base + PWM_REG_CTRL);
	val = (val & 0xFF008DFF) | 0x0006000;
	writel_relaxed(val, base + PWM_REG_CTRL);
	val = readl_relaxed(base + PWM_REG_CTRL);
	val = (val & 0xFFFFFFFE) | PWM_ENABLE;
	writel_relaxed(val, base + PWM_REG_CTRL);
	pwm_freq = clk_get_rate(pwm_clk) / 64;
	printk(KERN_INFO "pwm_freq %d\n",pwm_freq);
	pwm_freq_nstime = 1000000000 / pwm_freq;
	printk(KERN_INFO "pwm_freq_nstime %d\n",pwm_freq_nstime);
	writel_relaxed(100000,base + PWM_REG_HPR);//Period
	
	writel_relaxed(80000,base + PWM_REG_LPR);//Duty
	
	major = register_chrdev(0, "pwm_test", &pwm_fops);
	cls = class_create(THIS_MODULE, "pwm_test");
	device_create(cls, NULL, MKDEV(major, 0), NULL, "pwm_buzzer"); 
	
	printk(KERN_INFO "pwm sucess\n");
	
	return 0;
}

static struct of_device_id pwm_of_match[] = {
        { .compatible = "pwm_1"},
        {}
};
static int pwm_remove(struct platform_device *pdev)
{
	int val;
	device_destroy(cls, MKDEV(major, 0));
	class_destroy(cls);
	unregister_chrdev(major, "pwm_test");
	writel_relaxed(100000,base + PWM_REG_LPR);//Duty
	val = readl_relaxed(base + PWM_REG_CTRL);
	val = (val & 0xFFFFFFFE) | PWM_DISABLE;
	writel_relaxed(val, base + PWM_REG_CTRL);
	val = readl_relaxed(base + PWM_REG_CTRL);
	val = (val & 0xFFFFFFF9) | PWM_MODE_CAPTURE;
	writel_relaxed(val, base + PWM_REG_CTRL);
	val = readl_relaxed(base + PWM_REG_CTRL);
	val = (val & 0xFF008DFF) | 0x0006000;
	writel_relaxed(val, base + PWM_REG_CTRL);
	val = readl_relaxed(base + PWM_REG_CTRL);
	val = (val & 0xFFFFFFFE);
	writel_relaxed(val, base + PWM_REG_CTRL);
	return 0;
}
static struct platform_driver pwm_driver={
        .driver = {
                .name           ="pwm",
                .owner          =THIS_MODULE,
                .of_match_table = pwm_of_match,
        },
        .probe  = pwm_probe,
        .remove = pwm_remove,
};
module_platform_driver(pwm_driver);
MODULE_LICENSE("GPL");

关于这个的dts配置:

&pwm1 {
        status = "okay";
        compatible = "pwm_1";

};

猜你喜欢

转载自blog.csdn.net/qq_33166886/article/details/85164824