DTB (of API)

 

of_find_node_by_path()

include/linux/of.h

static inline struct device_node *of_find_node_by_path(const char *path)
{
        return of_find_node_opts_by_path(path, NULL);
}

full path 노드명과 매치되는 노드를 찾는다.

  • alias명으로 검색하는 경우에는 ‘/’ 문자로 시작하지 않아도 된다.

 

of_find_node_opts_by_path()

drivers/of/base.c

/**
 *      of_find_node_opts_by_path - Find a node matching a full OF path
 *      @path: Either the full path to match, or if the path does not
 *             start with '/', the name of a property of the /aliases
 *             node (an alias).  In the case of an alias, the node
 *             matching the alias' value will be returned.
 *      @opts: Address of a pointer into which to store the start of
 *             an options string appended to the end of the path with
 *             a ':' separator.
 *
 *      Valid paths:
 *              /foo/bar        Full path
 *              foo             Valid alias
 *              foo/bar         Valid alias + relative path
 *      
 *      Returns a node pointer with refcount incremented, use
 *      of_node_put() on it when done.
 */     
struct device_node *of_find_node_opts_by_path(const char *path, const char **opts)
{
        struct device_node *np = NULL;
        struct property *pp;
        unsigned long flags;
        const char *separator = strchr(path, ':');

        if (opts)
                *opts = separator ? separator + 1 : NULL; 
                                             
        if (strcmp(path, "/") == 0)
                return of_node_get(of_root);

        /* The path could begin with an alias */
        if (*path != '/') {
                int len;
                const char *p = separator;

                if (!p)
                        p = strchrnul(path, '/');
                len = p - path;

                /* of_aliases must not be NULL */
                if (!of_aliases)         
                        return NULL;
     
                for_each_property_of_node(of_aliases, pp) {
                        if (strlen(pp->name) == len && !strncmp(pp->name, path, len)) {
                                np = of_find_node_by_path(pp->value);
                                break;
                        }
                }
                if (!np)
                        return NULL;
                path = p;
        }

full path 또는 alias 명과 매치되는 노드를 찾는다. 옵션(‘:’  다음의 문자열)  문자열이 있는 경우 출력 인수가 주어진 경우 저장한다.

  • const char *separator = strchr(path, ‘:’);
    • path에서 ‘:’ 문자 위치를 찾는다.
  • if (opts) *opts = separator ? separator + 1 : NULL;
    • ‘:’문자가 있는 경우 opts에 ‘:’ 다음 문자를 가리키고 없는 경우 null을 대입한다.
  • if (strcmp(path, “/”) == 0) return of_node_get(of_root);
    • 루트 노드인 경우 전역 변수 of_root의 노드를 리턴한다.

노드명이 alias인 경우 전역 of_alias에 추가된 모든 속성의 값과 같은 경우 이 속성값으로 노드를 찾아 온다.

