Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions arch/arm/mach-snapdragon/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@

obj-y += board.o
obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += capsule_update.o
obj-$(CONFIG_OF_LIVE) += qcom_fixup_ddrinfo.o
obj-$(CONFIG_OF_LIVE) += of_fixup.o
82 changes: 82 additions & 0 deletions arch/arm/mach-snapdragon/of_fixup.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <stdlib.h>
#include <tee/optee.h>
#include <time.h>
#include "qcom_fixup_handlers.h"

/**
* find_ssphy_node() - Find the super-speed PHY node referenced by DWC3
Expand Down Expand Up @@ -283,5 +284,86 @@ EVENT_SPY_FULL(EVT_OF_LIVE_BUILT, qcom_of_fixup_nodes);

int ft_board_setup(void __maybe_unused *blob, struct bd_info __maybe_unused *bd)
{
struct fdt_header *fdt = blob;

ddrinfo_fixup_handler(fdt);

return 0;
}

int fixup_dt_node(void *fdt_ptr, int node_offset,
const char *property_name,
void *property_value,
enum fdt_fixup_type type)
{
int ret;

if ((!fdt_ptr || node_offset < 0) ||
(!property_value && type != ADD_SUBNODE))
return -1;

switch (type) {
case APPEND_PROP_U32:
fdt_set_totalsize(fdt_ptr,
(fdt_totalsize(fdt_ptr)
+ sizeof(struct fdt_property)
+ strlen(property_name) + 3
+ sizeof(u32)));
ret = fdt_appendprop_u32(fdt_ptr, node_offset,
property_name,
*(u32 *)property_value);
break;
case APPEND_PROP_U64:
fdt_set_totalsize(fdt_ptr,
(fdt_totalsize(fdt_ptr)
+ sizeof(struct fdt_property)
+ strlen(property_name) + 3
+ sizeof(u64)));
ret = fdt_appendprop_u64(fdt_ptr, node_offset,
property_name,
*(u64 *)property_value);
break;
case SET_PROP_U32:
fdt_set_totalsize(fdt_ptr,
(fdt_totalsize(fdt_ptr)
+ sizeof(struct fdt_property)
+ strlen(property_name) + 3
+ sizeof(u32)));
ret = fdt_setprop_u32(fdt_ptr, node_offset,
property_name,
*(u32 *)property_value);
break;
case SET_PROP_U64:
fdt_set_totalsize(fdt_ptr,
(fdt_totalsize(fdt_ptr)
+ sizeof(struct fdt_property)
+ strlen(property_name) + 3
+ sizeof(u64)));
ret = fdt_setprop_u64(fdt_ptr, node_offset,
property_name,
*(u64 *)property_value);
break;
case SET_PROP_STRING:
fdt_set_totalsize(fdt_ptr,
(fdt_totalsize(fdt_ptr)
+ sizeof(struct fdt_property)
+ strlen(property_name) + 3
+ strlen((char *)property_value)));
ret = fdt_setprop_string(fdt_ptr, node_offset,
property_name,
(char *)property_value);
break;
case ADD_SUBNODE:
fdt_set_totalsize(fdt_ptr,
(fdt_totalsize(fdt_ptr)
+ sizeof(struct fdt_property)
+ strlen(property_name) + 3));
ret = fdt_add_subnode(fdt_ptr, node_offset,
property_name);
break;
default:
ret = -1;
}

return ret;
}
161 changes: 161 additions & 0 deletions arch/arm/mach-snapdragon/qcom_fixup_ddrinfo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* DDRInfo Fixup
*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*
*/

#include <dm.h>
#include <smem.h>
#include <string.h>
#include <linux/libfdt.h>
#include "qcom_fixup_handlers.h"
#include "qcom-priv.h"

/* With the new SMEM architecture, SMEM IDs need to be defined in individual
* driver files
*/
#define SMEM_ID_DDRINFO 0x25B // 603

struct ddr_details_entry {
u8 manufacturer_id;
u8 device_type;
};

/**
* get_ddr_details() - Retrieves the DDR details entry from the SMEM.
* @ddr_detail: The DDR details entry to retrieve.
*
* This function retrieves the DDR details entry from the SMEM and prints it
* out.
*
* Return: 0 on success, -1 on failure
*/
static int get_ddr_details(struct ddr_details_entry *ddr_detail)
{
void *ddr_table_ptr;
struct udevice *dev;
size_t size;

if (uclass_get_device(UCLASS_SMEM, 0, &dev) != 0)
return log_msg_ret("Error: uclass_get_device\n", -1);
ddr_table_ptr = smem_get(dev, 0, SMEM_ID_DDRINFO, &size);

if (!ddr_table_ptr)
return log_msg_ret("Error: invalid DDR Entry\n", -1);
memcpy((void *)ddr_detail, ddr_table_ptr, sizeof(struct ddr_details_entry));

return 0;
}

