linux GPIO子系统.

简介:

  gpio源自GPIO控制器, 通常一个芯片会有多个GPIO控制器. GPIO驱动就是GPIO控制器驱动. 这部分驱动通常由

芯片原厂编写,不同芯片厂商的GPIO控制器差异很大, 但是他们基于linux内核会相同的架构编写,实现方式大同小异.

对于普通开发者来说,只需要知道怎么使用(申请,释放,设置输入输出...)就可以了,但是了解GPIO控制器驱动实现方式对深入理解

GPIO是有帮助的.

    首先看下GPIO控制器驱动是如何编写的,然后介绍驱动中如何使用GPIO,最后介绍sysfs,proc,debugfs下的GPIO相关内容(如果有的话.)

1. gpio控制器驱动

        struct gpio_chip 代表一个GPIO控制器(include/linux/gpio/driver.h), 定义如下:

1.1 gpio_chip 结构

        

/**
 * struct gpio_chip 是GPIO控制器的抽象, 代表一个GPIO控制器.
*/
struct gpio_chip {
	const char		*label;   //标签
	struct gpio_device	*gpiodev; //gpio_chip 关联的gpio_deivce, 一个gpiochip 就是一个gpio_device.
	struct device		*parent;  // gpio_device的父设备, 通常是注册这个chip设备.
	struct module		*owner;   // 所有者

	/**
	 * GPIO控制器驱动要实现的GPIO操作函数. 当然不必实现全部的功能.
	*/
	int			(*request)(struct gpio_chip *chip,unsigned offset);
	void		(*free)(struct gpio_chip *chip,unsigned offset);
	int			(*get_direction)(struct gpio_chip *chip,unsigned offset);
	int			(*direction_input)(struct gpio_chip *chip,unsigned offset);
	int			(*direction_output)(struct gpio_chip *chip,unsigned offset, int value);
	int			(*get)(struct gpio_chip *chip,unsigned offset);
	void		(*set)(struct gpio_chip *chip,unsigned offset, int value);
	void		(*set_multiple)(struct gpio_chip *chip,unsigned long *mask,unsigned long *bits);
	int			(*set_config)(struct gpio_chip *chip, unsigned offset,unsigned long config);
	int			(*to_irq)(struct gpio_chip *chip,unsigned offset);
	void		(*dbg_show)(struct seq_file *s,struct gpio_chip *chip);

	/**
	 * 一个gpio_chip 管理一组GPIO, 系统中所有GPIO拥有唯一的编号.
	 * base:指定当前gpio_chip 管理的这组GPIO的初始编号,=-1 表示使用动态分配的初始编号
	 * ngpio: 这ge gpio_chip 管理的GPIO数量.
	*/
	int			base;  
	u16			ngpio;
	const char		*const *names; //别名, 通常不设置.
	bool			can_sleep;

#if IS_ENABLED(CONFIG_GPIO_GENERIC)
	unsigned long (*read_reg)(void __iomem *reg);
	void (*write_reg)(void __iomem *reg, unsigned long data);
	unsigned long (*pin2mask)(struct gpio_chip *gc, unsigned int pin);
	void __iomem *reg_dat;
	void __iomem *reg_set;
	void __iomem *reg_clr;
	void __iomem *reg_dir;
	int bgpio_bits;
	spinlock_t bgpio_lock;
	unsigned long bgpio_data;
	unsigned long bgpio_dir;
#endif

	/*由GPIO管理中断,处理中断事件.*/
#ifdef CONFIG_GPIOLIB_IRQCHIP
	/*
	 * With CONFIG_GPIOLIB_IRQCHIP we get an irqchip inside the gpiolib
	 * to handle IRQs for most practical cases.
	 */

	/**
	 * @irq:
	 *
	 * Integrates interrupt chip functionality with the GPIO chip. Can be
	 * used to handle IRQs for most practical cases.
	 */
	struct gpio_irq_chip irq;
#endif


	/**
	 * 使用GPIO 设备树, 如果开启则可以使用
	 * of_get_name_gpio... 等等 of相关函数
	*/
#if defined(CONFIG_OF_GPIO)
	/*
	 * If CONFIG_OF is enabled, then all GPIO controllers described in the
	 * device tree automatically may have an OF translation
	 */

	/**
	 * @of_node:
	 * GPIO 控制器的设备树节点.
	 */
	struct device_node *of_node;

	/**
	 * @of_gpio_n_cells:
	 * 描述一个GPIO(不是gpio_chip)用到的关键字数量,
	 * Number of cells used to form the GPIO specifier.
	 */
	unsigned int of_gpio_n_cells;

	/**
	 * @of_xlate:
	 *
	 * Callback to translate a device tree GPIO specifier into a chip-
	 * relative GPIO number and flags.
	 */
	int (*of_xlate)(struct gpio_chip *gc,
			const struct of_phandle_args *gpiospec, u32 *flags);
#endif
};

1.2 注册一个gpio_chip

        驱动中只需要填充一个 struct chio_chip结构体然后调用注册函数即可,重点是注册函数做了什么.

static int sprd_gpio_probe(struct platform_device *pdev)
{
	struct gpio_irq_chip *irq;
	struct sprd_gpio *sprd_gpio;
	struct resource *res;
	int ret;

	sprd_gpio = devm_kzalloc(&pdev->dev, sizeof(*sprd_gpio), GFP_KERNEL);
	if (!sprd_gpio)
		return -ENOMEM;

	sprd_gpio->irq = platform_get_irq(pdev, 0);
	if (sprd_gpio->irq < 0) {
		dev_err(&pdev->dev, "Failed to get GPIO interrupt.\n");
		return sprd_gpio->irq;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值