  • if (*path != ‘/’) {
    • 노드명이 alias 타입으로 시작한 경우
  • if (!p) p = strchrnul(path, ‘/’);
    • p가 지정되지 않은 경우 p에 ‘/’ 문자열 위치를 대입한다.
  • len = p – path;
    • ‘/’ 문자열 위치에서 속성 첫 문자열 위치를 뺀 수로 compact alias 명의 길이가 된다.
  • for_each_property_of_node(of_aliases, pp) {
    • of_aliases 노드내의 모든 속성 만큼 루프를 돈다.
  • if (strlen(pp->name) == len && !strncmp(pp->name, path, len)) { np = of_find_node_by_path(pp->value); break; }
    • 속성명 길이와 len(alias명 길이)이 같고 그 길이만큼 속성명과 alias 명을 비교하여 같은 경우 속성 값으로 노드를 찾아 루프를 탈출한다.
  • if (!np) return NULL;
    • 찾지 못한 경우 null을 리턴한다.

 

        /* Step down the tree matching path components */
        raw_spin_lock_irqsave(&devtree_lock, flags);
        if (!np)
                np = of_node_get(of_root);
        while (np && *path == '/') {
                path++; /* Increment past '/' delimiter */
                np = __of_find_node_by_path(np, path);
                path = strchrnul(path, '/');
                if (separator && separator < path)
                        break;
        }
        raw_spin_unlock_irqrestore(&devtree_lock, flags);
        return np;
}
EXPORT_SYMBOL(of_find_node_opts_by_path);
  • if (!np) np = of_node_get(of_root);
    • 발견된 노드 정보가 없으면 루트 노드 정보를 가져온다.
  • while (np && *path == ‘/’) {
    • 노드들 중 alias명이 아닌 full path 노드명인 경우만 루프를 돈다.
  • np = __of_find_node_by_path(np, path);
    • 앞에 있는 ‘/’를 제외한 full path 노드명으로 노드를 찾아온다.
  • path = strchrnul(path, ‘/’);
    • full path 노드명에서 두 번째 ‘/’ 문자를 찾는다.
  • if (separator && separator < path) break;
    • 두 번째 ‘/’ 문자열의 위치가 separator보다 큰 경우 루프를 탈출하고 리턴한다.
  • 만일 못찾은 경우null을 리턴한다.

 

__of_find_node_path()

drivers/of/base.c

static struct device_node *__of_find_node_by_path(struct device_node *parent,
                                                const char *path)
{
        struct device_node *child;
        int len;

        len = strcspn(path, "/:");
        if (!len)
                return NULL;

        __for_each_child_of_node(parent, child) {
                const char *name = strrchr(child->full_name, '/');
                if (WARN(!name, "malformed device_node %s\n", child->full_name))
                        continue;
                name++;
                if (strncmp(path, name, len) == 0 && (strlen(name) == len))
                        return child;
        }
        return NULL;
}

child 노드의 compact 노드명과 요청 문자열을 비교하여 같은 경우 해당 child 노드를 리턴하고 찾지 못한 경우 null을 리턴한다. 요청 문자열은 ‘/’ 문자로 시작하면 안된다.

  • len = strcspn(path, “/:”);
    • path 문자열에 ‘/’ 또는 ‘:’ 문자가 발견되기 전 까지의 문자열 수를 len에 대입한다.
  • if (!len) return NULL;
    • 문자열의 길이가 0인 경우 null을 리턴한다.
  • __for_each_child_of_node(parent, child) {
    • parent 노드에 있는 child 노드에 대해 루프를 돈다.
  • const char *name = strrchr(child->full_name, ‘/’);
    • 서브 노드 full name에서 가장 뒤에 있는 ‘/’ 문자를 찾는다.
  • name++;
    • ‘/’ 문자를 skip 한다.
  • if (strncmp(path, name, len) == 0 && (strlen(name) == len)) return child;
    • 서브 노드의 compact 노드명과 path 문자열과 비교하여 같은 경우 해당 서브 노드를 리턴한다.

아래 그림은 지정한 부모 노드 바로 한 단계 밑에 위치한 서브 노드들의 compact 노드명을 대상으로 특정 노드명을 찾는 것을 보여준다.

__of_find_node_by_path-1

__for_each_child_of_node()

drivers/of/base.c

#define __for_each_child_of_node(parent, child) \
        for (child = __of_get_next_child(parent, NULL); child != NULL; \
             child = __of_get_next_child(parent, child))

parent 노드의 child 노드만큼 루프를 돈다.

 

아래 그림은 parent 노드 아래 3개의 child 노드가 있고 1번 부터 3번 까지 순서대로 루프를 도는 것을 보여준다.

__for_each_child_of_node-1

 

__of_get_next_child()

drivers/of/base.c

static struct device_node *__of_get_next_child(const struct device_node *node,
                                                struct device_node *prev)
{
        struct device_node *next;

        if (!node)
                return NULL;

        next = prev ? prev->sibling : node->child;
        for (; next; next = next->sibling)
                if (of_node_get(next))
                        break;
        of_node_put(prev);
        return next;
}

node의 child 노드를 찾는다. prev를 null로 하는 경우 첫 child 노드를 찾고 prev에 child 노드인 경우 다음 노드를 찾는다.

 

아래 그림은 __of_get_next_child() 함수를  3번 호출할 때의 상황을 나타내었다. prev값에 따라서 각각에 대응하는 next 노드를 알아오는 것을 보여준다.

__of_get_next_child-1

 

of_node_get()

drivers/of/dynamic.c

/**
 * of_node_get() - Increment refcount of a node
 * @node:       Node to inc refcount, NULL is supported to simplify writing of
 *              callers
 *
 * Returns node.
 */
struct device_node *of_node_get(struct device_node *node)
{
        if (node)
                kobject_get(&node->kobj);
        return node;
}
EXPORT_SYMBOL(of_node_get);
  • 해당 노드에 대한 참조 카운터를 증가시킨다.

 

of_node_put()

drivers/of/dynamic.c

/**
 * of_node_put() - Decrement refcount of a node
 * @node:       Node to dec refcount, NULL is supported to simplify writing of
 *              callers
 */
void of_node_put(struct device_node *node)
{
        if (node)
                kobject_put(&node->kobj);
}
EXPORT_SYMBOL(of_node_put);
  • 해당 노드에 대한 참조 카운터를 감소시킨다

 

for_each_property_of_node()

include/linux/of.h

#define for_each_property_of_node(dn, pp) \
        for (pp = dn->properties; pp != NULL; pp = pp->next)
  • dn 노드에 속한 모든 속성에 대해 루프를 돈다.

다음 그림은 지정된 노드에 포함된 전체 속성에 대한 루프를 도는 것을 보여준다.

for_each_property_of_node-1

 

of_get_property()

drivers/of/base.c

/*
 * 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);

        return pp ? pp->value : NULL;
}
EXPORT_SYMBOL(of_get_property);
  • devtree_lock으로 보호하면서 지정된 노드의 전체 속성들 중 요청 속성명을 찾아 발견되는 경우 해당 속성 길이를 lenp에 저장하고 해당 속성의 value 값을 리턴한다.

 

of_find_property()

drivers/of/base.c

struct property *of_find_property(const struct device_node *np,
                                  const char *name,
                                  int *lenp)
{
        struct property *pp;
        unsigned long flags;

        raw_spin_lock_irqsave(&devtree_lock, flags);
        pp = __of_find_property(np, name, lenp);
        raw_spin_unlock_irqrestore(&devtree_lock, flags);

        return pp;
}
EXPORT_SYMBOL(of_find_property);
  • devtree_lock으로 보호하면서 지정된 노드의 전체 속성들 중 요청 속성명을 찾아 발견되는 경우 속성 길이를 lenp에 저장하고 해당 속성을 리턴한다.

 

__of_find_property()

drivers/of/base.c

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) {
                        if (lenp)
                                *lenp = pp->length;
                        break;
                }
        }

        return pp;
}
  • 지정된 노드의 전체 속성들 중 요청 속성명을 찾아 발견되는 경우 속성 길이를 lenp에 저장하고 해당 속성을 리턴한다.

아래 그림은 지정된 노드에 포함된 속성들에서 속성명으로 검색하는 것을 보여준다.

__of_find_property-1

of_prop_cmp()

include/linux/of.h

#define of_prop_cmp(s1, s2)             strcmp((s1), (s2))

 

of_alias_add()

drivers/of/base.c

static void of_alias_add(struct alias_prop *ap, struct device_node *np,
                         int id, const char *stem, int stem_len)
{
        ap->np = np;
        ap->id = id;
        strncpy(ap->stem, stem, stem_len);
        ap->stem[stem_len] = 0;
        list_add_tail(&ap->link, &aliases_lookup);
        pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n",
                 ap->alias, ap->stem, ap->id, of_node_full_name(np));
}

alias 속성에 np, id, stem을 저장하고 전역 리스트 aliases_lookup에 추가한다.

 

속성 값을 읽어오는 of_property_read_***() 함수들

아래의 함수들은 인수로 요청한 노드에서 인수로 요청한 속성값으로 검색하여 속성 값을 함수명이 의미하는 데이터 사이즈로 읽어온다.

  • of_property_read_string_index()
  • of_property_read_u32_index()
  • of_property_read_bool()
  • of_property_read_u8()
  • of_property_read_u8_array()
  • of_property_read_u16()
  • of_property_read_u16_array()
  • of_property_read_u32()
  • of_property_read_u32_array()
  • of_property_read_s32()
  • of_property_read_u64()
  • of_property_read_u64_array()
  • of_property_read_string()

 

of_property_read_u32()

include/linux/of.h

static inline int of_property_read_u32(const struct device_node *np,
                                       const char *propname,
                                       u32 *out_value)
{               
        return of_property_read_u32_array(np, propname, out_value, 1);
}
  • np 노드에서 요청한 속성명으로 검색하여 해당 속성 값 중 1 개의 32bit unsigned int 값을 읽어 출력 인수 out_value에 저장한다.

 

of_property_read_u32_array()

drivers/of/base.c

/**
 * of_property_read_u32_array - Find and read an array of 32 bit integers
 * from a property.
 *
 * @np:         device node from which the property value is to be read.
 * @propname:   name of the property to be searched.
 * @out_values: pointer to return value, modified only if return value is 0.
 * @sz:         number of array elements to read 
 *
 * Search for a property in a device node and read 32-bit value(s) from
 * it. Returns 0 on success, -EINVAL if the property does not exist,
 * -ENODATA if property does not have a value, and -EOVERFLOW if the
 * property data isn't large enough.
 *
 * The out_values is modified only if a valid u32 value can be decoded.
 */
int of_property_read_u32_array(const struct device_node *np,
                               const char *propname, u32 *out_values,
                               size_t sz) 
{
        const __be32 *val = of_find_property_value_of_size(np, propname,
                                                (sz * sizeof(*out_values)));

        if (IS_ERR(val))
                return PTR_ERR(val);

        while (sz--)
                *out_values++ = be32_to_cpup(val++);
        return 0;
}
EXPORT_SYMBOL_GPL(of_property_read_u32_array);
  • 현재 노드의 요청 속성을 찾아 데이터 갯 수를 초과하는지 체크하여 이상 없는 경우 out_values에 요청한 sz 수 만큼의 32bit unsigned 값을 저장하고 0을 리턴한다. 실패 시 0이 아닌 수가 리턴된다.

 

of_find_property_value_of_size()

drivers/of/base.c

/**
 * of_find_property_value_of_size
 *
 * @np:         device node from which the property value is to be read.
 * @propname:   name of the property to be searched.
 * @len:        requested length of property value
 *
 * Search for a property in a device node and valid the requested size.
 * Returns the property value on success, -EINVAL if the property does not
 *  exist, -ENODATA if property does not have a value, and -EOVERFLOW if the
 * property data isn't large enough.
 *
 */
static void *of_find_property_value_of_size(const struct device_node *np,
                        const char *propname, u32 len)
{
        struct property *prop = of_find_property(np, propname, NULL);

        if (!prop)
                return ERR_PTR(-EINVAL);
        if (!prop->value)
                return ERR_PTR(-ENODATA);
        if (len > prop->length)
                return ERR_PTR(-EOVERFLOW);

        return prop->value;
}
  • 속성 값을 알아오는데 다음과 같은 경우 에러를 리턴한다.
    • 속성을 발견할 수 없을 때
    • 속성 값을 가리키는 값이 null일 때
    • 속성 값 길이보다 요청 길이가 더 클 때
    • 예) 32bit – reg = <0x0, 0x0>의 경우 prop->length=2 이므로 u32 형으로 sz=2 번까지 읽을 수 있다.

 

매치되는 노드들을 검색

of_find_matching_node_and_match()

drivers/of/base.c

/**
 *      of_find_matching_node_and_match - Find a node based on an of_device_id
 *                                        match table.
 *      @from:          The node to start searching from or NULL, the node
 *                      you pass will not be searched, only the next one
 *                      will; typically, you pass what the previous call
 *                      returned. of_node_put() will be called on it
 *      @matches:       array of of device match structures to search in
 *      @match          Updated to point at the matches entry which matched
 *
 *      Returns a node pointer with refcount incremented, use
 *      of_node_put() on it when done.
 */
struct device_node *of_find_matching_node_and_match(struct device_node *from,
                                        const struct of_device_id *matches,
                                        const struct of_device_id **match)
{
        struct device_node *np; 
        const struct of_device_id *m;
        unsigned long flags;

        if (match)
                *match = NULL;

        raw_spin_lock_irqsave(&devtree_lock, flags);
        for_each_of_allnodes_from(from, np) {
                m = __of_match_node(matches, np); 
                if (m && of_node_get(np)) {
                        if (match)
                                *match = m; 
                        break;
                }    
        }    
        of_node_put(from);
        raw_spin_unlock_irqrestore(&devtree_lock, flags);
        return np;
}
EXPORT_SYMBOL(of_find_matching_node_and_match);
  • raw_spin_lock_irqsave(&devtree_lock, flags);
    • devtree_lock spin lock을 사용하여 device tree를 보호하게 한다.
  • for_each_of_allnodes_from(from, np) {
    • 검색을 시작할 노드부터 끝 노드까지 루프를 돈다.
    • 검색 결과에 검색 시작 노드는 제외한다.
  • m = __of_match_node(matches, np);
    • 가장 적합한 디바이스 매치를 찾는다.
  • if (m && of_node_get(np)) { if (match) *match = m; break; }
    • 노드에 대해 참조 카운터를 증가시키고 출력 인수 match가 지정되어 있으면 찾은 of_device_id 구조체 포인터를 저장하고 루프를 빠져나간다.
  • of_node_put(from);
    • 시작 노드에 대해 참조 카운터를 감소시킨다.
  • raw_spin_unlock_irqrestore(&devtree_lock, flags);
    • 걸었던 spin lock을 release한다.

아래 그림은 psci_of_match[]에 등록된 디바이스를 device tree에서 찾아 of_device_id 구조체 포인터를 match에 저장하고 발견된 노드를 리턴하는 모습을 보여준다.

of_find_matching_node_and_match-1

 

__of_match_node()

drivers/of/base.c

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);
                if (score > best_score) {
                        best_match = matches;
                        best_score = score;
                }
        }

        return best_match;
}
  • of_device_id 구조체로된 매치 배열 matches에서 현재 노드 정보로 각각에 대해 score를 평가하고 가장 높은 score를 갖은 of_device_id 구조체 포인터를 리턴한다.

 

__of_device_is_compatible()

drivers/of/base.c

/**
 * __of_device_is_compatible() - Check if the node matches given constraints
 * @device: pointer to node
 * @compat: required compatible string, NULL or "" for any match
 * @type: required device_type value, NULL or "" for any match
 * @name: required node name, NULL or "" for any match
 *
 * Checks if the given @compat, @type and @name strings match the
 * properties of the given @device. A constraints can be skipped by
 * passing NULL or an empty string as the constraint.
 *
 * Returns 0 for no match, and a positive integer on match. The return
 * value is a relative score with larger values indicating better
 * matches. The score is weighted for the most specific compatible value
 * to get the highest score. Matching type is next, followed by matching
 * name. Practically speaking, this results in the following priority
 * order for matches:
 *
 * 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 match has highest priority */
        if (compat && compat[0]) {
                prop = __of_find_property(device, "compatible", NULL);
                for (cp = of_prop_next_string(prop, NULL); cp;
                     cp = of_prop_next_string(prop, cp), index++) {
                        if (of_compat_cmp(cp, compat, strlen(compat)) == 0) {
                                score = INT_MAX/2 - (index << 2);
                                break;
                        }
                }
                if (!score)
                        return 0;
        }

