diff -drupN a/scripts/dtc/updatetree.c b/scripts/dtc/updatetree.c --- a/scripts/dtc/updatetree.c 1970-01-01 03:00:00.000000000 +0300 +++ b/scripts/dtc/updatetree.c 2022-06-12 05:28:14.000000000 +0300 @@ -0,0 +1,743 @@ +#include "updatetree.h" + +extern struct script *script; + +/*public functions */ +int of_prop_string_count(const char *prop_val, int prop_len) +{ + int l = 0, i = 0; + const char *p, *end; + + p = prop_val; + end = p + prop_len; + + for (i = 0; p < end; i++, p += l) { + l = strnlen(p, end - p) + 1; + if (p + l > end) + return -1; + } + + return i <= 0 ? -1 : i; +} + +const char *of_prop_next_string(struct property *prop, const char *cur) +{ + const char *curv = cur; + + if (!prop) + return NULL; + + if (!cur) + return prop->val.val; + + curv += strlen(cur) + 1; + if (curv >= prop->val.val + prop->val.len) + return NULL; + + return curv; +} + +int sunxi_get_propval(struct node *node, const char *name) +{ + unsigned int value; + struct property *prop; + cell_t *info = NULL; + + prop = get_property(node, name); + if (prop) { + info = (cell_t *)prop->val.val; + value = fdt32_to_cpu(*info++); + return value; + } + + return -1; +} + +int sunxi_gpio_to_name(int port, int port_num, char *name) +{ + int index; + + if (!name) + return -1; + + if ((port*32+port_num) >= 1024) { + /* axp gpio name like this : GPIO0/GPIO1/.. */ + index = (port-1)*32+port_num - 1024; + sprintf(name, "GPIO%d", index); + } else { + /* sunxi gpio name like this : PA0/PA1/PB0 */ + sprintf(name, "P%c%d", ('A' + (port-1)), port_num); + } + + return 0; +} + +/*these functions mainly to process pin subkey*/ +#define PL_BASE (352) +#define AXP_BASE (1024) + +void sunxi_dt_update_gpio_group(struct dt_info *dti, + struct node *node, + struct script_entry *ep, + struct script_gpio_entry *entry) +{ + char *pinctrl_name = NULL, *string; + int val32, gpio_index, temp_val, phandle; + char *axp_pin_name[] = {"axp_pio", "axp_gpio0", "axp_gpio1"}; + bool axp_pin = false; + int i; + + struct data d; + struct property *prop; + struct node *pinctrl_node; + + prop = get_property(node, ep->name); + if (prop) + delete_property(prop); + + gpio_index = (entry->port - 1) * 32 + entry->port_num; + if (gpio_index < PL_BASE) + pinctrl_name = "pio"; + else if (gpio_index < AXP_BASE && gpio_index >= PL_BASE) + pinctrl_name = "r_pio"; + else + axp_pin = true; + + if (axp_pin) { + for (i = 0; i < 3; i++) { + pinctrl_name = axp_pin_name[i]; + pinctrl_node = sunxi_get_node(dti->dt, pinctrl_name); + if (pinctrl_node) + break; + } + } else { + pinctrl_node = sunxi_get_node(dti->dt, pinctrl_name); + } + + if (!pinctrl_node) { + printf("warning:can't find gpio node %s\n", pinctrl_name); + return; + } + + string = malloc(7 * sizeof(unsigned int)); + /*set gpio control */ + phandle = get_node_phandle(dti->dt, pinctrl_node); + val32 = cpu_to_fdt32(phandle); + memcpy(string, (char *)&val32, sizeof(val32)); + + /*set gpio bank */ + val32 = cpu_to_fdt32(entry->port-1); + memcpy(string + 1 * sizeof(val32), (char *)&val32, sizeof(val32)); + + /*set gpio bank index */ + val32 = cpu_to_fdt32(entry->port_num); + memcpy(string + 2 * sizeof(val32), (char *)&val32, sizeof(val32)); + + /*set gpio mul */ + val32 = cpu_to_fdt32(entry->data[0]); + memcpy(string + 3 * sizeof(val32), (char *)&val32, sizeof(val32)); + + /*set gpio pull */ + temp_val = entry->data[1] < 0 ? 0xFFFFFFFF : entry->data[1]; + val32 = cpu_to_fdt32(temp_val); + memcpy(string + 4 * sizeof(val32), (char *)&val32, sizeof(val32)); + + /*set gpio drive */ + temp_val = entry->data[2] < 0 ? 0xFFFFFFFF : entry->data[2]; + val32 = cpu_to_fdt32(temp_val); + memcpy(string + 5 * sizeof(val32), (char *)&val32, sizeof(val32)); + + /*set gpio data */ + temp_val = entry->data[3] < 0 ? 0xFFFFFFFF : entry->data[3]; + val32 = cpu_to_fdt32(temp_val); + memcpy(string + 6 * sizeof(val32), (char *)&val32, sizeof(val32)); + + d = data_copy_mem(string, 7 * sizeof(unsigned int)); + prop = build_property(ep->name, d); + add_property(node, prop); + free(string); +} + +int sunxi_dt_init_pinconf_prop(struct script_section *section, + struct dt_info *dti, + struct node *node, + int sleep_state) +{ + int i, len, phandle; + cell_t *cp = NULL; + + struct list_entry *o; + struct script_entry *ep; + struct script_gpio_entry *entry; + + struct data d0; + struct node *p_node = NULL; + struct property *prop; + struct property *pinctrl; + + /*remove pin config */ + for_each_entry_in_section(section->entries, o) { + ep = container_of(o, struct script_entry, entries); + entry = container_of(ep, struct script_gpio_entry, entry); + + if (entry->data[0] == 2 || entry->data[0] == 3 || + entry->data[0] == 4 || entry->data[0] == 5 || + entry->data[0] == 7) { + if (!sleep_state) + prop = get_property(node, "pinctrl-0"); + else + prop = get_property(node, "pinctrl-1"); + + if (prop) { + len = prop->val.len/sizeof(unsigned int); + cp = (cell_t *)prop->val.val; + for (i = 0; i < len; i++) { + phandle = fdt32_to_cpu(*cp++); + p_node = get_node_by_phandle(dti->dt, phandle); + delete_node(p_node); + } + delete_property(prop); + } + + /* build pinctrl-0 property */ + d0 = data_copy_mem(NULL, 0); + if (!sleep_state) + pinctrl = build_property("pinctrl-0", d0); + else + pinctrl = build_property("pinctrl-1", d0); + add_property(node, pinctrl); + + break; + } + } + + return 0; + +} + +cell_t sunxi_dt_add_new_node_to_pinctrl(struct node *pinctrl_node, + const char *dev_name, + const char *pname, + char *gpio_name, + int gpio_value[], + struct dt_info *dti) +{ + cell_t phandle; + int i, value_32, len, str_len; + char *label, node_name[32]; + struct data d; + struct node *child, *temp_node; + struct property *prop; + child = build_node(NULL, NULL); + + /* set label */ + str_len = strlen(dev_name)+strlen("_pins_")+2; + label = malloc(str_len); + strcpy(label, dev_name); + strcat(label, "_pins_"); + + for (i = 0; i < 8; i++) { + label[str_len-2] = (char)(i+'a'); + label[str_len-1] = '\0'; + temp_node = sunxi_get_node(dti->dt, label); + if (temp_node) + continue; + else + break; + } + add_label(&child->labels, label); + + /*set node name*/ + str_len = strlen(dev_name)+2; + strcpy(node_name, dev_name); + strcat(node_name, "@"); + for (i = 0; i < 8; i++) { + node_name[str_len-1] = (char)(i+'0'); + node_name[str_len] = '\0'; + temp_node = get_subnode(pinctrl_node, node_name); + if (temp_node) + continue; + else + break; + } + + /* set node name and phandle*/ + child->name = xstrdup(node_name); + + /* set fullpath */ + child->fullpath = join_path(pinctrl_node->fullpath, child->name); + + /*set phandle*/ + phandle = get_node_phandle(dti->dt, child); + add_child(pinctrl_node, child); + + /*add property of pins */ + d = data_copy_mem(gpio_name, strlen(gpio_name) + 1); + prop = build_property("allwinner,pins", d); + add_property(child, prop); + + d = data_copy_mem(dev_name, strlen(dev_name) + 1); + prop = build_property("allwinner,function", d); + add_property(child, prop); + + d = data_copy_mem(pname, strlen(pname) + 1); + prop = build_property("allwinner,pname", d); + add_property(child, prop); + + value_32 = cpu_to_fdt32(gpio_value[0]); + len = sizeof(unsigned int); + d = data_copy_mem((char *)&value_32, len); + prop = build_property("allwinner,muxsel", d); + add_property(child, prop); + + value_32 = cpu_to_fdt32(gpio_value[1]); + len = sizeof(unsigned int); + d = data_copy_mem((char *)&value_32, len); + prop = build_property("allwinner,pull", d); + add_property(child, prop); + + value_32 = cpu_to_fdt32(gpio_value[2]); + len = sizeof(unsigned int); + d = data_copy_mem((char *)&value_32, len); + prop = build_property("allwinner,drive", d); + add_property(child, prop); + + value_32 = cpu_to_fdt32(gpio_value[3]); + len = sizeof(unsigned int); + d = data_copy_mem((char *)&value_32, len); + prop = build_property("allwinner,data", d); + add_property(child, prop); + + return phandle; + +} +int insert_pinconf_node(const char *section_name, + struct dt_info *dti, + struct node *node, + struct script_entry *ep, + const char *prop_name) +{ + char gpio_name[32], *string; + cell_t *cp, *info; + int muxsel = 0, pull = 0, data = 0, drive = 0; + int i, ret, len, gpio_value[4], phandle, phandle_count; + + struct node *pin_node; + struct property *prop, *prop_temp; + struct script_gpio_entry *entry; + + entry = container_of(ep, struct script_gpio_entry, entry); + ret = sunxi_gpio_to_name(entry->port, entry->port_num, gpio_name); + if (ret) + return ret; + + gpio_value[0] = entry->data[0]; + gpio_value[1] = entry->data[1] < 0 ? 0xFFFFFFFF : entry->data[1]; + gpio_value[2] = entry->data[2] < 0 ? 0xFFFFFFFF : entry->data[2]; + gpio_value[3] = entry->data[3] < 0 ? 0xFFFFFFFF : entry->data[3]; + + prop = get_property(node, prop_name); + phandle_count = prop->val.len/sizeof(unsigned int); + cp = (cell_t *)prop->val.val; + + for (i = 0; i < phandle_count; i++) { + phandle = fdt32_to_cpu(*cp++); + pin_node = get_node_by_phandle(dti->dt, phandle); + + if (pin_node) { + /* if find a pinctrl node, check config*/ + prop_temp = get_property(pin_node, "allwinner,muxsel"); + if (prop_temp) { + info = (cell_t *)prop_temp->val.val; + muxsel = fdt32_to_cpu(*info++); + } + prop_temp = get_property(pin_node, "allwinner,pull"); + if (prop_temp) { + info = (cell_t *)prop_temp->val.val; + pull = fdt32_to_cpu(*info++); + } + prop_temp = get_property(pin_node, "allwinner,drive"); + if (prop_temp) { + info = (cell_t *)prop_temp->val.val; + drive = fdt32_to_cpu(*info++); + } + prop_temp = get_property(pin_node, "allwinner,data"); + if (prop_temp) { + info = (cell_t *)prop_temp->val.val; + data = fdt32_to_cpu(*info++); + } + + if (gpio_value[0] == muxsel && gpio_value[1] == pull && + gpio_value[2] == drive && gpio_value[3] == data) { + prop_temp = get_property(pin_node, "allwinner,pins"); + if (prop_temp) { + len = prop_temp->val.len + strlen(gpio_name) + 1; + string = malloc(len); + memcpy(string, prop_temp->val.val, prop_temp->val.len); + memcpy(string + prop_temp->val.len, gpio_name, strlen(gpio_name)); + string[len-1] = '\0'; + free(prop_temp->val.val); + prop_temp->val.val = malloc(len); + memcpy(prop_temp->val.val, string, len); + prop_temp->val.len = len; + free(string); + } + + prop_temp = get_property(pin_node, "allwinner,pname"); + if (prop_temp) { + len = prop_temp->val.len + strlen(ep->name) + 1; + string = malloc(len); + memcpy(string, prop_temp->val.val, prop_temp->val.len); + memcpy(string + prop_temp->val.len, ep->name, strlen(ep->name)); + string[len-1] = '\0'; + free(prop_temp->val.val); + prop_temp->val.val = malloc(len); + memcpy(prop_temp->val.val, string, len); + prop_temp->val.len = len; + free(string); + return 0; + } + } + } + } + + return -1; +} + +void create_pinconf_node(const char *section_name, + struct dt_info *dti, + struct node *node, + struct script_entry *ep, + struct property *prop) +{ + int value[4], phandle; + char gpio_name[32], *propname; + struct node *pinctrl = NULL; + struct data d_pinctrl_x; + struct property *pinctrl_x; + struct script_gpio_entry *entry; + + entry = container_of(ep, struct script_gpio_entry, entry); + sunxi_gpio_to_name(entry->port, entry->port_num, gpio_name); + value[0] = entry->data[0]; + value[1] = entry->data[1] < 0 ? 0xFFFFFFFF : entry->data[1]; + value[2] = entry->data[2] < 0 ? 0xFFFFFFFF : entry->data[2]; + value[3] = entry->data[3] < 0 ? 0xFFFFFFFF : entry->data[3]; + + if (entry->port * 32 < PL_BASE) + pinctrl = sunxi_get_node(dti->dt, "pio"); + else if (entry->port * 32 >= PL_BASE && entry->port < AXP_BASE) + pinctrl = sunxi_get_node(dti->dt, "r_pio"); + + phandle = sunxi_dt_add_new_node_to_pinctrl(pinctrl, section_name, ep->name, gpio_name, value, dti); + if (phandle) { + d_pinctrl_x = data_append_cell(prop->val, phandle); + propname = malloc(strlen(prop->name)); + strcpy(propname, prop->name); + delete_property(prop); + pinctrl_x = build_property(propname, d_pinctrl_x); + add_property(node, pinctrl_x); + } +} + +void sunxi_dt_update_pin_group_sleep(const char *section_name, + struct dt_info *dti, + struct node *node, + struct script_entry *ep) +{ + int ret = 0; + char gpio_name[32] = {0}; + struct property *prop; + struct script_gpio_entry *entry; + + entry = container_of(ep, struct script_gpio_entry, entry); + sunxi_gpio_to_name(entry->port, entry->port_num, gpio_name); + prop = get_property(node, "pinctrl-1"); + + ret = insert_pinconf_node(section_name, dti, node, ep, "pinctrl-1"); + if (ret) + create_pinconf_node(section_name, dti, node, ep, prop); +} + + +void sunxi_dt_update_pin_group_default(const char *section_name, + struct dt_info *dti, + struct node *node, + struct script_entry *ep) +{ + int ret = 0; + char gpio_name[32] = {0}; + + struct property *prop; + struct script_gpio_entry *entry; + + entry = container_of(ep, struct script_gpio_entry, entry); + sunxi_gpio_to_name(entry->port, entry->port_num, gpio_name); + prop = get_property(node, "pinctrl-0"); + + ret = insert_pinconf_node(section_name, dti, node, ep, "pinctrl-0"); + if (ret) + create_pinconf_node(section_name, dti, node, ep, prop); +} + +/*end process pinconf */ + +void sunxi_dt_update_propval_cells(const char *section_name, + struct script_entry *ep, + struct node *node) +{ + int len; + unsigned int value_32; + char temp[32], *string; + struct data d; + struct property *prop; + struct script_single_entry *entry; + + entry = container_of(ep, struct script_single_entry, entry); + strcpy(temp, section_name); + strcat(temp, "_used"); + + if (strcmp(ep->name, "used") == 0 || strcmp(ep->name, temp) == 0) { + + string = entry->value ? "okay" : "disabled"; + len = strlen(string) + 1; + prop = get_property(node, "status"); + + if (prop) { + free(prop->val.val); + prop->val.val = malloc(len); + strcpy(prop->val.val, string); + prop->val.len = len; + } else { + d = data_copy_mem(string, len); + prop = build_property("status", d); + add_property(node, prop); + } + } else { + value_32 = cpu_to_fdt32(entry->value); + len = sizeof(unsigned int); + prop = get_property(node, ep->name); + + if (prop) { + free(prop->val.val); + prop->val.val = malloc(len); + memcpy(prop->val.val, &value_32, len); + prop->val.len = len; + } else { + d = data_copy_mem((char *)&value_32, len); + prop = build_property(ep->name, d); + add_property(node, prop); + } + } +} + +void sunxi_dt_update_propval_string(const char *section_name, + struct script_entry *ep, + struct node *node) +{ + int len; + char *string; + + struct data d; + struct property *prop; + struct script_string_entry *entry; + + /*SCRIPT_VALUE_TYPE_STRING*/ + entry = container_of(ep, struct script_string_entry, entry); + string = entry->string; + len = entry->l; + + prop = get_property(node, ep->name); + if (prop) { + free(prop->val.val); + prop->val.val = malloc(len); + strcpy(prop->val.val, string); + prop->val.len = len; + } else { + d = data_copy_mem(string, len); + prop = build_property(ep->name, d); + add_property(node, prop); + } +} + +void sunxi_dt_update_propval_empty(const char *section_name, + struct script_entry *ep, + struct node *node) +{ + struct data d = {0}; + struct property *prop, *temp; + struct script_null_entry *entry; + + /* SCRIPT_VALUE_TYPE_STRING */ + entry = container_of(ep, struct script_null_entry, entry); + + prop = get_property(node, entry->entry.name); + if (prop) + delete_property(prop); + + temp = build_property(entry->entry.name, d); + add_property(node, temp); +} + +void sunxi_dt_update_propval_gpio(const char *section_name, + struct script_entry *ep, + struct node *node, + struct dt_info *dti, + int sleep_state) +{ + struct script_gpio_entry *entry; + entry = container_of(ep, struct script_gpio_entry, entry); + + switch (entry->data[0]) { + case 0: + case 1: + case 6: + sunxi_dt_update_gpio_group(dti, node, ep, entry); + break; + case 2: + case 3: + case 4: + case 5: + case 7: + if (sleep_state) + sunxi_dt_update_pin_group_sleep(section_name, dti, node, ep); + else + sunxi_dt_update_pin_group_default(section_name, dti, node, ep); + break; + } + +} +struct node *sunxi_get_node(struct node *tree, const char *string) +{ + struct node *nd; + + nd = get_node_by_label(tree, string); + if (!nd) + nd = get_node_by_type(tree, string); + + return nd; +} + +int sunxi_build_new_node(struct dt_info *dti, char pnode_name[], char node_name[]) +{ + char *label; + struct node *child, *parent; + + parent = sunxi_get_node(dti->dt, pnode_name); + child = build_node(NULL, NULL); + if (!child) + printf("build node faile[%s]\n", node_name); + + label = xstrdup(node_name); + add_label(&child->labels, label); + child->name = xstrdup(node_name); + child->fullpath = join_path(parent->fullpath, child->name); + add_child(parent, child); + + return 0; +} + +int process_mainkey(char *mainkey, char parent_name[], char child_name[], int *state) +{ + char *delim1 = "/"; + char *delim2 = "_suspend"; + char *buf = strstr(mainkey, delim1); + char *temp_buf; + + if (buf != NULL) { + sscanf(mainkey, "%31[^/]/%31[^@]", parent_name, child_name); + } else { + strcpy(parent_name, "soc"); + strcpy(child_name, mainkey); + } + + temp_buf = strstr(child_name, delim2); + if (temp_buf != NULL) { + memset(temp_buf, 0, strlen(temp_buf)); + *state = 1; + } else { + *state = 0; + } + + return 0; +} + +int dt_update_source(const char *fexname, FILE *f, struct dt_info *dti) +{ + + int ret = 0; + int sleep_state = false; + char p_key[32] = {0}; + char c_key[32] = {0}; + + struct node *sub_node, *parent_node; + struct list_entry *sec_list, *o; + struct script_section *section; + struct script_entry *ep; + struct property *device_type_prop; + + /*for build new device type property.*/ + struct data d; + struct property *new_prop; + + ret = script_parse(fexname); + if (ret) { + printf("parser sys_config.fex file failed.\n"); + exit(1); + } + + for_each_section_in_list(script->sections, sec_list) { + section = container_of(sec_list, + struct script_section, sections); + /* + * here mainly deal with section name like parent_key/child_key + */ + process_mainkey(section->name, p_key, c_key, &sleep_state); + printf("p=%s c=%s state=%d\n", p_key, c_key, sleep_state); + + parent_node = sunxi_get_node(dti->dt, p_key); + if (!parent_node) { + printf("[SCRIPT_TO_DTS]Can not get parent node.\n"); + exit(1); + } + + sub_node = sunxi_get_node(dti->dt, c_key); + if (!sub_node) { + sunxi_build_new_node(dti, p_key, c_key); + sub_node = sunxi_get_node(dti->dt, c_key); + } + + device_type_prop = get_property(sub_node, "device_type"); + if (!device_type_prop) { + d = data_copy_mem(c_key, strlen(c_key)+1); + new_prop = build_property("device_type", d); + add_property(sub_node, new_prop); + } + + sunxi_dt_init_pinconf_prop(section, dti, sub_node, sleep_state); + for_each_entry_in_section(section->entries, o) { + ep = container_of(o, struct script_entry, entries); + switch (ep->type) { + case 1: + case 2: + sunxi_dt_update_propval_cells(c_key, ep, sub_node); + break; + case 3: + sunxi_dt_update_propval_string(c_key, ep, sub_node); + break; + case 5: + sunxi_dt_update_propval_gpio(c_key, ep, sub_node, dti, sleep_state); + break; + case 6: + /*empty property */ + sunxi_dt_update_propval_empty(c_key, ep, sub_node); + break; + default: + printf("input type error.\n"); + break; + } + } + } + + return 0; +}