Hi3519-pinctrl驱动开发③consumer driver与pinctrl子系统交互

来源:互联网 发布:工业革命 知乎 编辑:程序博客网 时间:2024/05/21 19:32

前一篇文章介绍了如果创建consumer driver到pinctrl driver的mapping table,这个mapping table就是系统的配置表,在系统启动之初注册到pinctrl sub system中去,貌似是在pinctrl driver注册之前就注册了mapping table了。既然已经有了mapping table,那我们假设pinctrl driver也已经“编写完成”(假设可以用了),这时候编写一个设备驱动的时候需要使用pinctrl sub system提供的服务,这时候设备驱动如何和pinctrl sub system交互呢?
有一个概念需要理解,就是“state”,也就是“状态”,每个设备对应第一个引脚组,继续以spi0设备为例,假设spi0设备对应的引脚组有两个,分别是PA0、1、2、3和PB5、6、7、8。state表示的就是设备使用的引脚组中引脚的状态,往常单片机开发中没有这个概念,但是在linux中为了提供足够的便利性和功能支持使用了state这个概念,具体来说当设备spi0正常运行的时候引脚状态处于正常状态,一般叫做default状态,当spi0设备处于关闭或者说低功耗模式下的时候引脚状态处于低功耗状态,一般叫做idle状态或者sleep状态(引脚的低功耗状态可能就是高阻态)。这样看来一个设备的pins可以处于不同的状态,pinctrl sub system提供了一种机制:pinctrl state holder,这个holder是一个容器,每一个设备都对应一个pinctrl state holder,用来存放设备拥有的所有states,pinctrl state holder结构体的定义如下:

struct pinctrl {     struct list_head node;--系统中的所有device的pin control state holder被挂入到了一个全局链表中     struct device *dev;---该pin control state holder对应的device     struct list_head states;----该设备的所有的状态被挂入到这个链表中     struct pinctrl_state *state;---当前的pin control state     struct list_head dt_maps;----mapping table     struct kref users;------reference count };

pinctrl state holder结构体的名称为“pinctrl”,而pinctrl驱动的描述结构体的名称为“pinctrl_desc”,真的很郁闷为什么这么命名,我觉得可以是“pinctrl_state_holder”和“pinctrl”,这样对于理解会方便很多。
pinctrl state holder结构体中的states元素存放的就是device的state链表,state元素存放的是当前device处于的状态。说到这里state显得很神秘,state是由结构体pinctrl_state 描述的:

struct pinctrl_state {        struct list_head node;---链表元素        const char *name;---state的名称        struct list_head settings;---设置};

pinctrl_state 前两个元素很好理解,最后一个settings元素表示的是要设置成这个state的话要进行的配置,settings也是一个链表,也就是有多个setting。setting是结构体struct pinctrl_setting:

struct pinctrl_setting {        struct list_head node;---链表元素        enum pinctrl_map_type type;---map type        struct pinctrl_dev *pctldev;---pinctrl驱动        const char *dev_name;---使用这个state的设备名        union {                struct pinctrl_setting_mux mux;                struct pinctrl_setting_configs configs;        } data;};

这个结构体和struct pinctrl_map结构体很像,type为PIN_MAP_TYPE_MUX_GROUP时data为mux,struct pinctrl_setting_mux的定义如下:

struct pinctrl_setting_mux {        unsigned group;---the group selector to program        unsigned func;---the function selector to program};

其中group就是引脚组的索引,func就是功能的索引。state的组织原理图如下图:
这里写图片描述
state概念介绍完了,那么说每个device对应的pinctrl state holder中的states中的settings是怎么来的,难道说是device自己定义的?显然不能,这样的话驱动会有太多没用的程序,而且可移植性很差。具体是怎么创建device的states和state中的settings呢?我也没研究过,我猜测是这样的:mapping table在系统启动之初就建立好了,注册到pinctrl sub system中,在建立pinctrl state holder的时候pinctrl子系统会根据对应的mapping table中的mapping entry创建states和settings,先假设是这么回事。现在已经“知道了”states和settings是在建立pinctrl state holder的时候创建的,那么pinctrl state holder是如何创建的呢?
pinctrl state holder是动态定义的,且并不是每个device都对应一个pinctrl state holder,因为有的device是不用引脚的。需要引脚的device需要获取属于自己的pinctrl state holder,使用的pinctrl sub system接口函数是devm_pinctrl_get和pinctrl_get,前者是后者的resource managed版本。单看后者pinctrl_get函数:

