Linux内核-平台设备-platform

一、注册一个平台设备

  方法1:platform_device_register

  核心数据结构:

 1 struct platform_device {
 2     const char    *name;
 3     int        id;
 4     bool        id_auto;
 5     struct device    dev;
 6     u32        num_resources;
 7     struct resource    *resource;
 8 
 9     const struct platform_device_id    *id_entry;
10     char *driver_override; /* Driver name to force a match */
11 
12     /* MFD cell pointer */
13     struct mfd_cell *mfd_cell;
14 
15     /* arch specific additions */
16     struct pdev_archdata    archdata;
17 };
View Code

  核心接口

1 extern int platform_device_register(struct platform_device *);
View Code

  代码示例

static struct resource my_resoure1[]={
    {
        .start     = 0x00,
        .end    = 0x10,
        .name    = "resource1 MEM",
        .flags    = IORESOURCE_MEM,
    },
    
    {
        .start     = 0x11,
        .end    = 0x20,
        .name    = "resource2 MEM",
        .flags    = IORESOURCE_MEM,
    },
    
    {
        .start     = 5,
        .end    = 9,
        .name    = "resource3 IRQ",
        .flags    = IORESOURCE_IRQ,
    },
    {
        .start     = 10,
        .end    = 15,
        .name    = "resource4 IRQ",
        .flags    = IORESOURCE_IRQ,
    },
};
static struct platform_device my_device1 = {
    .name           = "xym-test-platform-device-1",
    .id                = -1,
    .num_resources     = ARRAY_SIZE(my_resoure1),
       .resource         = my_resoure1,
    
    .dev = {
        .release = my_platform_device_release, //不注册此接口,卸载驱动时会报警告
        .platform_data = &platform_data_1,
    },
};
struct platform_device * p_device_1 = &my_device1;

//device 1
ret = platform_device_register(&my_device1);
if (ret) 
{
    printk(KERN_INFO"Unable to device 1 register(%d)\n", ret);
    return ret;
}
View Code

  方法2:platform_device_register_full

  核心数据结构

 1 struct platform_device_info {
 2         struct device *parent;
 3         struct fwnode_handle *fwnode;
 4 
 5         const char *name;
 6         int id;
 7 
 8         const struct resource *res;
 9         unsigned int num_res;
10 
11         const void *data;
12         size_t size_data;
13         u64 dma_mask;
14 };
View Code

  核心接口

 1 extern struct platform_device *platform_device_register_full(const struct platform_device_info *pdevinfo);
 2 
 3 static inline struct platform_device *platform_device_register_simple(
 4         const char *name, int id,
 5         const struct resource *res, unsigned int num)
 6 
 7 static inline struct platform_device *platform_device_register_resndata(
 8         struct device *parent, const char *name, int id,
 9         const struct resource *res, unsigned int num,
10         const void *data, size_t size)
View Code

  代码示例

static struct resource my_resoure2[]={
    {
        .start     = 0x21,
        .end    = 0x30,
        .name    = "resource1 MEM",
        .flags    = IORESOURCE_MEM,
    },
    
    {
        .start     = 0x31,
        .end    = 0x40,
        .name    = "resource2 MEM",
        .flags    = IORESOURCE_MEM,
    },
    
    {
        .start     = 20,
        .end    = 30,
        .name    = "resource3 IRQ",
        .flags    = IORESOURCE_IRQ,
    },
    {
        .start     = 40,
        .end    = 50,
        .name    = "resource4 IRQ",
        .flags    = IORESOURCE_IRQ,
    },
};

static struct platform_device_info my_device_2 = {
    .name           = "xym-test-platform-device-2",
    .id                = -1,
    .num_res         = ARRAY_SIZE(my_resoure2),
    .res             = my_resoure2,
    .data            = &platform_data_2,
    .size_data        = sizeof(platform_data_2),
};
struct platform_device * p_device_2;

//device 2
p_device_2 = platform_device_register_full(&my_device_2);
if (!p_device_2) 
{
    printk(KERN_INFO"Unable to device 2 register\n");
    return ret;
}
View Code
static struct resource my_resoure3[]={
    {
        .start     = 0x41,
        .end    = 0x50,
        .name    = "resource1 MEM",
        .flags    = IORESOURCE_MEM,
    },
    
