A practical link of platform bus for Linux device driver Model (i)

Source: Internet
Author: User
Tags readable

1, first review before writing the driver and data together led driver code, the code is as follows:

#include  <linux/module.h> #include  <linux/init.h> #include  <linux/leds.h># Include <asm/io.h>//ioremap and Iounmap's header file Writel, etc./********************************** statically map the virtual address method, Using a static mapping table for kernel porting **********************************/#include  <mach/regs-gpio.h> #include  <mach/ Gpio-bank.h> #define &NBSP;GPJ0CONS5PV210_GPJ0CON//This macro is defined in Gpio-bank.h, is the virtual address, the macro also uses the REGS-GPIO.H macro,//And so on. #define  GPJ0DATS5PV210_GPJ0DATstatic struct led_classdev myled1;static struct  led_classdev myled2;static struct led_classdev myled3;//This function is bound to the Struct led_ Classdev the Brightness_set member of the myled variable of this struct type, when our user writes this led hardware, because is led drive frame//write, so we are through the LED driver frame brightness this file , to write or to read the LED hardware, the file should have a readable writable property in the drive frame, which is owned in the//struct //device_attribute structure and eventually bound to the device class. So finally our user to go through Brightness this property file to write the LED hardware, will go to execute Led_br//ightness_store This method, this method, and//by calling led_set_brightness this function, This function is passed Led_cdev->brightness_set (led_cdev, value).This statement eventually corresponds to the Brightness_set function pointer variable in the Struct //led_classdev struct, and this function pointer variable is in the structure we populate//struct led_ The Brightness_set function pointer in Classdev is already bound to the function of the writing hardware we wrote. So this line is going to get through. Value is the user to write values//value is an enumeration, is an enumeration of enum led_brightness types, this enumeration has three values, respectively led_off = 0   led_xxx = 122  led_full = 255,static void whyx210_led1_set ( Struct led_classdev *led_cdev, enum led_brightness value) {//PRINTK (KERN_INFO  ") Whyx210_led_set\n "); Writel (0x11111111, gpj0con);if  (Value == led_off)  {// User input 0 o'clock off the corresponding user input is Echo 0 > brightnesswritel (Readl (Gpj0dat)  |  (1 << 3) ,  gpj0dat);} else if  (value == led_full) {//user input 255 light corresponds to user input is echo 255 >  Brightnesswritel (Readl (Gpj0dat)  & ~ (1 << 3),  gpj0dat);//This operation keeps the other bit values unchanged}} Static void whyx210_led2_set (struct led_classdev *led_cdev, enum led_bRightness value) {//PRINTK (kern_info  "whyx210_led_set\n"); Writel (0x11111111, gpj0con);if  ( Value == led_off)  {//user input 0 o'clock the corresponding user input is Echo 0 > brightnesswritel (READL (GPJ0DAT)  |  (1 << 4),  gpj0dat);} else if  (value == led_full) {//user input 255 light corresponds to user input is echo 255 >  Brightnesswritel (Readl (Gpj0dat)  & ~ (1 << 4),  gpj0dat);//This operation keeps the other bit values unchanged}} Static void whyx210_led3_set (struct led_classdev *led_cdev, enum led_brightness  value) {//PRINTK (kern_info  "whyx210_led_set\n"); Writel (0x11111111, gpj0con);if  (value  == led_off)  {//user input 0 o'clock off the corresponding user input is Echo 0 > brightnesswritel (READL (GPJ0DAT)   |  (1 << 5),  gpj0dat);} else if  (value == led_full) {//user input 255 light corresponds to user input is echo 255 >  Brightnesswritel (Readl (Gpj0dat)  & ~ (1&NBSP;&Lt;< 5),  gpj0dat);//This operation keeps other bit values constant}}static int __init whyx210_led_init (void) {int  ret = -1;//led1//fill the structure of the Struct led_classdev type we want to register myled1.name =  "led1";//Future sys/ The name of the LED file under the class/leds/directory. LEDs this directory in the LED-CLASS.C in the kernel to help us achieve good, myled1.brightness = 255;myled1.brightness_set = whyx210_ led1_set;//to call the LED registration function provided in the LED driver frame led_classdev_register to register the drive//in LED-CLASS.C Int led_classdev_register ( Struct device *parent, struct led_classdev *led_cdev) ret = led_classdev_ Register (null, &myled1);if  (ret < 0)  {printk (kern_err  "led_classdev_ Register errro\n "); Return ret;} PRINTK (kern_info  "led_classdev_register success %s\n",  myled.name);/******************** led2//fill in the struct led_ we want to register Classdev type of structure myled2.name =  "led2";//The future sys/class/leds/directory of the LED fileName. LEDs this directory in the LED-CLASS.C in the kernel to help us achieve good, myled2.brightness = 255;myled2.brightness_set = whyx210_ led2_set;//to call the LED registration function provided in the LED driver frame led_classdev_register to register the drive//in LED-CLASS.C Int led_classdev_register ( Struct device *parent, struct led_classdev *led_cdev) ret = led_classdev_ Register (NULL,&NBSP;&AMP;MYLED2);if  (ret < 0)  {printk (kern_err  "led_classdev_ Register errro\n "); Return ret;} PRINTK (kern_info  "led_classdev_register success %s\n",  myled.name);/******************** led3//fill in the struct led_ we want to register The structure of the Classdev type myled3.name =  "LED3";//The name of the LED file in the future sys/class/leds/directory. LEDs this directory in the LED-CLASS.C in the kernel to help us achieve good, myled3.brightness = 255;myled3.brightness_set = whyx210_ led3_set;//to call the LED registration function provided in the LED driver frame led_classdev_register to register the drive//in LED-CLASS.C Int led_classdev_register ( Struct device&nbSp;*parent, struct led_classdev *led_cdev) Ret = led_classdev_register (NULL,  &AMP;MYLED3);if  (ret < 0)  {printk (kern_err  "led_classdev_register errro\n"); Return ret;} PRINTK (kern_info  "led_classdev_register success %s\n",  myled.name); return 0;} Static void __init whyx210_led_exit (void) {led_classdev_unregister (&myled1); led_classdev_ Unregister (&AMP;MYLED2); Led_classdev_unregister (&AMP;MYLED3);//PRINTK (kern_info  "Led_classdev_unregister  success.\n ");} Module_init (Whyx210_led_init); Module_exit (Whyx210_led_exit); Module_author ("why <[email protected]>"); Module_description ("Whyx210 led driver"); Module_license ("GPL"); Module_alias ("whyx210_led");

