Linux Platform devices Platform device driver

Source: Internet
Author: User

Device bus driver Model: http://blog.csdn.net/lizuobin2/article/details/51570196

This article main reference: Http://www.wowotech.net/device_model/platform_device.html


Platform platform device driver is based on the device bus driver model, it is simply to further encapsulate the device into a platform_device, device_driver further encapsulated into the Platform_device_driver, The device bus driver model has been analyzed earlier, the registration process of devices and device_driver and their hierarchical relationships in the Sysfs file system are not analyzed, this paper focuses on the platform platform device driver and the device bus driver model compared to the new additions to those things.


In the abstraction of the Linux device model, there is a class of devices called "Platform device" that the kernel describes (documentation/driver-model/platform.txt):

Platform devices is devices that typically appear as autonomous entities in the system. This includes legacy port-based devices and host bridges to peripheral buses, and most controllers integrated into system-  On-chip platforms.  What they usually has in common are direct addressing from a CPU bus. Rarely, a platform_device would be connected through a segment of some other kind of bus; But the its registers would still be directly addressable.

In summary, platform devices include: Port-based devices (deprecated, reserved for older devices only, legacy), bridge devices connected to physical buses, controllers integrated on SOC platforms, and devices connected to other bus (rarely seen). Wait a minute.
These devices have a basic feature: they can be addressed directly via the CPU bus (for example, "registers" commonly found in embedded systems). Therefore, because of this commonality, the kernel is based on the device model (devices and device_driver), which further encapsulates these devices, abstracting Paltform bus, platform device, and platform driver, To enable developers to easily develop the drive for such devices.
It can be said that paltform devices are very important to Linux driver engineers because most of the device drivers we write are designed to drive plaftom devices.


Platform_bus_type
We know that in the device bus driver model, bus like one months old, through its match function, will register to the bus device and driver to pair, then each different bus has its own match function, we look at Platform_bus_ Type.

struct Bus_type Platform_bus_type = {. Name= "platform",. dev_attrs= platform_dev_attrs,.match= platform_match,.uevent= Platform_uevent,.pm= &platform_dev_pm_ops,};
static int Platform_match (struct device *dev, struct device_driver *drv) {struct Platform_device *pdev = To_platform_devic E (dev); struct Platform_driver *pdrv = To_platform_driver (DRV);/* match against the ID table first */if (pdrv->id_table) Return platform_match_id (pdrv->id_table, pdev)! = null;/* Fall-back to driver name match */return (strcmp (Pdev->nam E, drv->name) = = 0);}

If id_table is defined in Platform_device_driver, the platform_match_id is called to match
If not, it's just a comparison between Platform_device_driver->name and Platform_device->name, which is why teachers often say, "register drivers in the kernel when writing platform device drivers." If there is a device with the same name, call the Driver->probe function .... Actually not exactly right haha, platform_match_id the situation to me to meet again analysis.

Platform_device from Device packaging

struct Platform_device {const char* name;intid;struct devicedev;u32num_resources;struct resource* resource;struct platform_device_id*id_entry;/* Arch Specific additions */struct pdev_archdataarchdata;};
Name, which is copied to Dev.init_name when the device is registered.
Dev, the real device, through container_of, will be able to find the entire platform_device, access to other members, as mentioned later resource
Num_resources, resource, the resource description of the device, is abstracted by the struct resource (INCLUDE/LINUX/IOPORT.H) structure.
In Linux, system resources include I/O, Memory, Register, IRQ, DMA, bus and many other types。 Most of these resources are exclusive and do not allow multiple devices to be used at the same time, so the Linux kernel provides APIs for assigning and managing these resources.
When a device needs to use some resources, it simply organizes these resources (such as name, type, start, end address, and so on) with a struct resource and saves it in the device's resource pointer. Then, when the device probe, the device requirements invoke the resource management interface to allocate and use these resources. The kernel's resource management logic can determine if these resources are used, whether they can be used, and so on.