/**
* set_mem_reg_node() - Sets the ram partition info to memory node
* @fdt_ptr: Pointer to the device tree
* @path_offset: Offset to the memory node
* @start_addr: Start address of the mem partition
* @mem_size: Size of the mem partition
*
* This function is responsible for setting the reg property of memory node
* in the device tree
*
* Return: 0 on success, -1 on failure
*/
static int set_mem_reg_node(struct fdt_header *fdt_ptr, u32 path_offset,
u64 start_addr, u64 mem_size)
{
int ret;

log_debug("Mem info start addr: %llx ,size %llx\n", start_addr, mem_size);
ret = fixup_dt_node(fdt_ptr, path_offset, "reg",
(void *)(&start_addr), APPEND_PROP_U64);
if (ret)
return log_msg_ret("Failed to append start_addr details in Reg prop\n", -1);

ret = fixup_dt_node(fdt_ptr, path_offset, "reg",
(void *)(&mem_size), APPEND_PROP_U64);
if (ret)
return log_msg_ret("Failed to append mem_size details in Reg prop\n", -1);

return 0;
}

/**
* set_ram_part_info() - Gets the ram partition info from smem and sets
* it to memory node
* @fdt_ptr: Pointer to the device tree
* @path_offset: Offset to the memory node
*
* This function is responsible for obtaining ram partition information info
* from smem and sets it to the device tree
* tree.
*
* Return: 0 on success, -1 on failure
*/
static int set_ram_part_info(struct fdt_header *fdt_ptr, u32 path_offset)
{
int ret = 0, res, part;
struct usable_ram_partition_table *rpt;
struct ram_partition_entry *rpe;

rpt = qcom_get_ram_partitions();
if (!rpt)
return -1;
rpe = &rpt->ram_part_entry[0];

for (part = 0; part < rpt->num_partitions; part++, rpe++)
if (rpe->partition_category == RAM_PARTITION_SDRAM &&
rpe->partition_type == RAM_PARTITION_SYS_MEMORY) {
res = set_mem_reg_node(fdt_ptr, path_offset,
rpe->start_address,
rpe->available_length);
if (res) {
log_err("Failed to set Mem info start addr: %llx ,size %llx\n",
rpe->start_address, rpe->available_length);
ret = -1;
}
}

return ret;
}

/**
* ddrinfo_fixup_handler() - DDRInfo Fixup handler function
* @fdt_ptr: Pointer to the device tree
*
* This function is responsible for updating the DDR information in the device
* tree.
*/
void ddrinfo_fixup_handler(struct fdt_header *fdt_ptr)
{
u32 path_offset, ret;
u64 prop_value;
struct ddr_details_entry ddr_details;

ret = get_ddr_details(&ddr_details);
if (ret) {
log_err("Error getting DDR details\n");
return;
}

path_offset = fdt_path_offset(fdt_ptr, "/memory");
if (path_offset < 0) {
log_err("Error getting memory offset: %d\n", path_offset);
return;
}

prop_value = (u64)ddr_details.device_type;
ret = fixup_dt_node(fdt_ptr, path_offset, "ddr_device_type",
(void *)(&prop_value), APPEND_PROP_U64);
if (ret)
log_err("Failed to append DDR device type data : %d\n", ret);

ret = fdt_delprop(fdt_ptr, path_offset, "reg");
if (!ret) {
ret = set_ram_part_info(fdt_ptr, path_offset);
if (ret)
log_err("set_ram_part_info failed");
}
}

/* End of File */
46 changes: 46 additions & 0 deletions arch/arm/mach-snapdragon/qcom_fixup_handlers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* SUBSET Parts Fixup: A tool for fixing up subset parts in a system
*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*
*/

#include <linux/libfdt.h>

enum fdt_fixup_type {
APPEND_PROP_U32 = 0,
APPEND_PROP_U64 = 1,
SET_PROP_U32 = 2,
SET_PROP_U64 = 3,
SET_PROP_STRING = 4,
ADD_SUBNODE = 5,
};

/**
* ddrinfo_fixup_handler() - DDRInfo Fixup handler function
* @fdt_ptr: Pointer to the device tree
*
* This function is responsible for updating the DDR information in
* the device tree.
*
* Return: None
*/
void ddrinfo_fixup_handler(struct fdt_header *fdt_ptr);

/**
* fixup_dt_node() - Exports a property to the firmware DT node.
* @fdt_ptr: The firmware DT node to update.
* @node_offset: The offset in the DT node where the property should be set.
* @property_name: The name of the property to set.
* @property_value: The value of the property to set.
* @type: Fixup type
* This function sets a property in the firmware DT node with the given name and
* value.
*
* Return: 0 on success, negative on failure.
*/
int fixup_dt_node(void *fdt_ptr, int node_offset,
const char *property_name,
void *property_value,
enum fdt_fixup_type type);