ipq6018: Support for new smem version

Change-Id: I2e847eface6d5604ff30ce245e767b8a9d923500
Signed-off-by: Antony Arun T <antothom@codeaurora.org>
This commit is contained in:
Antony Arun T 2019-01-17 13:38:40 +05:30
parent e4c52487fd
commit 871caf2276
4 changed files with 353 additions and 2 deletions

View file

@ -140,6 +140,236 @@ static struct smem *smem = (void *)(CONFIG_QCA_SMEM_BASE);
qca_smem_flash_info_t qca_smem_flash_info;
qca_smem_bootconfig_info_t qca_smem_bootconfig_info;
#ifdef CONFIG_SMEM_VERSION_C
#define SMEM_COMMON_HOST 0xFFFE
#ifndef CONFIG_QCA_SMEM_SIZE
#define CONFIG_QCA_SMEM_SIZE 0x100000
#endif
enum {
smem_enu_sucess,
smem_enu_failed,
smem_enu_no_init
};
u8 smem_enumeration_status = smem_enu_no_init;
/**
* struct smem_ptable_entry - one entry in the @smem_ptable list
* @offset: offset, within the main shared memory region, of the partition
* @size: size of the partition
* @flags: flags for the partition (currently unused)
* @host0: first processor/host with access to this partition
* @host1: second processor/host with access to this partition
* @reserved: reserved entries for later use
*/
struct smem_ptable_entry {
__le32 offset;
__le32 size;
__le32 flags;
__le16 host0;
__le16 host1;
__le32 reserved[8];
};
/**
* struct smem_private_ptable - partition table for the private partitions
* @magic: magic number, must be SMEM_PTABLE_MAGIC
* @version: version of the partition table
* @num_entries: number of partitions in the table
* @reserved: for now reserved entries
* @entry: list of @smem_ptable_entry for the @num_entries partitions
*/
struct smem_private_ptable {
u8 magic[4];
__le32 version;
__le32 num_entries;
__le32 reserved[5];
struct smem_ptable_entry entry[];
};
/**
* struct smem_private_entry - header of each item in the private partition
* @canary: magic number, must be SMEM_PRIVATE_CANARY
* @item: identifying number of the smem item
* @size: size of the data, including padding bytes
* @padding_data: number of bytes of padding of data
* @padding_hdr: number of bytes of padding between the header and the data
* @reserved: for now reserved entry
*/
struct smem_private_entry {
u16 canary; /* bytes are the same so no swapping needed */
__le16 item;
__le32 size; /* includes padding bytes */
__le16 padding_data;
__le16 padding_hdr;
__le32 reserved;
};
#define SMEM_PRIVATE_CANARY 0xa5a5
static const u8 SMEM_PTABLE_MAGIC[] = { 0x24, 0x54, 0x4f, 0x43 }; /* "$TOC" */
/**
* struct smem_partition_header - header of the partitions
* @magic: magic number, must be SMEM_PART_MAGIC
* @host0: first processor/host with access to this partition
* @host1: second processor/host with access to this partition
* @size: size of the partition
* @offset_free_uncached: offset to the first free byte of uncached memory in
* this partition
* @offset_free_cached: offset to the first free byte of cached memory in this
* partition
* @reserved: for now reserved entries
*/
struct smem_partition_header {
u8 magic[4];
__le16 host0;
__le16 host1;
__le32 size;
__le32 offset_free_uncached;
__le32 offset_free_cached;
__le32 reserved[3];
};
static const u8 SMEM_PART_MAGIC[] = { 0x24, 0x50, 0x52, 0x54 }; /*$PRT*/
struct smem_partition_header *smem_cmn_partition;
/* Pointer to the one and only smem handle */
static struct smem_private_entry *
phdr_to_first_private_entry(struct smem_partition_header *phdr)
{
void *p = phdr;
return p + sizeof(*phdr);
}
static struct smem_private_entry *
phdr_to_last_private_entry(struct smem_partition_header *phdr)
{
void *p = phdr;
return p + le32_to_cpu(phdr->offset_free_uncached);
}
static struct smem_private_entry *
private_entry_next(struct smem_private_entry *e)
{
void *p = e;
return p + sizeof(*e) + le16_to_cpu(e->padding_hdr) +
le32_to_cpu(e->size);
}
static void *entry_to_item(struct smem_private_entry *e)
{
void *p = e;
return p + sizeof(*e) + le16_to_cpu(e->padding_hdr);
}
static void *qcom_smem_get_private(struct smem_partition_header *phdr,
unsigned item,
size_t *size)
{
struct smem_private_entry *e, *end;
e = phdr_to_first_private_entry(phdr);
end = phdr_to_last_private_entry(phdr);
while (e < end) {
if (e->canary != SMEM_PRIVATE_CANARY) {
printf("Found invalid canary in\
host common partition\n");
return -EINVAL;
}
if (le16_to_cpu(e->item) == item) {
if (size != NULL)
*size = le32_to_cpu(e->size) -
le16_to_cpu(e->padding_data);
return entry_to_item(e);
}
e = private_entry_next(e);
}
return -ENOENT;
}
static int qcom_smem_enumerate_partitions()
{
struct smem_partition_header *header;
struct smem_ptable_entry *entry;
struct smem_private_ptable *ptable;
u32 version, host0, host1;
int i;
ptable = CONFIG_QCA_SMEM_BASE + CONFIG_QCA_SMEM_SIZE - SZ_4K;
if (memcmp(ptable->magic, SMEM_PTABLE_MAGIC, sizeof(ptable->magic)))
return -EINVAL;
version = le32_to_cpu(ptable->version);
if (version != 1) {
printf("Unsupported partition header version %d\n", version);
return -EINVAL;
}
for (i = 0; i < le32_to_cpu(ptable->num_entries); i++) {
entry = &ptable->entry[i];
host0 = le16_to_cpu(entry->host0);
host1 = le16_to_cpu(entry->host1);
if (host0 != SMEM_COMMON_HOST || host1 != SMEM_COMMON_HOST)
continue;
if (!le32_to_cpu(entry->offset))
continue;
printf("\noffset: 0X%X %u", entry->offset, entry->offset);
if (!le32_to_cpu(entry->size))
continue;
printf("\nsize: 0X%X %u", entry->size, entry->size);
if (smem_cmn_partition) {
printf("Already found a partition for host %x \n",
SMEM_COMMON_HOST);
return -EINVAL;
}
header = CONFIG_QCA_SMEM_BASE + le32_to_cpu(entry->offset);
host0 = le16_to_cpu(header->host0);
host1 = le16_to_cpu(header->host1);
if (memcmp(header->magic, SMEM_PART_MAGIC,
sizeof(header->magic))) {
printf("Partition %d has invalid magic\n", i);
return -EINVAL;
}
if (host0 != SMEM_COMMON_HOST || host1 != SMEM_COMMON_HOST) {
printf("Partition %d hosts are invalid\n", i);
return -EINVAL;
}
if (header->size != entry->size) {
printf("Partition %d has invalid size\n", i);
return -EINVAL;
}
if (le32_to_cpu(header->offset_free_uncached) > le32_to_cpu(header->size)) {
printf("Partition %d has invalid free pointer\n", i);
return -EINVAL;
}
smem_cmn_partition = header;
}
smem_enumeration_status = smem_enu_sucess;
return 0;
}
#endif
/**
* smem_read_alloc_entry - reads an entry from SMEM
* @type: the entry to read
@ -157,7 +387,10 @@ unsigned smem_read_alloc_entry(smem_mem_type_t type, void *buf, int len)
unsigned *dest = buf;
unsigned src;
unsigned size;
#ifdef CONFIG_SMEM_VERSION_C
void *ptr;
int ret;
#endif
if (((len & 0x3) != 0) || (((unsigned)buf & 0x3) != 0))
return 1;
@ -167,6 +400,27 @@ unsigned smem_read_alloc_entry(smem_mem_type_t type, void *buf, int len)
return 1;
}
#ifdef CONFIG_SMEM_VERSION_C
if(smem_enumeration_status == smem_enu_no_init) {
ret = qcom_smem_enumerate_partitions();
if (ret) {
printf("Common SMEM Partition is not available\n");
smem_enumeration_status = smem_enu_failed;
return ret;
}
}
if ( smem_enumeration_status == smem_enu_sucess) {
ptr = qcom_smem_get_private(smem_cmn_partition,type, &size);
if (IS_ERR(ptr)) {
ret = PTR_ERR(ptr);
return ret;
}
memcpy(dest, ptr, len);
return 0;
}
return -EINVAL;
#endif
ainfo = &smem->alloc_info[type];
if (readl(&ainfo->allocated) == 0)
{
@ -572,6 +826,29 @@ int smem_ram_ptable_init(struct smem_ram_ptable *smem_ram_ptable)
return 1;
}
/*
* smem_ptable_init - initializes RAM partition table from SMEM
*
*/
#ifdef CONFIG_SMEM_VERSION_C
int smem_ram_ptable_init_v2(struct usable_ram_partition_table *usable_ram_partition_table)
{
unsigned i;
i = smem_read_alloc_entry(SMEM_USABLE_RAM_PARTITION_TABLE,
usable_ram_partition_table,
sizeof(struct usable_ram_partition_table));
if (i != 0)
return 0;
if (usable_ram_partition_table->magic1 != _SMEM_RAM_PTABLE_MAGIC_1 ||
usable_ram_partition_table->magic2 != _SMEM_RAM_PTABLE_MAGIC_2) {
return 0;
}
return 1;
}
#endif
void qca_smem_part_to_mtdparts(char *mtdid, int len)
{
qca_smem_flash_info_t *sfi = &qca_smem_flash_info;

View file

@ -372,6 +372,30 @@ int board_late_init(void)
return 0;
}
#ifdef CONFIG_SMEM_VERSION_C
int ram_ptable_init_v2()
{
struct usable_ram_partition_table rtable;
int mx = ARRAY_SIZE(rtable.ram_part_entry);
int i, ret;
if (smem_ram_ptable_init_v2(&rtable) > 0) {
gd->ram_size = 0;
for (i = 0; i < mx; i++) {
if (rtable.ram_part_entry[i].partition_category == RAM_PARTITION_SDRAM &&
rtable.ram_part_entry[i].partition_type == RAM_PARTITION_SYS_MEMORY) {
gd->ram_size += rtable.ram_part_entry[i].length;
return 0;
}
}
} else {
gd->ram_size = fdtdec_get_uint(gd->fdt_blob, 0, "ddr_size", 256);
gd->ram_size <<= 20;
}
return 0;
}
#endif
int dram_init(void)
{
struct smem_ram_ptable rtable;
@ -379,6 +403,11 @@ int dram_init(void)
int mx = ARRAY_SIZE(rtable.parts);
if (smem_ram_ptable_init(&rtable) > 0) {
#ifdef CONFIG_SMEM_VERSION_C
if (rtable.version == 2) {
return ram_ptable_init_v2();
}
#endif
gd->ram_size = 0;
for (i = 0; i < mx; i++) {
if (rtable.parts[i].category == RAM_PARTITION_SDRAM &&

View file

@ -192,6 +192,49 @@
#define GCC_PCIE0_RCHNG_CMD_RCGR 0x01875070
#define GCC_PCIE0_RCHNG_CFG_RCGR 0x01875074
#ifdef CONFIG_SMEM_VERSION_C
#define RAM_PART_NAME_LENGTH 16
/**
* Number of RAM partition entries which are usable by APPS.
*/
#define RAM_NUM_PART_ENTRIES 32
struct ram_partition_entry
{
char name[RAM_PART_NAME_LENGTH]; /**< Partition name, unused for now */
u64 start_address; /**< Partition start address in RAM */
u64 length; /**< Partition length in RAM in Bytes */
u32 partition_attribute; /**< Partition attribute */
u32 partition_category; /**< Partition category */
u32 partition_domain; /**< Partition domain */
u32 partition_type; /**< Partition type */
u32 num_partitions; /**< Number of partitions on device */
u32 hw_info; /**< hw information such as type and frequency */
u8 highest_bank_bit; /**< Highest bit corresponding to a bank */
u8 reserve0; /**< Reserved for future use */
u8 reserve1; /**< Reserved for future use */
u8 reserve2; /**< Reserved for future use */
u32 reserved5; /**< Reserved for future use */
u64 available_length; /**< Available Partition length in RAM in Bytes */
};
struct usable_ram_partition_table
{
u32 magic1; /**< Magic number to identify valid RAM partition table */
u32 magic2; /**< Magic number to identify valid RAM partition table */
u32 version; /**< Version number to track structure definition changes
and maintain backward compatibilities */
u32 reserved1; /**< Reserved for future use */
u32 num_partitions; /**< Number of RAM partition table entries */
u32 reserved2; /** < Added for 8 bytes alignment of header */
/** RAM partition table entries */
struct ram_partition_entry ram_part_entry[RAM_NUM_PART_ENTRIES];
};
#endif
struct smem_ram_ptn {
char name[16];
unsigned long long start;

View file

@ -96,7 +96,9 @@
#define CONFIG_OF_COMBINE 1
#define CONFIG_QCA_SMEM_BASE 0x4AB00000
#define CONFIG_SMEM_VERSION_C
#define CONFIG_QCA_SMEM_BASE 0x48C00000
#define CONFIG_QCA_SMEM_SIZE 0x100000
#define CONFIG_IPQ_FDT_HIGH 0x48700000
#define CONFIG_IPQ_NO_MACS 6