Linux device-driven platform platform bus working principle (iii)

Source: Internet
Author: User



Equipment for data, driven for processing


1, take led-s3c24xx.c as an example to analyze the registration process of platform device and driver


the driving data structure of the LEDs is as follows:

static struct Platform_driver S3c24xx_led_driver = {. probe= s3c24xx_led_probe,.remove= s3c24xx_led_remove,.driver= {. Name= "s3c24xx_led",. owner= this_module,},};struct platform_driver data structure is 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;};


The device data structure of the LED is

static struct Platform_device mini2440_led1 = {. Name= "s3c24xx_led",. id= 1,.dev= {. platform_data= &mini2440_led1_ Pdata,},};

The name of the device and the name of the driver in the same, the device data structure of the ID value to distinguish between different led devices, because a board may have more than one led, with this ID value to distinguish between different LED lights, this ID value can be arbitrary to row, for example, there are four LEDs, The ID value can be set to a number from 1 to 4, and another way is that we do not go to the specified ID value, set the ID value to-1. Indicates the ID of the LED on the board, and the kernel helps us assign it. The Platform_data in member Dev is the data part of the device.

struct Platform_device's data structure contains

struct Platform_device {const char* name;intid;struct devicedev;u32num_resources;struct resource* resource;const struct platform_device_id*id_entry;/* Arch specific additions */struct pdev_archdataarchdata;};

You can see that the dev member variable is indeed TRUCT device data structure content

struct device {struct device*parent;struct device_private*p;struct kobject kobj; const char*init_name; /* initial name of the device */struct  device_type*type;struct mutexmutex;/* mutex to synchronize calls to *  Its driver. */struct bus_type*bus;/* type of bus device is on  */struct device_driver *driver;/* which driver has allocated this    device */void*platform_data;/* Platform specific data, device    CORE DOESN ' t touch it */struct dev_pm_infopower; #ifdef  config_ numaintnuma_node;/* numa node this device is close to */#endifu64 *dma_ mask;/* dma mask  (IF DMA ' Able device)  */u64coherent_dma_mask;/* Like  Dma_mask, but for&nBsp;    alloc_coherent mappings as     not all  hardware supports     64 bit addresses for consistent      allocations such descriptors. */struct device_dma_parameters  *dma_parms;struct list_headdma_pools;/* dma pools  (IF DMA ' ble)  */struct  dma_coherent_mem*dma_mem; /* internal for coherent mem      override *//* arch specific additions */struct dev_archdataarchdata; #ifdef  CONFIG_OFstruct device_node*of_node; #endifdev_tdevt;/* dev_t, creates the sysfs   "Dev"  */spinlock_tdevres_lock;struct list_headdevres_head;struct klist_nodeknode_class; Struct class*class;const struct attribute_group **groups;/* optional groups  */void (*release) (strUct device *dev);}; 


One can see that there is a void *platform_data in this struct device struct type ; a member that is a pointer to any type that is the data part of the device. Back to the data structure of the LED device

static struct Platform_device mini2440_led1 = {. Name= "s3c24xx_led",. id= 1,.dev= {. platform_data= &mini2440_led1_ Pdata,},};

Member of the struct device type Dev member Platform_data, this platform_data is a pointer to any type, this position is a white position, we can write a

Something that binds the finished object to this platform_data member, the void * type of the Platform_data member variable points to something that is left to us because it is void * type, so we can define a type by ourselves and then bind to it. , this place can be said to be a unique part of the data in a device, because the kernel device and the driver in the design, do not have all the equipment to define everything, so a void * Type of member variable let us define the device-specific data section.

The Platform_data member variable in the device data structure of this led is pointing to a min2440_led1_pdata so that the data structures that are written by the person who wrote the LED device are defined by themselves. Look at the data structure of this mini2440_led1_pdata variable.

static struct S3c24xx_led_platdata Mini2440_led1_pdata = {. Name= "led1",. gpio= S3C2410_GPB (5),. flags= s3c24xx_ledf_ ACTLOW | S3c24xx_ledf_tristate,.def_trigger= "Heartbeat",};

Look at the struct type of the mini2440_led1_pdata variable struct s3c24xx_led_platdata

struct S3c24xx_led_platdata {unsigned int gpio;unsigned int flags;char*name;char*def_trigger;};

This is a data structure type that is defined by itself, not a data structure type defined by the kernel beforehand, because the content of the part that the Platform_data member of the device points to is what we decide. This struct s3c24xx_led_platdata defines some parts of the data that are unique to the LEDs, and the platform_data of the different devices of the platform platform bus are certainly not the same, as we are going to define this not the same place, The data structure that the Platfrom_data member points to is the key, which is used to differentiate what device the Platform platform bus is, the particular part of the device.

For this led device the Platform_data member points to the LED device specific to their own defined data structure in the struct S3c24xx_led_platdata, the GPIO represents the pin number used by this led, Flags corresponds to the properties of the LEDs. Name indicates the name of the LED, and Def_trigger may indicate that the LED is to be tied to other hardware.

Below continues to divide this min2440_led1_pdata variable, the LED device-specific data section, which the transplant person himself defines

static struct S3c24xx_led_platdata Mini2440_led1_pdata = {. Name= "led1",. gpio= S3C2410_GPB (5),. flags= s3c24xx_ledf_ ACTLOW | S3c24xx_ledf_tristate,.def_trigger= "Heartbeat",};

The name is led1, the Gpio offset is S3C2410_GPB (5), the attribute flags is ..., and the Def_trgiger value is Heatbeat, indicating that the led1 will be used as a heartbeat lamp in the future.

We will write the data part of the LED, and then bind to the Plotform_data member, let this member point to our writing led specific device data section, in view of how to bind, a bit around

static struct Platform_device mini2440_led1 = {. Name= "s3c24xx_led",. id= 1,.dev= {. platform_data= &mini2440_led1_ Pdata,},};

Mini2440_led1_pdata this device-specific data structure is bound to the Platform_data members, the unique part of the information we achieve the LED device-specific data section, and finally the struct plat_device type of mini2440_ The data structure of the LED1 device is filled, and the mini2440_led1 variable is registered with the Register function, which represents the device of an LED.


Summary: Platform_data is actually some data about devices that are provided during device registration (such as the Gpio for the device, the interrupt number used, the device name ...). ), when registering a platform device, we provide the device data for this device, which after our device and driver match, the match function will be called to identify the device and the driver, the device and the driver match, will be transferred from the device to the driver, This data is provided for the future device and driver matching, the device data structure will be transferred to the driver, the drive to get the data, through the data to know the specific information of the device, and then to operate the device. The advantage of this is that we do not carry data in the driver source code, only responsible for the operation of the hardware, but do not know what hardware we specifically operate, the drive is through the device and drive match match, the device will be the data we provide to the driver, the driver know which device to operate, Because the data includes the resources used by the device (such as the device corresponding to the GPIO, the use of the interrupt number and so on), and the driver has a method of operation of this type of device, so the drive to get the data of this device, directly using the operation method can operate the device. Data and operation logic separate implementation is a good design logic, because of this, the driver has a general, when the hardware changed, that is, the device with the Gpio changed, we do not need to change the source of the drive, but at the time of the transplant, will replace the hardware after the resources of the device to change the line, Drive source code is not changed.


