ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

raspberryPlatformDriver

2021-05-27 09:02:23  阅读:151  来源: 互联网

标签:struct int dev platform raspberryPlatformDriver device fsled


fsdrv.c

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

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

#include <linux/slab.h>
#include <linux/ioctl.h>
#include <linux/uaccess.h>


#include<linux/io.h>
#include<linux/ioport.h>
#include<linux/platform_device.h>

#include "fsled.h"

#define FSLED_MAGOR 255
#define FSLED_DEV_NAME "fsled"

struct fsled_dev {
    unsigned int __iomem *con;
    unsigned int __iomem *dat;
    unsigned int __iomem *clear;
    unsigned int pin;
    atomic_t available;
    struct cdev cdev;
    struct device *dev;
};

struct class *fsled_cls;

static int fsled_open(struct inode *inode, struct file *filp){
    struct fsled_dev *fsled = container_of(inode->i_cdev, struct fsled_dev, cdev);

    printk("fsled_open\n");
    filp->private_data = fsled;
    if(atomic_dec_and_test(&fsled->available))
        return 0;
    else{
        atomic_inc(&fsled->available);
        return -EBUSY;
    }
}

static int fsled_release(struct inode *inode, struct file *filp){
    struct fsled_dev *fsled = filp->private_data;

    writel(readl(fsled->dat) & ~(0x1<<7), fsled->dat);
    atomic_inc(&fsled->available);
    return 0;
}

static long fsled_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){
    struct fsled_dev *fsled = filp->private_data;
    if(_IOC_TYPE(cmd) != FSLED_MAGIC)
        return -ENOTTY;

    switch(cmd){
        case FSLED_ON:
            printk("fsled_ioctl led on\n");
            writel(0x1<<12, fsled->dat);
            writel(0x00, fsled->clear);
            break;
        case FSLED_OFF:
            printk("fsled_ioctl led off\n");
            writel(0x00, fsled->dat);
            writel(0x1<<12, fsled->clear);
            break;
        default:
            return -ENOTTY;
    }
    return 0;
}


static struct file_operations fsled_ops = {
    .owner = THIS_MODULE,
    .open = fsled_open,
    .release = fsled_release,
    .unlocked_ioctl = fsled_ioctl,
};

static int fsled_probe(struct platform_device *pdev){
    int ret;
    dev_t dev;
    struct fsled_dev *fsled;
    struct resource *res;
    unsigned int pin = *(unsigned int *)pdev->dev.platform_data;
    
    printk("fsled_probe\n");
    dev = MKDEV(FSLED_MAGOR, pdev->id);
    ret = register_chrdev_region(dev, 1, FSLED_DEV_NAME);
    if(ret){
        goto reg_err;
    }

    fsled = kzalloc(sizeof(struct fsled_dev), GFP_KERNEL);
    if(!fsled){
        ret = -ENOMEM;
        goto mem_err;
    }

    cdev_init(&fsled->cdev, &fsled_ops);
    ret = cdev_add(&fsled->cdev, dev, 1);
    if (ret)
        goto add_err;
    printk("cdev finish\n");

    fsled->dev = device_create(fsled_cls, NULL, dev, NULL, "fsled");
    if(IS_ERR(fsled->dev)){
        ret = PTR_ERR(fsled->dev);
        printk("device_create failed\n");
        goto dev_err;
    }

    // get con address
    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    if(!res){
        ret = -ENOENT;
        printk("get_resource[0] failed\n");
        goto res_err;
    }
    fsled->con = ioremap(res->start, resource_size(res));
    if(!fsled->con){
        ret = -EBUSY;
        printk("get_resource[0] remap failed\n");
        goto map_err;
    }

    // get dat address
    res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
    if(!res){
        ret = -ENOENT;
        printk("get_resource[1] failed\n");
        goto res_err;
    }
    fsled->dat = ioremap(res->start, resource_size(res));
    if(!fsled->con){
        ret = -EBUSY;
        printk("get_resource[1] remap failed\n");
        goto map_err;
    }

    // get clear address
    res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
    if(!res){
        ret = -ENOENT;
        printk("get_resource[2] failed\n");
        goto res_err;
    }
    fsled->clear = ioremap(res->start, resource_size(res));
    if(!fsled->con){
        ret = -EBUSY;
        printk("get_resource[2] remap failed\n");
        goto map_err;
    }

    fsled->pin = pin;
    atomic_set(&fsled->available, 1);
    writel(0x1249249, fsled->con);
    //writel(readl(fsled.gpx2dat) & ~(0x1 << 7), fsled.gpx2dat);
    writel(0x00, fsled->dat);
    writel(0xFFFFFFFF, fsled->clear);
    platform_set_drvdata(pdev, fsled);
    printk("fsled_probe finish\n");

    return 0;

map_err:
dev_err:
res_err:
    cdev_del(&fsled->cdev);
add_err:
    kfree(fsled);
mem_err:
    unregister_chrdev_region(dev, 1);
reg_err:
    return ret;
}