Now the code of LED2 and Led3 is removed, leaving only led1, and we want to know how we use the Platform platform bus method to achieve the LED driver, we have probe function, and the Remove function, corresponding to the driver and device matching after the execution of the probe function, as well as the device and drive separation when the Remove function is unloading the drive function, we want to write the data part of the code into the platform Platform_data, in the driver code probe function, In the way of parameters, the data portion of the device is obtained, and the logical framework of the code separating the drive and the device data is realized.

The code above only leaves the led1 driver code as follows:

#include  <linux/module.h> #include  <linux/init.h> #include  <linux/leds.h># Include <asm/io.h>//ioremap and Iounmap's header file Writel, etc./********************************** statically map the virtual address method, Using a static mapping table for kernel porting **********************************/#include  <mach/regs-gpio.h> #include  <mach/ Gpio-bank.h> #define &NBSP;GPJ0CONS5PV210_GPJ0CON//This macro is defined in Gpio-bank.h, is the virtual address, the macro also uses the REGS-GPIO.H macro,//And so on. #define &NBSP;GPJ0DATS5PV210_GPJ0DATSTATIC&NBSP;STRUCT&NBSP;LED_CLASSDEV&NBSP;MYLED1;//This function is bound to the Struct led_ Classdev the Brightness_set member of the myled variable of this struct type, when our user writes this led hardware, because is led drive frame//write, so we are through the LED driver frame brightness this file , to write or to read the LED hardware, the file should have a readable writable property in the drive frame, which is owned in the//struct //device_attribute structure and eventually bound to the device class. So finally our user to go through Brightness this property file to write the LED hardware, will go to execute Led_br//ightness_store This method, this method, and//by calling led_set_brightness this function, This function is passed Led_cdev->brightness_set (led_cdev, value); This statement eventually corresponds to the Brightness_ in the STRUCT&NBSP;//LED_CLASSDEV structure. Set this function pointer variable, and this function pointer variable in our fill that struct body//struct&nbspThe Brightness_set function pointer in Led_classdev is already bound to the function of the writing hardware we wrote. So this line is going to get through. Value is the user to write values//value is an enumeration, is an enumeration of enum led_brightness types, this enumeration has three values, respectively led_off = 0   led_xxx = 122  led_full = 255,static void whyx210_led1_set ( Struct led_classdev *led_cdev, enum led_brightness value) {//PRINTK (KERN_INFO  ") Whyx210_led_set\n "); Writel (0x11111111, gpj0con);if  (Value == led_off)  {// User input 0 o'clock off the corresponding user input is Echo 0 > brightnesswritel (Readl (Gpj0dat)  |  (1 << 3) ,  gpj0dat);} else if  (value == led_full) {//user input 255 light corresponds to user input is echo 255 >  Brightnesswritel (Readl (Gpj0dat)  & ~ (1 << 3),  gpj0dat);//This operation keeps the other bit values unchanged}} Static int __init whyx210_led_init (void) {int ret = -1;//led1//Fills the struct we want to register The structure of the  led_classdev type myled1.name =  "led1";//The name of the LED file in the future sys/class/leds/directory. Leds This directory in the LED-CLASS.C in the kernel to help us achieve good, myled1.brightness = 255;myled1.brightness_set = whyx210_led1_ set;//to call the LED registration function provided for us in the LED driver frame led_classdev_register to register the drive//in LED-CLASS.C int led_classdev_register (struct  device *parent, struct led_classdev *led_cdev) Ret = led_classdev_register ( null, &myled1);if  (ret < 0)  {printk (kern_err  "led_classdev_register  Errro\n "); Return ret;} PRINTK (kern_info  "led_classdev_register success %s\n",  myled.name); return 0;} Static void __init whyx210_led_exit (void) {led_classdev_unregister (&myled1);} Module_init (Whyx210_led_init); Module_exit (Whyx210_led_exit); Module_author ("why <[email protected]>"); Module_description ("Whyx210 led driver"); Module_license ("GPL"); Module_alias ("whyx210_led");

