am335x评估板gpio驱动解析

一.注册硬件模块
1.硬件模块

struct omap_hwmod {
	const char			*name;
	struct omap_hwmod_class		*class;
	struct omap_device		*od;
	struct omap_hwmod_mux_info	*mux;
	struct omap_hwmod_irq_info	*mpu_irqs;
	struct omap_hwmod_dma_info	*sdma_reqs;
	struct omap_hwmod_rst_info	*rst_lines;
	union {
		struct omap_hwmod_omap2_prcm omap2;
		struct omap_hwmod_omap4_prcm omap4;
	}				prcm;
	const char			*main_clk;
	struct clk			*_clk;
	struct omap_hwmod_opt_clk	*opt_clks;
	char				*clkdm_name;
	struct clockdomain		*clkdm;
	char				*vdd_name;
	struct omap_hwmod_ocp_if	**masters; /* connect to *_IA */
	struct omap_hwmod_ocp_if	**slaves;  /* connect to *_TA */
	void				*dev_attr;
	u32				_sysc_cache;
	void __iomem			*_mpu_rt_va;
	spinlock_t			_lock;
	struct list_head		node;
	u16				flags;
	u8				_mpu_port_index;
	u8				response_lat;
	u8				rst_lines_cnt;
	u8				opt_clks_cnt;
	u8				masters_cnt;
	u8				slaves_cnt;
	u8				hwmods_cnt;
	u8				_int_flags;
	u8				_state;
	u8				_postsetup_state;
};
static struct omap_hwmod am33xx_gpio0_hwmod = {
	.name		= "gpio1",
	.class		= &am33xx_gpio_hwmod_class,
	.clkdm_name	= "l4_wkup_clkdm",
	.mpu_irqs	= am33xx_gpio0_irqs,
	.main_clk	= "gpio0_ick",
	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET | HWMOD_INIT_NO_RESET,
	.prcm		= {
		.omap4	= {
			.clkctrl_offs	= AM33XX_CM_WKUP_GPIO0_CLKCTRL_OFFSET,
			.modulemode	= MODULEMODE_SWCTRL,
		},
	},
	.opt_clks	= gpio0_opt_clks,
	.opt_clks_cnt	= ARRAY_SIZE(gpio0_opt_clks),
	.dev_attr	= &gpio_dev_attr,
	.slaves		= am33xx_gpio0_slaves,
	.slaves_cnt	= ARRAY_SIZE(am33xx_gpio0_slaves),
};
static __initdata struct omap_hwmod *am33xx_hwmods[] = {
........
	/* gpio class */
	&am33xx_gpio0_hwmod,
	&am33xx_gpio1_hwmod,
	&am33xx_gpio2_hwmod,
	&am33xx_gpio3_hwmod,
.........
	NULL,
};

........

2.注册模块

添加硬件模块到双向链表omap_hwmod_list,入口函数为
\arch\arm\mach-omap2\omap_hwmod_33xx_data.c

int __init am33xx_hwmod_init(void)

该函数的调用过程为start_kernel()->setup_arch()->init_early()->am33xx_init_early()->am33xx_hwmod_init()

二.创建/sys/devices/platform/omap目录

struct device omap_device_parent = {
	.init_name	= "omap",
	.parent         = &platform_bus,///sys/devices/platform目录
};


static int __init omap_device_init(void)
{
	bus_register_notifier(&platform_bus_type, &platform_nb);

	// 创建/sys/devices/platform/omap目录
	return device_register(&omap_device_parent);
}

//#define core_initcall(fn)		__define_initcall("1",fn,1)
core_initcall(omap_device_init);

三.创建platform_device(/sys/devices/platform/omap/omap_gpioX目录)

 //创建/sys/devices/platform/omap/omap_gpio0,omap_gpio1,omap_gpio2,omap_gpio3目录
static int __init omap2_gpio_init(void)
{
......
}


//#define postcore_initcall(fn)		__define_initcall("2",fn,2)
postcore_initcall(omap2_gpio_init);

四.创建platform_driver(创建/sys/bus/platform/drivers/omap_gpio目录)
1.创建/sys/bus/platform/drivers/omap_gpio目录

//\drivers\gpio\Gpio-omap.c
static struct platform_driver omap_gpio_driver = {
	.probe		= omap_gpio_probe,
	.driver		= {
		.name	= "omap_gpio",
	},
};

static int __init omap_gpio_drv_reg(void)
{
	return platform_driver_register(&omap_gpio_driver);
}
//#define postcore_initcall(fn)		__define_initcall("2",fn,2)
postcore_initcall(omap_gpio_drv_reg);

2.调用omap_gpio_probe
omap_gpio_probe()->omap_gpio_chip_init()->gpiochip_add();添加芯片控制器gpio_chip;

五.添加字符设备

static int gpio_open(struct inode *inode,struct file *filp)
static int gpio_release(struct inode *inode,struct file *filp)
static long gpio_ioctl(struct file *filp,  unsigned int cmd,  unsigned long arg)
struct file_operations gpio_fops = {
	.owner =    THIS_MODULE,
	.open =     gpio_open, // int (*open) (struct inode *, struct file *);
	.unlocked_ioctl =    gpio_ioctl,//long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
	.release =  gpio_release,// int (*release) (struct inode *, struct file *);
};

static int __init am335x_gpio_init(void)
{
	int result;
	dev_t dev = 0;

	//alloc_chrdev_region:分配设备号,并添加到chrdevs数组./proc/devices 里的设备号, 设备名从chrdevs[255]里取
	result = alloc_chrdev_region(&dev, gpio_minor, 1,"am335x_gpio"); 
	gpio_major = MAJOR(dev);
	if (result < 0) {
		printk(KERN_WARNING "Can't get major %d\n", gpio_major);
		return result;
	}
	printk("AM335X GPIO Driver Registered.\n");

	// 初始化cdev
	cdev_init(&gpio_cdev, &gpio_fops); 
	gpio_cdev.owner = THIS_MODULE;
	gpio_cdev.ops = &gpio_fops;
	// 添加cdev到cdev_map结构(probe),
	result = cdev_add (&gpio_cdev, dev, 1);

	// 创建一个class,生成/sys/class/am335x_gpio目录
	gpio_class = class_create(THIS_MODULE, "am335x_gpio"); 
	if (IS_ERR(gpio_class)) {
        	printk(KERN_WARNING "Class_create faild\n");
		cdev_del(&gpio_cdev);
		unregister_chrdev_region(dev, 0);
		return result;
	}
	// 创建一个device,生成/sys/class/am335x_gpio/am335x_gpio文件.udev程序搜索该目录生成/dev/am335x_gpio设备文件
	class_dev = device_create(gpio_class,NULL,dev,0,"am335x_gpio");

	head = (struct am335x_gpio_node *)kmalloc(sizeof(struct am335x_gpio_node), GFP_KERNEL);
	if(head == NULL)
	{
		return -1;
	}
	else  
    {  
        head->pin = 0;  
        head->next = NULL;    
    }  
	return 0;
}

//#define device_initcall(fn)		__define_initcall("6",fn,6)
//#define __initcall(fn) device_initcall(fn)
//#define module_init(x)	__initcall(x);
module_init(am335x_gpio_init);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值