summaryrefslogtreecommitdiff
path: root/gxp-firmware.c
diff options
context:
space:
mode:
Diffstat (limited to 'gxp-firmware.c')
-rw-r--r--gxp-firmware.c100
1 files changed, 52 insertions, 48 deletions
diff --git a/gxp-firmware.c b/gxp-firmware.c
index 5b1e5ab..7118a23 100644
--- a/gxp-firmware.c
+++ b/gxp-firmware.c
@@ -19,6 +19,7 @@
#include <gcip/gcip-alloc-helper.h>
#include <gcip/gcip-common-image-header.h>
#include <gcip/gcip-image-config.h>
+#include <gcip/gcip-pm.h>
#include "gxp-bpm.h"
#include "gxp-client.h"
@@ -92,6 +93,28 @@ err:
return ret;
}
+static bool check_firmware_config_version(struct gxp_dev *gxp,
+ const struct firmware *core_firmware[GXP_NUM_CORES])
+{
+ struct gcip_common_image_header *hdr =
+ (struct gcip_common_image_header *)core_firmware[0]->data;
+ struct gcip_image_config *cfg;
+
+ if (unlikely(core_firmware[0]->size < GCIP_FW_HEADER_SIZE))
+ return false;
+ cfg = get_image_config_from_hdr(hdr);
+ if (!cfg) {
+ dev_err(gxp->dev, "Core firmware doesn't have a valid image config");
+ return false;
+ }
+ if (cfg->config_version < FW_DATA_PROTOCOL_PER_VD_CONFIG) {
+ dev_err(gxp->dev, "Unsupported firmware image config version %d",
+ cfg->config_version);
+ return false;
+ }
+ return true;
+}
+
static int elf_load_segments(struct gxp_dev *gxp, const u8 *elf_data,
size_t size,
const struct gxp_mapped_resource *buffer)
@@ -295,11 +318,7 @@ static void gxp_program_reset_vector(struct gxp_dev *gxp, uint core,
static void *get_scratchpad_base(struct gxp_dev *gxp,
struct gxp_virtual_device *vd, uint core)
{
- if (vd && gxp_fw_data_use_per_vd_config(vd))
- return vd->core_cfg.vaddr +
- (vd->core_cfg.size / GXP_NUM_CORES) * core;
-
- return gxp->fwbufs[core].vaddr + AURORA_SCRATCHPAD_OFF;
+ return vd->core_cfg.vaddr + (vd->core_cfg.size / GXP_NUM_CORES) * core;
}
static void reset_core_config_region(struct gxp_dev *gxp,
@@ -308,17 +327,10 @@ static void reset_core_config_region(struct gxp_dev *gxp,
struct gxp_host_control_region *core_cfg;
core_cfg = get_scratchpad_base(gxp, vd, core);
- if (gxp_fw_data_use_per_vd_config(vd)) {
- core_cfg->core_alive_magic = 0;
- core_cfg->top_access_ok = 0;
- core_cfg->boot_status = GXP_BOOT_STATUS_NONE;
- gxp_firmware_set_boot_mode(gxp, vd, core,
- GXP_BOOT_MODE_COLD_BOOT);
- } else {
- memset(core_cfg, 0, AURORA_SCRATCHPAD_LEN);
- gxp_firmware_set_boot_mode(gxp, vd, core,
- GXP_BOOT_MODE_REQUEST_COLD_BOOT);
- }
+ core_cfg->core_alive_magic = 0;
+ core_cfg->top_access_ok = 0;
+ core_cfg->boot_status = GXP_BOOT_STATUS_NONE;
+ gxp_firmware_set_boot_mode(gxp, vd, core, GXP_BOOT_MODE_COLD_BOOT);
}
static int gxp_firmware_handshake(struct gxp_dev *gxp,
@@ -518,23 +530,23 @@ static ssize_t load_dsp_firmware_store(struct device *dev,
int ret;
/*
- * Lock the VD semaphore to ensure no core is executing the firmware
- * while requesting new firmware.
+ * TODO(b/281047946): Ensure no firmware is executing while requesting
+ * core firmware, which includes MCU firmware in MCU mode.
+ *
+ * Here we don't lock @gxp->vd_semaphore since it'll introduce wrong lock
+ * dependency, and this interface is only for developer debugging. We
+ * don't insist on preventing race condition here.
*/
- down_read(&gxp->vd_semaphore);
-
if (mgr->firmware_running) {
dev_warn(dev, "Cannot update firmware when any core is running\n");
- ret = -EBUSY;
- goto err_out;
+ return -EBUSY;
}
name_buf = fw_name_from_attr_buf(buf);
if (IS_ERR(name_buf)) {
dev_err(gxp->dev, "Invalid firmware prefix requested: %s\n",
buf);
- ret = PTR_ERR(name_buf);
- goto err_out;
+ return PTR_ERR(name_buf);
}
dev_notice(gxp->dev, "Requesting firmware be reloaded: %s\n", name_buf);
@@ -554,13 +566,10 @@ static ssize_t load_dsp_firmware_store(struct device *dev,
}
kfree(name_buf);
- up_read(&gxp->vd_semaphore);
return count;
err_firmware_load:
kfree(name_buf);
-err_out:
- up_read(&gxp->vd_semaphore);
return ret;
}
@@ -637,18 +646,25 @@ static int debugfs_firmware_run_set(void *data, u64 val)
list_add(&client->list_entry, &gxp->client_list);
mutex_unlock(&gxp->client_list_lock);
+ ret = gcip_pm_get(gxp->power_mgr->pm);
+ if (ret) {
+ dev_err(gxp->dev,
+ "Failed to increase the PM count or power up the block (ret=%d)\n", ret);
+ goto out_destroy_client;
+ }
+
down_write(&client->semaphore);
ret = gxp_client_allocate_virtual_device(client, GXP_NUM_CORES, 0);
if (ret) {
dev_err(gxp->dev, "Failed to allocate VD\n");
- goto err_destroy_client;
+ goto err_pm_put;
}
ret = gxp_client_acquire_block_wakelock(client, &acquired_block_wakelock);
if (ret) {
dev_err(gxp->dev, "Failed to acquire BLOCK wakelock\n");
- goto err_destroy_client;
+ goto err_pm_put;
}
ret = gxp_client_acquire_vd_wakelock(client, uud_states);
@@ -666,8 +682,9 @@ out:
err_release_block_wakelock:
gxp_client_release_block_wakelock(client);
-err_destroy_client:
+err_pm_put:
up_write(&client->semaphore);
+ gcip_pm_put(gxp->power_mgr->pm);
out_destroy_client:
mutex_lock(&gxp->client_list_lock);
list_del(&gxp->debugfs_client->list_entry);
@@ -829,6 +846,10 @@ int gxp_firmware_load_core_firmware(
ret = request_dsp_firmware(gxp, name_prefix, core_firmware);
if (ret)
return ret;
+ if (!check_firmware_config_version(gxp, core_firmware)) {
+ ret = -EOPNOTSUPP;
+ goto error;
+ }
ret = gxp_firmware_load_into_memories(gxp, core_firmware);
if (ret)
goto error;
@@ -866,7 +887,7 @@ void gxp_firmware_disable_ext_interrupts(struct gxp_dev *gxp, uint core)
static inline uint select_core(struct gxp_virtual_device *vd, uint virt_core,
uint phys_core)
{
- return gxp_fw_data_use_per_vd_config(vd) ? virt_core : phys_core;
+ return virt_core;
}
static int gxp_firmware_setup(struct gxp_dev *gxp,
@@ -1129,27 +1150,10 @@ void gxp_firmware_set_boot_mode(struct gxp_dev *gxp,
{
struct gxp_host_control_region *core_cfg;
- /* Callers shouldn't call the function under this condition. */
- if (!gxp->fwbufs[core].vaddr)
- return;
-
core_cfg = get_scratchpad_base(gxp, vd, core);
core_cfg->boot_mode = mode;
}
-u32 gxp_firmware_get_boot_mode(struct gxp_dev *gxp,
- struct gxp_virtual_device *vd, uint core)
-{
- struct gxp_host_control_region *core_cfg;
-
- /* Callers shouldn't call the function under this condition. */
- if (!gxp->fwbufs[core].vaddr)
- return 0;
-
- core_cfg = get_scratchpad_base(gxp, vd, core);
- return core_cfg->boot_mode;
-}
-
void gxp_firmware_set_boot_status(struct gxp_dev *gxp,
struct gxp_virtual_device *vd, uint core,
u32 status)