struct Resource {resource_size_t start;resource_size_t end;const char *name;unsigned long flags;struct resource *parent, *sibling, *child;};
static struct resource led_resource[] = {//jz2440 parameter, driver not tested [0] = {. Start = 0x56000010,.end   = 0x56000010 + 8-1,.flags = Ioresource_mem,},[1] = {. Start = 5,.end   = 5,.flags = ioresource_irq,},};static struct Platform_device led_dev = {. n Ame = "myled",//The device name matches the driver. id  = -1,.num_resources = Array_size (Led_resource),. Resource = Led_resource,.dev = {. rele ASE = LED_RELEASE,//.DEVT = MKDEV (252, 1),},};


Platform_device_dirver from the Device_driver package

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;struct platform_device_id *id_table;};
int Platform_driver_register (struct platform_driver *drv) {Drv->driver.bus = &platform_bus_type;if (drv-> Probe) Drv->driver.probe = platform_drv_probe;if (drv->remove) Drv->driver.remove = Platform_drv_remove;if ( Drv->shutdown) Drv->driver.shutdown = Platform_drv_shutdown;return Driver_register (&drv->driver);}
struct platform_driver structures and struct device_driver are very similar, top Platform_drv_probe, Platform_drv_remove, platform_drv_ Shutdown, just a little bit of conversion call Platform_driver in the probe, remove, shutdown functions, for example a little look at

static int platform_drv_probe (struct device *_dev) {struct Platform_driver *drv = To_platform_driver (_dev->driver); struct Platform_device *dev = To_platform_device (_dev); return drv->probe (dev);}


API provided by Platform device
/* include/linux/platform_device.h */extern int platform_device_register (struct platform_device *); extern void Platform_device_unregister (struct platform_device *); extern void Arch_setup_pdev_archdata (struct platform_device *); extern struct resource *platform_get_resource (struct  Platform_device *, unsigned int, unsigned int), extern int Platform_get_irq (struct platform_device *, unsigned int), extern struct resource *platform_get_resource_byname (struct platform_device *, unsigned int, const char *); extern int Platform_g Et_irq_byname (struct Platform_device *, const char *), extern int platform_add_devices (struct platform_device * *, int); extern struct Platform_device *platform_device_register_full (const struct platform_device_info *pdevinfo); Static inline struct Platform_device *platform_device_register_resndata (struct device *parent, const char *name, int ID, const struct resource *res, unsigned int num, const void *data, size_t size) Static inline struct Platform_device *platform_device_register_simple (const char *name, int ID, c                Onst struct resource *res, unsigned int num) static inline struct Platform_device *platform_device_register_data ( struct device *parent, const char *name, int id, const void *data, size_t size) extern struct PLATFO Rm_device *platform_device_alloc (const char *name, int id), extern int platform_device_add_resources (struct PLATFORM_                                         Device *pdev, const struct resource *res, unsigned int num); extern int Platform_device_add_data (struct platform_device *pdev, con St void *data, size_t size), extern int platform_device_add (struct platform_device *pdev), extern void Platform_device_del (struct platform_device *pdev); extern void Platform_device_put (struct platform_device *pdev);
Platform_device_register, Platform_device_unregister,platform device registration/Logoff interface, and the underlying device_register and other interfaces similar.
Arch_setup_pdev_archdata, sets the Archdata pointer in the Platform_device variable.
Platform_get_resource, Platform_get_irq, Platform_get_resource_byname, Platform_get_irq_byname, through these interfaces, You can get the resource information in the Platform_device variable, and get the number of the IRQ directly, and so on.
Platform_device_register_full, Platform_device_register_resndata, Platform_device_register_simple, platform_ Device_register_data, other forms of device registration. The caller only needs to provide some necessary information, such as name, ID, resource, etc., the Platform module will automatically assign a struct Platform_device variable, populate the content, register to the kernel.
Platform_device_alloc, dynamically assigns a struct Platform_device variable with name and ID as the parameter.
Platform_device_add_resources, add a description of the resource to the platform device.
Platform_device_add_data, add the custom data to the platform device (saved in the Pdev->dev.platform_data pointer).
Platform_device_add, Platform_device_del, Platform_device_put, other operating interfaces.

API provided by Platform driver
Platform_driver_registe, Platform_driver_unregister,platform driver registration, logout interface.
Platform_driver_probe, actively perform probe action.
Platform_set_drvdata, Platform_get_drvdata, sets or gets the private data driver saved in the device variable.

