static int of_set_property(void *blob, int nodeoffset, char *property_name, void *value, int valuelen) { int property_offset; int ret; /* If find the property name in the dt blob, update its value, * else to add this property */ ret = of_get_property_offset_by_name(blob, nodeoffset, property_name, &property_offset); if (ret) { ret = of_add_property(blob, nodeoffset, property_name, value, valuelen); if (ret) dbg_info("DT: fail to add property\n"); return ret; } ret = of_update_property_value(blob, property_offset, value, valuelen); if (ret) { dbg_info("DT: fail to update property\n"); return ret; } return 0; }
/** * omap_get_timer_dt - get a timer using device-tree * @match - device-tree match structure for matching a device type * @property - optional timer property to match * * Helper function to get a timer during early boot using device-tree for use * as kernel system timer. Optionally, the property argument can be used to * select a timer with a specific property. Once a timer is found then mark * the timer node in device-tree as disabled, to prevent the kernel from * registering this timer as a platform device and so no one else can use it. */ static struct device_node * __init omap_get_timer_dt(struct of_device_id *match, const char *property) { struct device_node *np; for_each_matching_node(np, match) { if (!of_device_is_available(np)) continue; if (property && !of_get_property(np, property, NULL)) continue; of_add_property(np, &device_disabled); return np; } return NULL; }
/* * of_update_property - Update a property in a node, if the property does * not exist, add it. * * Note that we don't actually remove it, since we have given out * who-knows-how-many pointers to the data using get-property. * Instead we just move the property to the "dead properties" list, * and add the new property to the property list */ int of_update_property(struct device_node *np, struct property *newprop) { struct property **next, *oldprop; unsigned long flags; int rc, found = 0; rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop); if (rc) return rc; if (!newprop->name) return -EINVAL; oldprop = of_find_property(np, newprop->name, NULL); if (!oldprop) return of_add_property(np, newprop); raw_spin_lock_irqsave(&devtree_lock, flags); next = &np->properties; while (*next) { if (*next == oldprop) { /* found the node */ newprop->next = oldprop->next; *next = newprop; oldprop->next = np->deadprops; np->deadprops = oldprop; found = 1; break; } next = &(*next)->next; } raw_spin_unlock_irqrestore(&devtree_lock, flags); if (!found) return -ENODEV; #ifdef CONFIG_PROC_DEVICETREE /* try to add to proc as well if it was initialized */ if (np->pde) proc_device_tree_update_prop(np->pde, newprop, oldprop); #endif /* CONFIG_PROC_DEVICETREE */ return 0; }
static int __init update_target_node_from_overlay( struct device_node *target, struct device_node *overlay) { struct property *prop; struct property *tprop; struct property *new_prop; int lenp = 0; int ret; for_each_property_of_node(overlay, prop) { /* Skip those we do not want to proceed */ if (!strcmp(prop->name, "name") || !strcmp(prop->name, "phandle") || !strcmp(prop->name, "linux,phandle")) continue; tprop = of_find_property(target, prop->name, &lenp); if (!tprop) { ret = of_add_property(target, prop); if (ret < 0) { pr_err("Prop %s can not be added on node %s\n", prop->name, target->full_name); return ret; } } else { new_prop = __of_copy_property(prop, GFP_KERNEL); if (!new_prop) { pr_err("Prop %s can not be duplicated\n", prop->name); return -EINVAL; } ret = of_update_property(target, new_prop); if (ret < 0) { pr_err("Prop %s can not be updated on node %s\n", prop->name, target->full_name); return ret; } } } return 0; }
/** * omap_get_timer_dt - get a timer using device-tree * @match - device-tree match structure for matching a device type * @property - optional timer property to match * * Helper function to get a timer during early boot using device-tree for use * as kernel system timer. Optionally, the property argument can be used to * select a timer with a specific property. Once a timer is found then mark * the timer node in device-tree as disabled, to prevent the kernel from * registering this timer as a platform device and so no one else can use it. */ static struct device_node * __init omap_get_timer_dt(const struct of_device_id *match, const char *property) { struct device_node *np; for_each_matching_node(np, match) { if (!of_device_is_available(np)) continue; if (property && !of_get_property(np, property, NULL)) continue; if (!property && (of_get_property(np, "ti,timer-alwon", NULL) || of_get_property(np, "ti,timer-dsp", NULL) || of_get_property(np, "ti,timer-pwm", NULL) || of_get_property(np, "ti,timer-secure", NULL))) continue; of_add_property(np, &device_disabled); return np; } return NULL; }
static void disable_serial_gpio(void) { struct device_node *np_tx, *np_rx, *np_tx_def, *np_rx_def; struct property *pp; static u32 pin_func_val; static struct property pin_func = { .name = "qcom,pin-func", .value = &pin_func_val, .length = sizeof(pin_func_val), }; static struct property output_low = { .name = "output-low", .value = NULL, .length = 0, }; static struct property bias_disable = { .name = "bias-disable", .value = NULL, .length = 0, }; np_tx = of_find_node_by_path( "/soc/pinctrl@fd510000/msm_gpio_4"); if (!np_tx) { pr_err("couldn't find msm_gpio_4 node\n"); return; } np_rx = of_find_node_by_path( "/soc/pinctrl@fd510000/msm_gpio_5"); if (!np_rx) { pr_err("couldn't find msm_gpio_5 node\n"); goto err0; } of_update_property(np_tx, &pin_func); of_update_property(np_rx, &pin_func); np_tx_def = of_find_node_by_name(np_tx, "default"); if (!np_tx_def) { pr_err("couldn't find msm_gpio_4_def node\n"); goto err1; } np_rx_def = of_find_node_by_name(np_rx, "default"); if (!np_rx_def) { pr_err("couldn't find msm_gpio_5_def node\n"); goto err2; } of_add_property(np_tx_def, &output_low); pp = of_find_property(np_rx_def, "bias-pull-up", NULL); if (pp) { of_remove_property(np_rx_def, pp); of_add_property(np_rx_def, &bias_disable); } of_add_property(np_rx_def, &output_low); of_node_put(np_rx_def); err2: of_node_put(np_tx_def); err1: of_node_put(np_rx); err0: of_node_put(np_tx); return; } static int __init init_console_setup(void) { if (need_serial_console) { pr_info("Adding %s%d as preferred console\n", CONSOLE_NAME, CONSOLE_IX); add_preferred_console(CONSOLE_NAME, CONSOLE_IX, CONSOLE_OPTIONS); } else { struct device_node *np; static struct property serial_con_status = { .name = "status", .value = "disabled", .length = sizeof("disabled"), }; np = of_find_node_by_path("/soc/serial@f991e000"); if (!np) { pr_err("couldn't find /soc/serial@f991e000 node\n"); return -EINVAL; } pr_info("disabling %s node", np->full_name); of_update_property(np, &serial_con_status); of_node_put(np); disable_serial_gpio(); } return 0; } early_initcall(init_console_setup);