Data Structure
struct software_node {
const char *name;
const struct software_node *parent;
const struct property_entry *properties;
};
struct swnode {
struct kobject kobj;
struct fwnode_handle fwnode;
const struct software_node *node;
int id;
/* hierarchy */
struct ida child_ids;
struct list_head entry;
struct list_head children;
struct swnode *parent;
unsigned int allocated:1;
unsigned int managed:1;
};
Provider
software_node_register()注册单个 software node, software_node_register_node_group()注册一组 software nodes. 都是将 software nodes 挂入一个全局链表.
// 定义属性
static const struct property_entry my_device_properties[] = {
PROPERTY_ENTRY_U32("reg", 0),
PROPERTY_ENTRY_U32("my_property", 1234),
{ }
};
// 定义 software node
static const struct software_node my_device_node = {
.name = "my-device",
.properties = my_device_properties,
};
// 定义 software node 组
static const struct software_node *my_device_node_group[] = {
&my_device_node,
NULL
};
// 注册 software node 组
software_node_register_node_group(my_device_node_group);
device_add_software_node() 这个 api 可以设置 dev->fwnode = &swnode->fwnode. 这样后续 consumer 可以通过 dev_fwnode()获取到 fwnode_handle.
int device_add_software_node(struct device *dev, const struct software_node *node);
int device_create_managed_software_node(struct rts_device *dev,
const struct property_entry *properties,
const struct software_node *parent);
Consumer
方法 1
通过 software_node_register_node_group 注册的 software nodes 需要传入 software node 到 software_node_fwnode()来获取 fwnode_handle, 才能使用 fwnode_xxx api.
struct fwnode_handle *fwnode;
static const struct software_node max17047_node = {
.name = "max17047",
.properties = max17047_properties,
};
fwnode = software_node_fwnode(&max17047_node);
也可以通过 name 来查找 software_node, 再通过 software_node_fwnode 获取 fwnode:
struct fwnode_handle *fwnode;
struct software_node *swnode;
swnode = software_node_find_by_name(NULL, "intel-xhci-usb-sw");
fwnode = software_node_fwnode(swnode);
方法 2
通过 device_add_software_node()和 device_create_managed_software_node()创建的 software node, 会设置 dev->fwnode, 将 device 和 fwnode_handle 联系起来.
这样直接通过 dev->fwnode 利用 fwnode_xxx api 就可以调用到底层 software_node 的回调函数.
通过 device_for_each_child_node 遍历 device 的 children node, 再通过 fwnode_property_read_u32 读取属性.
struct fwnode_handle *child;
device_for_each_child_node(dev, child) {
if (fwnode_property_read_u32(child, "reg", &ch->reg)) {
dev_err(dev, "channel without reg\n");
fwnode_handle_put(child);
return ERR_PTR(-EINVAL);
}
}
通过 dev_fwnode 获取 fwnode, 再通过 fwnode_property_read_u32 读取属性.
struct fwnode_handle *fwnode;
fwnode = dev_fwnode(dev);
fwnode_property_read_u32(fwnode, "reg", ®);
fwnode_property_read_u32(fwnode, "my_property", &my_property);