1、打开“drivers/of/base.c”
#define of_prop_cmp(s1, s2) strcmp((s1), (s2))
/*如果s1小于s2,则返回值小于0。
如果s1大于s2,则返回值大于0。
如果s1等于s2,则返回值等于0。*/
//函数功能:根据所给的“设备树的节点np”和“properties名字”在设备树里查找是否有“properties名字”
//np是指向设备树的节点
//name是指向要查找的properties名字
//lenp用来返回properties名字的长度
static struct property *__of_find_property(const struct device_node *np,
const char *name, int *lenp)
{
struct property *pp;
if (!np)return NULL;
for (pp = np->properties; pp; pp = pp->next)
{
if (of_prop_cmp(pp->name, name) == 0)
{ //如果pp->name等于name,则返回值等于0。
if (lenp) *lenp = pp->length;//保存properties名字的长度
break;
}
}
return pp;//返回property结构指针
}
const char *of_prop_next_string(struct property *prop, const char *cur)
{
const void *curv = cur;
if (!prop)return NULL;//如果prop=NULL,则返回NULL
if (!cur)return prop->value;//如果prop=NULL,则返回prop->value
curv += strlen(cur) + 1;//求cur字符串的长度,包括结束符;
if (curv >= prop->value + prop->length)//所给字符串的长度
return NULL;
return curv;
}
/*函数功能:根据name,在np指向的节点查找name所指向的字符串;返回属性名字的长度
保存在lenp中,并返回属性的指针值*/
static struct property *__of_find_property(const struct device_node *np,
const char *name, int *lenp)
{
struct property *pp;
if (!np) return NULL;//如果np=NULL,则返回NULL
for (pp = np->properties; pp; pp = pp->next)
{ /*np->properties指向属性*/
if (of_prop_cmp(pp->name, name) == 0)
{
/*根据所给的“设备树的节点np”和“name所指向的名字”在设备树里查找是否有“name所指向的名字”*/
if (lenp) *lenp = pp->length;//返回属性名字的长度
break;
}
}
return pp;
}
/*根据所给的节点查找给定名字的属性
* Find a property with a given name for a given node
* and return the value.
*/
const void *__of_get_property(const struct device_node *np,
const char *name, int *lenp)
{
struct property *pp = __of_find_property(np, name, lenp);
/*函数功能:根据name,在np指向的节点查找name所指向的字符串;返回属性名字的长度
保存在lenp中,并返回属性的指针值*/
return pp ? pp->value : NULL;
//如果pp!=NULL,则返回pp->value
}
//函数功能:如果根据所给的节点查找到了属性名为type,则返回1
static bool __of_node_is_type(const struct device_node *np, const char *type)
{
const char *match = __of_get_property(np, "device_type", NULL);
//根据所给的节点np查找device_type的属性,match=np->value
return np && match && type && !strcmp(match, type);
//np->value和type相同,返回1
}
//检查节点是否匹配所给的“name”,匹配则返回1;
bool of_node_name_eq(const struct device_node *np, const char *name)
{
const char *node_name;
size_t len;
if (!np)return false;
node_name = kbasename(np->full_name);//从np->full_name中提取名字;
len = strchrnul(node_name, '@') - node_name;//计算节点名字的长度
return (strlen(name) == len) && (strncmp(node_name, name, len) == 0);
//检查是否找到name所指向的字符串,匹配则返回1
}
#define INT_MAX 0x7fffffff
/**
函数功能:检查节点是否匹配所给的“compat,type和name”;
device: 指向节点的指针;
compat: 是compatible的缩写,要求匹配的字符串, 也可能是NULL或者是"";
type: 要求匹配的device_type值, 也可能是NULL或者是"";
name: 要求匹配的节点名字, 也可能是NULL或者是"";
返回值为0,表示不匹配;返回值大于0,表示匹配;
* 1. specific compatible && type && name
* 2. specific compatible && type
* 3. specific compatible && name
* 4. specific compatible
* 5. general compatible && type && name
* 6. general compatible && type
* 7. general compatible && name
* 8. general compatible
* 9. type && name
* 10. type
* 11. name
*/
static int __of_device_is_compatible(const struct device_node *device,
const char *compat, const char *type, const char *name)
{
struct property *prop;
const char *cp;
int index = 0, score = 0;
/* Compatible匹配具有最高优先级 */
if (compat && compat[0])//如果compat!=NULL,且compat[0]>0,则执行
{
prop = __of_find_property(device, "compatible", NULL);
/*根据所给的“设备树的节点device”和“properties名字compatible”在设备树里查找是否有“compatible”;
返回值是property结构指针
*/
for (cp = of_prop_next_string(prop, NULL); cp;
cp = of_prop_next_string(prop, cp), index++)
{
/*of_prop_next_string(prop, NULL)执行后cp=prop->value;*/
/*of_prop_next_string(prop, cp)cp=cp+strlen(cp) + 1;指向下一个prop->value*/
if (of_compat_cmp(cp, compat, strlen(compat)) == 0)
{ /*根据所给的“设备树的节点cp”和“compat所指向的名字”在设备树里查找是否有“compat所指向的名字”*/
score = INT_MAX/2 - (index << 2);
break;
}
}
if (!score)return 0;
}
/*匹配type比匹配的name的优先级要高;Matching type is better than matching name */
if (type && type[0])//如果type!=NULL,且type[0]>0,则执行
{
if (!__of_node_is_type(device, type))return 0;
//如果根据所给的device节点查找到了属性名为type,则返回1;
score += 2;
}
/* 要匹配的名字,Matching name is a bit better than not */
if (name && name[0])//如果name!=NULL,且name[0]>0,则执行
{
if (!of_node_name_eq(device, name))return 0;
//of_node_name_eq()检查节点是否匹配所给的“name”,匹配则返回1;
score++;
}
return score;
}
static
const struct of_device_id *__of_match_node(const struct of_device_id *matches,
const struct device_node *node)
{
const struct of_device_id *best_match = NULL;
int score, best_score = 0;
if (!matches)
return NULL;
for (; matches->name[0] || matches->type[0] || matches->compatible[0]; matches++) {
score = __of_device_is_compatible(node, matches->compatible,
matches->type, matches->name);
/*检查节点是否匹配所给的“compat,type和name”;*/
if (score > best_score) {
best_match = matches;
best_score = score;
}
}
return best_match;
}
/**判断device_node是否具有匹配的of_match结构
* of_match_node - Tell if a device_node has a matching of_match structure
* @matches: array of of device match structures to search in
* @node: the of device structure to match against
*
* Low level utility function used by device matching.
*/
const struct of_device_id *of_match_node(const struct of_device_id *matches,
const struct device_node *node)
{
const struct of_device_id *match;
unsigned long flags;
raw_spin_lock_irqsave(&devtree_lock, flags);
match = __of_match_node(matches, node);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
return match;
}
2、打开“drivers/of/device.c”
const struct of_device_id *of_match_device(const struct of_device_id *matches,
const struct device *dev)
{
if ((!matches) || (!dev->of_node))
return NULL;
return of_match_node(matches, dev->of_node);
/*使用of_match_node函数查找匹配的设备ID*/
}
const void *of_device_get_match_data(const struct device *dev)
{
const struct of_device_id *match;
match = of_match_device(dev->driver->of_match_table, dev);
if (!match)
return NULL;
return match->data;
}