soc/qualcomm/common: Add CMD-DB driver support
Introduce CMD-DB driver to enable reading command database entries, querying SoC resource data, and providing helper functions required by AOP and other subsystems. Test=Create an image.serial.bin and ensure it boots on X1P42100. Change-Id: I3788bf7c97cc1133ae4893f4fdeaf36882e71276 Signed-off-by: Swathi Tamilselvan <tswathi@qualcomm.corp-partner.google.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/90465 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Subrata Banik <subratabanik@google.com>
This commit is contained in:
parent
2277edff88
commit
01bc527afa
3 changed files with 339 additions and 0 deletions
247
src/soc/qualcomm/common/cmd_db.c
Normal file
247
src/soc/qualcomm/common/cmd_db.c
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <console/console.h>
|
||||
#include <device/mmio.h>
|
||||
#include <string.h>
|
||||
#include <soc/cmd_db.h>
|
||||
#include <types.h>
|
||||
#include <string.h>
|
||||
#include <endian.h>
|
||||
|
||||
/**
|
||||
* struct entry_header: header for each entry in cmd_db
|
||||
*
|
||||
* @id: resource's identifier
|
||||
* @priority: unused
|
||||
* @addr: the address of the resource
|
||||
* @len: length of the data
|
||||
* @offset: offset from :@data_offset, start of the data
|
||||
*/
|
||||
struct entry_header {
|
||||
u8 id[8];
|
||||
u32 priority[NUM_PRIORITY];
|
||||
u32 addr;
|
||||
u16 len;
|
||||
u16 offset;
|
||||
} __packed;
|
||||
/**
|
||||
* struct rsc_hdr: resource header information
|
||||
*
|
||||
* @slv_id: id for the resource
|
||||
* @header_offset: entry's header at offset from the end of the cmd_db_header
|
||||
* @data_offset: entry's data at offset from the end of the cmd_db_header
|
||||
* @cnt: number of entries for HW type
|
||||
* @version: MSB is major, LSB is minor
|
||||
* @reserved: reserved for future use.
|
||||
*/
|
||||
struct rsc_hdr {
|
||||
u16 slv_id;
|
||||
u16 header_offset;
|
||||
u16 data_offset;
|
||||
u16 cnt;
|
||||
u16 version;
|
||||
u16 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct cmd_db_header: The DB header information
|
||||
*
|
||||
* @version: The cmd db version
|
||||
* @magic: constant expected in the database
|
||||
* @header: array of resources
|
||||
* @checksum: checksum for the header. Unused.
|
||||
* @reserved: reserved memory
|
||||
* @data: driver specific data
|
||||
*/
|
||||
struct cmd_db_header {
|
||||
u32 version;
|
||||
u8 magic[4];
|
||||
struct rsc_hdr header[MAX_SLV_ID];
|
||||
u32 checksum;
|
||||
u32 reserved;
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* DOC: Description of the Command DB database.
|
||||
*
|
||||
* At the start of the command DB memory is the cmd_db_header structure.
|
||||
* The cmd_db_header holds the version, checksum, magic key as well as an
|
||||
* array for header for each slave (depicted by the rsc_header). Each h/w
|
||||
* based accelerator is a 'slave' (shared resource) and has slave id indicating
|
||||
* the type of accelerator. The rsc_header is the header for such individual
|
||||
* slaves of a given type. The entries for each of these slaves begin at the
|
||||
* rsc_hdr.header_offset. In addition each slave could have auxiliary data
|
||||
* that may be needed by the driver. The data for the slave starts at the
|
||||
* entry_header.offset to the location pointed to by the rsc_hdr.data_offset.
|
||||
*
|
||||
* Drivers have a stringified key to a slave/resource. They can query the slave
|
||||
* information and get the slave id and the auxiliary data and the length of the
|
||||
* data. Using this information, they can format the request to be sent to the
|
||||
* h/w accelerator and request a resource state.
|
||||
*/
|
||||
|
||||
static const u8 CMD_DB_MAGIC[] = { 0xdb, 0x30, 0x03, 0x0c };
|
||||
|
||||
static struct cmd_db_header *cmd_db_header;
|
||||
|
||||
static bool cmd_db_magic_matches(const struct cmd_db_header *header)
|
||||
{
|
||||
return memcmp(header->magic, CMD_DB_MAGIC, sizeof(CMD_DB_MAGIC)) == 0;
|
||||
}
|
||||
|
||||
static inline const void *rsc_to_entry_header(const struct rsc_hdr *hdr)
|
||||
{
|
||||
u16 offset = hdr->header_offset;
|
||||
return cmd_db_header->data + offset;
|
||||
}
|
||||
|
||||
static inline void *rsc_offset(const struct rsc_hdr *hdr,
|
||||
const struct entry_header *ent)
|
||||
{
|
||||
u16 offset = hdr->data_offset;
|
||||
u16 loffset = ent->offset;
|
||||
|
||||
return cmd_db_header->data + offset + loffset;
|
||||
}
|
||||
|
||||
enum cb_err cmd_db_ready(void)
|
||||
{
|
||||
if (cmd_db_header == NULL)
|
||||
return CB_ERR;
|
||||
else if (!cmd_db_magic_matches(cmd_db_header))
|
||||
return CB_ERR;
|
||||
|
||||
return CB_SUCCESS;
|
||||
}
|
||||
|
||||
static enum cb_err cmd_db_get_header(const char *id,
|
||||
const struct entry_header **eh,
|
||||
const struct rsc_hdr **rh)
|
||||
{
|
||||
const struct rsc_hdr *rsc_hdr;
|
||||
const struct entry_header *ent;
|
||||
enum cb_err ret;
|
||||
int i, j;
|
||||
u8 query[sizeof(ent->id)];
|
||||
size_t id_len;
|
||||
|
||||
ret = cmd_db_ready();
|
||||
if (ret != CB_SUCCESS)
|
||||
return ret;
|
||||
|
||||
memset(query, 0, sizeof(query));
|
||||
id_len = strlen(id);
|
||||
if (id_len > sizeof(query))
|
||||
id_len = sizeof(query);
|
||||
memcpy(query, id, id_len);
|
||||
|
||||
for (i = 0; i < MAX_SLV_ID; i++) {
|
||||
rsc_hdr = &cmd_db_header->header[i];
|
||||
if (!rsc_hdr->slv_id)
|
||||
break;
|
||||
|
||||
ent = rsc_to_entry_header(rsc_hdr);
|
||||
for (j = 0; j < rsc_hdr->cnt; j++, ent++) {
|
||||
if (memcmp(ent->id, query, sizeof(ent->id)) == 0) {
|
||||
if (eh)
|
||||
*eh = ent;
|
||||
if (rh)
|
||||
*rh = rsc_hdr;
|
||||
return CB_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CB_ERR;
|
||||
}
|
||||
|
||||
u32 cmd_db_read_addr(const char *id)
|
||||
{
|
||||
enum cb_err ret;
|
||||
const struct entry_header *ent;
|
||||
|
||||
ret = cmd_db_get_header(id, &ent, NULL);
|
||||
if (ret != CB_SUCCESS)
|
||||
return 0;
|
||||
|
||||
return ent->addr;
|
||||
}
|
||||
|
||||
const void *cmd_db_read_aux_data(const char *id, size_t *len)
|
||||
{
|
||||
enum cb_err ret;
|
||||
const struct entry_header *ent;
|
||||
const struct rsc_hdr *rsc_hdr;
|
||||
|
||||
ret = cmd_db_get_header(id, &ent, &rsc_hdr);
|
||||
if (ret != CB_SUCCESS)
|
||||
return NULL;
|
||||
|
||||
if (len)
|
||||
*len = ent->len;
|
||||
|
||||
return rsc_offset(rsc_hdr, ent);
|
||||
}
|
||||
|
||||
bool cmd_db_match_resource_addr(u32 addr1, u32 addr2)
|
||||
{
|
||||
if (addr1 == addr2)
|
||||
return true;
|
||||
else if (SLAVE_ID(addr1) == CMD_DB_HW_VRM &&
|
||||
VRM_ADDR(addr1) == VRM_ADDR(addr2))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
enum cmd_db_hw_type cmd_db_read_slave_id(const char *id)
|
||||
{
|
||||
enum cb_err ret;
|
||||
const struct entry_header *ent;
|
||||
u32 addr;
|
||||
|
||||
ret = cmd_db_get_header(id, &ent, NULL);
|
||||
if (ret != CB_SUCCESS)
|
||||
return CMD_DB_HW_INVALID;
|
||||
|
||||
addr = ent->addr;
|
||||
return (addr >> SLAVE_ID_SHIFT) & SLAVE_ID_MASK;
|
||||
}
|
||||
|
||||
bool cmd_db_is_standalone(void)
|
||||
{
|
||||
enum cb_err ret = cmd_db_ready();
|
||||
u32 standalone;
|
||||
|
||||
if (ret != CB_SUCCESS)
|
||||
return false;
|
||||
|
||||
standalone = cmd_db_header->reserved & CMD_DB_STANDALONE_MASK;
|
||||
return standalone != 0;
|
||||
}
|
||||
|
||||
enum cb_err cmd_db_init(uintptr_t base, size_t size)
|
||||
{
|
||||
if (base == 0 || size == 0) {
|
||||
printk(BIOS_ERR, "CMD_DB: Invalid base address or size\n");
|
||||
return CB_ERR;
|
||||
}
|
||||
|
||||
/* Map the command DB memory region */
|
||||
cmd_db_header = (struct cmd_db_header *)base;
|
||||
|
||||
if (!cmd_db_magic_matches(cmd_db_header)) {
|
||||
printk(BIOS_ERR, "CMD_DB: Invalid Command DB Magic\n");
|
||||
cmd_db_header = NULL;
|
||||
return CB_ERR;
|
||||
}
|
||||
|
||||
printk(BIOS_DEBUG, "CMD_DB: Initialized at 0x%lx, size: 0x%zx\n",
|
||||
base, size);
|
||||
|
||||
if (cmd_db_is_standalone())
|
||||
printk(BIOS_DEBUG, "CMD_DB: Running in standalone mode\n");
|
||||
|
||||
return CB_SUCCESS;
|
||||
}
|
||||
91
src/soc/qualcomm/common/include/soc/cmd_db.h
Normal file
91
src/soc/qualcomm/common/include/soc/cmd_db.h
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef __SOC_QUALCOMM_CMD_DB_H__
|
||||
#define __SOC_QUALCOMM_CMD_DB_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#define NUM_PRIORITY 2
|
||||
#define MAX_SLV_ID 8
|
||||
#define SLAVE_ID_MASK 0x7
|
||||
#define SLAVE_ID_SHIFT 16
|
||||
#define CMD_DB_STANDALONE_MASK BIT(0)
|
||||
|
||||
#define SLAVE_ID(addr) (((addr) >> 16) & 0xF)
|
||||
#define VRM_ADDR(addr) (((addr) >> 4) & 0xFFFF)
|
||||
|
||||
enum cmd_db_hw_type {
|
||||
CMD_DB_HW_INVALID = 0,
|
||||
CMD_DB_HW_MIN = 3,
|
||||
CMD_DB_HW_ARC = CMD_DB_HW_MIN,
|
||||
CMD_DB_HW_VRM = 4,
|
||||
CMD_DB_HW_BCM = 5,
|
||||
CMD_DB_HW_MAX = CMD_DB_HW_BCM,
|
||||
CMD_DB_HW_ALL = 0xff,
|
||||
};
|
||||
|
||||
/**
|
||||
* cmd_db_ready - Indicates if command DB is available
|
||||
*
|
||||
* Return: CB_SUCCESS on success, CB_ERR otherwise
|
||||
*/
|
||||
enum cb_err cmd_db_ready(void);
|
||||
|
||||
/**
|
||||
* cmd_db_read_addr() - Query command db for resource id address.
|
||||
*
|
||||
* @id: resource id to query for address
|
||||
*
|
||||
* Return: resource address on success, 0 on error
|
||||
*
|
||||
* This is used to retrieve resource address based on resource id.
|
||||
*/
|
||||
u32 cmd_db_read_addr(const char *id);
|
||||
|
||||
/**
|
||||
* cmd_db_read_aux_data() - Query command db for aux data.
|
||||
*
|
||||
* @id: Resource to retrieve AUX Data on
|
||||
* @len: size of data buffer returned
|
||||
*
|
||||
* Return: pointer to data on success, NULL otherwise
|
||||
*/
|
||||
const void *cmd_db_read_aux_data(const char *id, size_t *len);
|
||||
|
||||
/**
|
||||
* cmd_db_match_resource_addr() - Compare if both Resource addresses are same
|
||||
*
|
||||
* @addr1: Resource address to compare
|
||||
* @addr2: Resource address to compare
|
||||
*
|
||||
* Return: true if two addresses refer to the same resource, false otherwise
|
||||
*/
|
||||
bool cmd_db_match_resource_addr(u32 addr1, u32 addr2);
|
||||
|
||||
/**
|
||||
* cmd_db_read_slave_id - Get the slave ID for a given resource address
|
||||
*
|
||||
* @id: Resource id to query the DB for version
|
||||
*
|
||||
* Return: cmd_db_hw_type enum on success, CMD_DB_HW_INVALID on error
|
||||
*/
|
||||
enum cmd_db_hw_type cmd_db_read_slave_id(const char *id);
|
||||
|
||||
/**
|
||||
* cmd_db_is_standalone - Check if command DB is in standalone mode
|
||||
*
|
||||
* Return: true if standalone, false otherwise
|
||||
*/
|
||||
bool cmd_db_is_standalone(void);
|
||||
|
||||
/**
|
||||
* cmd_db_init - Initialize the command DB
|
||||
*
|
||||
* @base: Physical base address of the command DB memory region
|
||||
* @size: Size of the command DB memory region
|
||||
*
|
||||
* Return: CB_SUCCESS on success, CB_ERR otherwise
|
||||
*/
|
||||
enum cb_err cmd_db_init(uintptr_t base, size_t size);
|
||||
|
||||
#endif /* __SOC_QUALCOMM_CMD_DB_H__ */
|
||||
|
|
@ -52,6 +52,7 @@ ramstage-$(CONFIG_PCI) += ../common/pcie_common.c
|
|||
ramstage-y += ../common/spmi.c
|
||||
ramstage-$(CONFIG_PCI) += pcie.c
|
||||
ramstage-y += cpucp_load_reset.c
|
||||
ramstage-y += ../common/cmd_db.c
|
||||
|
||||
################################################################################
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue