Platform_device and platform_driver

Source: Internet
Author: User

Linux has been around for more than three months, and some structures in the Code have not been very clear. For example, the relationship between platform_device and platform_driver remains unclear. I searched it online and made a summary. The working order of the two is to first define platform_device-> note platform form_device->, and then define platform_driver-> note platform form_driver.

(1) the device Injection Process of platform_device must be called before the corresponding device driver is loaded. Because the driver injection process must match the device name that has been injected into the kernel. When the system is started, platform_device is injected into the initiat_arch_init () function in init. C. This function is declared as arch_initcall (cloud_arch_init); it will be called during system initialization. Arch_initcall has a higher priority than module_init. Therefore, it will be called before the platform driver injects the role. In the kernel, instead of using arch_initcall (cloud_arch_init) to inject the struct platform_device, we use. the init_machine member saves it in arch_initcall (customize_machine) waiting for calling (machine_start to machine_end defined in the mach-smdk6410.c); in fact, the quality is the same as put in. initcall3.init is waiting for calling. Then define the struct platform_driver and call the platform_driver_register () function in the driver initialization function. The specific process description is as follows:

Linux introduced the concept of platform from version 2.6. When developing the underlying driver, you must first confirm the device resource information, in the 2.6 kernel, the resources of each device are described in the structure platform_device. The struct is defined in kernel/include/Linux/platform_device.h,

struct platform_device{      const char * name;      u32  id;      struct device dev;      u32  num_resources;      struct resource * resource;};


An important element of this structure is resource, which stores the most important device resource information and is defined in kernel/include/Linux/ioport. h,
For example:

struct resource {       const char *name;       unsigned long start, end;       unsigned long flags;       struct resource *parent, *sibling, *child;};

Example:

static struct resource s3c_usb_resource[] = { [0] = {       .start = S3C_PA_USBHOST,       .end   = S3C_PA_USBHOST + S3C_SZ_USBHOST - 1,       .flags = IORESOURCE_MEM,     }, [1] = {       .start = IRQ_UHOST,       .end   = IRQ_UHOST,       .flags = IORESOURCE_IRQ,     }};


The above is the Resource Information allocated by USB Host 6410. The Group description describes the BUS address range occupied by the USB host device. The starting address and size are determined by the hardware. The Group ioresource_mem describes the memory type resources; the 2nd group describes the interrupt Number of the USB host device, which is also set by hardware. The ioresource_irq Group describes the interrupt resource information. The device driver obtains the corresponding resource information based on flags.

With the resource information, you can define platform_device:

struct platform_device s3c_device_usb = {         .name    = "s3c2410-ohci",  //s3c6410-usb         .id    = -1,         .num_resources   = ARRAY_SIZE(s3c_usb_resource),         .resource   = s3c_usb_resource,         .dev              = {                 .dma_mask = &s3c_device_usb_dmamask,                 .coherent_dma_mask = 0xffffffffUL             }};


With platform_device, you can call the platform_add_devices function to add the device to the system. All device resources in the system can be listed together in the following way, and then an array of pointers, such:

Static struct platform_device * smdk6410_devices [] _ initdata = {

......

& Amp; cloud_device_usbgadget,
& Initi_device_usb, // Jeff add.

......

}

Then run the following command in the initialization function smdk6410_machine_init () of 6410:

Platform_add_devices (smdk6410_devices, array_size (smdk6410_devices); add all devices to the system. The advantage of platform_add_devices is that it runs multiple platform_device_register at a time.

(2) The struct platform_driver must be implemented for the driver, which is also defined in kernel/include/Linux/platform_device.h:

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 (*suspend_late)(struct platform_device *, pm_message_t state);      int (*resume_early)(struct platform_device *);      int (*resume)(struct platform_device *);      struct pm_ext_ops *pm;      struct device_driver driver;};


The USB Host implementation here is:

static struct platform_driver ohci_hcd_s3c2410_driver = {     .probe  = ohci_hcd_s3c2410_drv_probe,     .remove  = ohci_hcd_s3c2410_drv_remove,     .shutdown = usb_hcd_platform_shutdown,     /*.suspend = ohci_hcd_s3c2410_drv_suspend, */     /*.resume = ohci_hcd_s3c2410_drv_resume, */     .driver  = {          .owner = THIS_MODULE,          .name = "s3c2410-ohci",        },};


Call the platform_driver_register () function platform_driver in the driver initialization (1124 rows of ohci-hcd.c) function, note that the platform_driver should be noted thatNameElement and the driver in the ohci_hcd_s3c2410_driver structure.The name must be the sameIn this way, when platform_driver_register () is added to the queue, the name of the element in the platform_device that has been added to the queue and the driver of the platform_driver currently added to the queue are displayed. name is used for comparison. Only when a platform_device with the same name is found, platform_driver can successfully inject the token. When the injection succeeds, the probe function pointer of the platform_driver structure element is called. Here, ohci_hcd_s3c2410_drv_probe is used to start loading the probe. All the functions in platform driver enter the number of platform devices.

(3) Why must the two names be matched to bind the device and driver? (1) During kernel initialization, kernel_init ()-> do_basic_setup ()-> driver_init ()-> platform_bus_init () initializes platform_bus (Virtual Bus); (2) platform_device_register ()-> platform_device_add ()-> (pdev-> Dev. bus = & platform_bus_type) mount the device to the virtual platform bus; (3) when the driver is injected with the license, platform_driver_register ()-> driver_register ()-> bus_add_driver ()-> driver_attach () -> bus_for_each_dev (): Perform _ driver_attach ()-> driver_probe_device () on each device mounted to the virtual platform bus, and infer that DRV-> bus-> match () whether or not platform_match exists and runs successfully. In this case, platform_match is run through the pointer, which is similar to javasstrncmp (pdev-> name, DRV-> name, bus_id_size). If the match exists, really_probe is called.(Actually, platform_driver-> probe (platform_device) of the corresponding device. Note that the number of _ Dev partitions of platform_drv_probe is obtained by next_device of bus_for_each_dev.) Start the real probe loading. If probe is successful, bind the device to the driver.

After you enter the probe function, you need to obtain the device resource information. You can obtain the specified resources based on the type specified by the number of dimensions, such as ioresource_mem.
Struct resource * platform_get_resource (struct platform_device * Dev, unsigned int type, unsigned int num); of course, you can also set the resource type, such as getting the interrupt number in the resource: struct int platform_get_irq (struct platform_device * Dev, unsigned int num );

The probe function is generally used to enable hardware devices, obtain struct resources, dynamically map virtual addresses, and inject detailed device types (because the platform device is only a virtual device type ); after removing the function, disable hardware devices, release the dynamic ing between struct resource and virtual address, and cancel the device of the detailed type. Peripheral devices that only have little dependency on the kernel itself (in other words, they do not need to be within the minimum system required for Kernel execution ), relatively independent resources (addresses and irqs) can be implemented using platform_driver. For example, LCD, USB, UART, and so on can be written with platfrom_driver. However, it is better that devices in the smallest system such as timer and IRQ do not use the platfrom_driver mechanism. In fact, the kernel implementation is the same.


Exam Original: http://blog.chinaunix.net/u1/49507/showart_494193.html

Exam Original: http://blog.csdn.net/yd4330152763132/archive/2010/02/01/5275776.aspx

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.