    {
        .start     = 0x51,
        .end    = 0x60,
        .name    = "resource2 MEM",
        .flags    = IORESOURCE_MEM,
    },
    
    {
        .start     = 60,
        .end    = 70,
        .name    = "resource3 IRQ",
        .flags    = IORESOURCE_IRQ,
    },
    {
        .start     = 80,
        .end    = 90,
        .name    = "resource4 IRQ",
        .flags    = IORESOURCE_IRQ,
    },
};

struct platform_device * p_device_3;

p_device_3 = platform_device_register_resndata(NULL, "xym-test-platform-device-3",-1,my_resoure3,ARRAY_SIZE(my_resoure3),&platform_data_3,sizeof(platform_data_3));    
    if (!p_device_3) 
    {
        printk(KERN_INFO"Unable to device 3 register\n");
        return ret;
    }
View Code
static struct resource my_resoure4[]={
    {
        .start     = 0x61,
        .end    = 0x70,
        .name    = "resource1 MEM",
        .flags    = IORESOURCE_MEM,
    },
    
    {
        .start     = 0x71,
        .end    = 0x80,
        .name    = "resource2 MEM",
        .flags    = IORESOURCE_MEM,
    },
    
    {
        .start     = 100,
        .end    = 110,
        .name    = "resource3 IRQ",
        .flags    = IORESOURCE_IRQ,
    },
    {
        .start     = 120,
        .end    = 130,
        .name    = "resource4 IRQ",
        .flags    = IORESOURCE_IRQ,
    },
};
struct platform_device * p_device_4;

//device 4
p_device_4 = platform_device_register_simple("xym-test-platform-device-4",-1,my_resoure4,ARRAY_SIZE(my_resoure4));
    if (!p_device_4) 
    {
        printk(KERN_INFO"Unable to device 4 register\n");
        return ret;
    }
View Code

  方法3、DTS注册

/ {
        platform_device_test,test{

        compatible = "dts_test";
        #address-cells = <1>;
        #size-cells = <1>;
        reg = <0x500 0x32>,<0x200 0x32>;
        reg-names = "test mem1","resource2 MEM";

        interrupt-parent = <&vic0>;
        interrupts = <IRQ_TIMER0>,<IRQ_TIMER1>;
        interrupt-names = "test irq1","resource4 IRQ";
        };
};    
View Code

二、获取平台设备资源

  核心接口

1 extern struct resource *platform_get_resource(struct platform_device *unsigned int, unsigned int);
2 extern int platform_get_irq(struct platform_device *, unsigned int);
3 extern struct resource *platform_get_resource_byname(struct platform_device *,unsigned int,const char *);
4 extern int platform_get_irq_byname(struct platform_device *, const char *);
View Code

  代码示例

struct resource *presource;

    int irq = 0;
    
    printk(KERN_INFO"---------------------------\n");
    printk(KERN_INFO"%s\n",__func__);
    printk(KERN_INFO"%s\n",pdev->name);
    if(pdev->dev.platform_data)
    {
        printk(KERN_INFO"platform_data is %d\n",*((int*)pdev->dev.platform_data));
    }
    
    presource = platform_get_resource(pdev,IORESOURCE_MEM,0);
    if(!presource)
    {
        printk(KERN_INFO"get mem1 resource failed\n");
        return -1;
    }
    printk(KERN_INFO"resoure1 name %s\n",presource->name);
    printk(KERN_INFO"resoure1 start 0x%08X\n",presource->start);
    printk(KERN_INFO"resoure1 end 0x%08X\n",presource->end);
    
    presource = NULL;
    presource = platform_get_resource_byname(pdev,IORESOURCE_MEM,"resource2 MEM");
    if(!presource)
    {
        printk(KERN_INFO"get mem2 resource failed\n");
        return -1;
    }
    printk(KERN_INFO"resoure1 name %s\n",presource->name);
    printk(KERN_INFO"resoure1 start 0x%08X\n",presource->start);
    printk(KERN_INFO"resoure1 end 0x%08X\n",presource->end);


    irq = platform_get_irq(pdev,0);

    if(irq < 0)
    {
        printk(KERN_INFO"get irq1 resource failed\n");
        return -1;        
    }
    printk(KERN_INFO"irq1 value is %d\n",irq);
    irq = 0;

    irq = platform_get_irq_byname(pdev,"resource4 IRQ");
    if(irq < 0)
    {
        printk(KERN_INFO"get irq2 resource failed\n");
        return -1;        
    }
    printk(KERN_INFO"irq2 value is %d\n",irq);
    printk(KERN_INFO"---------------------------\n\n\n");
