From 871caf2276a4b415b92abb82fc364ad7f12e041b Mon Sep 17 00:00:00 2001 From: Antony Arun T Date: Thu, 17 Jan 2019 13:38:40 +0530 Subject: [PATCH] ipq6018: Support for new smem version Change-Id: I2e847eface6d5604ff30ce245e767b8a9d923500 Signed-off-by: Antony Arun T --- arch/arm/cpu/armv7/qca/common/smem.c | 279 ++++++++++++++++++++++++++- board/qca/arm/common/board_init.c | 29 +++ board/qca/arm/ipq6018/ipq6018.h | 43 +++++ include/configs/ipq6018.h | 4 +- 4 files changed, 353 insertions(+), 2 deletions(-) diff --git a/arch/arm/cpu/armv7/qca/common/smem.c b/arch/arm/cpu/armv7/qca/common/smem.c index 32e081095a..e16dc64e8e 100644 --- a/arch/arm/cpu/armv7/qca/common/smem.c +++ b/arch/arm/cpu/armv7/qca/common/smem.c @@ -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; diff --git a/board/qca/arm/common/board_init.c b/board/qca/arm/common/board_init.c index 05592e32e9..0606656423 100644 --- a/board/qca/arm/common/board_init.c +++ b/board/qca/arm/common/board_init.c @@ -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 && diff --git a/board/qca/arm/ipq6018/ipq6018.h b/board/qca/arm/ipq6018/ipq6018.h index b8d8b08e08..ea2ea07e04 100644 --- a/board/qca/arm/ipq6018/ipq6018.h +++ b/board/qca/arm/ipq6018/ipq6018.h @@ -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; diff --git a/include/configs/ipq6018.h b/include/configs/ipq6018.h index 8bdbf983cc..0441ee76fe 100644 --- a/include/configs/ipq6018.h +++ b/include/configs/ipq6018.h @@ -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