Lazy People API
extern struct Platform_device *platform_create_bundle (       struct platform_driver *driver, int (*probe) (struct Platform_device *),       struct resource *res, unsigned int n_res,       const void *data, size_t size);
As long as a platform_driver is provided (to explicitly pass in the driver probe interface) and the resource information used by the device is informed, the Platform module helps to allocate resources and perform probe operations. This is the easiest way to use devices that do not require hot plugging.


A simple example:

Development Board: Mini2440

Kernel version: 2.6.32.2

#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h > #include <linux/device.h> #include <linux/interrupt.h> #include <linux/sched.h> #include < linux/irq.h> #include <asm/uaccess.h> #include <linux/input.h> #include <linux/platform_device.h  >//device Resource static struct resource led_resource[] = {//jz2440 parameter, driver not tested [0] = {. Start = 0x56000010,.end = 0x56000010 + 8- 1,.flags = ioresource_mem,},[1] = {. Start = 5,.end = 5,.flags = ioresource_irq,},};static void led_release (struct Devic E *dev) {}//creates a device static struct platform_device Led_dev = {. Name = "Myled",//The device name matches the driver. id = -1,.num_resources = Array_ SIZE (Led_resource),. Resource = Led_resource,.dev = {. Release = Led_release,//.devt = MKDEV (252, 1),},};static int Led_dev _init (void) {///to Bus registration Led_dev match DRV list for pairing platform_device_register (&led_dev); return 0;} static void Led_dev_exit (void) {platform_device_unregister (&led_dev);} Module_iniT (led_dev_init); Module_exit (Led_dev_exit); Module_license ("GPL");

#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h > #include <linux/device.h> #include <linux/interrupt.h> #include <linux/sched.h> #include < linux/irq.h> #include <asm/uaccess.h> #include <linux/platform_device.h> #include <linux/io.h> static int major;static struct class *cls;static struct device *dev;static volatile unsigned long *gpio_con;static volatil e unsigned long *gpio_dat;static int pin;static int led_open (struct inode *inode, struct file *file) {*gpio_con &= ~ (0x << (pin*2); *gpio_con |= (0x01 << (pin*2)); return 0;} Static ssize_t led_write (struct file *file, const char __user *buf,size_t count, loff_t *ppos) {int Val;copy_from_user (&amp ; Val, buf, Count); if (val = = 1) {*gpio_dat &= ~ (1<<pin);} Else{*gpio_dat &= (1<<pin);} return 0;} static struct File_operations Led_fops = {. Owner = This_module,.open = Led_open,.write = led_write,};static int Led_probe (struct platform_device *pdev) {struct resource *res;//the last parameter 0 represents a 1th resource of that type res = Platform_get_resource (Pdev, IO Resource_mem, 0); Gpio_con = Ioremap (Res->start, Res->end-res->start + 1); Gpio_dat = Gpio_con + 1;res = Platform _get_resource (Pdev, IORESOURCE_IRQ, 0);p in = RES-&GT;START;PRINTK ("Led_probe, found led\n");//Register device driver to create device node major = Register_chrdev (0, "myled", &led_fops);//Create Class CLS = Class_create (This_module, "myled");//create device Node dev = device_create ( CLS, NULL, MKDEV (major, 0), NULL, "led"); return 0;} static int led_remove (struct platform_device *pdev) {PRINTK ("led_remove, remove led\n");//Delete device node Device_unregister (dev );//Destroy Class Class_destroy (CLS);//Unregister device driver Unregister_chrdev (major, "myled");//Cancel Memory Map Iounmap (Gpio_con); return 0;} struct Platform_driver led_drv = {. Probe = led_probe,//matches to dev after calling Probe.remove = Led_remove,.driver = {. Name = "Myled",},}; static int led_drv_init (void) {platform_driver_register (&led_drv); return 0;} static void Led_drv_exit (void) {Platform_drivEr_unregister (&AMP;LED_DRV);} Module_init (Led_drv_init); Module_exit (Led_drv_exit); Module_license ("GPL");



Linux Platform devices Platform device driver

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.