Usually write the Linux character device often contact file_operations and miscdevice, and then apply for the device number, register the character device, not related to the device driver model, and in the driver model, Device_driver is not related to the function of device operation, File_operations, etc., only some power management, hot swap related functions. Platform_device is also mainly in the management of resource, so feel the two are not okay, it is also very strange why two sets of things to achieve, and the two can not be matched up. We made some excerpts from the original blog for Platform_device and Platform_driver.
Platform_device and Platform_driver have not been clear about the relationship. Search on the Internet, do a summary. The order of the two is the first definition of Platform_device-a registration PLATFORM_DEVICE->, and then the platform_driver-> registration platform_driver is defined.
1) Define Platform_device
2) Registration Plat_form_device
3) Define Platform_driver
4) Registration Platform_driver
(
The function is written in steps:
1) Resource
2) Platform_device
3) static struct Platform_device *smdk6410_devices[] __initdata = {... &s3c_device_usbgadget, &s3c_device_ USB,//jeff add ...}
Platform_add_devices (Smdk6410_devices, Array_size (smdk6410_devices));
4) Platform_driver
1) The registration process for the Platform_device device must be called before the corresponding device driver is loaded, because the driver registration needs to match the registered device name in the kernel. Platform_device is registered in the S3c_arch_init () function in init.c during system startup . This function is declared as Arch_initcall (S3c_arch_init); will be called during the system initialization phase . the Arch_initcall priority is higher than module_init, so it is called before the platform driver is registered. Instead of registering the Platform_device struct with Arch_initcall (s3c_arch_init), the kernel now saves it through the. Init_machine member in Arch_initcall (customize_ Machine) waits for a call (Machine_start to Machine_end defined in mach-smdk6410.c); the substance is the same. Initcall3.init wait for the call. The struct struct platform_driver is then defined, and the function Platform_driver_register () is registered Platform_driver in the driver initialization function. The detailed procedure is described as follows:
Linux introduced the concept of platform from the 2.6 release, in the development of the underlying driver, the first thing to be sure is the device resource information, in the 2.6 kernel, each device's resources are described by the structure platform_device, The structure is defined in the kernel/include/linux/platform_device.h,
struct Platform_device { constChar * name; U32 ID; struct device Dev; U32 num_resources; struct resource * resource; };
An important element of the structure is resource, which is the most important device resource information, defined in Kernel/include/linux/ioport.h,
Like what:
struct Resource { constChar *name; Long start, end; Long flags; struct resource *parent, *sibling, * child;
For example:
Static struct resource s3c_usb_resource[] = { [0] = { = S3c_pa_usbhost, . End 1, = ioresource_mem, }, [1] = { = irq_uhost, . End = irq_uhost, = Ioresource_irq, }
If there is no limit on the number, what is the upper limit?
The above is the resource information assigned by USB host 6410. The 1th group describes the bus address range used by this USB host device, starting address and size is determined by hardware, ioresource_mem means that the 1th group describes the resource information of the memory type, and the 2nd group describes the interrupt number of the USB host device, which is also set by the hardware. IORESOURCE_IRQ indicates that the 2nd group describes the interrupt resource information. The device driver obtains the corresponding resource information according to flags.
with the resource Information (premise), you can define the 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 = { = &s3c_device_usb_dmamask, 0xffffffffUL } };
With Platform_device, you can call the function platform_add_devices to add the device to the system. Device resources in the system can be enumerated in this way, and then into an array of pointers, such as:
Static struct platform_device *smdk6410_devices[] __initdata =&&s3c_device_usb, // Jeff Add. ......}
Then execute in the 6410 initialization function smdk6410_machine_init ():
Platform_add_devices (Smdk6410_devices, Array_size (smdk6410_devices)); Add all the device to the system . The advantage of platform_add_devices is that it executes multiple platform_device_register at once.
(2) As for the driver to implement struct struct platform_driver, also defined in kernel/include/linux/platform_device.h:
structPlatform_driver {int(*probe) (structPlatform_device *); int(*remove) (structPlatform_device *); void(*shutdown) (structPlatform_device *); int(*suspend) (structPlatform_device *, pm_message_t State); int(*suspend_late) (structPlatform_device *, pm_message_t State); int(*resume_early) (structPlatform_device *); int(*resume) (structPlatform_device *); structPm_ext_ops *pm; structDevice_driver driver; };
The USB host implementation at that point is:
Static structPlatform_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", }, };
calls the function Platform_driver_register () in the driver initialization (OHCI-HCD.C 1124 line) function to register the Platform_driver, It is important to note that name element and ohci_hcd_s3c2410_driver structure in the S3C_DEVICE_USB structure. The name must be the same , so that Platform_driver_register () is registered with the name of all registered Platform_device elements and the currently registered PLATFORM_ Driver Driver.name is compared, platform_driver can register successfully only if a platform_device with the same name is found. When the registration succeeds, it calls the PLATFORM_DRIVER structure element probe function pointer, and here is ohci_hcd_s3c2410_drv_probe to start probing the load. The functions in platform driver are entered with the platform device as a parameter.
(3) Why does the name of two name have to match to implement device and driver bindings? (1) Kernel_init ()->do_basic_setup ()->driver_init ()->platform_bus_init () Initialization of Platform_bus (virtual bus) at kernel initialization ; (2) When the device is registered Platform_device_register ()->platform_device_add () (Pdev->dev.bus = &platform_bus_type) Hang the device under the virtual platform bus; (3) When the driver is registered Platform_driver_register ()->driver_register ()->bus_add_driver () Driver_attach ()->bus_for_each_dev (), for each device hanging on the virtual platform bus as __driver_attach ()->driver_probe_device (), Determine if Drv->bus->match () is present and successful, at which point the Platform_match is executed by the pointer, comparing STRNCMP (Pdev->name, Drv->name, Bus_id_size) , if it matches, call Really_probe (the Platform_driver->probe (platform_device) of the corresponding device that is actually executed, and note Platform_drv_probe's _ The dev parameter is obtained by Bus_for_each_dev's Next_device ) to start a true probe load, and if probe succeeds then bind the device to that drive.
When you enter the probe function, you need to obtain the resource information of the device, depending on the type specified by the parameter type, such as IORESOURCE_MEM, to obtain the specified resource separately.
struct resource * Platform_get_resource (struct platform_device *dev, unsigned int type, unsigned int num); Of course, you can also fix resource types, such as Take the interrupt number in the resource: struct int platform_get_irq (struct platform_device *dev, unsigned int num);
The probe function generally accomplishes the hardware device enable, the acquisition of the struct resource and the dynamic mapping of the virtual address and the registration of the specific type device (because the platform device is only a virtual device type); The Remove function completes the shutdown of the hardware device, the struct Resource and the release of dynamic mappings for virtual addresses and the logoff of specific types of devices . As long as the core itself is running on a less dependent peripheral device (in other words, as long as the device is not within the minimum system required to run the kernel), it is possible to use Platform_driver to have separate resources (addresses and IRQs) . such as: Lcd,usb,uart, etc., can be written with platfrom_driver, and timer,irq such as the smallest system within the device is best not platfrom_driver mechanism, in fact, the implementation of the kernel is also the case.
Reference Original: http://www.cnblogs.com/Ph-one/p/4671593.html
Reference Original: Http://blog.csdn.net/yd4330152763132/archive/2010/02/01/5275776.aspx
Reference Original: http://blog.csdn.net/zhandoushi1982/article/details/5130207
Blog: http://www.cnblogs.com/Ph-one/p/4762710.html
Modify:
Crazy Fuzi
2015/08/27
Platform_device and Platform_driver