View Code

三、销毁设备

1 platform_device_unregister(&my_device);
2 platform_device_unregister(p_device_2);
View Code

 四、注册平台设备驱动

核心数据结构

struct platform_driver {
    int (*probe)(struct platform_device *);
    int (*remove)(struct platform_device *);
    void (*shutdown)(struct platform_device *);
    int (*suspend)(struct platform_device *, pm_message_t state);
    int (*resume)(struct platform_device *);
    struct device_driver driver;
    const struct platform_device_id *id_table;
    bool prevent_deferred_probe;
};
View Code

核心接口

platform_driver_register
View Code

代码示例

static struct platform_driver my_driver1 = {
    
    .driver = {
        .name     =  "xym-test-platform-device-1",
        },
    .probe        = my_platform_probe,
    .remove        = my_platform_remove,
    .shutdown    = my_platform_shutdown,
    .suspend    = my_platform_suspend,
    .resume        = my_platform_resume,
};

ret = platform_driver_register(&my_driver1);
if (ret) 
{
    printk(KERN_INFO"Unable to driver 1 register(%d)\n", ret);
    return ret;
}
View Code

其中,driver中的 ”.name“ 字段和device中的 ”.name“ 相同,即可完成驱动和设备的匹配,即进入probe阶段。

结果输出

        

完整代码如下:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/ioport.h>


static struct resource my_resoure1[]={
    {
        .start     = 0x00,
        .end    = 0x10,
        .name    = "resource1 MEM",
        .flags    = IORESOURCE_MEM,
    },
    
    {
        .start     = 0x11,
        .end    = 0x20,
        .name    = "resource2 MEM",
        .flags    = IORESOURCE_MEM,
    },
    
    {
        .start     = 5,
        .end    = 9,
        .name    = "resource3 IRQ",
        .flags    = IORESOURCE_IRQ,
    },
    {
        .start     = 10,
        .end    = 15,
        .name    = "resource4 IRQ",
        .flags    = IORESOURCE_IRQ,
    },
};
static struct resource my_resoure2[]={
    {
        .start     = 0x21,
        .end    = 0x30,
        .name    = "resource1 MEM",
        .flags    = IORESOURCE_MEM,
    },
    
    {
        .start     = 0x31,
        .end    = 0x40,
        .name    = "resource2 MEM",
        .flags    = IORESOURCE_MEM,
    },
    
    {
        .start     = 20,
        .end    = 30,
        .name    = "resource3 IRQ",
        .flags    = IORESOURCE_IRQ,
    },
    {
        .start     = 40,
        .end    = 50,
        .name    = "resource4 IRQ",
        .flags    = IORESOURCE_IRQ,
    },
};

static struct resource my_resoure3[]={
    {
        .start     = 0x41,
        .end    = 0x50,
        .name    = "resource1 MEM",
        .flags    = IORESOURCE_MEM,
    },
    
    {
        .start     = 0x51,
        .end    = 0x60,
        .name    = "resource2 MEM",
        .flags    = IORESOURCE_MEM,
    },
    
    {
        .start     = 60,
        .end    = 70,
        .name    = "resource3 IRQ",
        .flags    = IORESOURCE_IRQ,
    },
    {
        .start     = 80,
        .end    = 90,
        .name    = "resource4 IRQ",
        .flags    = IORESOURCE_IRQ,
    },
};

static struct resource my_resoure4[]={
    {
        .start     = 0x61,
        .end    = 0x70,
        .name    = "resource1 MEM",
        .flags    = IORESOURCE_MEM,
    },
    
    {
        .start     = 0x71,
        .end    = 0x80,
        .name    = "resource2 MEM",
        .flags    = IORESOURCE_MEM,
    },
    
    {
        .start     = 100,
        .end    = 110,
        .name    = "resource3 IRQ",
        .flags    = IORESOURCE_IRQ,
    },
    {
        .start     = 120,
        .end    = 130,
        .name    = "resource4 IRQ",
        .flags    = IORESOURCE_IRQ,
    },
};

static int platform_data_1 = 1;
static int platform_data_2 = 2;
static int platform_data_3 = 3;
static int platform_data_4 = 4;

static int my_platform_probe(struct platform_device * pdev)
{
    struct resource *presource;

    int irq = 0;
    
    printk(KERN_INFO"---------------------------\n");
    printk(KERN_INFO"%s\n",__func__);
    printk(KERN_INFO"%s\n",pdev->name);
    if(pdev->dev.platform_data)
    {
        printk(KERN_INFO"platform_data is %d\n",*((int*)pdev->dev.platform_data));
    }
    
    presource = platform_get_resource(pdev,IORESOURCE_MEM,0);
    if(!presource)
    {
        printk(KERN_INFO"get mem1 resource failed\n");
        return -1;
    }
    printk(KERN_INFO"resoure1 name %s\n",presource->name);
    printk(KERN_INFO"resoure1 start 0x%08X\n",presource->start);
    printk(KERN_INFO"resoure1 end 0x%08X\n",presource->end);
    
    presource = NULL;
    presource = platform_get_resource_byname(pdev,IORESOURCE_MEM,"resource2 MEM");
    if(!presource)
    {
        printk(KERN_INFO"get mem2 resource failed\n");
        return -1;
    }
    printk(KERN_INFO"resoure1 name %s\n",presource->name);
    printk(KERN_INFO"resoure1 start 0x%08X\n",presource->start);
    printk(KERN_INFO"resoure1 end 0x%08X\n",presource->end);


    irq = platform_get_irq(pdev,0);

    if(irq < 0)
    {
        printk(KERN_INFO"get irq1 resource failed\n");
        return -1;        
    }
    printk(KERN_INFO"irq1 value is %d\n",irq);
    irq = 0;

    irq = platform_get_irq_byname(pdev,"resource4 IRQ");
    if(irq < 0)
    {
        printk(KERN_INFO"get irq2 resource failed\n");
        return -1;        
    }
    printk(KERN_INFO"irq2 value is %d\n",irq);
    printk(KERN_INFO"---------------------------\n\n\n");

    return 0;
}
static int my_platform_remove(struct platform_device * pdev)
{
    printk(KERN_INFO"%s\n",__func__);
    return 0;
}
static void my_platform_shutdown(struct platform_device *pdev)
{
    printk(KERN_INFO"%s\n",__func__);
}
static int my_platform_suspend(struct platform_device * pdev, pm_message_t state)
{
    printk(KERN_INFO"%s\n",__func__);
    return 0;
}
static int my_platform_resume(struct platform_device * pdev)
{
    printk(KERN_INFO"%s\n",__func__);
    return 0;
}

static void my_platform_device_release(struct device *dev)
{
    printk(KERN_INFO"%s\n",__func__);
}


static struct platform_device my_device1 = {
    .name           = "xym-test-platform-device-1",
    .id                = -1,
    .num_resources     = ARRAY_SIZE(my_resoure1),
       .resource         = my_resoure1,
    
    .dev = {
        .release = my_platform_device_release, //不注册此接口,卸载驱动时会报警告
        .platform_data = &platform_data_1,
    },
};
struct platform_device * p_device_1 = &my_device1;

static struct platform_driver my_driver1 = {
    
    .driver = {
        .name     =  "xym-test-platform-device-1",
        },
    .probe        = my_platform_probe,
    .remove        = my_platform_remove,
    .shutdown    = my_platform_shutdown,
    .suspend    = my_platform_suspend,
    .resume        = my_platform_resume,
};



static struct platform_device_info my_device_2 = {
    .name           = "xym-test-platform-device-2",
    .id                = -1,
    .num_res         = ARRAY_SIZE(my_resoure2),
    .res             = my_resoure2,
    .data            = &platform_data_2,
    .size_data        = sizeof(platform_data_2),
};
struct platform_device * p_device_2;
        
static struct platform_driver my_driver2 = {
    
    .driver = {
        .name    =  "xym-test-platform-device-2",

        },
    .probe        = my_platform_probe,
    .remove     = my_platform_remove,
    .shutdown    = my_platform_shutdown,
    .suspend    = my_platform_suspend,
    .resume     = my_platform_resume,
};


struct platform_device * p_device_3;
        
static struct platform_driver my_driver3 = {
    
    .driver = {
        .name    =  "xym-test-platform-device-3",

        },
    .probe        = my_platform_probe,
    .remove     = my_platform_remove,
    .shutdown    = my_platform_shutdown,
    .suspend    = my_platform_suspend,
    .resume     = my_platform_resume,
};

struct platform_device * p_device_4;
        
static struct platform_driver my_driver4 = {
    
    .driver = {
        .name    =  "xym-test-platform-device-4",

        },
    .probe        = my_platform_probe,
    .remove     = my_platform_remove,
    .shutdown    = my_platform_shutdown,
    .suspend    = my_platform_suspend,
    .resume     = my_platform_resume,
};

static struct of_device_id oz1c007_match_table[] = {
    { .compatible = "dts_test"},
};

static struct platform_driver my_driver5 = {
    
    .driver = {
        .name    =  "xym-test-platform-device-5",
        .of_match_table = oz1c007_match_table,
        .owner        = THIS_MODULE,
        },
    .probe        = my_platform_probe,
    .remove     = my_platform_remove,
    .shutdown    = my_platform_shutdown,
    .suspend    = my_platform_suspend,
    .resume     = my_platform_resume,

};

static int  platform_device_init(void)
{
    int ret = 0;

    
    printk(KERN_INFO"%s\n",__func__);
    
    //device 1
    ret = platform_device_register(&my_device1);
    if (ret) 
    {
        printk(KERN_INFO"Unable to device 1 register(%d)\n", ret);
        return ret;
    }
    ret = platform_driver_register(&my_driver1);
    if (ret) {
        printk(KERN_INFO"Unable to driver 1 register(%d)\n", ret);
        return ret;
    }

    //device 2
    p_device_2 = platform_device_register_full(&my_device_2);
    if (!p_device_2) 
    {
        printk(KERN_INFO"Unable to device 2 register\n");
        return ret;
    }
    ret = platform_driver_register(&my_driver2);
    if (ret) {
        printk(KERN_INFO"Unable to driver 2 register(%d)\n", ret);
        return ret;
    }

    //device 3
    p_device_3 = platform_device_register_resndata(NULL, "xym-test-platform-device-3",-1,my_resoure3,ARRAY_SIZE(my_resoure3),&platform_data_3,sizeof(platform_data_3));    
    if (!p_device_3) 
    {
        printk(KERN_INFO"Unable to device 3 register\n");
        return ret;
    }
    ret = platform_driver_register(&my_driver3);
    if (ret) 
    {
        printk(KERN_INFO"Unable to driver 4 register(%d)\n", ret);
        return ret;
    }
    
    //device 4
    p_device_4 = platform_device_register_simple("xym-test-platform-device-4",-1,my_resoure4,ARRAY_SIZE(my_resoure4));
    if (!p_device_4) 
    {
        printk(KERN_INFO"Unable to device 4 register\n");
        return ret;
    }
    platform_device_add_data(p_device_4, &platform_data_4,sizeof(platform_data_4));
    ret = platform_driver_register(&my_driver4);
    if (ret) 
    {
        printk(KERN_INFO"Unable to driver 4 register(%d)\n", ret);
        return ret;
    }
    
    //device 5 dts
    ret = platform_driver_register(&my_driver5);
    if (ret) {
        printk(KERN_INFO"Unable to driver 5 register(%d)\n", ret);
        return ret;
    }

    printk(KERN_INFO"---------------------------\n\n\n");
    return ret;
}


static void platform_device_destory(void)
{
    printk(KERN_INFO"%s\n",__func__);

    platform_device_unregister(p_device_1);
    platform_device_unregister(p_device_2);
    platform_device_unregister(p_device_3);
    platform_device_unregister(p_device_4);
    
    platform_driver_unregister(&my_driver1);
    platform_driver_unregister(&my_driver2);
    platform_driver_unregister(&my_driver3);
    platform_driver_unregister(&my_driver4);
    
    platform_driver_unregister(&my_driver5);

}


static int __init platform_test_init(void)
{
    printk(KERN_INFO"Enter platform test\n\n");
    platform_device_init();
    return 0;
}

static void __exit platform_test_exit(void)
{
    printk(KERN_INFO"Exit platform test\n");
    platform_device_destory();
    
}

module_init(platform_test_init);
module_exit(platform_test_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marvin.xin");
MODULE_DESCRIPTION("A Test Module for Platform driver");
View Code

猜你喜欢

转载自www.cnblogs.com/forthetechnology/p/10647252.html