linux驱动之--平台总线

一.平台总线模型
1. 创建路口,出口函数
a) module_init(plat_led_drv_init); //入口
b) module_exit(plat_led_drv_exit); //出口
c) MODULE_LICENSE(“GPL”); //GPL协议
2. 注册一个pdrv
static int __init plat_led_drv_init(void)
{
printk(“————%s———-\n”, FUNCTION);
//注册一个pdrv
return platform_driver_register(&led_pdrv);
}
3. 构建一个pdrv
struct platform_driver led_pdrv = {
.probe = led_pdrv_probe,
.remove = led_pdrv_remove,
.driver = {
.name=”samsung_led_drv”,// /sys/bus/platform/drivers/samsung_led_drv
},
.id_table = led_id_table, //用于匹配,该成员不是必须的
};
4. 创建设备列表
const struct platform_device_id led_id_table[] = {
{“s3c2410_led”, 0x1111},
{“s3c6410_led”, 0x2222},
{“s5pc100_led”, 0x3333},
{“s5pv210_led”, 0x4444},
};
5. 实现.probe
int led_pdrv_probe(struct platform_device *pdev)
{
printk(“————%s———-\n”, FUNCTION);
int ret;
led_dev = kzalloc(sizeof(struct led_desc), GFP_KERNEL);
if(led_dev == NULL)
{
printk(KERN_ERR “kzalloc error\n”);
return -ENOMEM;
}

//获取到pdev中自定义数据
led_dev->pdata = pdev->dev.platform_data;
printk(" led name = %s\n", led_dev->pdata->name);

//  1, 申请主设备号
led_dev->dev_major = register_chrdev(0, "led_pdrv", &led_pdrv_fop);
if(led_dev->dev_major < 0)
{
    printk(KERN_ERR "register_chrdev error\n");
    ret = led_dev->dev_major;
    goto err_0;
}
// 2,利用udev/mdev机制创建设备文件(节点) class_create, device_create (与内核相关)
led_dev->cls =   class_create(THIS_MODULE, "led_pdrv_cls");
if(IS_ERR(led_dev->cls))
{
    printk(KERN_ERR "class_create error\n");
    ret = PTR_ERR(led_dev->cls);  //根据错误的指针自动转换成一个出错码
    goto err_1;
}
led_dev->dev = device_create(led_dev->cls, NULL,
            MKDEV(led_dev->dev_major, 10), NULL, "led%d", 10);
if(IS_ERR(led_dev->dev))
{
    printk(KERN_ERR "device_create error\n");
    ret = PTR_ERR(led_dev->dev);  //根据错误的指针自动转换成一个出错码
    goto err_2;
}
//3,硬件部分初始化
led_dev->res= platform_get_resource(pdev, IORESOURCE_MEM, 0);
if(IS_ERR(led_dev->res))
{
    printk(KERN_ERR "platform_get_resource error\n");
    ret = PTR_ERR(led_dev->res);  //根据错误的指针自动转换成一个出错码
    goto err_3;
}
//ioremap将一个IO地址空间映射到内核的虚拟地址空间上去,便于访问
led_dev->reg_base = ioremap(led_dev->res->start, resource_size(led_dev->res));
//如果需要去拿中断号码
int irqno = platform_get_irq(pdev, 0);
printk("----irqno = %d\n", irqno);

return 0;

err_3:
device_destroy(led_dev->cls, MKDEV(led_dev->dev_major, 10));
err_2:
class_destroy(led_dev->cls);
err_1:
unregister_chrdev(led_dev->dev_major, “led_pdrv”);
err_0:
kfree(led_dev);
return ret;
}
6. 构建操作函数
const struct file_operations led_pdrv_fop = {
.open = led_pdrv_open,
.write = led_pdrv_write,
.release = led_pdrv_close,
};
7. 实现.open
int led_pdrv_open (struct inode *inode, struct file *filp)
{
printk(“————%s———-\n”, FUNCTION);
//做初始化
//gpc0配成输出功能
int shift = led_dev->pdata->shift_num * 4;

unsigned int val = __raw_readl(led_dev->reg_base);
val &= ~(0xff<<shift);
val |= (0x11<<shift);
__raw_writel(val, led_dev->reg_base);
return 0;

}
8. 实现.write
ssize_t led_pdrv_write(struct file *inode, const char __user *buf, size_t count, loff_t *fpos)
{
int ret;
int value;
int shift = led_dev->pdata->shift_num ;
ret = copy_from_user(&value,buf, count);
if(ret > 0)
{
printk(KERN_ERR”copy_from_user errorm\n”);
return -EFAULT;
}
if(value){
__raw_writel(__raw_readl(led_dev->reg_base + 4) | (0x3<

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值