Now that the device and the driver match, the device will transfer the specific data portion of the device we provide to the driver, then the driver can know which hardware to operate in its own way, then the device transmits the data part to the driver, in the probe function

Static int s3c24xx_led_probe (Struct platform_device *dev) {Struct s3c24xx_led_platdata  *pdata = dev->dev.platform_data;struct s3c24xx_gpio_led *led;int ret;led  = kzalloc (sizeof (struct s3c24xx_gpio_led),  gfp_kernel);if  (led == null)  {dev_err (&dev->dev,  "no memory for device\n"); return -enomem;} Platform_set_drvdata (dev, led);led->cdev.brightness_set = s3c24xx_led_set;led-> Cdev.default_trigger = pdata->def_trigger;led->cdev.name = pdata->name;led-> Cdev.flags |= led_core_suspendresume;led->pdata = pdata;/* no point in  having a pull-up if we are always driving */if  (pdata-> flags & s3c24xx_ledf_tristate)  {s3c2410_gpio_setpin (pdata->gpio, 0); S3c2410_gpio_ Cfgpin (PDATA-&GT;GPIO,&NBSP;S3C2410_GPIO_INPUT);}  else {s3c2410_gpio_pullup (pdata->gpio, 0); S3c2410_gpio_setpin (pdata->gpio, 0); S3c2410_gpio_cfgpin (pdata->gpio, s3c2410_gpio_output);} /* register our new led device */ret = led_classdev_register (&dev- >dev, &led->cdev);if  (ret < 0)  {dev_err (&dev->dev,  "Led_ Classdev_register failed\n "); Kfree (LED); Return ret;} return 0;}

We can see a line of code starting in the probe function of the LED driver code

struct S3c24xx_led_platdata *pdata = dev->dev.platform_data;

This line of code is to transfer the data portion of the device to the driver, because the driver's probe function defines a struct s3c24xx_led_platdata type of pdata struct pointer, and the probe function parameter is

struct Platform_device type of dev pointer, through the above analysis we know that the data structure of this device, the data structure of this device has a member variable dev, this dev is a struct device type structure, this struct There is a PLATFORM_DATA member variable in the device type structure that points to the data part that we write about the unit, in which the data type of this particular data part is S3c24xx_led_platdata, So we can see from the above code that the driver code of the probe function, through the pdata pointer to the unique data part of the LED device Platform_data, which is the device will provide us with the data part of the process of transmission to the driver.


This article is from the "Whylinux" blog, make sure to keep this source http://whylinux.blog.51cto.com/10900429/1930747

Linux device-driven platform platform bus working principle (iii)

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.