Turn from: http://blog.sina.com.cn/s/blog_6b94d5680101cn0t.html
Platform Model driver programming, the need to implement Platform_device (device) and platform_driver (drive) on the platform (Virtual bus) registration, matching, mutual binding, and then as a common character device for the corresponding application, In short, if you are writing a platform driver based on a character device, the core of the character device is the core structure of the platform-Cdev, file_operations (the operator interface he contains), Dev _t (device number), device file (/dev), etc., because of the character driven by the platform mechanism, its essence is character driven.
In general, a platform bus is already initialized and mounted in the 2.6 kernel in the Sysfs file system. So when we write the platform model driver, we need to do two things: 1: Realize platform Drive 2: Implement platform device, however, in the process of implementing these two tasks, many other small tasks need to be implemented, which are described later. The core architecture of the platform model-driven implementation process is simple, as shown below.
Platform Drive model three objects: Platform bus, platform device, platform drive. Platform bus corresponding to the kernel structure: struct bus_type--> It contains the most critical functions: match () platform device corresponding to the core structure: struct Platform_device--> registration: Platform_device_register (Unregiste) platform drives the corresponding kernel structure: struct platform_driver--> registration: Platform_driver_register ( Unregiste)
A brief introduction to the platform-driven work process: device (or driver) registration, will cause the bus to call its own match function to find whether the current platform bus is mounted with the device (or driver) name matching the driver (or device), if the existence of the two sides bound If the device is registered first, the driver has not yet registered, then when the device is registered on the bus, it will not match the driver with the same name, and then when the driver registers on the bus, because the device is registered, then the bus will immediately match the device and the driver with the same name as the binding, and then call the probe function in the driver. If the driver is first registered, the same device driver will match the failure, the matching failure will cause its probe function is not called, but to wait until the device registration is successful and matching the binding will not be invoked.
Next, we'll explain the detailed process of implementing platform drive and device as follows.
detailed process to implement platform drive 1: Defining Drive InstancesMini2440_led_platform_driverstatic struct Platform_driver
Mini2440_led_platform_driver= {. Probe =
Mini2440_led_probe,. Remove = __devexit_p (
Mini2440_led_remove),. Driver = {. Name = "
Mini2440_led_platform_device_driver",. Owner = This_module,}};
2: Implement drive instance member function: ProbeMini2440_led_probeThe functions to be implemented in the probe function include: device number application, character device kernel object Cdev definition, initialization, binding file_operations, registering character device kernel object Cdev, dynamically creating device files under/dev.
3:platform model drives the character device to implement the core structure file_operations, the first step of the Cdev to useThe interface functions to be used in the file_operations structure are realized by open, write, read and so on.
4: Implement driver instance member function: Remove Mini2440_led_removeThe function to be implemented in the Remove function is to cancel the related equipment and resources in contrast with the probe. "Probe and remove functions actually correspond to the module loading and unloading functions that are implemented when the platform mechanism is written to drive, and in the platform mechanism, the load and unload functions of the module call the device or driver registration function."
5: Implementation of the driver load and unload functions:In the load function, call the driver's registration function, Platform_driver_register (...) In the Unload function, call the driven unload function, Platform_driver_unregister (...) ;
implement the detailed process of the platform devicePlatform devices are implemented in two ways: 1: The most stupid one: directly in the kernel source code to add the relevant resource code, \ARCH\ARM\MACH-S3C2440\MACH-MINI2440.C 2: Write the device module, with the INSMOD command to load the device module onto the platform bus. Of course, the second one, but the principle of these two methods and to write the code are the same, but the first do not register themselves, because the system initialization will be mach-mini2440.c in the struct Platform_device *mini2440_devices[] All devices contained in the __INITDATA device array are registered on the bus. And the second kind of manual registration, a word live.
1: Defining Device and Resource instancesstatic struct
Resource mini2440_led_resource[]= {[0] = {. Start = 0x56000010,. end = 0x56000010 +. Flags = Ioresource_mem},}; static struct
Platform_device mini2440_platform_device_led= {. Name = "
Mini2440_led_platform_device_driver",. id =-1,. num_resources = Array_size (Mini2440_led_resource),. Resource =
Mini2440_led_resource,. Dev = {. Release =
Mini2440_led_platform_device_release, }, };
2: Implement the member function of the device Releasestatic void Mini2440_led_platform_device_release (struct device * dev) {return;}
3: Implementation of the device loading and unloading functions:In the load function, call the device's registration function, Platform_device_register (...) In the Unload function, invoke the Unload function of the device, Platform_device_unregister (...) Simultaneous registration of multiple devices: platform_add_devices (struct platform_devices **devs,int num); struct platform_devices **devs device array, num contains the number of devices
Drive and equipment successfully registered, we can all in/sys/bus/platform/devices (drivers)/below view
The following is a code listing://////////////////////////////Device module: #include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <asm/io.h> #include <asm/uaccess.h> #include <linux/device.h> #include <linux/cdev.h> #include <linux/platform_device.h>
static void Mini2440_led_platform_device_release (struct device * dev) { return;} static struct Resource mini2440_led_resource[] = { [0] = { .start = 0x56000010, .end = 0x56000010 + 12, .flags = Ioresource_mem },}; static struct Platform_device mini2440_platform_device_led = { .name = "Mini2440_led_platform_device_driver", .id =-1, &NBSP;&NBSP;&NBsp; .num_resources = array_size (mini2440_led_resource), .resource = Mini2440_led_resource, .dev = { .release = mini2440_ Led_platform_device_release, },}; static int __init mini2440_led_platform_device_init (void) {&NBSP;&NBSP;&NBSP;&NBSP;PRINTK ("mini2440_led_platform_ Device add ok!\n "); Return Platform_device_register (&mini2440_platform_device_led); } static void __exit mini2440_led_platform_device_exit (void) {&NBSP;&NBSP;&NBSP;&NBSP;PRINTK ("Mini2440_led_platform _device remove ok!\n "); Platform_device_unregister (&mini2440_platform_device_led); } module_author ("xxxx"); Module_license ("GPL"); Module_init (mini2440_led_platform_device_init); Module_exit (Mini2440_led_platform_device_exit); Drive module: #include <linux/init.h> #include <linux/module.h> #include <linux /fs.h> #include <asm/io.h> #include <asm/uaccess.h> #include <linux/device.h> #include <linux/ Cdev.h> #include <linux/platform_device.h>
#define GLOBAL_LED_MAJOR 250
static unsigned int global_led_major = global_led_major; static struct Cdev *led_cdev = NULL; static struct Class *led_class = NULL;
Static volatile unsigned long *gpfcon = NULL; Static volatile unsigned long *gpfdat = NULL; Static volatile unsigned long *gpfup = NULL;
static int Mini2440_led_open (struct inode * inode,struct file * file) {PRINTK ("mini2440_open[kernel_space]\n"); *gpfcon &=~ ((0x3<<0) | (0x3<<8) | (0X3<<10) | (0x3<<12) | (0x3<<14)); *gpfcon |= (0x1<<0) | (0x1<<8) | (0X1<<10) | (0x1<<12) | (0X1<<14); return 0; Static ssize_t mini2440_led_read (struct file * file,const Char __user * in,size_t size,loff_t * off) {PRINTK ("mini2440_ Read[kernel_space]\n "); return 0; Static ssize_t mini2440_led_write (struct file * file,const Char __user * in,size_t size,loff_t * off) { &nbs P;&NBSP;INT ret; Char ker_buf; PRINTK ("mini2440_write[kernel_space]\n"); ret = Copy_from_user (&ker_buf,in,size); PRINTK ("Ker_buf =%d\n", ker_buf); if (ker_buf) {*gpfdat &=~ (0x1<<4) | ( 0X1<<5) | (0x1<<6) | (0x1<<7)); *gpfdat |= (0x1<<0); else {*gpfdat |= (0x1<<4) | ( 0X1<<5) | (0x1<<6) | (0X1<<7); *gpfdat; = ~ (0x1<<0); return 0; } struct File_operations led_fops = {. Owner = This_module,. Open = Mini2440_led_open,. Read = mini2440_led_re AD,. Write = Mini2440_led_write,}; static int __devinit mini2440_led_probe (struct platform_device *pdev) {int ret; int err; dev_t devno; struct resource *pi Oresource_mem; Devno = Mkdev (global_led_major,0); PRINTK (Kern_alert "mini2440_led_probe!\n"); if (devno) {ret = Register_chrdev_region (devno,1, "Mini2440_led_platfor_driver");} else {ret = Alloc_chrdev_region ;d evno,0,1, "Mini2440_led_platfor_driver"); Global_led_major = Major (Devno); } if (Ret < 0) {return ret;} Led_cdev = Cdev_alloc (); Cdev_init (Led_cdev,&led_fops); Led_cdev->owner = This_module; Err = Cdev_add (led_cdev,devno,1); Led_class = Class_create (This_module, "mini2440_led_platfor_driver"); Device_create (Led_class,null,mkdev (global_led_major,0), NULL, "platfor_driver_for_mini2440_led"); Pioresource_mem = Platform_get_resource (pdev,ioresource_mem,0); Gpfcon= Ioremap (Pioresource_mem->start,pioresource_mem->end-pioresource_mem->start); Gpfdat = Gpfcon + 1; Gpfup = Gpfcon + 2; if (err) {PRINTK (kern_notice "Error%d adding Led_cdev", err); return-1;} else {PRINTK (kern_notice) platform_driver_for_m ini2440_led init ok!\n "); return 0; } }
static int __devexit mini2440_led_remove (struct platform_device *pdev) {PRINTK ("mini2440_led_remove!\n"); Cdev_del (le D_cdev); Iounmap (Gpfcon); Unregister_chrdev_region (Mkdev (global_led_major,0), 1); Device_destroy (Led_class, Mkdev (global_led_major,0)); Class_destroy (Led_class); return 0; static struct Platform_driver Mini2440_led_platform_driver = {. Probe = Mini2440_led_probe,. Remove = __devexit_p (mini2 440_led_remove),. Driver = {. Name = "Mini2440_led_platform_device_driver",. Owner = This_module,}}; static int __init mini2440_led_platform_driver_init (void) {PRINTK ("platform_driver_for_mini2440_led init\n"); Platform_driver_register (&mini2440_led_platform_driver); }
static void __exit mini2440_led_platform_driver_exit (void) {PRINTK ("platform_driver_for_mini2440_led exit\n"); PLATF Orm_driver_unregister (&mini2440_led_platform_driver); } module_author ("xxx"); Module_license ("GPL"); Module_param (Global_led_major,int,s_irugo); Module_init (Mini2440_led_platform_driver_init); Module_exit (Mini2440_led_platform_driver_exit); Makefiel
Ifneq ($ (kernelrelease),) obj-m: = MINI2440_LED_PLATFORM_DRIVER.O else Kdir: =/home/tools/linux-2.6.32.2 all:make-c $ (kdir) m=/linux_prg/platform_driver_device_module/driver_module/modules modules clean:rm-f *.ko *.o *.mod.o *.m OD.C *.symvers endif
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.