static int fsled_remove(struct platform_device *pdev){
    dev_t dev;
    struct fsled_dev *fsled = platform_get_drvdata(pdev);
    printk("fsled_remove\n");
    dev = MKDEV(FSLED_MAGOR, pdev->id);

    iounmap(fsled->con);
    cdev_del(&fsled->cdev);
    kfree(fsled);
    unregister_chrdev_region(dev, 1);
    device_destroy(fsled_cls, dev);
    return 0;
}


struct platform_driver fsled_drv = {
    // int (*probe)(struct platform_device *);
    .probe = fsled_probe,
	// int (*remove)(struct platform_device *);
    .remove = fsled_remove,
	// void (*shutdown)(struct platform_device *);
	// int (*suspend)(struct platform_device *, pm_message_t state);
	// int (*resume)(struct platform_device *);
	.driver = {
        .name = "fsled",
        .owner = THIS_MODULE,
    },
	// const struct platform_device_id *id_table;
	// bool prevent_deferred_probe;
};

static int __init fsled_init(void){
    int ret;
    fsled_cls = class_create(THIS_MODULE, "fsled");
    if(IS_ERR(fsled_cls)){
        printk("class_create failed\n");
        return PTR_ERR(fsled_cls);
    }

    ret = platform_driver_register(&fsled_drv);
    if(ret){
        printk("platform_driver_register failed \n");
        class_destroy(fsled_cls);
    }

    return ret;
}

static void __exit fsled_exit(void){
    platform_driver_unregister(&fsled_drv);
    class_destroy(fsled_cls);
}

// module_platform_driver(fsled_drv);

module_init(fsled_init);
module_exit(fsled_exit);

// #define platform_driver_register(drv) 
// 	__platform_driver_register(drv, THIS_MODULE)
// extern int __platform_driver_register(struct platform_driver *,
// 					struct module *);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jianxiongs <XXXXX@qq.com>");
MODULE_DESCRIPTION("A simple module");

fsdev.c

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

#include <linux/platform_device.h>

static void fsdev_release(struct device *dev){

}

static struct resource led_resource[] = {
    [0] = DEFINE_RES_MEM(0x3F200004, 4),
    [1] = DEFINE_RES_MEM(0x3F20001C, 4),
    [2] = DEFINE_RES_MEM(0x3F200028, 4),
};

unsigned int ledpin = 2;

struct platform_device fsled_device = {
    .name = "fsled",
    .id = 0,
    .num_resources = ARRAY_SIZE(led_resource),
    .resource = led_resource,
    .dev = {
        .release = fsdev_release,
        .platform_data = &ledpin,
    }
};

static struct platform_device *fsled_devices[] = {
    &fsled_device,
};

static int __init fsdev_init(void){
    printk("fsdev_init\n");
    return platform_add_devices(fsled_devices, ARRAY_SIZE(fsled_devices));
}

static void __exit fsdev_exit(void){
    printk("fsdev_exit\n");
    platform_device_unregister(&fsled_device);
}

module_init(fsdev_init);
module_exit(fsdev_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jianxiongs <XXXXX@qq.com>");
MODULE_DESCRIPTION("A simple module");

fsled.h

#ifndef __FSLED_H
#define __FSLED_H

#define FSLED_MAGIC 'f'

#define FSLED_ON _IOW(FSLED_MAGIC, 0, unsigned int)
#define FSLED_OFF _IOW(FSLED_MAGIC, 1, unsigned int)

#define LEd2 0
#define LEd3 1
#define LEd4 2
#define LEd5 3

#endif

标签:struct,int,dev,platform,raspberryPlatformDriver,device,fsled
来源: https://blog.csdn.net/xiaoxiongxiongshi/article/details/117318865

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有