Embedded LINUX driver learning 14 software and hardware separation programming (3) code example (implemented by struce device member void *platform_data)
1. Code example (define hardware information)
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
struct led_phy_struct {
unsigned long phy_addr;
int gpio;
} ;
struct led_phy_struct led_phy_obj[ ] = {
{
. phy_addr = 0XC001B000 ,
. gpio = 26
} ,
{
. phy_addr = 0XC001C000 ,
. gpio = 11
} ,
{
. phy_addr = 0XC001C000 ,
. gpio = 7
} ,
{
. phy_addr = 0XC001C000 ,
. gpio = 12
} ,
{
. phy_addr = 0 ,
. gpio = 0
}
} ;
void dd_close ( struct device * dev) {
} ;
struct platform_device pd_myled_struct = {
. name = "LED_" ,
. id = 1 ,
. dev = {
. platform_data = led_phy_obj,
. release = dd_close
}
} ;
static int myled_init ( void ) {
platform_device_register ( & pd_myled_struct) ;
return 0 ;
}
static void myled_exit ( void ) {
platform_device_unregister ( & pd_myled_struct) ;
}
module_init ( myled_init) ;
module_exit ( myled_exit) ;
MODULE_LICENSE ( "GPL" ) ;
2. Code example (software driven)
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/io.h>
struct led_phy_struct {
unsigned long phy_addr ;
int gpio;
} ;
struct led_phy_struct * led_phy_obj;
int myled_probe ( struct platform_device * pd) {
int i = 0 ;
void * void_addr;
unsigned long * base, * outenb, * altfn;
led_phy_obj = ( struct led_phy_struct * ) pd-> dev. platform_data;
while ( led_phy_obj[ i] . phy_addr != 0 ) {
void_addr = ioremap ( led_phy_obj[ i] . phy_addr, 0x24 ) ;
base = ( unsigned long * ) void_addr;
outenb = ( unsigned long * ) ( void_addr+ 0x4 ) ;
altfn = ( unsigned long * ) ( void_addr + 0x20 ) ;
* base & = ~ ( 0x1 << led_phy_obj[ i] . gpio) ;
* outenb | = ( 0x1 << led_phy_obj[ i] . gpio) ;
if ( led_phy_obj[ i] . gpio < 15 ) {
altfn = ( unsigned long * ) ( void_addr + 0x20 ) ;
* altfn & = ~ ( 0x3 << ( led_phy_obj[ i] . gpio * 2 ) ) ;
* altfn | = ( 0x1 << ( led_phy_obj[ i] . gpio * 2 ) ) ;
}
else {
altfn = ( unsigned long * ) ( void_addr + 0x24 ) ;
* altfn & = ~ ( 0x3 << ( ( led_phy_obj[ i] . gpio- 16 ) * 2 ) ) ;
* altfn | = ( 0x1 << ( ( led_phy_obj[ i] . gpio- 16 ) * 2 ) ) ;
}
iounmap ( void_addr) ;
i ++ ;
}
return 0 ;
}
static int myled_remove ( struct platform_device * pd) {
int i = 0 ;
void * void_addr;
unsigned long * base;
led_phy_obj = ( struct led_phy_struct * ) pd-> dev. platform_data;
while ( led_phy_obj[ i] . phy_addr != 0 ) {
void_addr = ioremap ( led_phy_obj[ i] . phy_addr, 0x24 ) ;
base = ( unsigned long * ) void_addr;
* base | = ( 0x1 << led_phy_obj[ i] . gpio) ;
iounmap ( void_addr) ;
i ++ ;
}
return 0 ;
}
struct platform_driver pd_myled_struct = {
. probe = myled_probe,
. remove = myled_remove,
. driver = {
. name = "LED_"
}
} ;
static int myled_drv_init ( void ) {
platform_driver_register ( & pd_myled_struct) ;
return 0 ;
}
static void myled_drv_exit ( void ) {
platform_driver_unregister ( & pd_myled_struct) ;
}
module_init ( myled_drv_init) ;
module_exit ( myled_drv_exit) ;
MODULE_LICENSE ( "GPL" ) ;