Platform device and platform driver

Source: Internet
Author: User

I have been operating Linux for more than three months. I have never understood some of the structures in the Code. For example, the relationship between platform_device and platform_driver is unclear. I searched it online and made a summary. The working order of the two is to define platform_device-> Register platform_device->, and then define platform_driver-> Register platform_driver.

The registration process of the platform_device device must be called before the driver of the corresponding device is loaded, because the device name already registered in the kernel needs to be matched during driver registration. Platform_device is registered in the initiation_arch_init () function of init. C at system startup. 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.
Called before driver registration. In the kernel, instead of registering the platform_device struct using arch_initcall (initi_arch_init. 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); the essence is the same as placing it 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 ()
Register platform_driver. The detailed process is described as follows:

Linux introduced the platform concept 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 using 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, defined in kernel \ include \ Linux \ ioport. H, struct Resource

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

For example:

Static struct resource initi_usb_resource [] = {[0] = {. start = maid host ,. end = maid-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 1st group describes the BUS address range occupied by the USB host device. The starting address and size are determined by the hardware. The ioresource_mem group indicates that the 1st group describes the memory-type resources; the 2nd group describes the interrupt Number of the USB host device, which is also set by hardware. ioresource_irq indicates that the 2nd 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 initi_device_usb = {. name = "s3c2410-ohci", // s3c6410-usb. id =-1 ,. num_resources = array_size (initi_usb_resource ),. resource = initi_usb_resource ,. dev = {. dma_mask = & jx_device_usb_dmamask ,. coherent_dma_mask = 0 xfffffffful }};

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

Static struct platform_device * smdk6410_devices [] _ initdata = {

......

& Amp; cloud_device_usbgadget, & amp; cloud_device_usb, // Jeff add.

......

}

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 benefit of platform_add_devices is that it executes multiple platform_device_register at a time.

The struct platform_driver needs to be implemented by 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 *, destination 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 ",},};

The platform_driver_register () function is called in the driver initialization (line 1 of the ohci-hcd.c) function to register the platform_driver. Note that the driver is in the name element and the ohci_hcd_s3c2410_driver structure of the courseware _ device_usb structure. the name must be the same. In this way, when platform_driver_register () is registered, the name of all elements in the registered platform_device and the driver of the currently registered platform_driver will be used. name. Only when platform_device with the same name is found can platform_driver be registered successfully. When the registration is successful, the probe function pointer of the platform_driver structure element is called. Here, ohci_hcd_s3c2410_drv_probe is used to start probe loading. Platform
All functions in driver are input using platform device as parameters.

Why do the two names must match to bind 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) mounts the device to the virtual platform bus. (3) when the driver registers, platform_driver_register ()-> driver_register ()-> bus_add_driver ()-> driver_attach () -> bus_for_each_dev (): Performs _ driver_attach ()-> driver_probe_device () on each device mounted to the virtual platform bus to determine whether DRV-> bus-> match () whether the request exists and is successfully executed. Execute platform_match through the pointer to compare strncmp (pdev-> name, DRV-> name,
Bus_id_size). If yes, call really_probe (actually the platform_driver-> probe (platform_device) of the corresponding device. Note that the _ Dev parameter 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 entering the probe function, you need to obtain the device's resource information and obtain the specified resources based on the type specified by the parameter, such as ioresource_mem. Struct resource * platform_get_resource (struct platform_device * Dev, unsignedint 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 generally enables hardware devices, obtains struct resources, dynamically maps virtual addresses, and registers devices of specific types (because platform devices are just virtual devices ); the remove function disables hardware devices, releases the dynamic ing of struct resources and virtual addresses, and cancels devices of specific types. As long as the peripheral device is not dependent on the kernel itself (in other words, as long as it is not within the minimum system required for the kernel operation), it is relatively independent of its own resources (addresses
And irqs), can be implemented using platform_driver. For example, LCD, USB, UART, and so on can all be written using platfrom_driver, while it is better to use the platfrom_driver mechanism for devices in the smallest system such as timer and IRQ. In fact, the kernel implementation is also like this.

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.