The code for makefile is as follows:

#ubuntu中的内核源码树目录 #kern_ver = $ (Shell uname-r) #KERN_DIR =/lib/modules/$ (kern_ver)/build# My compiled jiuding kernel's source tree directory Kern_dir =/root /xin_x210/kernelobj-m+= leds-why210.oall:make-c $ (kern_dir) m= ' pwd ' modules #arm-linux-gcc app.c-o APPCP:CP *.ko/root/ rootfs/rootfs/driver_test/-F#CP app/root/rootfs/rootfs/driver_test/-f.phony:cleanclean:make-c $ (KERN_DIR) M= ' pwd ' Modules Clean#rm App-f

Makefile's code doesn't move.

We then modify and add the probe function and the structure required by the LED driver in the LED driver code. Add the probe function and the Remove function, and add and populate the structure required by the LED driver, and the INIT function is the function that executes when the ISMOD loads the driver module, and the Exit function is the function that is executed when the driver module is unloaded. The contents of these two functions are changed to the method of registering driver (LED driver structure) with the registration function provided by platform and the cancellation drive (LED driver structure) provided by platform. The following code is changed:

#include  <linux/module.h> #include  <linux/init.h> #include  <linux/leds.h># Include <asm/io.h>//ioremap and Iounmap's header file Writel, etc./********************************** statically map the virtual address method, Using a static mapping table for kernel porting **********************************/#include  <mach/regs-gpio.h> #include  <mach/ gpio-bank.h> #include  <linux/platform_device.h> #define  gpj0cons5pv210_gpj0con// This macro is defined in the Gpio-bank.h, is the virtual address, the macro also uses the regs-gpio.h in the macro,//And so on. #define  GPJ0DATS5PV210_GPJ0DATstatic struct led_classdev myled1;static void  Whyx210_led1_set (struct led_classdev *led_cdev, enum led_brightness value) {//PRINTK ( kern_info  "whyx210_led_set\n"); Writel (0x11111111, gpj0con);if  (Value == led_off)  {//user input 0 o'clock the corresponding user input is Echo 0 > brightnesswritel (Readl (Gpj0dat)  |  (1 < < 3),  gpj0dat);} else if  (value == led_full) {//user input 255 light corresponds to user input is echo&Nbsp;255 > brightnesswritel (Readl (Gpj0dat)  & ~ (1 << 3),  GPJ0DAT);//This operation keeps other bit values constant}}static int why_led_remove (Struct platform_device *dev) {Led_ Classdev_unregister (&myled1); return 0;} Static int why_led_probe (Struct platform_device *dev) {int ret = -1;//led1// Populate the structure of the Struct led_classdev type we want to register myled1.name =  "led1";//The name of the LED file in the future sys/class/leds/directory. LEDs this directory in the LED-CLASS.C in the kernel to help us achieve good, myled1.brightness = 255;myled1.brightness_set = whyx210_ led1_set;//to call the LED registration function provided in the LED driver frame led_classdev_register to register the drive//in LED-CLASS.C Int led_classdev_register ( Struct device *parent, struct led_classdev *led_cdev) ret = led_classdev_ Register (null, &myled1);if  (ret < 0)  {printk (kern_err  "led_classdev_ Register errro\n "); Return ret;} return 0;} Static struct platform_driver why_led_driver = {.probe= why_led_probe,.remove= why_led_remove,.driver= {.name=  " Why_led ",. Owner= this_module,},};static int __init whyx210_led_init (void) {return  Platform_driver_register (&why_led_driver);} Static void __init whyx210_led_exit (void) {platform_driver_unregister (&why_led_driver);} Module_init (Whyx210_led_init); Module_exit (Whyx210_led_exit); Module_author ("why <[email protected]>"); Module_description ("Whyx210 led driver"); Module_license ("GPL"); Module_alias ("whyx210_led");

Analysis, at this time the contents of the probe and remove functions are not correct, with makefile compiled can be compiled through, generate a Leds-why210.ko driver module, we will copy this driver module to the root file system, the implementation of Insmod, the corresponding whyx210 _led_init function will be executed, will be LED drive structure data structure register to the kernel, at this time we in the root file system/sys/bus/platform/driver/directory will see a why_led file, indicating that our driver registration succeeded, But it is not, because we do not provide platform bus required platform_device,probe function and remove is also wrong, if correct, we provide platform_device after registering it, When the driver is loaded when there is an LED device, the match function will match the driver of the LED and the device, and the driver's probe function will be executed, and the data part of the LED is in Platform_device. In the driver's probe function will be platform_device in the data section, and finally in the probe function will do some registration, at this time, in the root file system/sys/bus/platform/driver/why_led directory There will be something else , this time our led driver is ready to use.

This article from "Whylinux" blog, declined reprint!

A practical link of platform bus for Linux device driver Model (i)

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.