platform的bus总线结构将一个硬件驱动分为device设备和driver驱动两部分。使用platform将两个联系到一起

就是把device和driver分开注册到内核中去。在根据相应的name之类的去匹配使用。
device_driver:device和driver的相关性数据和函数存放
struct device_driver {
	const char		*name;            //设备驱动程序的名字
	struct bus_type		*bus;            //所属总线类型
	struct module		*owner;            //模块所有者
	const char		*mod_name;	/* used for built-in modules */
	bool suppress_bind_attrs;	/* disables bind/unbind via sysfs */
	const struct of_device_id	*of_match_table;            //match device table
	int (*probe) (struct device *dev);                        //匹配度到设备的name与driver中的name一致时将会在注册时执行
	int (*remove) (struct device *dev);                        //移除一个绑定的驱动
	void (*shutdown) (struct device *dev);                  //关机
	int (*suspend) (struct device *dev, pm_message_t state);      //将设备调到休眠模式
	int (*resume) (struct device *dev);                        //唤醒休眠模式
	const struct attribute_group **groups;
	const struct dev_pm_ops *pm;                              //电源管理操作
	struct driver_private *p;
};
platform_device :硬件相关
struct platform_device {
	const char	* name;
	int		id;
	struct device	dev;
	u32		num_resources;
	struct resource	* resource;
	const struct platform_device_id	*id_entry;
	/* MFD cell pointer */
	struct mfd_cell *mfd_cell;
	/* arch specific additions */
	struct pdev_archdata	archdata;
};
platform_driver
这里的platform是一个普通的驱动,可用最原始的方法来注册创建class类,再在下面添加具体的设备文件来使用。platform只是bus中的一种,挂载到platform_bus_type。
struct platform_driver {
	int (*probe)(struct platform_device *);
	int (*remove)(struct platform_device *);
	void (*shutdown)(struct platform_device *);
	int (*suspend)(struct platform_device *, pm_message_t state);
	int (*resume)(struct platform_device *);
	struct device_driver driver;
	const struct platform_device_id *id_table;
};
resource
struct resource {
	resource_size_t start;
	resource_size_t end;
	const char *name;
	unsigned long flags;
	struct resource *parent, *sibling, *child;
};
platform_get_resource
获取platform资源
  struct resource *platform_get_resource(struct platform_device *dev, unsigned int type, unsigned int num)
  // type:资源类型
  // num:资源索引
platform_driver_register-
  int platform_driver_register(struct platform_driver *drv)
platform_driver_unregister
  void platform_driver_unregister(struct platform_driver *drv)
platform_device_register
  int platform_device_register(struct platform_device *pdev)
platform_device_unregister
  void platform_device_unregister(struct platform_device *pdev)
led_dev.c
  //定义资源
static struct resource myled_resource[] = {
        //内存资源
	[0] = {
		.start = 0x56000050,
		.end   = 0x56000050 + 8 - 1,
		.flags = IORESOURCE_MEM,
	},
        //中断资源
	[1] = {
		.start = 4,
		.end   = 4,
		.flags = IORESOURCE_IRQ,
	},
};
static int myled_release(struct platform_device *pdev)
{
}
static struct platform_device myled_dev = {
	.name = "myled",
	.id = -1,
	.num_resources = ARRAY_SIZE(myled_resource),      //申请内存
	.resource = myled_resource,                       //赋值
	.dev = {
		.release = myled_release,                  //释放函数
	},
};
static int myled_init(void)
{
	platform_device_register(&myled_dev);
	return 0;
}
static void myled_exit(void)
{
	platform_device_unregister(&myled_dev);
}
module_init(myled_init);
module_exit(myled_exit);
MODULE_LICENSE("GPL");
led_drv.c
static struct class *myled_class;
static struct class_device *myled_device_class;
static volatile unsigned long *gpfcon;
static volatile unsigned long *gpfdat;
static unsigned int pin;
static int myled_open (struct inode *inode, struct file *file)
{
	/*	设置gpio	*/
	*gpfcon &= ~(3 << (pin * 2));
	*gpfcon |= (1 << (pin * 2));
	return 0;
}
static ssize_t myled_write (struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
	int val;
	copy_from_user(&val, buf, count);
	if(val)
	{
		/*	点灯	*/
		*gpfdat &= ~(1 << pin);
	}
	else
	{
		/*	灭灯	*/
		*gpfdat |= (1 << pin);
	}
	return 0;
}
static struct file_operations myled_fops = {
	.owner = THIS_MODULE,
	.open  = myled_open,
	.write = myled_write,
};
int major;
static int myled_probe (struct platform_device *pdev)
{
	struct resource *res;
	/*	从平台获取信息	*/
        //根据platform_device的资源进行ioremap
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	gpfcon = ioremap(res->start, res->end - res->start + 1);
	gpfdat = gpfcon + 1;
	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	pin = res->start;
	
	/*	注册字符设备	*/
	major = register_chrdev(0, "myled", &myled_fops);
	myled_class = class_create(THIS_MODULE, "myled");
	myled_device_class = class_device_create(myled_class, NULL, MKDEV(major, 0), NULL, "myled");
	return 0;
}
static int myled_remove(struct platform_device *pdev)
{
	/*	卸载字符设备	*/
	unregister_chrdev(major, "myled");
	class_device_unregister(myled_device_class);
	class_destroy(myled_class);
	iounmap(gpfcon);
}
static struct platform_driver myled_drv = {
	.probe = myled_probe,
	.remove = myled_remove,
	.driver = {
		.name = "myled",
	},
};
static int myled_drv_init(void)
{
	platform_driver_register(&myled_drv);
	return 0;
}
static void myled_drv_exit(void)
{
	platform_driver_unregister(&myled_drv);
}
module_init(myled_drv_init);
module_exit(myled_drv_exit);
MODULE_LICENSE("GPL");
led_test.c
int main(int argc, char **argv)
{
	int fb;
	int val;
	fb = open("/dev/myled", O_RDWR);
	if(fb < 0)
	{
		printf("can‘t open!\n");
	}
	if(argc != 2)
	{
		printf("Uage: \n");
		printf("%s <on | off>\n", argv[0]);
		return 0;
	}
	if(strcmp(argv[1], "on") == 0)
	{
		val = 1;
	}
	else
	{
		val = 0;
	}
	write(fb, &val, 4);
	return 0;
}
Makefile
KERN_DIR = /home/book/linux-2.6.22.6
all:
	make -C $(KERN_DIR) M=`pwd` modules 
clean:
	make -C $(KERN_DIR) M=`pwd` modules clean
	rm -rf modules.order
obj-m	+= led_drv.o
obj-m	+= led_dev.o原文:https://www.cnblogs.com/huangdengtao/p/13336659.html