SmartAudio/lichee/brandy/u-boot-2014.07/lib/libfdt/fdt_acc.c

333 lines
8.0 KiB
C
Raw Normal View History

2018-07-13 01:31:50 +00:00
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
* SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
*/
#include <common.h>
#include "libfdt.h"
#include "fdt_support.h"
#include "fdt_acc.h"
#include "common.h"
//<2F><><EFBFBD>ض<EFBFBD>Ӧ<EFBFBD><D3A6>name<6D><65>head node<64><65>ƫ<EFBFBD><C6AB><EFBFBD><EFBFBD>
//<2F><>0<EFBFBD><30>ʾ<EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD><30><D6B5>ʾ<EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD>
DECLARE_GLOBAL_DATA_PTR;
int fdtfast_search_head(char *head_base, char *dtb_base, char *head_buff, char *name)
{
struct head_node *head = NULL, *next_head;
char *tmp_name = name, *next_end_char;
uint full_string_sum = 0, full_string_len = 0;
uint at_flag = 0;
int i;
//ȡ<><C8A1><EFBFBD>׽ڵ<D7BD>
head = (struct head_node *)head_buff;
//<2F><><EFBFBD><EFBFBD>name<6D><65>/
while(*tmp_name == '/')
tmp_name ++;
//<2F>ҵ<EFBFBD><D2B5><EFBFBD>һ<EFBFBD><D2BB>/<2F><><EFBFBD><EFBFBD><EFBFBD>߿<EFBFBD><DFBF>ַ<EFBFBD>
next_end_char = tmp_name;
while(1) {
if (*next_end_char == '/')
break;
if (*next_end_char == '\0')
break;
if (*next_end_char == '@')
at_flag = 1;
full_string_sum += *next_end_char;
full_string_len ++;
next_end_char ++;
}
//printf("%s %d\n", __FILE__, __LINE__);
//printf("string_sum=%d\n", full_string_sum);
for(i=0;i<head->head_count;i++) {
next_head = (struct head_node *)(head->head_offset + head_base) + i;
//printf("next_head->name_offset=0x%x\n", next_head->name_offset);
//<2F>Ƚ<EFBFBD><C8BD>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD>
//printf("offset=0x%x\n", (uint)((unsigned long)next_head - (unsigned long)head_base));
//printf("i=%d\n", i);
if (!memcmp(tmp_name, next_head->name_offset + dtb_base, full_string_len)) {
//<2F><><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5>Dz<EFBFBD><C7B2><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD>
if ((next_head->repeate_count) && (at_flag))
continue; //<2F>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD>֣<EFBFBD><D6A3><EFBFBD><EFBFBD><EFBFBD>
//<2F>ڵ<EFBFBD>û<EFBFBD><C3BB><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD>֣<EFBFBD><D6A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (*next_end_char != '\0')
return fdtfast_search_head(head_base, dtb_base, (char *)next_head, next_end_char);
else
return (int)((unsigned long)next_head - (unsigned long)head_base);
}
}
return 0;
}
struct fdt_property *fdtfast_search_prop(char *dtbfast_buffer, char *fdt_buffer, uint32_t offset, char *name)
{
struct fdt_header *fdt = (struct fdt_header *)fdt_buffer;
struct prop_node *node;
struct head_node *head;
char *tmp_name = name;
uint32_t string_sum = 0, i;
char *fdt_string_base, *fdt_string_off;
head = (struct head_node *)(dtbfast_buffer + offset + sizeof(struct dtbfast_header));
while(*tmp_name)
string_sum += *tmp_name++;
fdt_string_base = fdt_buffer + cpu_to_be32(fdt->off_dt_strings);
for(i=0;i<head->data_count;i++) {
node = (struct prop_node *)(dtbfast_buffer + head->data_offset + sizeof(struct dtbfast_header)) + i;
if (string_sum == node->name_sum) {
fdt_string_off = fdt_string_base + node->name_offset;
if (!strcmp(name, fdt_string_off)) {
return (struct fdt_property *)(fdt_buffer + cpu_to_be32(fdt->off_dt_struct) + node->offset);
}
}
}
return NULL;
}
int fdtfast_path_offset(const void *fdt, const char *path)
{
char *dtbfast_buffer = gd->fdtfast_blob;
char *dtb_buffer = (char *)fdt;
uint32_t base_header_size = sizeof(struct dtbfast_header);
struct fdt_header *fdt_head;
uint32_t offset;
fdt_head = (struct fdt_header *)dtb_buffer;
if (path == NULL)
return 0;
// printf("path=%s\n", path);
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"/"<22><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>aliase<73><65><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA>aliase<73>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD>
if (path[0] != '/') {
struct fdt_property *prop_node;
offset = fdtfast_search_head(dtbfast_buffer + base_header_size,
dtb_buffer + cpu_to_be32(fdt_head->off_dt_struct),
dtbfast_buffer + base_header_size, "/aliases");
//printf("%s %d\n", __FILE__, __LINE__);
if (offset == 0) {
printf("dtbfast path offset err: cant find aliases\n");
return 0;
}
prop_node = fdtfast_search_prop(dtbfast_buffer, dtb_buffer, offset, (char *)path);
//printf("%s %d\n", __FILE__, __LINE__);
return fdtfast_search_head(dtbfast_buffer + base_header_size,
dtb_buffer + cpu_to_be32(fdt_head->off_dt_struct),
dtbfast_buffer + base_header_size,
prop_node->data);
}
else
return fdtfast_search_head(dtbfast_buffer + base_header_size, dtb_buffer +
cpu_to_be32(fdt_head->off_dt_struct),
dtbfast_buffer + base_header_size, (char *)path);
}
int fdtfast_setprop_string(const void *fdt, uint32_t offset, const char *name, const void *val)
{
struct fdt_property *prop_node;
char *dtbfast_buffer = gd->fdtfast_blob;
char *data, *src;
int i=0;
//printf("%s %d\n", __FILE__, __LINE__);
prop_node = fdtfast_search_prop(dtbfast_buffer, (char *)fdt, offset, (char *)name);
if (prop_node == NULL) {
printf("can not find the string named %s\n", name);
return -1;
}
if (cpu_to_be32(prop_node->len) < 4) {
printf("the name len is too short\n");
return -1;
}
data = (char *)prop_node->data;
src = (char *)val;
while(src[i]) {
data[i] = src[i];
i ++;
}
while(i < cpu_to_be32(prop_node->len))
data[i++] = '\0';
return 0;
}
int fdtfast_set_node_status(void *fdt, int nodeoffset, enum fdt_status status, unsigned int error_code)
{
//char buf[16];
int ret = 0;
if (nodeoffset < 0)
return nodeoffset;
//printf("%s %d\n", __FILE__, __LINE__);
switch (status) {
case FDT_STATUS_OKAY:
ret = fdtfast_setprop_string(fdt, nodeoffset, "status", "okay");
break;
case FDT_STATUS_DISABLED:
ret = fdtfast_setprop_string(fdt, nodeoffset, "status", "bad");
break;
case FDT_STATUS_FAIL:
ret = fdtfast_setprop_string(fdt, nodeoffset, "status", "fail");
break;
//case FDT_STATUS_FAIL_ERROR_CODE:
// sprintf(buf, "fail-%d", error_code);
// ret = fdtfast_setprop_string(fdt, nodeoffset, "status", buf);
// break;
default:
printf("Invalid fdt status: %x\n", status);
ret = -1;
break;
}
return ret;
}
int fdtfast_setprop_u32(void *fdt, int nodeoffset, const char *name,
uint32_t val)
{
struct fdt_property *prop_node;
char *dtbfast_buffer = gd->fdtfast_blob;
uint32_t *data;
prop_node = fdtfast_search_prop(dtbfast_buffer, (char *)fdt, nodeoffset, (char *)name);
if (prop_node == NULL) {
printf("can not find the string named %s\n", name);
return -1;
}
if (cpu_to_be32(prop_node->len) != 4) {
printf("the name len is invalid\n");
return -1;
}
data = (uint32_t *)prop_node->data;
*data = val;
return 0;
}
int fdtfast_getprop_u32(const void *fdt, int nodeoffset,
const char *name, uint32_t *val)
{
struct fdt_property *prop_node;
char *dtbfast_buffer = gd->fdtfast_blob;
int len, j;
uint32_t *p;
if (val == NULL) {
printf("the input buff is empty\n");
return -1;
}
prop_node = fdtfast_search_prop(dtbfast_buffer, (char *)fdt, nodeoffset, (char *)name);
if (prop_node == NULL) {
printf("can not find the string named %s\n", name);
return -1;
}
len = cpu_to_be32(prop_node->len);
if (len & 3) {
printf("the name len %d is invalid\n", len);
return -1;
}
for (j = 0, p = (uint32_t *)prop_node->data; j < len/4; j++)
{
*val = fdt32_to_cpu(p[j]);
val++;
}
return len/4;
}
int fdtfast_getprop_string(const void *fdt, int nodeoffset,
const char *name, char **val)
{
struct fdt_property *prop_node;
char *dtbfast_buffer = gd->fdtfast_blob;
int len;
if (val == NULL) {
printf("the input buff is empty\n");
return -1;
}
prop_node = fdtfast_search_prop(dtbfast_buffer, (char *)fdt, nodeoffset, (char *)name);
if (prop_node == NULL) {
printf("can not find the string named %s\n", name);
return -1;
}
len = cpu_to_be32(prop_node->len);
*val = prop_node->data;
return len;
}
int fdtfast_getprop_gpio(const void *fdt, int nodeoffset,
const char* prop_name, user_gpio_set_t* gpio_list)
{
int ret ;
u32 data[10];
memset(data, 0, sizeof(data));
ret = fdtfast_getprop_u32(fdt, nodeoffset, prop_name, data);
if (ret < 0) {
printf("can not find gpio\n");
return -1;
}
strcpy(gpio_list->gpio_name, prop_name);
gpio_list->port = data[1] + 1; //0: PA
gpio_list->port_num = data[2];
gpio_list->mul_sel = data[3];
gpio_list->pull = data[4];
gpio_list->drv_level = data[5];
gpio_list->data = data[6];
debug("name = %s, port = %x,portnum=%x,mul_sel=%x,pull=%x drive= %x, data=%x\n",
gpio_list->gpio_name,
gpio_list->port,
gpio_list->port_num,
gpio_list->mul_sel,
gpio_list->pull,
gpio_list->drv_level,
gpio_list->data);
return 0;
}