mirror of
https://gitee.com/Vancouver2017/luban-lite-t3e-pro.git
synced 2025-12-14 10:28:54 +00:00
V1.0.6
This commit is contained in:
14
packages/artinchip/of/SConscript
Normal file
14
packages/artinchip/of/SConscript
Normal file
@@ -0,0 +1,14 @@
|
||||
Import('AIC_ROOT')
|
||||
Import('PRJ_KERNEL')
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
CPPPATH = [cwd]
|
||||
|
||||
src = []
|
||||
group = []
|
||||
|
||||
src = Glob('*.c')
|
||||
group = DefineGroup('of_dtb', src, depend = ['LPKG_USING_FDTLIB'], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
966
packages/artinchip/of/of.c
Normal file
966
packages/artinchip/of/of.c
Normal file
@@ -0,0 +1,966 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
83
packages/artinchip/of/of.h
Normal file
83
packages/artinchip/of/of.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2024, ArtInChip Technology Co., Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <aic_core.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int offset;
|
||||
} ofnode;
|
||||
|
||||
ofnode of_first_subnode(ofnode node);
|
||||
ofnode of_next_subnode(ofnode node);
|
||||
int of_node_to_offset(ofnode node);
|
||||
|
||||
int of_fdt_dt_init_bare_nornand(void);
|
||||
int of_fdt_dt_init_bare_mmc(void);
|
||||
#define of_for_each_subnode(node, parent) \
|
||||
for (node = of_first_subnode(parent); \
|
||||
of_node_to_offset(node) >= 0; \
|
||||
node = of_next_subnode(node))
|
||||
|
||||
int of_dtb_is_available(void);
|
||||
void of_relocate_dtb(unsigned long pos);
|
||||
int aic_of_fdt_example(void);
|
||||
bool of_fdt_device_is_available(ofnode node);
|
||||
int of_find_node_by_path(const char *path, ofnode *node);
|
||||
int of_find_subnode(ofnode node, const char *subnode_name, ofnode *subnode);
|
||||
int of_parent_node(ofnode node, ofnode *parent_node);
|
||||
const char *of_get_nodename(ofnode node);
|
||||
int of_get_subnode_by_name(ofnode node, const char *name);
|
||||
int of_read_addr_cells(ofnode node);
|
||||
int of_read_size_cells(ofnode node);
|
||||
int of_node_delete_prop(ofnode node, const char *name);
|
||||
int of_node_write_prop(ofnode node, const char *name, const void *val, int len);
|
||||
int of_node_append_prop_string(ofnode node, const char *name, const void *str);
|
||||
int of_node_append_prop_u32(ofnode node, const char *name, uint32_t val);
|
||||
const int of_property_read_size(ofnode node, const char *name);
|
||||
int of_property_read_u64(ofnode node, const char *name, u64 *data);
|
||||
int of_property_read_u32(ofnode node, const char *name, u32 *data);
|
||||
int of_property_read_u16(ofnode node, const char *name, u16 *data);
|
||||
int of_property_read_u8(ofnode node, const char *name, u8 *data);
|
||||
const int of_property_read_u64_array(ofnode node, const char *name,
|
||||
int *cnt, u64 *data_arr);
|
||||
const int of_property_read_u32_array(ofnode node, const char *name,
|
||||
int *count, u32 *data_array);
|
||||
const int of_property_read_u16_array(ofnode node, const char *name,
|
||||
int *count, u16 *data_array);
|
||||
const int of_property_read_u8_array(ofnode node, const char *name,
|
||||
int *count, u8 *data_array);
|
||||
const int of_property_get_u64_array_number(ofnode node, const char *name,
|
||||
int *cnt);
|
||||
const int of_property_get_u32_array_number(ofnode node, const char *name,
|
||||
int *count);
|
||||
const int of_property_get_u16_array_number(ofnode node, const char *name,
|
||||
int *count);
|
||||
const int of_property_get_u8_array_number(ofnode node, const char *name,
|
||||
int *count);
|
||||
const int of_property_read_u64_by_index(ofnode node, const char *name,
|
||||
int index, u64 *out_value);
|
||||
const int of_property_read_u32_by_index(ofnode node, const char *name,
|
||||
int index, u32 *out_value);
|
||||
const int of_property_read_u16_by_index(ofnode node, const char *name,
|
||||
int index, u16 *out_value);
|
||||
const int of_property_read_u8_by_index(ofnode node, const char *name,
|
||||
int index, u8 *out_value);
|
||||
const bool of_property_read_bool(ofnode node, const char *name);
|
||||
const void *of_property_read_string(ofnode node, const char *name, int *size);
|
||||
const int of_property_read_string_count(ofnode node, const char *name);
|
||||
const char **of_property_read_string_array(ofnode node, const char *name);
|
||||
const int of_property_read_string_index(ofnode node, const char *name,
|
||||
const char *propname, int *index);
|
||||
const char *of_property_read_string_by_index(ofnode node, const char *name,
|
||||
int index);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
BIN
packages/artinchip/of/of_example.dtb
Normal file
BIN
packages/artinchip/of/of_example.dtb
Normal file
Binary file not shown.
Reference in New Issue
Block a user