smart210驱动(5)leds-platform

Makefile

TARGET	:= leds_dev

obj-m	+= $(TARGET).o

ROOTFS	= /home/flinn/smart210-SDK/fs/drv
KERNEL	= /home/flinn/smart210-SDK/linux-3.10.79

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

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

install:
	sudo cp $(TARGET).ko $(ROOTFS)

make.sh

#!/bin/bash

echo -e "\e[1;31m##make clean \e[0m"
make clean

echo -e "\e[1;31m##make \e[0m"
make

echo -e "\e[1;31m##make install \e[0m"
make install

leds_dev.c

/*
* linux-3.10.27
* arm-linux-gcc-4.5.1
*
* @ leds driver
*/

#include <linux/module.h>
#include <linux/init.h>   /* module_init, ... */
#include <linux/kernel.h> /* everything */

#include <linux/cdev.h>   /* cdev_init, ... */
#include <linux/fs.h>     /* file_operations,  */
#include <linux/device.h>  /* class_create,... */
#include <linux/platform_device.h>
#include <linux/slab.h>   /* kmalloc, ... */
#include <asm/io.h>       /* ioremap,... */

#include <linux/uaccess.h>   /* copy_from_user, ... */


static void	leds_dev_release(struct device *dev)
{
	pr_info("%s called .\n", __func__);
}

static struct resource leds_dev_res[] = 
{	
	{
		.start = 0xE0200280,
		.end = 0xE0200280 + 0x10,
		.flags = IORESOURCE_MEM,
	},
};

static struct platform_device leds_dev = 
{
	.name = "myleds",
	.dev = {
		.release = leds_dev_release,
	},
	.num_resources = ARRAY_SIZE(leds_dev_res),
	.resource = &leds_dev_res[0],
};

static int leds_dev_init(void)
{
	int ret = 0;
	pr_info("%s called.\n", __func__);

	ret = platform_device_register(&leds_dev);
	if(ret < 0){
		pr_err("register leds dev err.\n");
		return ret;
	}
	
	return 0;
}

static void leds_dev_exit(void)
{
	pr_info("%s called.\n", __func__);
	
	platform_device_unregister(&leds_dev);
}

module_init(leds_dev_init);
module_exit(leds_dev_exit);
MODULE_LICENSE("GPL");

leds_drv.c

/*
* linux-3.10.27
* arm-linux-gcc-4.5.1
*
* @ leds driver
*/

#include <linux/module.h>
#include <linux/init.h>   /* module_init, ... */
#include <linux/kernel.h> /* everything */

#include <linux/cdev.h>   /* cdev_init, ... */
#include <linux/fs.h>     /* file_operations,  */
#include <linux/device.h>  /* class_create,... */
#include <linux/platform_device.h>
#include <linux/slab.h>   /* kmalloc, ... */
#include <asm/io.h>       /* ioremap,... */

#include <linux/uaccess.h>   /* copy_from_user, ... */

struct _gpio {
	unsigned long __iomem con;
	unsigned long __iomem dat;
	unsigned long __iomem pud;
	unsigned long __iomem drv;
	unsigned long __iomem conpdn;
	unsigned long __iomem pudpdn;
};


#define DEF_DEVICE_NAME			"myleds"
struct priv_data
{
	char *name;
	int major;

	dev_t dev;
	struct cdev *cdev;
	struct class *class;	
};

static struct priv_data *priv_data;
static struct _gpio *gpio_regs;

static int leds_open (struct inode *inode, struct file *file)
{
	pr_info("%s called.\n", __func__);
	
	return 0;
}

static int leds_close (struct inode *inode, struct file *file)
{
	pr_info("%s called.\n", __func__);

	return 0;
}


static ssize_t leds_write (struct file *pfile, const char __user *usrbuf, 
	size_t len, loff_t *offset )
{       
	int revbuf[8];
    int cmd, opt;
        
    printk(KERN_INFO "write \n");   
    if(copy_from_user(revbuf,usrbuf,8))
    {       
        return -EFAULT;
    }
        
    cmd = revbuf[0];
    opt = revbuf[1];
        
    printk(KERN_NOTICE "cmd : %d opt : %d \n", cmd, opt);
    if(cmd == 0)    // close
    {        	
        gpio_regs->dat |= (1 << opt);
    }
    else if(1 == cmd)  // open
    {       
        gpio_regs->dat &= ~(1 << opt);
    }
    else
    {       
        // do nothing .
    }
        
    return 0;
}

