tiny4412 驱动 (9)beep

先说原理图

其中XpwmTOUT0接的GPD0_0

对于Makefile:

TARGET  := beep

obj-m   += $(TARGET).o

ROOTFS = /home/flinn/tmp/rootfs
KERNEL = /home/flinn/tiny4412-SDK/linux-4.19.27

all:
        make -C $(KERNEL) M=`pwd` modules

clean:
        make -C $(KERNEL) M=`pwd` clean
        
install:
        #make -C $(KERNEL) M=`pwd` modules_install INSTALL_MOD_PATH=$(ROOTFS)
        sudo cp $(TARGET).ko $(ROOTFS)

beep.c

/*
* beep sdriver on linux-4.19.27(without dt)
* arm-linux-gcc-6.2.1
*/

#include <linux/module.h>

#include <linux/fs.h>
#include <linux/errno.h>

#include <linux/kernel.h>

#include <linux/mutex.h>
#include <linux/proc_fs.h>

#include <linux/init.h>
#include <linux/device.h>

#include <linux/gfp.h>
#include <linux/slab.h>   /* kmalloc, */
#include <linux/cdev.h>

#include <linux/uaccess.h> /* copy_from_usr, */
#include <asm/io.h>       /* ioremap, */



#define DEV_NAME		"beep"

struct beep_dev
{
	struct cdev *cdev;
	dev_t dev;
	int major;
	char name[32];
	struct class *class;
};


static struct beep_dev *beep_dev = NULL;

/*
* resource
* GPD0_0 for buzzer
*
* Note(s) : GPD0_1 as LCD
*/

struct _gpio
{
	unsigned long con;          /* configuration register */
	unsigned long data;         /* data register */
	unsigned long pud;          /* pull-up/ pull-down register */
	unsigned long drv;          /* drive strength control register */
	unsigned long conpdn;       /* power down mode configuration register */
	unsigned long pudpdn;       /* power down mode pull-up/ pull-down register 0x000 */
};

#define BEEP_GPIOD_CON_ADDR		0x114000A0

static struct _gpio *beep_gpio = NULL;


static int beep_open (struct inode *inode, struct file *file)
{
	printk(KERN_INFO "open \n");	

	/* set GPMD_0 as output */
	beep_gpio->con |= (1 << 0);
	
	return 0;
}

static int beep_close (struct inode *inode, struct file *file)
{
	printk(KERN_INFO "close \n");	
	
	return 0;
}

static ssize_t beep_write (struct file *file, const char __user *usrbuf, size_t len, loff_t *off)
{
	char cmd,opt;
	char rev_buf[8] = {0};
	
	printk(KERN_INFO "write \n");		

	if(copy_from_user(rev_buf,usrbuf,8))
		return -EFAULT;

	cmd = rev_buf[0];
	opt = rev_buf[1];

	printk(KERN_NOTICE "cmd : %d opt : %d \n", cmd, opt);

	if(cmd == 0)
	{
		// off
		beep_gpio->data &= ~(1<<0);		
	}
	else if(cmd == 1)
	{
		// on
		beep_gpio->data |= (1<<0);
	}
	else
	{
		// do nothing.
	}
	
	return 0;
}

static long beep_ioctl (struct file *file, unsigned int cmd, unsigned long arg)
{
	printk(KERN_INFO "ioctl \n");	

	return 0;
}


const struct file_operations beep_ops = 
{
	.owner = THIS_MODULE,
	.open = beep_open,
	.release = beep_close,
	.unlocked_ioctl = beep_ioctl,
	.write = beep_write,
};


static int beep_drv_init(void)
{
	int ret = 0;
	
	printk(KERN_INFO "beep drv init.\n");

	beep_dev = kmalloc(sizeof(struct beep_dev),GFP_KERNEL);
	if(!beep_dev)
		return -ENOMEM;

	strcpy(beep_dev->name, DEV_NAME);

	ret = alloc_chrdev_region(&beep_dev->dev, 0, 1, beep_dev->name);
	beep_dev->major = MAJOR(beep_dev->dev);
	
	if(ret < 0)
	{
		kfree(beep_dev);
		return ret;
	}

	beep_dev->cdev = cdev_alloc();
	if(!beep_dev->cdev)
	{
		unregister_chrdev_region(beep_dev->dev,1);
		kfree(beep_dev);
		return -EFAULT;
	}
	cdev_init(beep_dev->cdev,&beep_ops);
	beep_dev->cdev->owner = THIS_MODULE;
	beep_dev->cdev->ops = &beep_ops;
	cdev_add(beep_dev->cdev,beep_dev->dev,1);

	beep_dev->class = class_create(THIS_MODULE,beep_dev->name);
	ret = PTR_ERR(beep_dev->class);
	if (IS_ERR(beep_dev->class))
	{
		cdev_del(beep_dev->cdev);
		unregister_chrdev_region(beep_dev->dev,1);
		kfree(beep_dev);
		return -EFAULT;
	}

	device_create(beep_dev->class,NULL,beep_dev->dev,NULL,beep_dev->name,beep_dev);

	beep_gpio = (struct _gpio *)ioremap(BEEP_GPIOD_CON_ADDR, 0x20);
	
	return 0;
}

static void beep_drv_exit(void)
{
	printk(KERN_INFO "beep drv exit.\n");
	iounmap(beep_gpio);

	device_destroy(beep_dev->class, beep_dev->dev);
	class_destroy(beep_dev->class);
	cdev_del(beep_dev->cdev);
	unregister_chrdev_region(beep_dev->dev,1);
	kfree(beep_dev);
}

module_init(beep_drv_init);
module_exit(beep_drv_exit);
MODULE_LICENSE("GPL");

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值