Bus_drv_dev Model: function Rewriting just change the dev hardware code, DRV does not need to be rewritten.
LED Example
Here is an example of this separation using a light LED example:
LED_DEV.C defines the resources for this platform device:
Static struct resource led_resource[] = {
[0] = {
. Start = 0x56000010, Physical address of//gpfcon
. end = 0x56000010 + 8-1,
. Flags = Ioresource_mem,
},
[1] = {
. Start = 6,//F6 pin
. end = 6,
. Flags = IORESOURCE_IRQ,
},
};
Define a platform device:
struct Platform_device device_led = {
. Name = "Myled",
. id =-1,
. num_resources = Array_size (Led_resource),
. resource = Led_resource,
. dev={
. Release = Led_release,
},
};
Register this "platform device" in the entry function
static int led_dev_init (void)
{
Platform_device_register (&device_led);
return 0;
}
Exit function is to unload this platform device
static void Led_dev_exit (void)
{
Platform_device_unregister (&device_led);
}
led_drv.c Define a platform driver
static
struct platform_driver led_drv = {
. Probe = Led_probe,
. remove = Led_remove,
. Driver = {
. Name = "Myled",
}
};
It is important to note that the name of the platform and the platform device of Dev are identical. This led_driver function is called if the platform device and platform driver match.
/* Assign/Set/register a platform_driver */
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/irq.h>
#include <asm/uaccess.h>
#include <asm/io.h>
static int major;
static struct class *cls;
Static volatile unsigned long *gpio_con;
Static volatile unsigned long *gpio_dat;
static int pin;
static int Led_open (struct inode *inode, struct file *file)
{
PRINTK ("first_drv_open\n");
/* Configured as OUTPUT */
*gpio_con &= ~ (0x3<< (pin*2));
*gpio_con |= (0x1<< (pin*2));
return 0;
}
Static ssize_t led_write (struct file *file, const char __user *buf, size_t count, loff_t * PPOs)
{
int Val;
Copy_from_user (&val, buf, Count); Copy_to_user ();
if (val = = 1)
{
Lighting
*gpio_dat &= ~ (1<<pin);
}
Else
{
Extinguishing lamp
*gpio_dat |= (1<<pin);
}
return 0;
}
static struct File_operations Led_fops = {
. Owner = This_module,/* This is a macro that pushes the __this_module variable created automatically when the module is compiled */
. open = Led_open,
. Write=led_write,
};
static int led_probe (struct platform_device *pdev)
{
struct resource*res;
/* Ioremap According to Platform_device's resources */
res = Platform_get_resource (Pdev, Ioresource_mem, 0);
Gpio_con = Ioremap (Res->start, Res->end-res->start + 1);
Gpio_dat = Gpio_con + 1;
res = Platform_get_resource (Pdev, IORESOURCE_IRQ, 0);
Pin = res->start;
/* Register character device drivers */
PRINTK ("Led_probe, found led\n");
Major = Register_chrdev (0, "myled", &led_fops);
CLS = Class_create (This_module, "myled");
Class_device_create (CLS, NULL, MKDEV (major, 0), NULL, "led"); /*/dev/led */
return 0;
}
static int led_remove (struct platform_device *pdev)
{
/* Uninstall character device drivers */
/* Iounmap */
PRINTK ("Led_remove, remove led\n");
class_device_destroy (CLS, MKDEV (major, 0));
class_destroy (CLS);
unregister_chrdev (Major, "myled");
iounmap (Gpio_con);
return 0;
"
struct Platform_driver led_drv = {
. probe= Led_probe,
. remove= Led_remove,
. driver= {
. Name= "Myled",
}
};
static int led_drv_init (void)
{
Platform_driver_register (&LED_DRV);
return 0;
}
static void Led_drv_exit (void)
{
Platform_driver_unregister (&LED_DRV);
}
Module_init (Led_drv_init);
Module_exit (Led_drv_exit);
Module_license ("GPL");
This driver is divided into the left and right sides, that is, Dev and DRV, in Led_dev. Assign, set, register a platform_device, assign in Led_drv, set, register a platform_driver.
The separation layering concept of Linux drives