summaryrefslogtreecommitdiff
path: root/gxp-firmware.c
diff options
context:
space:
mode:
Diffstat (limited to 'gxp-firmware.c')
-rw-r--r--gxp-firmware.c93
1 files changed, 38 insertions, 55 deletions
diff --git a/gxp-firmware.c b/gxp-firmware.c
index 2af783e..df4e192 100644
--- a/gxp-firmware.c
+++ b/gxp-firmware.c
@@ -26,7 +26,7 @@
#include "gxp-notification.h"
#include "gxp-pm.h"
#include "gxp-telemetry.h"
-#include "gxp-tmp.h"
+#include "gxp-vd.h"
/* TODO (b/176984045): Clean up gxp-firmware.c */
@@ -303,10 +303,8 @@ out_firmware_unload:
static int gxp_firmware_handshake(struct gxp_dev *gxp, uint core)
{
u32 offset;
- u32 psm_status;
u32 expected_top_value;
- void __iomem *core_psm_base, *core_scratchpad_base, *addr;
- uint state;
+ void __iomem *core_scratchpad_base;
int ctr;
/* Raise wakeup doorbell */
@@ -316,21 +314,12 @@ static int gxp_firmware_handshake(struct gxp_dev *gxp, uint core)
gxp_doorbell_set(gxp, CORE_WAKEUP_DOORBELL);
/* Wait for core to come up */
- dev_notice(gxp->dev, "Waiting for core %u to power up...\n",
- core);
- core_psm_base =
- ((u8 *)gxp->regs.vaddr) + LPM_BLOCK + CORE_PSM_BASE(core);
+ dev_notice(gxp->dev, "Waiting for core %u to power up...\n", core);
ctr = 1000;
while (ctr) {
- addr = core_psm_base + PSM_STATUS_OFFSET;
- psm_status = (u32) readl(addr); /* 0x60041688 */
- if (psm_status & PSM_STATE_VALID_MASK) {
- state = psm_status & PSM_CURR_STATE_MASK;
- if ((state == PSM_STATE_ACTIVE)
- || (state == PSM_STATE_CLK_GATED))
- break;
- }
- cpu_relax();
+ if (gxp_lpm_is_powered(gxp, core))
+ break;
+ udelay(1 * GXP_TIME_DELAY_FACTOR);
ctr--;
}
@@ -346,18 +335,20 @@ static int gxp_firmware_handshake(struct gxp_dev *gxp, uint core)
core_scratchpad_base = gxp->fwbufs[core].vaddr + AURORA_SCRATCHPAD_OFF;
- ctr = 500;
- offset = SCRATCHPAD_MSG_OFFSET(MSG_CORE_ALIVE);
- while (ctr--) {
- if (readl(core_scratchpad_base + offset) == Q7_ALIVE_MAGIC)
- break;
- msleep(1 * GXP_TIME_DELAY_FACTOR);
- }
/*
* Currently, the hello_world FW writes a magic number
* (Q7_ALIVE_MAGIC) to offset MSG_CORE_ALIVE in the scratchpad
* space as an alive message
*/
+ ctr = 5000;
+ offset = SCRATCHPAD_MSG_OFFSET(MSG_CORE_ALIVE);
+ usleep_range(500 * GXP_TIME_DELAY_FACTOR, 1000 * GXP_TIME_DELAY_FACTOR);
+ while (ctr--) {
+ if (readl(core_scratchpad_base + offset) == Q7_ALIVE_MAGIC)
+ break;
+ usleep_range(1 * GXP_TIME_DELAY_FACTOR,
+ 10 * GXP_TIME_DELAY_FACTOR);
+ }
if (readl(core_scratchpad_base + offset) != Q7_ALIVE_MAGIC) {
dev_err(gxp->dev, "Core %u did not respond!\n", core);
return -EIO;
@@ -377,11 +368,14 @@ static int gxp_firmware_handshake(struct gxp_dev *gxp, uint core)
* handshaking in Gem5.
*/
/* TODO (b/182528386): Fix handshake for verifying TOP access */
+ ctr = 1000;
offset = SCRATCHPAD_MSG_OFFSET(MSG_TOP_ACCESS_OK);
expected_top_value = BIT(0);
-#ifdef CONFIG_GXP_USE_SW_MAILBOX
- expected_top_value |= BIT(31 - core);
-#endif // CONFIG_GXP_USE_SW_MAILBOX
+ while (ctr--) {
+ if (readl(core_scratchpad_base + offset) == expected_top_value)
+ break;
+ udelay(1 * GXP_TIME_DELAY_FACTOR);
+ }
if (readl(core_scratchpad_base + offset) != expected_top_value) {
dev_err(gxp->dev, "TOP access from core %u failed!\n", core);
return -EIO;
@@ -479,7 +473,8 @@ void gxp_fw_destroy(struct gxp_dev *gxp)
*/
}
-int gxp_firmware_run(struct gxp_dev *gxp, uint core)
+int gxp_firmware_run(struct gxp_dev *gxp, struct gxp_virtual_device *vd,
+ uint virt_core, uint core)
{
int ret = 0;
struct work_struct *work;
@@ -503,21 +498,24 @@ int gxp_firmware_run(struct gxp_dev *gxp, uint core)
goto out_firmware_unload;
}
+ /* Switch PLL_CON0_NOC_USER MUX to the normal state to guarantee LPM works */
+ gxp_pm_force_cmu_noc_user_mux_normal(gxp);
ret = gxp_firmware_handshake(gxp, core);
if (ret) {
dev_err(gxp->dev, "Firmware handshake failed on core %u\n",
core);
gxp_pm_core_off(gxp, core);
- goto out_firmware_unload;
+ goto out_check_noc_user_mux;
}
-
- /* Initialize ioctl response queues */
- INIT_LIST_HEAD(&(gxp->mailbox_resp_queues[core]));
- init_waitqueue_head(&(gxp->mailbox_resp_waitqs[core]));
+ /*
+ * Check if we need to set PLL_CON0_NOC_USER MUX to low state for
+ * AUR_READY requested state.
+ */
+ gxp_pm_check_cmu_noc_user_mux(gxp);
/* Initialize mailbox */
- gxp->mailbox_mgr->mailboxes[core] = gxp_mailbox_alloc(gxp->mailbox_mgr,
- core);
+ gxp->mailbox_mgr->mailboxes[core] =
+ gxp_mailbox_alloc(gxp->mailbox_mgr, vd, virt_core, core);
if (IS_ERR(gxp->mailbox_mgr->mailboxes[core])) {
dev_err(gxp->dev,
"Unable to allocate mailbox (core=%u, ret=%ld)\n", core,
@@ -541,16 +539,16 @@ int gxp_firmware_run(struct gxp_dev *gxp, uint core)
return ret;
+out_check_noc_user_mux:
+ gxp_pm_check_cmu_noc_user_mux(gxp);
out_firmware_unload:
gxp_firmware_unload(gxp, core);
return ret;
}
-void gxp_firmware_stop(struct gxp_dev *gxp, uint core)
+void gxp_firmware_stop(struct gxp_dev *gxp, struct gxp_virtual_device *vd,
+ uint virt_core, uint core)
{
- struct gxp_async_response *cur, *nxt;
- unsigned long flags;
-
if (!(gxp->firmware_running & BIT(core)))
dev_err(gxp->dev, "Firmware is not running on core %u\n", core);
@@ -561,25 +559,10 @@ void gxp_firmware_stop(struct gxp_dev *gxp, uint core)
gxp_notification_unregister_handler(gxp, core,
HOST_NOTIF_TELEMETRY_STATUS);
- gxp_mailbox_release(gxp->mailbox_mgr,
+ gxp_mailbox_release(gxp->mailbox_mgr, vd, virt_core,
gxp->mailbox_mgr->mailboxes[core]);
dev_notice(gxp->dev, "Mailbox %u released\n", core);
- /*
- * TODO(b/226211187) response queues should be owned by VDs
- * This step should not be necessary until a VD is destroyed once the
- * queues are owned directly by the VD and not shared by all users of
- * a physical core.
- */
- /* Flush and free any abandoned responses left in the queue */
- spin_lock_irqsave(&gxp->mailbox_resps_lock, flags);
- list_for_each_entry_safe(cur, nxt, &gxp->mailbox_resp_queues[core],
- list_entry) {
- list_del(&cur->list_entry);
- kfree(cur);
- }
- spin_unlock_irqrestore(&gxp->mailbox_resps_lock, flags);
-
gxp_pm_core_off(gxp, core);
gxp_firmware_unload(gxp, core);
}