获取到资源,利用资源进行硬件初始化
/* led_test.c */
#include
#include
#include
#include
int main(void)
{
int fd;
int on;
fd = open("/dev/led0", O_RDWR);
while (1) {
on = 1;
write(fd,&on, 4);
sleep(1);
on = 0;
write(fd,&on, 4);
sleep(1);
}
close(fd);
return 0;
}
/* plat_led_dev.c */
#include
#include
#include
#define GPC0CON 0xE0200060
#define GPC_SIZE 24
//用于演示,没有实际设备对应
#define GPA0CON 0xE0200000
#define GPA_SIZE 24
struct resource led_res[] = {
/*实际所用到的*/
[0] = {
.start = GPC0CON,
.end = GPC0CON + GPC_SIZE - 1,
.flags = IORESOURCE_MEM,
},
/*假如有其他的资源,比如有中断*/
[1] = {
.start = 888,
.end = 1212,
.flags = IORESOURCE_IRQ,
},
[2] = {
.start = GPA0CON,
.end = GPA0CON + GPC_SIZE - 1,
.flags = IORESOURCE_MEM,
},
};
struct platform_device led_pdev = {
.name = "s5pv210_led",
.id = -1,
.num_resources = ARRAY_SIZE(led_res),
.resource = led_res,
};
static int __init plat_led_dev_init(void)
{
/*注册一个平台设备*/
printk("------*_^%s--------\n",__FUNCTION__);
return platform_device_register(&led_pdev);
}
static void __exit plat_led_dev_exit(void)
{
/*注销平台设备*/
platform_device_unregister(&led_pdev);
printk("------*_^%s--------\n",__FUNCTION__);
}
module_init(plat_led_dev_init);
module_exit(plat_led_dev_exit);
MODULE_LICENSE("GPL");
/* plat_led_drv.c */
#include
#include
#include
#include
#include
#include
#include
/*设计一个对象,表示一个全局的设备对象*/
struct samsung_led{
int dev_major;
struct class *cls;
struct device *dev;
struct resource *res;
void *reg_addr; //虚拟地址
};
struct samsung_led * led_dev;
int led_pdrv_open(struct inode *inode, struct file *filp)
{
printk("-------^_* %s-----------\n", __FUNCTION__);
return 0;
}
ssize_t led_pdrv_write(struct file *filp, const char __user *buf, size_t count, loff_t *fpos)
{
int value;
int ret;
ret = copy_from_user(&value, buf, count);
if (ret > 0) {
printk("copy_from_user error\n");
return -EFAULT;
}
if (value) {
//点灯
__raw_writel(__raw_readl(led_dev->reg_addr + 4) | (0x3<<3), led_dev->reg_addr + 4);
}else{
__raw_writel(__raw_readl(led_dev->reg_addr + 4) & ~(0x3<<3), led_dev->reg_addr + 4);
}
return count;
}
int led_pdrv_close(struct inode *inode, struct file *filp)
{
printk("-------^_* %s-----------\n", __FUNCTION__);
return 0;
}
struct file_operations led_fops = {
.open = led_pdrv_open,
.write = led_pdrv_write,
.release = led_pdrv_close,
};
int led_pdrv_probe(struct platform_device *pdev)
{
/*需要向应用空间提供接口
1,申请设备号
2,创建文件
*/
printk("-------^_* %s-----------\n", __FUNCTION__);
/*申请空间*/
led_dev = kzalloc(sizeof(struct samsung_led), GFP_KERNEL);
/*动态申请设备*/
led_dev->dev_major = register_chrdev(0, "led_drv", &led_fops);
/*创建设备类*/
led_dev->cls = class_create(THIS_MODULE, "led_cls");
/*创建字符设备*/
led_dev->dev = device_create(led_dev->cls,NULL, MKDEV(led_dev->dev_major, 0), NULL, "led%d", 0);
led_dev->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
//可以进行映射
led_dev->reg_addr = ioremap(led_dev->res->start, resource_size(led_dev->res));
//获取中断
int irqno = platform_get_irq(pdev, 0);
printk("irqno = %d\n", irqno );
// 配置gpio为输出
unsigned int temp = __raw_readl(led_dev->reg_addr);
temp &= ~(0xff<<12);
temp |= (0x11<<12);
__raw_writel(temp,led_dev->reg_addr);
return 0;
}
int led_pdrv_remove(struct platform_device *pdev)
{
iounmap(led_dev->reg_addr);
device_destroy(led_dev->cls,MKDEV(led_dev->dev_major, 0));
class_destroy(led_dev->cls);
unregister_chrdev(led_dev->dev_major,"led_drv");
kfree(led_dev);
return 0;
}
/*用于匹配*/
const struct platform_device_id led_id_table[] = {
{"s3c2410_led", 1111},
{"s3c6410_led", 2222},
{"s5pv210_led", 3333},
};
struct platform_driver led_drv = {
.probe = led_pdrv_probe,
.remove = led_pdrv_remove,
.driver = {
.name = "s5pv210_led" // 随便写,用于匹配,/sys/bus/platform/drivers/samsung_led_drv
},
.id_table = led_id_table,//优先匹配列表中的名字,如果没有列表,就匹配父类中name
};
static int __init plat_led_drv_init(void)
{
/*注册一个平台驱动*/
printk("------*_^%s--------\n",__FUNCTION__);
return platform_driver_register(&led_drv);
}
static void __exit plat_led_drv_exit(void)
{
/*注销平台驱动*/
platform_driver_unregister(&led_drv);
printk("------*_^%s--------\n",__FUNCTION__);
}
module_init(plat_led_drv_init);
module_exit(plat_led_drv_exit);
MODULE_LICENSE("GPL");
# Makefile
ROOTFS_DIR = /opt/filesystem
MODULE_NAME = plat_led_dev
MODULE_NAME2 = plat_led_drv
APP_NAME = led_test
CROSS_COMPILE = arm-cortex_a8-linux-gnueabi-
CC = $(CROSS_COMPILE)gcc
ifeq ($(KERNELRELEASE), )
KERNEL_DIR = /home/linux-3.0.8
CUR_DIR = $(shell pwd)
all :
make -C $(KERNEL_DIR) M=$(CUR_DIR) modules
$(CC) $(APP_NAME).c -o $(APP_NAME)
clean :
make -C $(KERNEL_DIR) M=$(CUR_DIR) clean
rm -rf $(APP_NAME)
install:
cp -raf *.ko $(APP_NAME) $(ROOTFS_DIR)/drv_module
else
obj-m = $(MODULE_NAME).o
obj-m += $(MODULE_NAME2).o
endif