From e43c58af5d9c01c45fe97e10809849bad98385a0 Mon Sep 17 00:00:00 2001 From: Ivan Priest Date: Thu, 22 Nov 2018 13:56:11 +0000 Subject: [PATCH] [NEUS7920-477] wlbt: Load optional Common HCF Load HCF files for Common configuration, and pass to Common FW via the mxconf structure. Change-Id: Idc196e11454118c8410a4b3895d538dfdd19d7f3 SCSC-Bug-Id: SSB-46627 Signed-off-by: Ivan Priest --- drivers/misc/samsung/scsc/Kconfig | 7 + drivers/misc/samsung/scsc/Makefile | 5 +- drivers/misc/samsung/scsc/mxconf.h | 19 +- drivers/misc/samsung/scsc/mxfwconfig.c | 224 ++++++++++++++++++ drivers/misc/samsung/scsc/mxfwconfig.h | 35 +++ drivers/misc/samsung/scsc/mxman.c | 11 +- drivers/misc/samsung/scsc/scsc_logring_main.c | 2 + drivers/misc/samsung/scsc/scsc_mx_impl.c | 9 + drivers/misc/samsung/scsc/scsc_mx_impl.h | 3 + include/scsc/scsc_logring.h | 1 + 10 files changed, 311 insertions(+), 5 deletions(-) create mode 100644 drivers/misc/samsung/scsc/mxfwconfig.c create mode 100644 drivers/misc/samsung/scsc/mxfwconfig.h diff --git a/drivers/misc/samsung/scsc/Kconfig b/drivers/misc/samsung/scsc/Kconfig index 3b30cb008c85..4e7e3f8f84c8 100644 --- a/drivers/misc/samsung/scsc/Kconfig +++ b/drivers/misc/samsung/scsc/Kconfig @@ -162,3 +162,10 @@ config SCSC_LOG_COLLECTION ---help--- Enable LOG collection to collect Chunks (host and FW) and generate a SBL file +config SCSC_COMMON_HCF + bool "Enable Common HCF loader" + depends on SCSC_CORE + default n + ---help--- + Enable Common HCF loader + diff --git a/drivers/misc/samsung/scsc/Makefile b/drivers/misc/samsung/scsc/Makefile index a5fdb79ba5ee..920c71a71bbb 100644 --- a/drivers/misc/samsung/scsc/Makefile +++ b/drivers/misc/samsung/scsc/Makefile @@ -87,8 +87,9 @@ scsc_mx-$(CONFIG_SCSC_CORE_CM) += \ mifstream.o \ mxmgmt_transport.o \ gdb_transport.o \ - mx140_file.o \ - scsc_lerna.o + scsc_lerna.o \ + mxfwconfig.o \ + mx140_file.o # Maxwell logger scsc_mx-$(CONFIG_SCSC_MXLOGGER) += mxlogger.o diff --git a/drivers/misc/samsung/scsc/mxconf.h b/drivers/misc/samsung/scsc/mxconf.h index d263bb1b4a02..1a566dbc2ea3 100644 --- a/drivers/misc/samsung/scsc/mxconf.h +++ b/drivers/misc/samsung/scsc/mxconf.h @@ -48,7 +48,7 @@ * mismatches. */ #define MXCONF_VERSION_MAJOR 0 -#define MXCONF_VERSION_MINOR 3 /* For FM status */ +#define MXCONF_VERSION_MINOR 4 /* For Common HCF override */ /* Types */ @@ -107,6 +107,16 @@ struct mxlogconf struct mxstreamconf stream_conf; } __MXPACKED; + +/** + * Maxwell Infrastructure Configuration Override (HCF block) + */ +struct mxmibref { + uint32_t offset; + uint32_t size; +} __MXPACKED; + + /** * Maxwell Infrastructure Configuration */ @@ -158,6 +168,13 @@ struct mxconf { #define MXCONF_FLAGS_FM_ON (BIT(0)) /* FM already on */ uint32_t flags; + /* FROM MINOR_4 */ + + /** + * Common HCF offset + */ + struct mxmibref fwconfig; + } __MXPACKED; #endif /* MXCONF_H__ */ diff --git a/drivers/misc/samsung/scsc/mxfwconfig.c b/drivers/misc/samsung/scsc/mxfwconfig.c new file mode 100644 index 000000000000..fa6ec7d01181 --- /dev/null +++ b/drivers/misc/samsung/scsc/mxfwconfig.c @@ -0,0 +1,224 @@ +/***************************************************************************** + * + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved + * + ****************************************************************************/ + +#include +#include + +#include "mxfwconfig.h" +#include "miframman.h" +#include "scsc_mx_impl.h" +#include "mxconf.h" + +#ifdef CONFIG_SCSC_LOG_COLLECTION +#include +#endif + +#define MXFWCONFIG_CFG_SUBDIR "common" +#define MXFWCONFIG_CFG_FILE_HW "common.hcf" +#define MXFWCONFIG_CFG_FILE_SW "common_sw.hcf" + +static void mxfwconfig_get_dram_ref(struct scsc_mx *mx, struct mxmibref *cfg_ref); + +/* Load config into non-shared DRAM */ +static int mxfwconfig_load_cfg(struct scsc_mx *mx, struct mxfwconfig *cfg, const char *filename) +{ + int r = 0; + u32 i; + + if (cfg->configs >= SCSC_MX_MAX_COMMON_CFG) { + SCSC_TAG_ERR(MX_CFG, "Too many common config files (%u)\n", cfg->configs); + return -E2BIG; + } + + i = cfg->configs++; /* Claim next config slot */ + + /* Load config file from file system into DRAM */ + r = mx140_file_request_conf(mx, &cfg->config[i].fw, MXFWCONFIG_CFG_SUBDIR, filename); + if (r) + return r; + + /* Initial size of file */ + cfg->config[i].cfg_len = cfg->config[i].fw->size; + cfg->config[i].cfg_data = cfg->config[i].fw->data; + + /* Validate file in DRAM */ + if (cfg->config[i].cfg_len >= MX_COMMON_HCF_HDR_SIZE && /* Room for header */ + /*(cfg->config[i].cfg[6] & 0xF0) == 0x10 && */ /* Curator subsystem */ + cfg->config[i].cfg_data[7] == 1) { /* First file format */ + int j; + + cfg->config[i].cfg_hash = 0; + + /* Calculate hash */ + for (j = 0; j < MX_COMMON_HASH_SIZE_BYTES; j++) { + cfg->config[i].cfg_hash = + (cfg->config[i].cfg_hash << 8) | cfg->config[i].cfg_data[j + MX_COMMON_HASH_OFFSET]; + } + + SCSC_TAG_INFO(MX_CFG, "CFG hash: 0x%.04x\n", cfg->config[i].cfg_hash); + + /* All good - consume header and continue */ + cfg->config[i].cfg_len -= MX_COMMON_HCF_HDR_SIZE; + cfg->config[i].cfg_data += MX_COMMON_HCF_HDR_SIZE; + } else { + SCSC_TAG_ERR(MX_CFG, "Invalid HCF header size %zu\n", cfg->config[i].cfg_len); + + /* Caller must call mxfwconfig_unload_cfg() to release the buffer */ + return -EINVAL; + } + + /* Running shtotal payload */ + cfg->shtotal += cfg->config[i].cfg_len; + + SCSC_TAG_INFO(MX_CFG, "Loaded common config %s, size %zu, payload size %zu, shared dram total %zu\n", + filename, cfg->config[i].fw->size, cfg->config[i].cfg_len, cfg->shtotal); + + return r; +} + +/* Unload config from non-shared DRAM */ +static int mxfwconfig_unload_cfg(struct scsc_mx *mx, struct mxfwconfig *cfg, u32 index) +{ + if (index >= SCSC_MX_MAX_COMMON_CFG) { + SCSC_TAG_ERR(MX_CFG, "Out of range index (%u)\n", index); + return -E2BIG; + } + + if (cfg->config[index].fw) { + SCSC_TAG_DBG3(MX_CFG, "Unload common config %u\n", index); + + mx140_file_release_conf(mx, cfg->config[index].fw); + + cfg->config[index].fw = NULL; + cfg->config[index].cfg_data = NULL; + cfg->config[index].cfg_len = 0; + } + + return 0; +} + +/* + * Load Common config files + */ +int mxfwconfig_load(struct scsc_mx *mx, struct mxmibref *cfg_ref) +{ + struct mxfwconfig *cfg = scsc_mx_get_mxfwconfig(mx); + struct miframman *miframman = scsc_mx_get_ramman(mx); + int r; + u32 i; + u8 *dest; + + /* HW file is optional */ + r = mxfwconfig_load_cfg(mx, cfg, MXFWCONFIG_CFG_FILE_HW); + if (r) + goto done; + + /* SW file is optional, but not without HW file */ + r = mxfwconfig_load_cfg(mx, cfg, MXFWCONFIG_CFG_FILE_SW); + if (r == -EINVAL) { + /* If SW file is corrupt, abandon both HW and SW */ + goto done; + } + + /* Allocate shared DRAM */ + cfg->shdram = miframman_alloc(miframman, cfg->shtotal, 4, MIFRAMMAN_OWNER_COMMON); + if (!cfg->shdram) { + SCSC_TAG_ERR(MX_CFG, "MIF alloc failed for %zu octets\n", cfg->shtotal); + r = -ENOMEM; + goto done; + } + + /* Copy files into shared DRAM */ + for (i = 0, dest = (u8 *)cfg->shdram; + i < cfg->configs; + i++) { + /* Add to shared DRAM block */ + memcpy(dest, cfg->config[i].cfg_data, cfg->config[i].cfg_len); + dest += cfg->config[i].cfg_len; + } + +done: + /* Release the files from non-shared DRAM */ + for (i = 0; i < cfg->configs; i++) + mxfwconfig_unload_cfg(mx, cfg, i); + + /* Configs abandoned on error */ + if (r) + cfg->configs = 0; + + /* Pass offset of common HCF data. + * FW must ignore if zero length, so set up even if we loaded nothing. + */ + mxfwconfig_get_dram_ref(mx, cfg_ref); + + return r; +} + +/* + * Unload Common config data + */ +void mxfwconfig_unload(struct scsc_mx *mx) +{ + struct mxfwconfig *cfg = scsc_mx_get_mxfwconfig(mx); + struct miframman *miframman = scsc_mx_get_ramman(mx); + + /* Free config block in shared DRAM */ + if (cfg->shdram) { + SCSC_TAG_INFO(MX_CFG, "Free common config %zu bytes shared DRAM\n", cfg->shtotal); + + miframman_free(miframman, cfg->shdram); + + cfg->configs = 0; + cfg->shtotal = 0; + cfg->shdram = NULL; + } +} + +/* + * Get ref (offset) of config block in shared DRAM + */ +static void mxfwconfig_get_dram_ref(struct scsc_mx *mx, struct mxmibref *cfg_ref) +{ + struct mxfwconfig *mxfwconfig = scsc_mx_get_mxfwconfig(mx); + struct scsc_mif_abs *mif = scsc_mx_get_mif_abs(mx); + + if (!mxfwconfig->shdram) { + cfg_ref->offset = (scsc_mifram_ref)0; + cfg_ref->size = 0; + } else { + mif->get_mifram_ref(mif, mxfwconfig->shdram, &cfg_ref->offset); + cfg_ref->size = mxfwconfig->shtotal; + } + + SCSC_TAG_INFO(MX_CFG, "cfg_ref: 0x%x, size %u\n", cfg_ref->offset, cfg_ref->size); +} + +/* + * Init config file module + */ +int mxfwconfig_init(struct scsc_mx *mx) +{ + struct mxfwconfig *cfg = scsc_mx_get_mxfwconfig(mx); + + cfg->configs = 0; + cfg->shtotal = 0; + cfg->shdram = NULL; + + return 0; +} + +/* + * Exit config file module + */ +void mxfwconfig_deinit(struct scsc_mx *mx) +{ + struct mxfwconfig *cfg = scsc_mx_get_mxfwconfig(mx); + + /* Leaked memory? */ + WARN_ON(cfg->configs > 0); + WARN_ON(cfg->shdram); +} + diff --git a/drivers/misc/samsung/scsc/mxfwconfig.h b/drivers/misc/samsung/scsc/mxfwconfig.h new file mode 100644 index 000000000000..f24d44c599ef --- /dev/null +++ b/drivers/misc/samsung/scsc/mxfwconfig.h @@ -0,0 +1,35 @@ +/***************************************************************************** + * + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved + * + ****************************************************************************/ + +#ifndef __MXFWCONFIG_H +#define __MXFWCONFIG_H + +#define SCSC_MX_MAX_COMMON_CFG 2 +#define MX_COMMON_HCF_HDR_SIZE 8 +#define MX_COMMON_HASH_SIZE_BYTES 2 /* Hash will be contained in a uint32 */ +#define MX_COMMON_HASH_OFFSET 4 + +struct mxfwconfig { + u32 configs; /* Number of files */ + void *shdram; /* Combined payload in shared DRAM */ + size_t shtotal; /* Size of combined payload in shared DRAM */ + + struct { + const struct firmware *fw; /* File image in DRAM */ + const u8 *cfg_data; /* Payload in DRAM */ + size_t cfg_len; /* Length of payload */ + u32 cfg_hash; /* ID hash */ + } config[SCSC_MX_MAX_COMMON_CFG]; +}; + +struct mxmibref; + +int mxfwconfig_init(struct scsc_mx *mx); +void mxfwconfig_deinit(struct scsc_mx *mx); +int mxfwconfig_load(struct scsc_mx *mx, struct mxmibref *cfg_ref); +void mxfwconfig_unload(struct scsc_mx *mx); + +#endif // __MXFWCONFIG_H diff --git a/drivers/misc/samsung/scsc/mxman.c b/drivers/misc/samsung/scsc/mxman.c index b58197828ae1..e34ed4215b1c 100755 --- a/drivers/misc/samsung/scsc/mxman.c +++ b/drivers/misc/samsung/scsc/mxman.c @@ -34,6 +34,7 @@ #ifdef CONFIG_SCSC_QOS #include "mifqos.h" #endif +#include "mxfwconfig.h" #include #include #include @@ -841,13 +842,12 @@ static int transports_init(struct mxman *mxman) mxconf->version.minor = MXCONF_VERSION_MINOR; /* Pass pre-existing FM status to FW */ -#if (MXCONF_VERSION_MINOR >= 3) mxconf->flags = 0; #ifdef CONFIG_SCSC_FM mxconf->flags |= is_fm_on ? MXCONF_FLAGS_FM_ON : 0; #endif SCSC_TAG_INFO(MXMAN, "mxconf flags 0x%08x\n", mxconf->flags); -#endif + /* serialise mxmgmt transport */ mxmgmt_transport_config_serialise(scsc_mx_get_mxmgmt_transport(mx), &mxconf->mx_trans_conf); /* serialise Cortex-R4 gdb transport */ @@ -866,6 +866,10 @@ static int transports_init(struct mxman *mxman) *scsc_mx_get_mxlog_transport(mx)->mif_stream.buffer.write_index ); +#ifdef CONFIG_SCSC_COMMON_HCF + /* Load Common Config HCF */ + mxfwconfig_load(mxman->mx, &mxconf->fwconfig); +#endif return 0; } @@ -1117,6 +1121,7 @@ static int mxman_start(struct mxman *mxman) miframabox_init(scsc_mx_get_aboxram(mxman->mx), start_mifram_heap2 + length_mifram_heap2); mifmboxman_init(scsc_mx_get_mboxman(mxman->mx)); mifintrbit_init(scsc_mx_get_intrbit(mxman->mx), mif); + mxfwconfig_init(mxman->mx); /* Initialise transports */ r = transports_init(mxman); @@ -1896,6 +1901,7 @@ static void mxman_stop(struct mxman *mxman) panicmon_deinit(scsc_mx_get_panicmon(mxman->mx)); transports_release(mxman); + mxfwconfig_unload(mxman->mx); mxlog_release(scsc_mx_get_mxlog(mxman->mx)); /* unregister channel handler */ @@ -1904,6 +1910,7 @@ static void mxman_stop(struct mxman *mxman) fw_crc_wq_stop(mxman); /* Unitialise components (they may perform some checks - e.g. all memory freed) */ + mxfwconfig_deinit(mxman->mx); mifintrbit_deinit(scsc_mx_get_intrbit(mxman->mx)); miframman_deinit(scsc_mx_get_ramman(mxman->mx)); miframman_deinit(scsc_mx_get_ramman2(mxman->mx)); diff --git a/drivers/misc/samsung/scsc/scsc_logring_main.c b/drivers/misc/samsung/scsc/scsc_logring_main.c index 194e043805a4..9b623c4529f3 100644 --- a/drivers/misc/samsung/scsc/scsc_logring_main.c +++ b/drivers/misc/samsung/scsc/scsc_logring_main.c @@ -222,6 +222,7 @@ ADD_DEBUG_MODULE_PARAM(kic_common, SCSC_FULL_DEBUG, KIC_COMMON); ADD_DEBUG_MODULE_PARAM(wlbtd, SCSC_FULL_DEBUG, WLBTD); ADD_DEBUG_MODULE_PARAM(wlog, SCSC_DEBUG, WLOG); ADD_DEBUG_MODULE_PARAM(lerna, SCSC_FULL_DEBUG, LERNA); +ADD_DEBUG_MODULE_PARAM(mxcfg, SCSC_FULL_DEBUG, MX_CFG); #ifdef CONFIG_SCSC_DEBUG_COMPATIBILITY ADD_DEBUG_MODULE_PARAM(init_deinit, SCSC_FULL_DEBUG, SLSI_INIT_DEINIT); ADD_DEBUG_MODULE_PARAM(netdev, SCSC_DBG4, SLSI_NETDEV); @@ -296,6 +297,7 @@ int *scsc_droplevels[] = { &scsc_droplevel_wlbtd, &scsc_droplevel_wlog, &scsc_droplevel_lerna, + &scsc_droplevel_mxcfg, #ifdef CONFIG_SCSC_DEBUG_COMPATIBILITY &scsc_droplevel_init_deinit, &scsc_droplevel_netdev, diff --git a/drivers/misc/samsung/scsc/scsc_mx_impl.c b/drivers/misc/samsung/scsc/scsc_mx_impl.c index cfd339bdd556..dd6cf22a7a2b 100644 --- a/drivers/misc/samsung/scsc/scsc_mx_impl.c +++ b/drivers/misc/samsung/scsc/scsc_mx_impl.c @@ -30,9 +30,11 @@ #include "suspendmon.h" #include "scsc/api/bt_audio.h" +#include "mxfwconfig.h" #ifdef CONFIG_SCSC_WLBTD #include "scsc_wlbtd.h" #endif + struct scsc_mx { struct scsc_mif_abs *mif_abs; struct mifintrbit intr; @@ -58,6 +60,7 @@ struct scsc_mx { struct panicmon panicmon; struct mxlog_transport mxlog_transport; struct suspendmon suspendmon; + struct mxfwconfig mxfwconfig; }; @@ -204,3 +207,9 @@ struct suspendmon *scsc_mx_get_suspendmon(struct scsc_mx *mx) { return &mx->suspendmon; } + +struct mxfwconfig *scsc_mx_get_mxfwconfig(struct scsc_mx *mx) +{ + return &mx->mxfwconfig; +} + diff --git a/drivers/misc/samsung/scsc/scsc_mx_impl.h b/drivers/misc/samsung/scsc/scsc_mx_impl.h index 479e5743c8bd..d7b1e13a1374 100644 --- a/drivers/misc/samsung/scsc/scsc_mx_impl.h +++ b/drivers/misc/samsung/scsc/scsc_mx_impl.h @@ -19,6 +19,7 @@ struct mxman; struct srvman; struct mxmgmt_transport; struct mxproc; +struct mxfwconfig; struct scsc_mx *scsc_mx_create(struct scsc_mif_abs *mif); void scsc_mx_destroy(struct scsc_mx *mx); @@ -47,6 +48,8 @@ struct mxlog_transport *scsc_mx_get_mxlog_transport(struct scsc_mx *mx); struct mxlogger *scsc_mx_get_mxlogger(struct scsc_mx *mx); struct panicmon *scsc_mx_get_panicmon(struct scsc_mx *mx); struct suspendmon *scsc_mx_get_suspendmon(struct scsc_mx *mx); +struct mxfwconfig *scsc_mx_get_mxfwconfig(struct scsc_mx *mx); + int mx140_file_download_fw(struct scsc_mx *mx, void *dest, size_t dest_size, u32 *fw_image_size); int mx140_request_file(struct scsc_mx *mx, char *path, const struct firmware **firmp); int mx140_release_file(struct scsc_mx *mx, const struct firmware *firmp); diff --git a/include/scsc/scsc_logring.h b/include/scsc/scsc_logring.h index 0f3274e63df7..707fc46055fc 100644 --- a/include/scsc/scsc_logring.h +++ b/include/scsc/scsc_logring.h @@ -62,6 +62,7 @@ enum scsc_logring_tags { WLBTD, WLOG, LERNA, + MX_CFG, #ifdef CONFIG_SCSC_DEBUG_COMPATIBILITY SLSI_INIT_DEINIT, SLSI_NETDEV, -- 2.20.1