const struct file_operations fops = 
{
	.owner = THIS_MODULE,
	.open = leds_open,
	.release = leds_close,
	.write = leds_write,		
};

static int leds_drv_probe(struct platform_device *pdev)
{
	struct resource *res = NULL;
	int ret = 0;
	struct device *dev = &pdev->dev;
	
	pr_info("%s called.\n", __func__);

	if(!dev)
	{
		pr_err("no resource available.\n");
		return -EFAULT;
	}

	//priv_data = kmalloc(sizeof(struct priv_data), GFP_KERNEL);
	priv_data = devm_kzalloc(dev, sizeof(*priv_data), GFP_KERNEL);
	if(!priv_data){
		pr_err("no mem.\n");
		return -ENOMEM;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

	gpio_regs = devm_ioremap_resource(dev, res);
	if (IS_ERR(gpio_regs))
		return PTR_ERR(gpio_regs);

	priv_data->name = DEF_DEVICE_NAME;
	priv_data->major = 0;

	if(priv_data->major){
		priv_data->dev = MKDEV(priv_data->major, 0);
		register_chrdev_region(priv_data->dev, 1, priv_data->name);
	}
	else {
		ret = alloc_chrdev_region(&priv_data->dev, 1, 1, priv_data->name);
		priv_data->major = MAJOR(priv_data->dev);		
	}

	if(ret < 0){
		pr_err("register chrdev fail.\n");
		return -EFAULT;
	}

	priv_data->cdev = cdev_alloc();
	if(!priv_data->cdev){
		pr_err("alloc cdev err.\n");
		unregister_chrdev_region(priv_data->dev, 1);
	}
	cdev_init(priv_data->cdev, &fops);
	priv_data->cdev->ops = &fops;
	priv_data->cdev->owner = THIS_MODULE;
	cdev_add(priv_data->cdev, priv_data->dev, 1);

	/* add device */
	priv_data->class = class_create(THIS_MODULE, priv_data->name);
	if(!priv_data->class){
		pr_err("class create err.\n");
		goto cls_err;
	}

	/* create the device below /dev/ */
	device_create(priv_data->class, NULL, priv_data->dev, NULL, priv_data->name);

	/* set as output */
	gpio_regs->con |= (1 << 4 * 0) + (1 << 4 * 1) + \
				(1 << 4 * 2) + (1 << 4 * 3);

	gpio_regs->dat = 0x0f;
	
	return 0;

cls_err:
	cdev_del(priv_data->cdev);
	unregister_chrdev_region(priv_data->dev, 1);
	return -EFAULT;
}

static int leds_drv_remove(struct platform_device *pdev)
{
	pr_info("%s called.\n", __func__);
	device_destroy(priv_data->class, priv_data->dev);
	class_destroy(priv_data->class);
	
	cdev_del(priv_data->cdev);
	unregister_chrdev_region(priv_data->dev, 1);
	return 0;
}

const struct of_device_id leds_ids = {
	.compatible = "smart210,leds",
}; 

static struct platform_driver leds_drv = 
{	
	.probe = leds_drv_probe,
	.remove = leds_drv_remove,
	.driver = {
		.name = "myleds",
		.of_match_table = &leds_ids,
	},
};

static int leds_drv_init(void)
{
	int ret = 0;
	pr_info("%s called.\n", __func__);

	ret = platform_driver_register(&leds_drv);
	if(ret < 0){
		pr_err("register leds drv err.\n");
		return ret ;
	}
	
	return 0;
}

static void leds_drv_exit(void)
{
	pr_info("%s called.\n", __func__);
	
	platform_driver_unregister(&leds_drv);
}

module_init(leds_drv_init);
module_exit(leds_drv_exit);
MODULE_LICENSE("GPL");

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值