868 struct pinctrl *pinctrl_get(struct device *dev)869 {870         struct pinctrl *p;871 872         if (WARN_ON(!dev))873                 return ERR_PTR(-EINVAL);874 875         /*876          * See if somebody else (such as the device core) has already877          * obtained a handle to the pinctrl for this device. In that case,878          * return another pointer to it.879          */880         p = find_pinctrl(dev);881         if (p != NULL) {882                 dev_dbg(dev, "obtain a copy of previously claimed pinctrl\n");883                 kref_get(&p->users);884                 return p;885         }886 887         return create_pinctrl(dev);888 }

第880行中的find_pinctrl函数用来查找当前系统是否已经定义了该device的pinctrl state holder,如果没有定义的话就调用887行中的 create_pinctrl函数创建该device的pinctrl state holder。create_pinctrl如下:

 788 static struct pinctrl *create_pinctrl(struct device *dev) 789 { 790         struct pinctrl *p; 791         const char *devname; 792         struct pinctrl_maps *maps_node; 793         int i; 794         struct pinctrl_map const *map; 795         int ret; 796  797         /* 798          * create the state cookie holder struct pinctrl for each 799          * mapping, this is what consumers will get when requesting 800          * a pin control handle with pinctrl_get() 801          */ 802         p = kzalloc(sizeof(*p), GFP_KERNEL); 803         if (p == NULL) { 804                 dev_err(dev, "failed to alloc struct pinctrl\n"); 805                 return ERR_PTR(-ENOMEM); 806         } 807         p->dev = dev; 808         INIT_LIST_HEAD(&p->states); 809         INIT_LIST_HEAD(&p->dt_maps); 810  811         ret = pinctrl_dt_to_map(p); 812         if (ret < 0) { 813                 kfree(p); 814                 return ERR_PTR(ret); 815         } 816  817         devname = dev_name(dev); 818  819         mutex_lock(&pinctrl_maps_mutex); 820         /* Iterate over the pin control maps to locate the right ones */ 821         for_each_maps(maps_node, i, map) { 822                 /* Map must be for this device */ 823                 if (strcmp(map->dev_name, devname)) 824                         continue; 825  826                 ret = add_setting(p, map); 827                 /* 828                  * At this point the adding of a setting may: 829                  * 830                  * - Defer, if the pinctrl device is not yet available 831                  * - Fail, if the pinctrl device is not yet available, 832                  *   AND the setting is a hog. We cannot defer that, since 833                  *   the hog will kick in immediately after the device 834                  *   is registered. 835                  * 836                  * If the error returned was not -EPROBE_DEFER then we 837                  * accumulate the errors to see if we end up with 838                  * an -EPROBE_DEFER later, as that is the worst case. 839                  */ 840                 if (ret == -EPROBE_DEFER) { 841                         pinctrl_free(p, false); 842                         mutex_unlock(&pinctrl_maps_mutex); 843                         return ERR_PTR(ret); 844                 } 845         } 846         mutex_unlock(&pinctrl_maps_mutex); 847  848         if (ret < 0) { 849                 /* If some other error than deferral occured, return here */ 850                 pinctrl_free(p, false); 851                 return ERR_PTR(ret); 852         } 853  854         kref_init(&p->users); 855  856         /* Add the pinctrl handle to the global list */ 857         mutex_lock(&pinctrl_list_mutex); 858         list_add_tail(&p->node, &pinctrl_list); 859         mutex_unlock(&pinctrl_list_mutex); 860  861         return p; 862 }

