組み込みLINUXドライバーが14のソフトウェアとハードウェアの分離プログラミング(3)コード例を学習(struceデバイスメンバーvoid * platform_dataによって実装)
1.コード例(ハードウェア情報の定義)
#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.コード例(ソフトウェア駆動)
#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");