        /* Matching type is better than matching name */
        if (type && type[0]) {
                if (!device->type || of_node_cmp(type, device->type))
                        return 0;
                score += 2;
        }

        /* Matching name is a bit better than not */
        if (name && name[0]) {
                if (!device->name || of_node_cmp(name, device->name))
                        return 0;
                score++;
        }

        return score;
}

요청한 노드에 대해 compatible 평가 점수를 알아온다.

compat 문자열, type 문자열, name 문자열이 주어진 경우 각각에 매치되지 않으면 실패로 간주하여 0을 리턴한다. 그 외에 compat 문자열이 매치되는 경우 가장 점수가 높고 type 문자열을 매치 시키면 2점이 추가되고 노드명이 매치되면 1점이 추가된다.

  • if (compat && compat[0]) {
    • compat 문자열이 주어졌을 때
  • prop = __of_find_property(device, “compatible”, NULL);
    • 지정된 노드에서 “compatible” 속성을 찾는다.
  • for (cp = of_prop_next_string(prop, NULL); cp; cp = of_prop_next_string(prop, cp), index++) {
    • 루프를 돌며 다음 속성을 알아온다.
  • if (of_compat_cmp(cp, compat, strlen(compat)) == 0) { score = INT_MAX/2 – (index << 2); break; }
    • 대소문자 구분 없이 compat 문자열과 속성 값이 같은 경우 score에 INT_MAX/2 – (index x 4)를 한후 루프를 탈출한다.
  • if (!score) return 0;
    • 루프가 끝날 때까지 score가 0인 경우 실패로 간주하여 0을 리턴한다.
  • if (type && type[0]) {
    • 타입이 주어진 경우
  • if (!device->type || of_node_cmp(type, device->type)) return 0;
    • 대소문자 구분 없이 타입이 매치되지 않으면 실패로 간주하여 0을 리턴한다.
  • score += 2;
    • 타입이 매치된 경우 score에 2를 더한다.
  • if (name && name[0]) {
    • 디바이스명이 지정된 경우
  • if (!device->name || of_node_cmp(name, device->name)) return 0;
    • 대소문자 구분없이 노드명이 매치되지 않으면 실패로 간주하여 0을 리턴한다.
  • 노드명이 매치되면 score에 1을 더한다.

 

 

 

전체 노드 검색

for_each_of_allnodes()

include/linux/of.h

#define for_each_of_allnodes(dn) for_each_of_allnodes_from(NULL, dn)
  • 루트 노드부터 끝까지 루프를 돈다.

for_each_of_allnodes-1

 

for_each_of_allnodes_from()

include/linux/of.h

#define for_each_of_allnodes_from(from, dn) \
        for (dn = __of_find_all_nodes(from); dn; dn = __of_find_all_nodes(dn))

 

__of_find_all_nodes()

drivers/of/base.c

struct device_node *__of_find_all_nodes(struct device_node *prev)
{
        struct device_node *np;
        if (!prev) {
                np = of_root;
        } else if (prev->child) {
                np = prev->child;
        } else {
                /* Walk back up looking for a sibling, or the end of the structure */
                np = prev;
                while (np->parent && !np->sibling)
                        np = np->parent;
                np = np->sibling; /* Might be null at the end of the tree */
        }
        return np;
}
  • if (!prev) { np = of_root;
    • 인수로 받은 prev가 null인 경우 루트 노드부터 시작한다.
  • } else if (prev->child) { np = prev->child;
    • 인수로 받은 prev->child가 존재하는 경우 np를 첫 child 노드로 설정한다.
  • } else { np = prev;
    • child 노드가 없는 경우 np를 prev 노드로 설정한다.
  •  while (np->parent && !np->sibling) np = np->parent;
    • 부모 노드가 존재하고 우측 형재 노드가 없는 경우 부모 노드를 설정한다.
  • np = np->sibling;
    • 우측 형재 노드를 선택한다.
    • 만일 트리의 마지막이라면 null이된다.

아래 그림은 prev 값에 따라 리턴되는 노드를 보여준다.

__of_find_all_nodes-1

__of_find_all_nodes-2

__of_find_all_nodes-3

 

구조체

of_device_id 구조체

/*
 * Struct used for matching a device
 */
struct of_device_id { 
        char    name[32];
        char    type[32]; 
        char    compatible[128];
        const void *data;
};
  • name
    • 노드명
  • type
    • 디바이스 타입 문자열
  • compatible
    • compatible 디바이스 문자열
  • data
    • 데이터
      • PSCI에서 사용하는 경우 psci_initcall_t() 함수 포인터 등이 담겨있다.

 

참고

답글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.