简单看一下程序,802行分配pinctrl state holder内存空间,811行使用函数pinctrl_dt_to_map创建mapping table,这是使用DTS的方式创建的,我们使用的是Machine Driver的方式创建的,结果都是一样的,都是创建一个mapping table,只是DTS方式更加灵活方便,不需要修改内核代码就能系统支持不同的Board。这里有个疑问,没有使用DTS方式的话pinctrl_dt_to_map函数是不是会返回错误呢?这样就会在814行返回了,返回的话后面的初始化就没有得到执行,我看了一下pinctrl_dt_to_map函数的部分源码:

175 int pinctrl_dt_to_map(struct pinctrl *p)176 {177         struct device_node *np = p->dev->of_node;178         int state, ret;179         char *propname;180         struct property *prop;181         const char *statename;182         const __be32 *list;183         int size, config;184         phandle phandle;185         struct device_node *np_config;186 187         /* CONFIG_OF enabled, p->dev not instantiated from DT */188         if (!np) {189                 if (of_have_populated_dt())190                         dev_dbg(p->dev,191                                 "no of_node; not parsing pinctrl DT\n");192                 return 0;193         }194 195         /* We may store pointers to property names within the node */196         of_node_get(np);......

117行中获取p->dev->of_node,188行判断np是否为null,如果为null表示没有使用Device Tree机制,同时返回0表示没有错误。回到create_pinctrl函数,这样一来pinctrl_dt_to_map并没有完成解析DT来创建mapping table的任务,因为根本没有DT。接下里821行的“for_each_maps(maps_node, i, map)”其实就是遍历了系统全局变量pinctrl_maps链表中的每个pinctrl_maps,宏展开后是这样的:

list_for_each_entry(maps_node, &pinctrl_maps, node)        for (i=0,map=&maps_node->maps[i];i<maps_node->num_maps;i++,map=&maps_node>maps[i])

list_for_each_entry的含义参见文章:http://blog.csdn.net/tq384998430/article/details/73188601,简单来说就是list_for_each_entry宏中maps_node是一个迭代变量,&pinctrl_maps是链表头指针,node是结构体中的元素名称。整体意思就是从链表pinctrl_maps中挨个获取pinctrl_maps元素赋值给maps_node,然后循环将maps_node中的元素赋值给map进入循环中执行。注意这里两个pinctrl_maps的区别,一个pinctrl_maps是core.c文件中定义的链表全局变量:

59:LIST_HEAD(pinctrl_maps);

另一个是结构体struct pinctrl_maps。前者pinctrl_maps链表中的元素都是struct pinctrl_maps类型。
下面再看create_pinctrl函数的826行,add_setting,很显然这是通过map元素来创建pinctrl state holder中的state和settings,add_setting函数源码就不看了,意图很明显。经过list_for_each_entry循环和第二层的for循环后将所有与创建pinctrl state holder的device相关的maps都生成了相应的states和settings,这样consumer driver就能使用这些个states了。下面来说具体怎么使用定义好了的state holder中的states。
前面使用pinctrl_get已经创建了device的pinctrl state holder,并且根据mapping table初始化了pinctrl state holder中的states和settings(对应的devm_pinctrl_put和pinctrl_put两个函数用于释放pinctrl state holder资源)。现在假设一个场景是spi0设备驱动从pinctrl sub system中获取到了自己的pinctrl state holder,然后它要设置自己需要的引脚的状态到default状态,那么它可以使用函数pinctrl_lookup_state,函数原型为:

struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *p, const char *name);

这个函数根据state name在pin control state holder找到对应的pin control state。具体的state是各个device自己定义的,不过pin control subsystem自己定义了一些标准的pin control state,定义在pinctrl-state.h文件中:

#define PINCTRL_STATE_DEFAULT "default" #define PINCTRL_STATE_IDLE "idle" #define PINCTRL_STATE_SLEEP "sleep"

调用pinctrl_lookup_state示例:

dev->pins->default_state = pinctrl_lookup_state(dev->pins->p,PINCTRL_STATE_DEFAULT);

获取到了default_state之后可以调用pinctrl_select_state函数:

int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state);

这个函数用来选中一个特定的state,意思就是设置引脚成该state所描述的状态,这个设置过程就是由pinctrl驱动完成的了。

原创粉丝点击