mirror of
https://gitee.com/Vancouver2017/luban-lite-t3e-pro.git
synced 2025-12-14 18:38:55 +00:00
967 lines
26 KiB
C
967 lines
26 KiB
C
/*
|
|
* Copyright (c) 2022-2024, ArtInChip Technology Co., Ltd
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Authors: Li Siyao <siyao.li@artinchip.com>
|
|
*/
|
|
|
|
#include <libfdt.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <rtconfig.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <aic_core.h>
|
|
#include <env.h>
|
|
#include "of.h"
|
|
#include <math.h>
|
|
#ifdef KERNEL_BAREMETAL
|
|
#include <mtd.h>
|
|
#endif
|
|
#ifdef KERNEL_RTTHREAD
|
|
#include <rtdevice.h>
|
|
#endif
|
|
|
|
#if defined(AIC_SDMC_DRV) && defined(KERNEL_BAREMETAL)
|
|
#include <mmc.h>
|
|
#include <partition_table.h>
|
|
|
|
#define GPT_HEADER_SIZE (34 * 512)
|
|
#ifdef IMAGE_CFG_JSON_PARTS_GPT
|
|
#define MMC_GPT_PARTS IMAGE_CFG_JSON_PARTS_GPT
|
|
#else
|
|
#define MMC_GPT_PARTS ""
|
|
#endif
|
|
#endif
|
|
|
|
#define AIC_BYTES_SIZE 4
|
|
#define AIC_CONFIG_PART "config"
|
|
#define AIC_MMC_CONFIG_DEV "mmc0p8"
|
|
#define AIC_DTB_DATA_BASE_ADDR 0x800
|
|
|
|
#ifdef AIC_DRAM_TOTAL_SIZE
|
|
#define AIC_DDR_DTB_ADDR 0x40000000 + AIC_DRAM_TOTAL_SIZE - 256 * 1024
|
|
#endif
|
|
#ifdef AIC_PSRAM_SIZE
|
|
#define AIC_PSRAM_DTB_ADDR 0x40000000 + AIC_PSRAM_SIZE - 256 * 1024
|
|
#endif
|
|
|
|
static void *g_aic_initial_blob = NULL;
|
|
|
|
bool of_fdt_device_is_available(ofnode node)
|
|
{
|
|
CHECK_PARAM(g_aic_initial_blob, false);
|
|
const char *status;
|
|
status = fdt_getprop(g_aic_initial_blob, node.offset, "status", NULL);
|
|
|
|
if (!status)
|
|
return true;
|
|
|
|
if (!strcmp(status, "ok") || !strcmp(status, "okay"))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
void of_relocate_dtb(unsigned long pos)
|
|
{
|
|
g_aic_initial_blob = (void *)pos;
|
|
}
|
|
|
|
/**
|
|
* This function is used to debug the result of the mtd parsing
|
|
*/
|
|
#if 0
|
|
#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
|
|
static void mtd_dump_hex(const rt_uint8_t *ptr, rt_size_t buflen)
|
|
{
|
|
unsigned char *buf = (unsigned char *)ptr;
|
|
int i, j;
|
|
for (i = 0; i < buflen; i += 16)
|
|
{
|
|
printf("%06x: ", i);
|
|
for (j = 0; j < 16; j++)
|
|
if (i + j < buflen)
|
|
printf("%02x ", buf[i + j]);
|
|
else
|
|
printf(" ");
|
|
printf(" ");
|
|
for (j = 0; j < 16; j++)
|
|
if (i + j < buflen)
|
|
printf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
|
|
printf("\n");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
int of_dtb_is_available(void)
|
|
{
|
|
int ret = -1;
|
|
int dtb_data_size = 0;
|
|
struct fdt_header *dtb_header_data = g_aic_initial_blob;
|
|
|
|
dtb_data_size = fdt_totalsize(dtb_header_data);
|
|
if (dtb_data_size == 0) {
|
|
printf("The DTB data size is 0 K\n");
|
|
goto __exit;
|
|
} else {
|
|
printf("The %s partition exist, and the DTB data size is %d K\n",
|
|
AIC_CONFIG_PART, dtb_data_size / 1024);
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
__exit:
|
|
return ret;
|
|
}
|
|
|
|
#ifdef KERNEL_BAREMETAL
|
|
#ifdef AIC_SDMC_DRV
|
|
int of_fdt_dt_init_bare_mmc(void)
|
|
{
|
|
int ret = -1;
|
|
u8 *mmc_data = NULL;
|
|
int dtb_data_size = 0;
|
|
int mmc_blk_size = 512;
|
|
unsigned long mmc_id = 0;
|
|
unsigned long blkoffset = 0;
|
|
struct aic_sdmc *host = NULL;
|
|
void *psram_or_ddr_dtb_addr = NULL;
|
|
struct aic_partition *part = NULL;
|
|
struct aic_partition *parts = NULL;
|
|
struct fdt_header *dtb_header_data = NULL;
|
|
u32 itb_head_offset = AIC_DTB_DATA_BASE_ADDR / mmc_blk_size;
|
|
|
|
ret = mmc_init(mmc_id);
|
|
if (ret) {
|
|
printf("SDMC %ld init failed.\n", mmc_id);
|
|
return ret;
|
|
}
|
|
|
|
host = find_mmc_dev_by_index(mmc_id);
|
|
if (host== NULL) {
|
|
printf("Can't find mmc device!");
|
|
return ret;
|
|
}
|
|
|
|
parts = mmc_new_partition(MMC_GPT_PARTS, (GPT_HEADER_SIZE));
|
|
if (!parts)
|
|
return ret;
|
|
|
|
if (parts->start != GPT_HEADER_SIZE) {
|
|
pr_err("First partition start offset is not correct\n");
|
|
goto __exit;
|
|
}
|
|
|
|
part = parts;
|
|
blkoffset = part->start;
|
|
|
|
while (part) {
|
|
if (!strcmp(part->name, AIC_CONFIG_PART))
|
|
break;
|
|
blkoffset += part->size;
|
|
part = part->next;
|
|
}
|
|
|
|
blkoffset /= mmc_blk_size;
|
|
|
|
dtb_header_data = (struct fdt_header *)malloc(sizeof(struct fdt_header));
|
|
if (dtb_header_data == NULL) {
|
|
printf("Unable to allocate memory for dtb_header_data");
|
|
goto __exit;
|
|
}
|
|
|
|
mmc_data = malloc(mmc_blk_size);
|
|
if (mmc_data == NULL) {
|
|
printf("Unable to allocate memory for mmc_data");
|
|
goto __exit;
|
|
}
|
|
|
|
/* Read the size of the dtb data in the dtb data header.*/
|
|
mmc_bread(host, blkoffset + itb_head_offset, 1, (void *)mmc_data);
|
|
|
|
memcpy(dtb_header_data, mmc_data, sizeof(struct fdt_header));
|
|
dtb_data_size = fdt_totalsize(dtb_header_data);
|
|
if (dtb_data_size == 0) {
|
|
printf("The DTB data size is 0 K\n");
|
|
goto __exit;
|
|
}
|
|
|
|
#ifdef AIC_PSRAM_SIZE
|
|
psram_or_ddr_dtb_addr = (void *)AIC_PSRAM_DTB_ADDR;
|
|
#endif
|
|
#ifdef AIC_DRAM_TOTAL_SIZE
|
|
psram_or_ddr_dtb_addr = (void *)AIC_DDR_DTB_ADDR;
|
|
#endif
|
|
|
|
if (psram_or_ddr_dtb_addr == NULL) {
|
|
printf("Please check RAM config\n");
|
|
goto __exit;
|
|
}
|
|
|
|
mmc_bread(host, blkoffset + itb_head_offset, dtb_data_size / mmc_blk_size,
|
|
(void *)psram_or_ddr_dtb_addr);
|
|
|
|
g_aic_initial_blob = psram_or_ddr_dtb_addr;
|
|
if (fdt_check_header(g_aic_initial_blob) != 0) {
|
|
printf("ERROR: Invalid device tree blob\n");
|
|
goto __exit;
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
__exit:
|
|
if (mmc_data)
|
|
free(mmc_data);
|
|
if (dtb_header_data)
|
|
free(dtb_header_data);
|
|
if (parts)
|
|
mmc_free_partition(parts);
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
#if defined(AIC_SPINOR_DRV) || defined(AIC_SPINAND_DRV)
|
|
|
|
int of_fdt_dt_init_bare_nornand(void)
|
|
{
|
|
struct mtd_dev *mtd;
|
|
unsigned long offset = AIC_DTB_DATA_BASE_ADDR;
|
|
struct fdt_header dtb_header_data;
|
|
int dtb_data_size = 0;
|
|
void *psram_or_ddr_dtb_addr = NULL;
|
|
|
|
if (g_aic_initial_blob != NULL) {
|
|
printf("FDT has inited\n");
|
|
return 0;
|
|
}
|
|
|
|
mtd = mtd_get_device(AIC_CONFIG_PART);
|
|
if (!mtd) {
|
|
printf("Failed to get mtd %s\n", AIC_CONFIG_PART);
|
|
return -1;
|
|
}
|
|
|
|
/* Read the size of the dtb data in the dtb data header.*/
|
|
mtd_read(mtd, offset, (void *)&dtb_header_data, sizeof(struct fdt_header));
|
|
|
|
dtb_data_size = fdt_totalsize(&dtb_header_data);
|
|
if (dtb_data_size == 0) {
|
|
printf("The DTB data size is 0 K\n");
|
|
return -1;
|
|
}
|
|
|
|
/* store the dtb data in the last 256k address of psram/ddr */
|
|
#ifdef AIC_PSRAM_SIZE
|
|
psram_or_ddr_dtb_addr = (void *)AIC_PSRAM_DTB_ADDR;
|
|
#endif
|
|
#ifdef AIC_DRAM_TOTAL_SIZE
|
|
psram_or_ddr_dtb_addr = (void *)AIC_DDR_DTB_ADDR;
|
|
#endif
|
|
mtd_read(mtd, offset, psram_or_ddr_dtb_addr, dtb_data_size);
|
|
g_aic_initial_blob = psram_or_ddr_dtb_addr;
|
|
|
|
if (fdt_check_header(g_aic_initial_blob) != 0) {
|
|
printf("ERROR: Invalid device tree blob\n");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
int of_find_node_by_path(const char *path, ofnode *node)
|
|
{
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
node->offset = fdt_path_offset(g_aic_initial_blob, path);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int of_node_to_offset(ofnode node)
|
|
{
|
|
return node.offset;
|
|
}
|
|
|
|
int of_find_subnode(ofnode node, const char *subnode_name, ofnode *subnode)
|
|
{
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
subnode->offset = fdt_subnode_offset(g_aic_initial_blob,
|
|
of_node_to_offset(node), subnode_name);
|
|
|
|
return 0;
|
|
}
|
|
|
|
const char *of_get_nodename(ofnode node)
|
|
{
|
|
CHECK_PARAM(g_aic_initial_blob, NULL);
|
|
|
|
return fdt_get_name(g_aic_initial_blob, of_node_to_offset(node), NULL);
|
|
}
|
|
|
|
ofnode of_first_subnode(ofnode node)
|
|
{
|
|
ofnode subnode;
|
|
|
|
if (!g_aic_initial_blob) {
|
|
subnode.offset = 0;
|
|
} else {
|
|
subnode.offset = fdt_first_subnode(g_aic_initial_blob,
|
|
of_node_to_offset(node));
|
|
}
|
|
|
|
return subnode;
|
|
}
|
|
|
|
/**
|
|
* of_next_subnode - get the sibling node by given name
|
|
*
|
|
* @node: the node
|
|
* @return the Sibling node, or NULL if there is none
|
|
*/
|
|
ofnode of_next_subnode(ofnode node)
|
|
{
|
|
ofnode subnode;
|
|
|
|
if (!g_aic_initial_blob) {
|
|
subnode.offset = 0;
|
|
} else {
|
|
subnode.offset = fdt_next_subnode(g_aic_initial_blob,
|
|
of_node_to_offset(node));
|
|
}
|
|
|
|
return subnode;
|
|
}
|
|
|
|
int of_parent_node(ofnode node, ofnode *parent_node)
|
|
{
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
parent_node->offset = fdt_parent_offset(g_aic_initial_blob,
|
|
of_node_to_offset(node));
|
|
return 0;
|
|
}
|
|
|
|
int of_read_addr_cells(ofnode node)
|
|
{
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
return fdt_address_cells(g_aic_initial_blob, of_node_to_offset(node));
|
|
}
|
|
|
|
int of_read_size_cells(ofnode node)
|
|
{
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
return fdt_size_cells(g_aic_initial_blob, of_node_to_offset(node));
|
|
}
|
|
|
|
int of_node_write_prop(ofnode node, const char *name, const void *val, int len)
|
|
{
|
|
int ret;
|
|
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
ret = fdt_setprop(g_aic_initial_blob, of_node_to_offset(node), name,
|
|
val, len);
|
|
if (ret < 0) {
|
|
printf("Set the prop-%s failed\n", name);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int of_node_delete_prop(ofnode node, const char *name)
|
|
{
|
|
int ret;
|
|
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
ret = fdt_delprop(g_aic_initial_blob, of_node_to_offset(node), name);
|
|
if (ret < 0) {
|
|
printf("Delete the prop-%s failed\n", name);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* fdt_appendprop_string - append a string to a property
|
|
* @fdt: pointer to the device tree blob
|
|
* @nodeoffset: offset of the node whose property to change
|
|
* @name: name of the property to change
|
|
* @str: string value to append to the property
|
|
*/
|
|
int of_node_append_prop_string(ofnode node, const char *name, const void *str)
|
|
{
|
|
int ret;
|
|
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
ret = fdt_appendprop_string(g_aic_initial_blob, of_node_to_offset(node), name, str);
|
|
if (ret < 0) {
|
|
printf("Append the prop-%s failed\n", (char *)str);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* of_node_append_prop_u32 - append a 32-bit integer value to a property
|
|
* @fdt: pointer to the device tree blob
|
|
* @nodeoffset: offset of the node whose property to change
|
|
* @name: name of the property to change
|
|
* @val: 32-bit integer value to append to the property (native endian)
|
|
*/
|
|
int of_node_append_prop_u32(ofnode node, const char *name, uint32_t val)
|
|
{
|
|
int ret;
|
|
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
ret = fdt_appendprop_u32(g_aic_initial_blob, of_node_to_offset(node), name, val);
|
|
if (ret < 0) {
|
|
printf("Append the prop-%s failed\n", name);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
const int of_property_read_size(ofnode node, const char *name)
|
|
{
|
|
int size;
|
|
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
if (fdt_getprop(g_aic_initial_blob, of_node_to_offset(node), name, &size) == NULL)
|
|
return -1;
|
|
|
|
return size;
|
|
}
|
|
|
|
int of_property_read_u64(ofnode node, const char *name, u64 *data)
|
|
{
|
|
int size;
|
|
const fdt64_t *value = NULL;
|
|
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
value = fdt_getprop(g_aic_initial_blob, of_node_to_offset(node), name, &size);
|
|
if (size < AIC_BYTES_SIZE) {
|
|
printf("Error: value array length is less than 4 bytes.");
|
|
return -1;
|
|
}
|
|
*data = fdt64_to_cpu(*value);
|
|
|
|
return 0;
|
|
}
|
|
|
|
const int of_property_read_u64_array(ofnode node, const char *name,
|
|
int *cnt, u64 *data_arr)
|
|
{
|
|
int size;
|
|
const fdt64_t *value = NULL;
|
|
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
value = fdt_getprop(g_aic_initial_blob, of_node_to_offset(node), name, &size);
|
|
*cnt = size / 8;
|
|
for (int i = 0; i < *cnt; i++) {
|
|
data_arr[i] = 0;
|
|
data_arr[i] = fdt64_to_cpu(*value++);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
const int of_property_get_u64_array_number(ofnode node, const char *name,
|
|
int *cnt)
|
|
{
|
|
int size;
|
|
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
fdt_getprop(g_aic_initial_blob, of_node_to_offset(node), name, &size);
|
|
*cnt = size / 8;
|
|
|
|
return 0;
|
|
}
|
|
|
|
const int of_property_read_u64_by_index(ofnode node, const char *name,
|
|
int index, u64 *out_value)
|
|
{
|
|
int size;
|
|
const fdt64_t *value = NULL;
|
|
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
value = fdt_getprop(g_aic_initial_blob, of_node_to_offset(node), name, &size);
|
|
if (value)
|
|
*out_value = fdt64_to_cpu(*(value + index));
|
|
|
|
return 0;
|
|
}
|
|
|
|
int of_property_read_u32(ofnode node, const char *name, u32 *data)
|
|
{
|
|
int size;
|
|
const fdt32_t *value = NULL;
|
|
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
value = fdt_getprop(g_aic_initial_blob, of_node_to_offset(node), name, &size);
|
|
if (size < AIC_BYTES_SIZE) {
|
|
printf("Error: value array length is less than 4 bytes.\n");
|
|
return -1;
|
|
}
|
|
*data = fdt32_to_cpu(*value);
|
|
|
|
return 0;
|
|
}
|
|
|
|
const int of_property_read_u32_array(ofnode node, const char *name,
|
|
int *cnt, u32 *data_arr)
|
|
{
|
|
int size;
|
|
const fdt32_t *value = NULL;
|
|
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
value = fdt_getprop(g_aic_initial_blob, of_node_to_offset(node), name, &size);
|
|
*cnt = size / 4;
|
|
for (int i = 0; i < *cnt; i++) {
|
|
data_arr[i] = 0;
|
|
data_arr[i] = fdt32_to_cpu(*value++);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
const int of_property_get_u32_array_number(ofnode node, const char *name, int *cnt)
|
|
{
|
|
int size;
|
|
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
fdt_getprop(g_aic_initial_blob, of_node_to_offset(node), name, &size);
|
|
*cnt = size / 4;
|
|
|
|
return 0;
|
|
}
|
|
|
|
const int of_property_read_u32_by_index(ofnode node, const char *name,
|
|
int index, u32 *out_value)
|
|
{
|
|
int size;
|
|
const fdt32_t *value = NULL;
|
|
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
value = fdt_getprop(g_aic_initial_blob, of_node_to_offset(node), name, &size);
|
|
*out_value = fdt32_to_cpu(*(value + index));
|
|
|
|
return 0;
|
|
}
|
|
|
|
int of_property_read_u16(ofnode node, const char *name, u16 *data)
|
|
{
|
|
int size;
|
|
const fdt32_t *value = NULL;
|
|
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
value = fdt_getprop(g_aic_initial_blob, of_node_to_offset(node), name, &size);
|
|
if (size < AIC_BYTES_SIZE / 2) {
|
|
printf("Error: value array length is less than 2 bytes.\n");
|
|
return -1;
|
|
}
|
|
*data = fdt16_to_cpu(*value >> 16);
|
|
|
|
return 0;
|
|
}
|
|
|
|
const int of_property_read_u16_array(ofnode node, const char *name,
|
|
int *cnt, u16 *data_arr)
|
|
{
|
|
int size;
|
|
const fdt32_t *value = NULL;
|
|
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
value = fdt_getprop(g_aic_initial_blob, of_node_to_offset(node), name, &size);
|
|
*cnt = size / 4;
|
|
for (int i = 0; i < *cnt; i++) {
|
|
data_arr[i] = 0;
|
|
data_arr[i] = fdt16_to_cpu(*value++ >> 16);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
const int of_property_get_u16_array_number(ofnode node, const char *name,
|
|
int *cnt)
|
|
{
|
|
int size;
|
|
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
fdt_getprop(g_aic_initial_blob, of_node_to_offset(node), name, &size);
|
|
*cnt = size / 4;
|
|
|
|
return 0;
|
|
}
|
|
|
|
const int of_property_read_u16_by_index(ofnode node, const char *name,
|
|
int index, u16 *out_value)
|
|
{
|
|
int size;
|
|
const fdt32_t *value = NULL;
|
|
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
value = fdt_getprop(g_aic_initial_blob, of_node_to_offset(node), name, &size);
|
|
*out_value = fdt16_to_cpu(*(value + index) >> 16);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int of_property_read_u8(ofnode node, const char *name, u8 *data)
|
|
{
|
|
int size;
|
|
const fdt32_t *value = NULL;
|
|
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
value = fdt_getprop(g_aic_initial_blob, of_node_to_offset(node), name, &size);
|
|
if (size < AIC_BYTES_SIZE / 4) {
|
|
printf("Error: value array length is less than 1 bytes.\n");
|
|
return -1;
|
|
}
|
|
*data = *value >> 24;
|
|
|
|
return 0;
|
|
}
|
|
|
|
const int of_property_read_u8_array(ofnode node, const char *name, int *cnt,
|
|
u8 *data_arr)
|
|
{
|
|
int size;
|
|
const fdt32_t *value = NULL;
|
|
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
value = fdt_getprop(g_aic_initial_blob, of_node_to_offset(node), name, &size);
|
|
*cnt = size / 4;
|
|
for (int i = 0; i < *cnt; i++) {
|
|
data_arr[i] = *value++ >> 24;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
const int of_property_get_u8_array_number(ofnode node, const char *name,
|
|
int *cnt)
|
|
{
|
|
int size;
|
|
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
fdt_getprop(g_aic_initial_blob, of_node_to_offset(node), name, &size);
|
|
*cnt = size / 4;
|
|
|
|
return 0;
|
|
}
|
|
|
|
const int of_property_read_u8_by_index(ofnode node, const char *name,
|
|
int index, u8 *out_value)
|
|
{
|
|
int size;
|
|
const fdt32_t *value = NULL;
|
|
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
value = fdt_getprop(g_aic_initial_blob, of_node_to_offset(node), name, &size);
|
|
*out_value = *(value + index) >> 24;
|
|
|
|
return 0;
|
|
}
|
|
|
|
const bool of_property_read_bool(ofnode node, const char *name)
|
|
{
|
|
const struct fdt_property *data;
|
|
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
data = fdt_get_property(g_aic_initial_blob, of_node_to_offset(node), name, NULL);
|
|
|
|
return data ? true : false;
|
|
}
|
|
|
|
const void *of_property_read_string(ofnode node, const char *name, int *size)
|
|
{
|
|
CHECK_PARAM(g_aic_initial_blob, NULL);
|
|
|
|
return fdt_getprop(g_aic_initial_blob, of_node_to_offset(node), name, size);
|
|
}
|
|
|
|
const int of_property_read_string_count(ofnode node, const char *name)
|
|
{
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
return fdt_stringlist_count(g_aic_initial_blob, of_node_to_offset(node),
|
|
name);
|
|
}
|
|
|
|
const char **of_property_read_string_array(ofnode node, const char *name)
|
|
{
|
|
int len;
|
|
int str_cnt;
|
|
const char **value = NULL;
|
|
|
|
CHECK_PARAM(g_aic_initial_blob, NULL);
|
|
|
|
str_cnt = of_property_read_string_count(node, name);
|
|
value = malloc(str_cnt * sizeof(char *));
|
|
if (value == NULL)
|
|
return NULL;
|
|
|
|
for (int i = 0; i < str_cnt; i++)
|
|
value[i] = fdt_stringlist_get(g_aic_initial_blob,
|
|
of_node_to_offset(node), name, i, &len);
|
|
|
|
return value;
|
|
}
|
|
|
|
const int of_property_read_string_index(ofnode node, const char *name,
|
|
const char *propname, int *index)
|
|
{
|
|
CHECK_PARAM(g_aic_initial_blob, -EINVAL);
|
|
|
|
*index = fdt_stringlist_search(g_aic_initial_blob, of_node_to_offset(node),
|
|
name, propname);
|
|
if (index == NULL)
|
|
return 0;
|
|
return -1;
|
|
}
|
|
|
|
const char *of_property_read_string_by_index(ofnode node, const char *name,
|
|
int index)
|
|
{
|
|
CHECK_PARAM(g_aic_initial_blob, NULL);
|
|
|
|
int len;
|
|
const char *value;
|
|
|
|
value = fdt_stringlist_get(g_aic_initial_blob, of_node_to_offset(node),
|
|
name, index, &len);
|
|
if (value == NULL)
|
|
return NULL;
|
|
return value;
|
|
}
|
|
|
|
int aic_of_fdt_example(void)
|
|
{
|
|
ofnode node = {0};
|
|
ofnode subnode = {0};
|
|
ofnode subsubnode = {0};
|
|
ofnode parent_node = {0};
|
|
ofnode cur_node = {0};
|
|
int len;
|
|
u64 val_u64 =0;
|
|
u32 val_u32 =0;
|
|
u16 val_u16 = 0;
|
|
u8 val_u8 = 0;
|
|
int cnt = 0;
|
|
int cnt_u64 = 0;
|
|
int cnt_u32 = 0;
|
|
int cnt_u16 = 0;
|
|
int cnt_u8 = 0;
|
|
const char **str_arr;
|
|
const char *prop_str;
|
|
const char *subnode_name;
|
|
bool bool_ret;
|
|
int size_u64, size_u32, size_u16, size_u8;
|
|
int str_idx = 0;
|
|
u64 val_u64_out = 0;
|
|
u32 val_u32_out = 0;
|
|
u16 val_u16_out = 0;
|
|
u8 val_u8_out = 0;
|
|
|
|
of_find_node_by_path("/soc/gpai/gpai0", &node);
|
|
prop_str = of_property_read_string(node, "status", &len);
|
|
if (prop_str)
|
|
printf("[status] %s\n", prop_str);
|
|
of_node_write_prop(node, "status", "okay", sizeof("okay"));
|
|
prop_str = of_property_read_string(node, "status", &len);
|
|
if (prop_str)
|
|
printf("[status] %s - After modify\n\n", prop_str);
|
|
of_node_delete_prop(node, "status");
|
|
prop_str = of_property_read_string(node, "status", &len);
|
|
if (prop_str == NULL)
|
|
printf("[status] :NONE \n\n");
|
|
|
|
printf("[aic,high-level-thd]\n");
|
|
of_property_read_u32(node, "aic,high-level-thd", &val_u32);
|
|
printf("u32: 0x%08X ", val_u32);
|
|
of_property_read_u16(node, "aic,high-level-thd", &val_u16);
|
|
printf("u16: 0x%04X ", val_u16);
|
|
of_property_read_u8(node, "aic,high-level-thd", &val_u8);
|
|
printf("u8: 0x%02X\n", val_u8);
|
|
|
|
of_find_node_by_path("/soc", &node);
|
|
bool_ret = of_property_read_bool(node, "u-boot,dm-pre-reloc");
|
|
if (bool_ret) {
|
|
printf("prop has u-boot,dm-pre-reloc\n");
|
|
}
|
|
printf("addr_cell: %d\n", of_read_addr_cells(node));
|
|
printf("size_cell: %d\n\n", of_read_size_cells(node));
|
|
|
|
of_property_read_u64(node, "clock-frequency", &val_u64);
|
|
printf("[clock-frequency]-u64: 0x%16llX\n", val_u64);
|
|
size_u64 = of_property_read_size(node, "clock-frequency");
|
|
if (size_u64) {
|
|
u64 *value_reg_64 = (u64 *)malloc(2 * sizeof(u64));
|
|
memset(value_reg_64, 0, 2 * sizeof(u64));
|
|
of_property_read_u64_array(node, "clock-frequency", &cnt_u64,
|
|
value_reg_64);
|
|
printf("[clock-frequency] %d numbers\n", cnt_u64);
|
|
cnt_u64 = 0;
|
|
of_property_get_u64_array_number(node, "clock-frequency", &cnt_u64);
|
|
printf("[clock-frequency] %d numbers\n", cnt_u64);
|
|
for (int i = 0; i < cnt_u64; i++) {
|
|
printf("0x%16llX ", value_reg_64[i]);
|
|
}
|
|
of_property_read_u64_by_index(node, "clock-frequency", 0 ,
|
|
&val_u64_out);
|
|
printf("\n");
|
|
printf("[clock-frequency]-NO.%d : 0x%16llX \n", 0, val_u64_out);
|
|
printf("\n");
|
|
free(value_reg_64);
|
|
}
|
|
|
|
of_find_node_by_path("/soc/gpai", &node);
|
|
int str_cnt = of_property_read_string_count(node, "clock-names");
|
|
printf("[clock-names]-str %d numbers\n", str_cnt);
|
|
of_property_read_string_index(node, "clock-names", "gpai", &str_idx);
|
|
printf("[clock-names]-gpai-index : %d\n", str_idx);
|
|
prop_str = of_property_read_string_by_index(node, "clock-names", str_idx);
|
|
if (prop_str)
|
|
printf("[clock-names]-%d index : %s\n", str_idx, prop_str);
|
|
|
|
of_find_node_by_path("/soc/gpai", &node);
|
|
str_arr= of_property_read_string_array(node, "clock-names");
|
|
if (str_arr == NULL) {
|
|
printf("Can't get string array\n");
|
|
} else {
|
|
int str_cnt = of_property_read_string_count(node, "clock-names");
|
|
for (int i = 0; i < str_cnt; i++) {
|
|
printf("%d-%s ", i, str_arr[i]);
|
|
}
|
|
printf("\n\n");
|
|
}
|
|
|
|
size_u32 = of_property_read_size(node, "reg");
|
|
if (size_u32 > 0) {
|
|
u32 *value_reg = (u32 *)malloc(size_u32 * sizeof(u32));
|
|
memset(value_reg, 0, size_u32 * sizeof(u32));
|
|
of_property_read_u32_array(node, "reg", &cnt, value_reg);
|
|
printf("[reg] %d numbers\n", cnt);
|
|
for (int i = 0; i < cnt; i++) {
|
|
printf("0x%08X ", value_reg[i]);
|
|
}
|
|
printf("\n\n");
|
|
free(value_reg);
|
|
}
|
|
|
|
uint32_t appd_val = 0xaaabbb;
|
|
of_node_append_prop_u32(node, "brightness-levels", appd_val);
|
|
size_u32 = of_property_read_size(node, "brightness-levels");
|
|
if (size_u32 > 0) {
|
|
u32 *value_u32 = (u32 *)malloc(size_u32 * sizeof(u32));
|
|
memset(value_u32, 0, size_u32 * sizeof(u32));
|
|
of_property_read_u32_array(node, "brightness-levels", &cnt_u32,
|
|
value_u32);
|
|
printf("[brightness-levels] %d numbers\n", cnt_u32);
|
|
for (int i = 0; i < cnt_u32; i++) {
|
|
printf("0x%08X ", value_u32[i]);
|
|
if (!((i + 1) % 4))
|
|
printf("\n");
|
|
}
|
|
of_property_read_u32_by_index(node, "brightness-levels", 6 , &val_u32_out);
|
|
printf("[brightness-levels]-NO.%d : %d \n", 6, val_u32_out);
|
|
of_property_get_u32_array_number(node, "brightness-levels",&cnt_u32);
|
|
printf("[brightness-levels]-u32 %d numbers\n", cnt_u32);
|
|
printf("\n");
|
|
free(value_u32);
|
|
}
|
|
|
|
size_u16 = of_property_read_size(node, "brightness-levels");
|
|
if (size_u16 > 0) {
|
|
u16 *value_u16 = (u16 *)malloc(size_u16 * sizeof(u16));
|
|
memset(value_u16, 0, size_u16 * sizeof(u16));
|
|
of_property_read_u16_array(node, "brightness-levels", &cnt_u16,
|
|
value_u16);
|
|
printf("[brightness-levels]-u16 %d numbers\n", cnt_u16);
|
|
for (int i = 0; i < cnt_u16; i++) {
|
|
printf("0x%04X ", value_u16[i]);
|
|
if (!((i + 1) % 4))
|
|
printf("\n");
|
|
}
|
|
of_property_read_u16_by_index(node, "brightness-levels", 6 ,
|
|
&val_u16_out);
|
|
printf("[brightness-levels]-NO.%d : %d \n", 6, val_u16_out);
|
|
printf("\n");
|
|
free(value_u16);
|
|
}
|
|
|
|
size_u8 = of_property_read_size(node, "brightness-levels");
|
|
if (size_u8 > 0) {
|
|
u8 *value_u8 = (u8 *)malloc(size_u8 * sizeof(u8));
|
|
memset(value_u8, 0, size_u8 * sizeof(u8));
|
|
of_property_read_u8_array(node, "brightness-levels", &cnt_u8, value_u8);
|
|
printf("[brightness-levels]-u8 %d numbers\n", cnt_u8);
|
|
for (int i = 0; i < cnt_u8; i++) {
|
|
printf("0x%02X ", value_u8[i]);
|
|
if (!((i + 1) % 4))
|
|
printf("\n");
|
|
}
|
|
of_property_read_u8_by_index(node, "brightness-levels", 6 ,
|
|
&val_u8_out);
|
|
printf("[brightness-levels]-NO.%d : %d \n", 6, val_u8_out);
|
|
printf("\n");
|
|
free(value_u8);
|
|
}
|
|
|
|
cnt = 0;
|
|
of_find_node_by_path("/soc", &parent_node);
|
|
printf("[for_each_subnode]:\n");
|
|
of_for_each_subnode(cur_node, parent_node) {
|
|
if (of_get_nodename(cur_node))
|
|
printf("[%d] %s\n", cnt++, of_get_nodename(cur_node));
|
|
}
|
|
|
|
of_find_node_by_path("/soc/gpai", &node);
|
|
const char *name = of_get_nodename(node);
|
|
printf("\nNode name: %s\n", name);
|
|
|
|
of_find_node_by_path("/soc", &node);
|
|
of_find_subnode(node, "gpai", &subnode);
|
|
subnode_name = of_get_nodename(subnode);
|
|
printf("Subnode name: %s\n", subnode_name);
|
|
subsubnode = of_first_subnode(subnode);
|
|
printf("Subsubnode name: %s\n", of_get_nodename(subsubnode));
|
|
subsubnode = of_next_subnode(subnode);
|
|
printf("Subsubnode name: %s\n", of_get_nodename(subsubnode));
|
|
of_parent_node(subnode, &parent_node);
|
|
printf("Parentnode name: %s\n", of_get_nodename(parent_node));
|
|
|
|
if (of_fdt_device_is_available(subnode))
|
|
printf("subnode_name is available\n");
|
|
|
|
return 0;
|
|
}
|