一、开发环境
1、硬件平台:FS2410
2、主机:Ubuntu 10.10
3、内核版本: linux 2.6.35
4、交叉编译工具链:arm-none-linux-gnueabi-
二、详细代码
1、led_device.c(platform_device)
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
struct resource led_resource[] = {
[0] = {
.start = 0x56000050,
.end = 0x56000054,
.flags = IORESOURCE_MEM,
}
};
struct platform_device led_device = {
.name = "led",
.id = -1,
.num_resources = ARRAY_SIZE(led_resource),
.resource = led_resource,
};
static int __init led_device_init(void)
{
int ret;
ret = platform_device_register(&led_device);
if(ret < 0)
printk("failed to register led_device");
return ret;
}
static void __exit led_device_exit(void)
{
platform_device_unregister(&led_device);
return;
}
module_init(led_device_init);
module_exit(led_device_exit);
MODULE_AUTHOR("yhr");
MODULE_LICENSE("GPL");
2、led_driver.c(platform_driver)
#include <linux/module.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <mach/map.h>
static int led_major = 249;
static volatile unsigned int *gpfcon;
static volatile unsigned int *gpfdat;
struct cdev led_cdev;
void init_led(void)
{
writel(readl(gpfcon) & ~(0xff << 8), gpfcon);
writel(readl(gpfcon) | (0x55 << 8), gpfcon);
writel(readl(gpfdat) & ~(0xf << 4), gpfdat);
return ;
}
static int led_open(struct inode *inode, struct file *filp)
{
init_led();
return 0;
}
static int led_release(struct inode *inode, struct file *filp)
{
writel(readl(gpfdat) | (0xf << 4), gpfdat);
return 0;
}
static ssize_t led_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
return 0;
}
static ssize_t led_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)
{
return 0;
}
static struct file_operations led_fops = {
.owner = THIS_MODULE,
.open = led_open,
.release = led_release,
.read = led_read,
.write = led_write,
};
static void led_setup_cdev(struct cdev *dev, int index)
{
int err;
dev_t devno = MKDEV(led_major, index);
cdev_init(dev, &led_fops);
dev->owner = THIS_MODULE;
err = cdev_add(dev, devno, 1);
if(err)
printk("Error %d adding led %d\n", err, index);
return ;
}
static int led_cdev_init(void)
{
int ret;
dev_t devno = MKDEV(led_major, 0);
if(led_major)
ret = register_chrdev_region(devno, 1, "2410_led");
else
{
ret = alloc_chrdev_region(&devno, 0, 1, "2410_led");
led_major = MAJOR(devno);
}
if(ret < 0)
return ret;
led_setup_cdev(&led_cdev, 0);
printk("led_major : %d\n", led_major);
return 0;
}
static int led_probe(struct platform_device *pdev)
{
struct resource *res;
struct resource *led_mem;
int size;
int ret;
ret = led_cdev_init();
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if(res == NULL)
{
printk("failed to get resource\n");
}
size = resource_size(res);
led_mem = request_mem_region(res->start, size, pdev->name);
if(led_mem == NULL)
{
printk("failed to request_mem_region\n");
}
gpfcon = ioremap(res->start, size);
gpfdat = ioremap(res->end, size);
return ret;
}
static int led_remove(struct platform_device *pdev)
{
struct resource *res;
int size;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if(res == NULL)
{
printk("failed to get resource\n");
}
size = resource_size(res);
iounmap(gpfcon);
iounmap(gpfdat);
release_mem_region(res->start, size);
cdev_del(&led_cdev);
unregister_chrdev_region(MKDEV(led_major, 0), 1);
return 0;
}
struct platform_driver led_driver = {
.probe = led_probe,
.remove = led_remove,
.driver = {
.name = "led",
.owner = THIS_MODULE,
},
};
static int __init led_driver_init(void)
{
int ret;
ret = platform_driver_register(&led_driver);
if(ret < 0)
printk("failed to register led_driver\n");
return ret;
}
static void __exit led_driver_exit(void)
{
platform_driver_unregister(&led_driver);
return ;
}
module_init(led_driver_init);
module_exit(led_driver_exit);
MODULE_AUTHOR("yhr");
MODULE_LICENSE("GPL");
3、Makefile
ifeq ($(KERNELRELEASE),)
# set your object kernel dir
KERNELDIR = /home/linux/linux-2.6.35
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions Module* modules*
.PHONY: modules modules_install clean
else
obj-m := led_device.o led_driver.o
endif