static int pm8607_regulator_dt_init(struct platform_device *pdev, struct pm8607_regulator_info *info, struct regulator_config *config) { struct device_node *nproot, *np; nproot = pdev->dev.parent->of_node; if (!nproot) return -ENODEV; nproot = of_get_child_by_name(nproot, "regulators"); if (!nproot) { dev_err(&pdev->dev, "failed to find regulators node\n"); return -ENODEV; } for_each_child_of_node(nproot, np) { if (!of_node_cmp(np->name, info->desc.name)) { config->init_data = of_get_regulator_init_data(&pdev->dev, np, &info->desc); config->of_node = np; break; } } of_node_put(nproot); return 0; }
static int pm860x_backlight_dt_init(struct platform_device *pdev, struct pm860x_backlight_data *data, char *name) { struct device_node *nproot, *np; int iset = 0; nproot = of_node_get(pdev->dev.parent->of_node); if (!nproot) return -ENODEV; nproot = of_find_node_by_name(nproot, "backlights"); if (!nproot) { dev_err(&pdev->dev, "failed to find backlights node\n"); return -ENODEV; } for_each_child_of_node(nproot, np) { if (!of_node_cmp(np->name, name)) { of_property_read_u32(np, "marvell,88pm860x-iset", &iset); data->iset = PM8606_WLED_CURRENT(iset); of_property_read_u32(np, "marvell,88pm860x-pwm", &data->pwm); break; } } of_node_put(nproot); return 0; }
/** * add_changeset_node() - add @node (and children) to overlay changeset * @ovcs: overlay changeset * @target_node: where to place @node in live tree * @node: node from within overlay device tree fragment * * If @node does not already exist in @target_node, add changeset entry * to add @node in @target_node. * * If @node already exists in @target_node, and the existing node has * a phandle, the overlay node is not allowed to have a phandle. * * If @node has child nodes, add the children recursively via * build_changeset_next_level(). * * NOTE_1: A live devicetree created from a flattened device tree (FDT) will * not contain the full path in node->full_name. Thus an overlay * created from an FDT also will not contain the full path in * node->full_name. However, a live devicetree created from Open * Firmware may have the full path in node->full_name. * * add_changeset_node() follows the FDT convention and does not include * the full path in node->full_name. Even though it expects the overlay * to not contain the full path, it uses kbasename() to remove the * full path should it exist. It also uses kbasename() in comparisons * to nodes in the live devicetree so that it can apply an overlay to * a live devicetree created from Open Firmware. * * NOTE_2: Multiple mods of created nodes not supported. * If more than one fragment contains a node that does not already exist * in the live tree, then for each fragment of_changeset_attach_node() * will add a changeset entry to add the node. When the changeset is * applied, __of_attach_node() will attach the node twice (once for * each fragment). At this point the device tree will be corrupted. * * TODO: add integrity check to ensure that multiple fragments do not * create the same node. * * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if * invalid @overlay. */ static int add_changeset_node(struct overlay_changeset *ovcs, struct device_node *target_node, struct device_node *node) { const char *node_kbasename; struct device_node *tchild; int ret = 0; node_kbasename = kbasename(node->full_name); for_each_child_of_node(target_node, tchild) if (!of_node_cmp(node_kbasename, kbasename(tchild->full_name))) break; if (!tchild) { tchild = __of_node_dup(node, node_kbasename); if (!tchild) return -ENOMEM; tchild->parent = target_node; ret = of_changeset_attach_node(&ovcs->cset, tchild); if (ret) return ret; return build_changeset_next_level(ovcs, tchild, node); } if (node->phandle && tchild->phandle) ret = -EINVAL; else ret = build_changeset_next_level(ovcs, tchild, node); of_node_put(tchild); return ret; }
static int xdmsc_parse_of(struct xdmsc_dev *xdmsc) { struct device *dev = xdmsc->xvip.dev; struct device_node *node = dev->of_node; struct device_node *ports; struct device_node *port; u32 port_id = 0; int rval; rval = of_property_read_u32(node, "xlnx,max-height", &xdmsc->max_height); if (rval < 0) { dev_err(dev, "missing xlnx,max-height property!"); return -EINVAL; } else if (xdmsc->max_height > XDEMOSAIC_MAX_HEIGHT || xdmsc->max_height < XDEMOSAIC_MIN_HEIGHT) { dev_err(dev, "Invalid height in dt"); return -EINVAL; } rval = of_property_read_u32(node, "xlnx,max-width", &xdmsc->max_width); if (rval < 0) { dev_err(dev, "missing xlnx,max-width property!"); return -EINVAL; } else if (xdmsc->max_width > XDEMOSAIC_MAX_WIDTH || xdmsc->max_width < XDEMOSAIC_MIN_WIDTH) { dev_err(dev, "Invalid width in dt"); return -EINVAL; } ports = of_get_child_by_name(node, "ports"); if (!ports) ports = node; /* Get the format description for each pad */ for_each_child_of_node(ports, port) { if (port->name && (of_node_cmp(port->name, "port") == 0)) { rval = of_property_read_u32(port, "reg", &port_id); if (rval < 0) { dev_err(dev, "No reg in DT"); return rval; } if (port_id != 0 && port_id != 1) { dev_err(dev, "Invalid reg in DT"); return -EINVAL; } } } xdmsc->rst_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(xdmsc->rst_gpio)) { if (PTR_ERR(xdmsc->rst_gpio) != -EPROBE_DEFER) dev_err(dev, "Reset GPIO not setup in DT"); return PTR_ERR(xdmsc->rst_gpio); } return 0; }
static int s2mps13_pmic_dt_parse_pdata(struct sec_pmic_dev *iodev, struct sec_platform_data *pdata) { struct device_node *pmic_np, *regulators_np, *reg_np; struct sec_regulator_data *rdata; unsigned int i; pmic_np = iodev->dev->of_node; if (!pmic_np) { dev_err(iodev->dev, "could not find pmic sub-node\n"); return -ENODEV; } regulators_np = of_find_node_by_name(pmic_np, "regulators"); if (!regulators_np) { dev_err(iodev->dev, "could not find regulators sub-node\n"); return -EINVAL; } /* count the number of regulators to be supported in pmic */ pdata->num_regulators = 0; for_each_child_of_node(regulators_np, reg_np) { pdata->num_regulators++; } rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) * pdata->num_regulators, GFP_KERNEL); if (!rdata) { dev_err(iodev->dev, "could not allocate memory for regulator data\n"); return -ENOMEM; } pdata->regulators = rdata; s2mps13_desc_type = iodev->rev_num ? S2MPS13_DESC_TYPE1 : S2MPS13_DESC_TYPE0; for_each_child_of_node(regulators_np, reg_np) { for (i = 0; i < ARRAY_SIZE(regulators[s2mps13_desc_type]); i++) if (!of_node_cmp(reg_np->name, regulators[s2mps13_desc_type][i].name)) break; if (i == ARRAY_SIZE(regulators[s2mps13_desc_type])) { dev_warn(iodev->dev, "don't know how to configure regulator %s\n", reg_np->name); continue; } rdata->id = i; rdata->initdata = of_get_regulator_init_data( iodev->dev, reg_np); rdata->reg_node = reg_np; rdata++; } return 0; }
/** * of_get_child_by_name - Find the child node by name for a given parent * @node: parent node * @name: child name to look for. * * This function looks for child node for given matching name * * Returns a node pointer if found, with refcount incremented, use * of_node_put() on it when done. * Returns NULL if node is not found. */ struct device_node *of_get_child_by_name(const struct device_node *node, const char *name) { struct device_node *child; for_each_child_of_node(node, child) if (child->name && (of_node_cmp(child->name, name) == 0)) break; return child; }
/* Register all SoC external sub-devices */ static int fimc_md_register_sensor_entities(struct fimc_md *fmd) { struct device_node *parent = fmd->pdev->dev.of_node; struct device_node *node, *ports; int index = 0; int ret; /* * Runtime resume one of the FIMC entities to make sure * the sclk_cam clocks are not globally disabled. */ if (!fmd->pmf) return -ENXIO; ret = pm_runtime_get_sync(fmd->pmf); if (ret < 0) return ret; fmd->num_sensors = 0; /* Attach sensors linked to MIPI CSI-2 receivers */ for_each_available_child_of_node(parent, node) { struct device_node *port; if (of_node_cmp(node->name, "csis")) continue; /* The csis node can have only port subnode. */ port = of_get_next_child(node, NULL); if (!port) continue; ret = fimc_md_parse_port_node(fmd, port, index); if (ret < 0) { of_node_put(node); goto rpm_put; } index++; } /* Attach sensors listed in the parallel-ports node */ ports = of_get_child_by_name(parent, "parallel-ports"); if (!ports) goto rpm_put; for_each_child_of_node(ports, node) { ret = fimc_md_parse_port_node(fmd, node, index); if (ret < 0) { of_node_put(node); break; } index++; }
/** * of_find_node_by_path - Find a node matching a full OF path * @path: The full path to match * * Returns a node pointer with refcount incremented, use * of_node_put() on it when done. */ struct device_node *of_find_node_by_path(const char *path) { struct device_node *np = allnodes; read_lock(&devtree_lock); for (; np; np = np->allnext) { if (np->full_name && (of_node_cmp(np->full_name, path) == 0) && of_node_get(np)) break; } read_unlock(&devtree_lock); return np; }
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; }
struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt( struct platform_device *pdev, struct mc13xxx_regulator *regulators, int num_regulators) { struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev); struct mc13xxx_regulator_init_data *data, *p; struct device_node *parent, *child; int i, parsed = 0; if (!pdev->dev.parent->of_node) return NULL; parent = of_get_child_by_name(pdev->dev.parent->of_node, "regulators"); if (!parent) return NULL; data = devm_kzalloc(&pdev->dev, sizeof(*data) * priv->num_regulators, GFP_KERNEL); if (!data) { of_node_put(parent); return NULL; } p = data; for_each_child_of_node(parent, child) { int found = 0; for (i = 0; i < num_regulators; i++) { if (!regulators[i].desc.name) continue; if (!of_node_cmp(child->name, regulators[i].desc.name)) { p->id = i; p->init_data = of_get_regulator_init_data( &pdev->dev, child, ®ulators[i].desc); p->node = child; p++; parsed++; found = 1; break; } } if (!found) dev_warn(&pdev->dev, "Unknown regulator: %s\n", child->name); }
/** * of_find_node_by_path - Find a node matching a full OF path * @path: The full path to match * * Returns a node pointer with refcount incremented, use * of_node_put() on it when done. */ struct device_node *of_find_node_by_path(const char *path) { struct device_node *np = of_allnodes; unsigned long flags; raw_spin_lock_irqsave(&devtree_lock, flags); for (; np; np = np->allnext) { if (np->full_name && (of_node_cmp(np->full_name, path) == 0) && of_node_get(np)) break; } raw_spin_unlock_irqrestore(&devtree_lock, flags); return np; }
/** * of_find_node_by_type - Find a node by its "device_type" property * @from: The node to start searching from, or NULL to start searching * the entire device tree. 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 from for you. * @type: The type string to match against * * Returns a node pointer with refcount incremented, use * of_node_put() on it when done. */ struct device_node *of_find_node_by_type(struct device_node *from, const char *type) { struct device_node *np; read_lock(&devtree_lock); np = from ? from->allnext : allnodes; for (; np; np = np->allnext) if (np->type && (of_node_cmp(np->type, type) == 0) && of_node_get(np)) break; of_node_put(from); read_unlock(&devtree_lock); return np; }
/** * of_find_node_by_type - Find a node by its "device_type" property * @from: The node to start searching from, or NULL to start searching * the entire device tree. 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 from for you. * @type: The type string to match against * * Returns a node pointer with refcount incremented, use * of_node_put() on it when done. */ struct device_node *of_find_node_by_type(struct device_node *from, const char *type) { struct device_node *np; unsigned long flags; raw_spin_lock_irqsave(&devtree_lock, flags); np = from ? from->allnext : of_allnodes; for (; np; np = np->allnext) if (np->type && (of_node_cmp(np->type, type) == 0) && of_node_get(np)) break; of_node_put(from); raw_spin_unlock_irqrestore(&devtree_lock, flags); return np; }
/** * of_graph_get_port_by_id() - get the port matching a given id * @parent: pointer to the parent device node * @id: id of the port * * Return: A 'port' node pointer with refcount incremented. The caller * has to use of_node_put() on it when done. */ struct device_node *of_graph_get_port_by_id(struct device_node *parent, u32 id) { struct device_node *node, *port; node = of_get_child_by_name(parent, "ports"); if (node) parent = node; for_each_child_of_node(parent, port) { u32 port_id = 0; if (of_node_cmp(port->name, "port") != 0) continue; of_property_read_u32(port, "reg", &port_id); if (id == port_id) break; }
/* of_* functions will be removed after merge of of_graph patches */ static struct device_node * of_get_child_by_name_reg(struct device_node *parent, const char *name, u32 reg) { struct device_node *np; for_each_child_of_node(parent, np) { u32 r; if (!np->name || of_node_cmp(np->name, name)) continue; if (of_property_read_u32(np, "reg", &r) < 0) r = 0; if (reg == r) break; }
/** * Find a node with the give full name by recursively following any of * the child node links. */ static struct device_node *__of_find_node_by_full_name(struct device_node *node, const char *full_name) { struct device_node *child, *found; if (node == NULL) return NULL; /* check */ if (of_node_cmp(node->full_name, full_name) == 0) return node; for_each_child_of_node(node, child) { found = __of_find_node_by_full_name(child, full_name); if (found != NULL) return found; }
/** * of_find_compatible_node - Find a node based on type and one of the * tokens in its "compatible" property * @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 * @type: The type string to match "device_type" or NULL to ignore * @compatible: The string to match to one of the tokens in the device * "compatible" list. * * Returns a node pointer with refcount incremented, use * of_node_put() on it when done. */ struct device_node *of_find_compatible_node(struct device_node *from, const char *type, const char *compatible) { struct device_node *np; read_lock(&devtree_lock); np = from ? from->allnext : allnodes; for (; np; np = np->allnext) { if (type && !(np->type && (of_node_cmp(np->type, type) == 0))) continue; if (of_device_is_compatible(np, compatible) && of_node_get(np)) break; } of_node_put(from); read_unlock(&devtree_lock); return np; }
struct device_node * omapdss_of_get_next_endpoint(const struct device_node *parent, struct device_node *prev) { struct device_node *ep = NULL; if (!parent) return NULL; do { ep = of_get_next_child(parent, prev); if (!ep) return NULL; prev = ep; } while (of_node_cmp(ep->name, "endpoint") != 0); return ep; }
/** * Find a node with the give full name by recursively following any of * the child node links. */ static struct device_node *find_node_by_full_name(struct device_node *node, const char *full_name) { struct device_node *child, *found; if (!node) return NULL; if (!of_node_cmp(node->full_name, full_name)) return of_node_get(node); for_each_child_of_node(node, child) { found = find_node_by_full_name(child, full_name); if (found != NULL) { of_node_put(child); return found; } }
struct device_node * omapdss_of_get_next_port(const struct device_node *parent, struct device_node *prev) { struct device_node *port = NULL; if (!parent) return NULL; if (!prev) { struct device_node *ports; /* * It's the first call, we have to find a port subnode * within this node or within an optional 'ports' node. */ ports = of_get_child_by_name(parent, "ports"); if (ports) parent = ports; port = of_get_child_by_name(parent, "port"); /* release the 'ports' node */ of_node_put(ports); } else { struct device_node *ports; ports = of_get_parent(prev); if (!ports) return NULL; do { port = of_get_next_child(ports, prev); if (!port) { of_node_put(ports); return NULL; } prev = port; } while (of_node_cmp(port->name, "port") != 0); of_node_put(ports); } return port; }
static int compare_of(struct device *dev, void *data) { struct device_node *np = data; /* Special case for DI, dev->of_node may not be set yet */ if (strcmp(dev->driver->name, "imx-ipuv3-crtc") == 0) { struct ipu_client_platformdata *pdata = dev->platform_data; return pdata->of_node == np; } /* Special case for LDB, one device for two channels */ if (of_node_cmp(np->name, "lvds-channel") == 0) { np = of_get_parent(np); of_node_put(np); } return dev->of_node == np; }
/** * of_find_compatible_node - Find a node based on type and one of the * tokens in its "compatible" property * @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 * @type: The type string to match "device_type" or NULL to ignore * @compatible: The string to match to one of the tokens in the device * "compatible" list. * * Returns a node pointer with refcount incremented, use * of_node_put() on it when done. */ struct device_node *of_find_compatible_node(struct device_node *from, const char *type, const char *compatible) { struct device_node *np; unsigned long flags; raw_spin_lock_irqsave(&devtree_lock, flags); np = from ? from->allnext : of_allnodes; for (; np; np = np->allnext) { if (type && !(np->type && (of_node_cmp(np->type, type) == 0))) continue; if (__of_device_is_compatible(np, compatible) && of_node_get(np)) break; } of_node_put(from); raw_spin_unlock_irqrestore(&devtree_lock, flags); return np; }
/** * device_get_named_child_node - Return first matching named child node handle * @dev: Device to find the named child node for. * @childname: String to match child node name against. */ struct fwnode_handle *device_get_named_child_node(struct device *dev, const char *childname) { struct fwnode_handle *child; /* * Find first matching named child node of this device. * For ACPI this will be a data only sub-node. */ device_for_each_child_node(dev, child) { if (is_of_node(child)) { if (!of_node_cmp(to_of_node(child)->name, childname)) return child; } else if (is_acpi_data_node(child)) { if (acpi_data_node_match(child, childname)) return child; } } return NULL; }
static struct device_node *ipu_drm_get_port_by_id(struct device_node *parent, int port_id) { struct device_node *port; int id, ret; port = of_get_child_by_name(parent, "port"); while (port) { ret = of_property_read_u32(port, "reg", &id); if (!ret && id == port_id) return port; do { port = of_get_next_child(parent, port); if (!port) return NULL; } while (of_node_cmp(port->name, "port")); } return NULL; }
/** * v4l2_of_get_next_endpoint() - get next endpoint node * @parent: pointer to the parent device node * @prev: previous endpoint node, or NULL to get first * * Return: An 'endpoint' node pointer with refcount incremented. Refcount * of the passed @prev node is not decremented, the caller have to use * of_node_put() on it when done. */ struct device_node *v4l2_of_get_next_endpoint(const struct device_node *parent, struct device_node *prev) { struct device_node *endpoint; struct device_node *port = NULL; if (!parent) return NULL; if (!prev) { struct device_node *node; /* * It's the first call, we have to find a port subnode * within this node or within an optional 'ports' node. */ node = of_get_child_by_name(parent, "ports"); if (node) parent = node; for_each_child_of_node(parent, node) { if (!of_node_cmp(node->name, "port")) { port = node; break; } } if (port) { /* Found a port, get an endpoint. */ endpoint = of_get_next_child(port, NULL); of_node_put(port); } else { endpoint = NULL; } if (!endpoint) pr_err("%s(): no endpoint nodes specified for %s\n", __func__, parent->full_name); } else {
struct mc13xxx_regulator_init_data * __devinit mc13xxx_parse_regulators_dt( struct platform_device *pdev, struct mc13xxx_regulator *regulators, int num_regulators) { struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev); struct mc13xxx_regulator_init_data *data, *p; struct device_node *parent, *child; int i; of_node_get(pdev->dev.parent->of_node); parent = of_find_node_by_name(pdev->dev.parent->of_node, "regulators"); if (!parent) return NULL; data = devm_kzalloc(&pdev->dev, sizeof(*data) * priv->num_regulators, GFP_KERNEL); if (!data) return NULL; p = data; for_each_child_of_node(parent, child) { for (i = 0; i < num_regulators; i++) { if (!of_node_cmp(child->name, regulators[i].desc.name)) { p->id = i; p->init_data = of_get_regulator_init_data( &pdev->dev, child); p->node = child; p++; break; } } } return data; }
/* Register all SoC external sub-devices */ static int fimc_md_of_sensors_register(struct fimc_md *fmd, struct device_node *np) { struct device_node *parent = fmd->pdev->dev.of_node; struct device_node *node, *ports; int index = 0; int ret; /* Attach sensors linked to MIPI CSI-2 receivers */ for_each_available_child_of_node(parent, node) { struct device_node *port; if (of_node_cmp(node->name, "csis")) continue; /* The csis node can have only port subnode. */ port = of_get_next_child(node, NULL); if (!port) continue; ret = fimc_md_parse_port_node(fmd, port, index); if (ret < 0) return ret; index++; } /* Attach sensors listed in the parallel-ports node */ ports = of_get_child_by_name(parent, "parallel-ports"); if (!ports) return 0; for_each_child_of_node(ports, node) { ret = fimc_md_parse_port_node(fmd, node, index); if (ret < 0) break; index++; }
static int s2mps13_pmic_dt_parse_pdata(struct sec_pmic_dev *iodev, struct sec_platform_data *pdata) { struct device_node *pmic_np, *regulators_np, *reg_np; struct sec_regulator_data *rdata; unsigned int i, s2mps13_desc_type; int ret; u32 val; pmic_np = iodev->dev->of_node; if (!pmic_np) { dev_err(iodev->dev, "could not find pmic sub-node\n"); return -ENODEV; } /* If pmic revision number over 0x02, get 3 gpio values */ if (SEC_PMIC_REV(iodev) > 0x02) { if (of_gpio_count(pmic_np) < 3) { dev_err(iodev->dev, "could not find pmic gpios\n"); return -EINVAL; } pdata->smpl_warn = of_get_gpio(pmic_np, 0); pdata->g3d_pin = of_get_gpio(pmic_np, 1); pdata->dvs_pin = of_get_gpio(pmic_np, 2); ret = of_property_read_u32(pmic_np, "g3d_en", &val); if (ret) return -EINVAL; pdata->g3d_en = !!val; ret = of_property_read_u32(pmic_np, "dvs_en", &val); if (ret) return -EINVAL; pdata->dvs_en = !!val; ret = of_property_read_u32(pmic_np, "smpl_warn_en", &val); if (ret) return -EINVAL; pdata->smpl_warn_en = !!val; } else { dev_err(iodev->dev, "cannot control g3d_en & dvs_en\n"); } pdata->ap_buck_avp_en = false; pdata->sub_buck_avp_en = false; if (of_find_property(pmic_np, "ap-buck-avp-en", NULL)) pdata->ap_buck_avp_en = true; if (of_find_property(pmic_np, "sub-buck-avp-en", NULL)) pdata->sub_buck_avp_en = true; regulators_np = of_find_node_by_name(pmic_np, "regulators"); if (!regulators_np) { dev_err(iodev->dev, "could not find regulators sub-node\n"); return -EINVAL; } /* count the number of regulators to be supported in pmic */ pdata->num_regulators = 0; for_each_child_of_node(regulators_np, reg_np) { pdata->num_regulators++; } rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) * pdata->num_regulators, GFP_KERNEL); if (!rdata) { dev_err(iodev->dev, "could not allocate memory for regulator data\n"); return -ENOMEM; } pdata->regulators = rdata; s2mps13_desc_type = SEC_PMIC_REV(iodev) ? S2MPS13_DESC_TYPE1 : S2MPS13_DESC_TYPE0; for_each_child_of_node(regulators_np, reg_np) { for (i = 0; i < ARRAY_SIZE(regulators[s2mps13_desc_type]); i++) if (!of_node_cmp(reg_np->name, regulators[s2mps13_desc_type][i].name)) break; if (i == ARRAY_SIZE(regulators[s2mps13_desc_type])) { dev_warn(iodev->dev, "don't know how to configure regulator %s\n", reg_np->name); continue; } rdata->id = i; rdata->initdata = of_get_regulator_init_data( iodev->dev, reg_np); rdata->reg_node = reg_np; rdata++; } return 0; }
/*! 20140104 * cpus device node 자식의 cpu device node의 reg property 값을 가지고 * dtb 유효성 검사 후 __cpu_logical_map 초기화 */ void __init arm_dt_init_cpu_maps(void) { /* * Temp logical map is initialized with UINT_MAX values that are * considered invalid logical map entries since the logical map must * contain a list of MPIDR[23:0] values where MPIDR[31:24] must * read as 0. */ struct device_node *cpu, *cpus; u32 i, j, cpuidx = 1; /*! 20140104 mpidr[23:0] 값 추출 / MPIDR_HWID_BITMASK 0xFFFFFF */ u32 mpidr = is_smp() ? read_cpuid_mpidr() & MPIDR_HWID_BITMASK : 0; /*! 20140104 * 0 ~ NR_CPUS(4)-1 까지의 Index에 MPIDR_INVALID(0xFF000000) 을 삽입 * - gcc manual - * To initialize a range of elements to the same value, * write '[FIRST ...LAST] = VALUE'. This is a GNU extension. For example, * ex) int widths[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 }; */ u32 tmp_map[NR_CPUS] = { [0 ... NR_CPUS-1] = MPIDR_INVALID }; bool bootcpu_valid = false; /*! 20140104 cpus device node를 찾음 */ cpus = of_find_node_by_path("/cpus"); if (!cpus) return; /*! 20140104 * cpus { #address-cells = <0x1>; #size-cells = <0x0>; cpu@0 { device_type = "cpu"; compatible = "arm,cortex-a15"; reg = <0x0>; clock-frequency = <0x6b49d200>; }; cpu@1 { device_type = "cpu"; compatible = "arm,cortex-a15"; reg = <0x1>; clock-frequency = <0x6b49d200>; }; ...생략 }; */ /*! 20140104 * parent = cpus / child = cpu (child 는 각 cpus device node의 cpu device node를 나타냄) * of_get_next_child는 parent의 자식에 대한 device node 또는 자식의 sibling들을 반환 * - for_each_child_of_node - * for (child = of_get_next_child(parent, NULL); child != NULL; * child = of_get_next_child(parent, child)) */ for_each_child_of_node(cpus, cpu) { u32 hwid; /*! 20140104 cpu device node의 type이 'cpu'인지 확인 */ if (of_node_cmp(cpu->type, "cpu")) continue; pr_debug(" * %s...\n", cpu->full_name); /* * A device tree containing CPU nodes with missing "reg" * properties is considered invalid to build the * cpu_logical_map. */ /*! 20140104 cpu device node의 reg property의 값을 hwid에 할당 */ if (of_property_read_u32(cpu, "reg", &hwid)) { pr_debug(" * %s missing reg property\n", cpu->full_name); return; } /* * 8 MSBs must be set to 0 in the DT since the reg property * defines the MPIDR[23:0]. */ /*! 20140104 * hwid & ~MPIDR_HWID_BITMASK(0xFF000000) * 상위 8bit가 설정되어 있으면 return */ if (hwid & ~MPIDR_HWID_BITMASK) return; /* * Duplicate MPIDRs are a recipe for disaster. * Scan all initialized entries and check for * duplicates. If any is found just bail out. * temp values were initialized to UINT_MAX * to avoid matching valid MPIDR[23:0] values. */ /*! 20140104 동일한 reg 값이 존재하면 중복됫다고 하고 return */ for (j = 0; j < cpuidx; j++) if (WARN(tmp_map[j] == hwid, "Duplicate /cpu reg " "properties in the DT\n")) return; /* * Build a stashed array of MPIDR values. Numbering scheme * requires that if detected the boot CPU must be assigned * logical id 0. Other CPUs get sequential indexes starting * from 1. If a CPU node with a reg property matching the * boot CPU MPIDR is detected, this is recorded so that the * logical map built from DT is validated and can be used * to override the map created in smp_setup_processor_id(). */ /*! 20140104 hwid == mpidr 과 같으면 booting cpu 보통 첫번째 cpu, i = cpuidx */ if (hwid == mpidr) { i = 0; bootcpu_valid = true; } else { i = cpuidx++; } /*! 20140104 Kernel config 값인 nr_cpu_ids 값보다 cpuidx가 크면 nr_cpu_ids 이상의 cpu값들은 무시됨 */ if (WARN(cpuidx > nr_cpu_ids, "DT /cpu %u nodes greater than " "max cores %u, capping them\n", cpuidx, nr_cpu_ids)) { cpuidx = nr_cpu_ids; break; } tmp_map[i] = hwid; }
static int max17135_pmic_dt_parse_pdata(struct platform_device *pdev, struct max17135_platform_data *pdata) { struct max17135 *max17135 = dev_get_drvdata(pdev->dev.parent); struct device_node *pmic_np, *regulators_np, *reg_np; struct max17135_regulator_data *rdata; int i, ret; pmic_np = of_node_get(max17135->dev->of_node); if (!pmic_np) { dev_err(&pdev->dev, "could not find pmic sub-node\n"); return -ENODEV; } regulators_np = of_find_node_by_name(pmic_np, "regulators"); if (!regulators_np) { dev_err(&pdev->dev, "could not find regulators sub-node\n"); return -EINVAL; } pdata->num_regulators = of_get_child_count(regulators_np); dev_dbg(&pdev->dev, "num_regulators %d\n", pdata->num_regulators); rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) * pdata->num_regulators, GFP_KERNEL); if (!rdata) { of_node_put(regulators_np); dev_err(&pdev->dev, "could not allocate memory for" "regulator data\n"); return -ENOMEM; } pdata->regulators = rdata; for_each_child_of_node(regulators_np, reg_np) { for (i = 0; i < ARRAY_SIZE(max17135_reg); i++) if (!of_node_cmp(reg_np->name, max17135_reg[i].name)) break; if (i == ARRAY_SIZE(max17135_reg)) { dev_warn(&pdev->dev, "don't know how to configure" "regulator %s\n", reg_np->name); continue; } rdata->id = i; rdata->initdata = of_get_regulator_init_data(&pdev->dev, reg_np, &max17135_reg[i]); rdata->reg_node = reg_np; rdata++; } of_node_put(regulators_np); CHECK_PROPERTY_ERROR_KFREE(vneg_pwrup); CHECK_PROPERTY_ERROR_KFREE(gvee_pwrup); CHECK_PROPERTY_ERROR_KFREE(vpos_pwrup); CHECK_PROPERTY_ERROR_KFREE(gvdd_pwrup); CHECK_PROPERTY_ERROR_KFREE(gvdd_pwrdn); CHECK_PROPERTY_ERROR_KFREE(vpos_pwrdn); CHECK_PROPERTY_ERROR_KFREE(gvee_pwrdn); CHECK_PROPERTY_ERROR_KFREE(vneg_pwrdn); dev_dbg(&pdev->dev, "vneg_pwrup %d, vneg_pwrdn %d, vpos_pwrup %d," "vpos_pwrdn %d, gvdd_pwrup %d, gvdd_pwrdn %d, gvee_pwrup %d," "gvee_pwrdn %d\n", max17135->vneg_pwrup, max17135->vneg_pwrdn, max17135->vpos_pwrup, max17135->vpos_pwrdn, max17135->gvdd_pwrup, max17135->gvdd_pwrdn, max17135->gvee_pwrup, max17135->gvee_pwrdn); max17135->max_wait = max17135->vpos_pwrup + max17135->vneg_pwrup + max17135->gvdd_pwrup + max17135->gvee_pwrup; max17135->gpio_pmic_wakeup = of_get_named_gpio(pmic_np, "gpio_pmic_wakeup", 0); if (!gpio_is_valid(max17135->gpio_pmic_wakeup)) { dev_err(&pdev->dev, "no epdc pmic wakeup pin available\n"); goto err; } ret = devm_gpio_request_one(&pdev->dev, max17135->gpio_pmic_wakeup, GPIOF_OUT_INIT_LOW, "epdc-pmic-wake"); if (ret < 0) goto err; max17135->gpio_pmic_vcom_ctrl = of_get_named_gpio(pmic_np, "gpio_pmic_vcom_ctrl", 0); if (!gpio_is_valid(max17135->gpio_pmic_vcom_ctrl)) { dev_err(&pdev->dev, "no epdc pmic vcom_ctrl pin available\n"); goto err; } ret = devm_gpio_request_one(&pdev->dev, max17135->gpio_pmic_vcom_ctrl, GPIOF_OUT_INIT_LOW, "epdc-vcom"); if (ret < 0) goto err; max17135->gpio_pmic_v3p3 = of_get_named_gpio(pmic_np, "gpio_pmic_v3p3", 0); if (!gpio_is_valid(max17135->gpio_pmic_v3p3)) { dev_err(&pdev->dev, "no epdc pmic v3p3 pin available\n"); goto err; } ret = devm_gpio_request_one(&pdev->dev, max17135->gpio_pmic_v3p3, GPIOF_OUT_INIT_LOW, "epdc-v3p3"); if (ret < 0) goto err; max17135->gpio_pmic_intr = of_get_named_gpio(pmic_np, "gpio_pmic_intr", 0); if (!gpio_is_valid(max17135->gpio_pmic_intr)) { dev_err(&pdev->dev, "no epdc pmic intr pin available\n"); goto err; } ret = devm_gpio_request_one(&pdev->dev, max17135->gpio_pmic_intr, GPIOF_IN, "epdc-pmic-int"); if (ret < 0) goto err; max17135->gpio_pmic_pwrgood = of_get_named_gpio(pmic_np, "gpio_pmic_pwrgood", 0); if (!gpio_is_valid(max17135->gpio_pmic_pwrgood)) { dev_err(&pdev->dev, "no epdc pmic pwrgood pin available\n"); goto err; } ret = devm_gpio_request_one(&pdev->dev, max17135->gpio_pmic_pwrgood, GPIOF_IN, "epdc-pwrstat"); if (ret < 0) goto err; err: return 0; }