设备驱动中的pinctrl(kernel-4.7)
来源:互联网 发布:光猫 连接端口23失败 编辑:程序博客网 时间:2024/06/02 12:22
在查看kernel源码时,很容易忽略大量的英文注释,其实,英文注解很好的提示代码的功用,所以,网上没有好的参考资料,可以参考英文注释来分析。
下面是driver/pinctrl/core.h中关于pinctrl的重要结构体定义:
/** * struct pinctrl_dev - pin control class device * @node: node to include this pin controller in the global pin controller list * @desc: the pin controller descriptor supplied when initializing this pin * controller * @pin_desc_tree: each pin descriptor for this pin controller is stored in * this radix tree * @gpio_ranges: a list of GPIO ranges that is handled by this pin controller, * ranges are added to this list at runtime * @dev: the device entry for this pin controller * @owner: module providing the pin controller, used for refcounting * @driver_data: driver data for drivers registering to the pin controller * subsystem * @p: result of pinctrl_get() for this device * @hog_default: default state for pins hogged by this device * @hog_sleep: sleep state for pins hogged by this device * @mutex: mutex taken on each pin controller specific action * @device_root: debugfs root for this device */struct pinctrl_dev { struct list_head node; struct pinctrl_desc *desc; struct radix_tree_root pin_desc_tree; struct list_head gpio_ranges; struct device *dev; struct module *owner; void *driver_data; struct pinctrl *p; struct pinctrl_state *hog_default; struct pinctrl_state *hog_sleep; struct mutex mutex;#ifdef CONFIG_DEBUG_FS struct dentry *device_root;#endif}; /** * struct pinctrl - per-device pin control state holder * @node: global list node * @dev: the device using this pin control handle * @states: a list of states for this device * @state: the current state * @dt_maps: the mapping table chunks dynamically parsed from device tree for * this device, if any * @users: reference count */struct pinctrl { struct list_head node; struct device *dev; struct list_head states; struct pinctrl_state *state; struct list_head dt_maps; struct kref users;}; /** * struct pinctrl_state - a pinctrl state for a device * @node: list node for struct pinctrl's @states field * @name: the name of this state * @settings: a list of settings for this state */struct pinctrl_state { struct list_head node; const char *name; struct list_head settings;};
下面include/linux/pinctrl.h中pinctrl操作重要的结构体,阅读英文注释了解功用:
/** * struct pinctrl_pin_desc - boards/machines provide information on their * pins, pads or other muxable units in this struct * @number: unique pin number from the global pin number space * @name: a name for this pin * @drv_data: driver-defined per-pin data. pinctrl core does not touch this */struct pinctrl_pin_desc { unsigned number; const char *name; void *drv_data;};/** * struct pinctrl_gpio_range - each pin controller can provide subranges of * the GPIO number space to be handled by the controller * @node: list node for internal use * @name: a name for the chip in this range * @id: an ID number for the chip in this range * @base: base offset of the GPIO range * @pin_base: base pin number of the GPIO range if pins == NULL * @pins: enumeration of pins in GPIO range or NULL * @npins: number of pins in the GPIO range, including the base number * @gc: an optional pointer to a gpio_chip */struct pinctrl_gpio_range { struct list_head node; const char *name; unsigned int id; unsigned int base; unsigned int pin_base; unsigned const *pins; unsigned int npins; struct gpio_chip *gc;};/** * struct pinctrl_ops - global pin control operations, to be implemented by * pin controller drivers. * @get_groups_count: Returns the count of total number of groups registered. * @get_group_name: return the group name of the pin group * @get_group_pins: return an array of pins corresponding to a certain * group selector @pins, and the size of the array in @num_pins * @pin_dbg_show: optional debugfs display hook that will provide per-device * info for a certain pin in debugfs * @dt_node_to_map: parse a device tree "pin configuration node", and create * mapping table entries for it. These are returned through the @map and * @num_maps output parameters. This function is optional, and may be * omitted for pinctrl drivers that do not support device tree. * @dt_free_map: free mapping table entries created via @dt_node_to_map. The * top-level @map pointer must be freed, along with any dynamically * allocated members of the mapping table entries themselves. This * function is optional, and may be omitted for pinctrl drivers that do * not support device tree. */struct pinctrl_ops { int (*get_groups_count) (struct pinctrl_dev *pctldev); const char *(*get_group_name) (struct pinctrl_dev *pctldev, unsigned selector); int (*get_group_pins) (struct pinctrl_dev *pctldev, unsigned selector, const unsigned **pins, unsigned *num_pins); void (*pin_dbg_show) (struct pinctrl_dev *pctldev, struct seq_file *s, unsigned offset); int (*dt_node_to_map) (struct pinctrl_dev *pctldev, struct device_node *np_config, struct pinctrl_map **map, unsigned *num_maps); void (*dt_free_map) (struct pinctrl_dev *pctldev, struct pinctrl_map *map, unsigned num_maps);};/** * struct pinctrl_desc - pin controller descriptor, register this to pin * control subsystem * @name: name for the pin controller * @pins: an array of pin descriptors describing all the pins handled by * this pin controller * @npins: number of descriptors in the array, usually just ARRAY_SIZE() * of the pins field above * @pctlops: pin control operation vtable, to support global concepts like * grouping of pins, this is optional. * @pmxops: pinmux operations vtable, if you support pinmuxing in your driver * @confops: pin config operations vtable, if you support pin configuration in * your driver * @owner: module providing the pin controller, used for refcounting * @num_custom_params: Number of driver-specific custom parameters to be parsed * from the hardware description * @custom_params: List of driver_specific custom parameters to be parsed from * the hardware description * @custom_conf_items: Information how to print @params in debugfs, must be * the same size as the @custom_params, i.e. @num_custom_params */struct pinctrl_desc { const char *name; const struct pinctrl_pin_desc *pins; unsigned int npins; const struct pinctrl_ops *pctlops; const struct pinmux_ops *pmxops; const struct pinconf_ops *confops; struct module *owner;#ifdef CONFIG_GENERIC_PINCONF unsigned int num_custom_params; const struct pinconf_generic_params *custom_params; const struct pin_config_item *custom_conf_items;#endif};
当内核使用pinctrl,pinctrl模块被初始化,将cpu的pin在pinctrl框架中注册一个pin的描述符,这个描述符包含了每个pin描述符组成的数列,用来对特定的pin进行操作。kernel中给出pinctrl的使用示例,如下:
一个PGA的 chip底层 :
A B C D E F G H 8 o o o o o o o o 7 o o o o o o o o 6 o o o o o o o o 5 o o o o o o o o 4 o o o o o o o o 3 o o o o o o o o 2 o o o o o o o o 1 o o o o o o o o
将以上每个pin的控制器和名字都加入到驱动中,一边对pin进行操作:
#include <linux/pinctrl/pinctrl.h>const struct pinctrl_pin_desc foo_pins[] = { PINCTRL_PIN(0, "A8"), PINCTRL_PIN(1, "B8"), PINCTRL_PIN(2, "C8"), ... PINCTRL_PIN(61, "F1"), PINCTRL_PIN(62, "G1"), PINCTRL_PIN(63, "H1"),};static struct pinctrl_desc foo_desc = { .name = "foo", .pins = foo_pins, .npins = ARRAY_SIZE(foo_pins), .owner = THIS_MODULE,};int __init foo_probe(void){ struct pinctrl_dev *pctl; pctl = pinctrl_register(&foo_desc, <PARENT>, NULL); if (!pctl) pr_err("could not register foo pin driver\n");}
每个具体的pin的名字和功用需要查看芯片手册来进行注册使用。
driver/pinctrl.h中定义了PINCTR_PIN()创建对pin的注册。
/* Convenience macro to define a single named or anonymous pin descriptor */#define PINCTRL_PIN(a, b) { .number = a, .name = b }#define PINCTRL_PIN_ANON(a) { .number = a }
如果需要对一组pin 进行控制操作,则使用pinctrl子系统提供的group管理进行。例如,如果有一组SPI接口使用的pins:on { 0, 8, 16, 24 },
一组I2C使用的pins:on { 24, 25 } ,这两组pinctrl的注册使用可以用pinctlr_ops来实现:
#include <linux/pinctrl/pinctrl.h>struct foo_group { const char *name; const unsigned int *pins; const unsigned num_pins;};static const unsigned int spi0_pins[] = { 0, 8, 16, 24 };static const unsigned int i2c0_pins[] = { 24, 25 };static const struct foo_group foo_groups[] = { { .name = "spi0_grp", .pins = spi0_pins, .num_pins = ARRAY_SIZE(spi0_pins), }, { .name = "i2c0_grp", .pins = i2c0_pins, .num_pins = ARRAY_SIZE(i2c0_pins), },};static int foo_get_groups_count(struct pinctrl_dev *pctldev){ return ARRAY_SIZE(foo_groups);}static const char *foo_get_group_name(struct pinctrl_dev *pctldev, unsigned selector){ return foo_groups[selector].name;}static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, const unsigned **pins, unsigned *num_pins){ *pins = (unsigned *) foo_groups[selector].pins; *num_pins = foo_groups[selector].num_pins; return 0;}static struct pinctrl_ops foo_pctrl_ops = { .get_groups_count = foo_get_groups_count, .get_group_name = foo_get_group_name, .get_group_pins = foo_get_group_pins,};static struct pinctrl_desc foo_desc = { ... .pctlops = &foo_pctrl_ops,};
pinctrl子系统将会调用get_groups_count()
来获取定义好的一组pins,然后调用其他函数来获取组中pin名。上面是简单示例,具体的驱动中会需要定义更复杂的group来实现特定的pin操作。
pin的配置在驱动中可以将配置条件到mapping table中,
#include <linux/pinctrl/pinctrl.h>#include <linux/pinctrl/pinconf.h>#include "platform_x_pindefs.h"static int foo_pin_config_get(struct pinctrl_dev *pctldev, unsigned offset, unsigned long *config){ struct my_conftype conf; ... Find setting for pin @ offset ... *config = (unsigned long) conf;}static int foo_pin_config_set(struct pinctrl_dev *pctldev, unsigned offset, unsigned long config){ struct my_conftype *conf = (struct my_conftype *) config; switch (conf) { case PLATFORM_X_PULL_UP: ... } }}static int foo_pin_config_group_get (struct pinctrl_dev *pctldev, unsigned selector, unsigned long *config){ ...}static int foo_pin_config_group_set (struct pinctrl_dev *pctldev, unsigned selector, unsigned long config){ ...}static struct pinconf_ops foo_pconf_ops = { .pin_config_get = foo_pin_config_get, .pin_config_set = foo_pin_config_set, .pin_config_group_get = foo_pin_config_group_get, .pin_config_group_set = foo_pin_config_group_set,};/* Pin config operations are handled by some pin controller */static struct pinctrl_desc foo_desc = { ... .confops = &foo_pconf_ops,};
未完待续。。。。
- 设备驱动中的pinctrl(kernel-4.7)
- 设备驱动中的device(kernel-4.7)
- 设备驱动中的device_driver(kernel-4.7)
- 设备驱动中的bus(kernel-4.7)
- 设备驱动中的kobject(kernel-4.7)
- 设备驱动中的kset(kernel-4.7)
- 设备驱动中的platform(kernel-4.7)
- 设备驱动中的class(kernel-4.7)
- 设备驱动中的i2c(kernel-4.7)
- 设备驱动中的tty(kernel-4.7)
- 设备驱动中的gadget(kernel-4.7)
- 设备驱动中的mutex(kernel-4.7)
- 设备驱动中的inode(kernel-4.7)
- 设备驱动中的spin_lock(kernel-4.7)
- 设备驱动中的misc(kernel-4.7)
- 设备驱动中的iomem(kernel-4.7)
- 设备驱动中的mmc(kernel-4.7)
- 设备驱动中的pci(kernel-4.7)
- python——web后台开发实现网址生成二维码
- 记录Java各种各样的BUG
- PLSQL developer破解版-sql注入防范
- 前端性能优化总结
- C++socket客户端select异步连接发送接收数据
- 设备驱动中的pinctrl(kernel-4.7)
- Android最佳性能实践(四)——布局优化技巧
- 深度探索QT窗口系统---几何篇1
- zmq 中的 zmq_init
- elasticsearch shield 认证的两种方式(http/java api)
- 一.spring-core IoC container(1) container概述和Bean基础
- 2.js按钮特效大全
- JAVA设计模式(二)工厂模式与观察者模式
- ORA-01861: 文字与格式字符串不匹配