前一篇文章介绍了如果创建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 already
877 * 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驱动完成的了。