Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 367
lps: restore secondary cores on wake up#4839
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
c7a23e20452b85b50798728c23a450b8d5acd59a287d559a35314d67File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -160,25 +160,44 @@ void cpu_alloc_core_context(int core) | ||
| dcache_writeback_region(sof_get(), sizeof(*sof_get())); | ||
| } | ||
| void cpu_power_down_core(void) | ||
| void cpu_power_down_core(uint32_t flags) | ||
| { | ||
| arch_interrupt_global_disable(); | ||
| idc_free(); | ||
| /* Power down with memory on is performed by secondary cores during | ||
| * d0 -> d0ix before they are disabled by primary core. | ||
| */ | ||
| if (flags & CPU_POWER_DOWN_MEMORY_ON) { | ||
| /* disable idc interrupts */ | ||
| idc_free(IDC_FREE_IRQ_ONLY); | ||
| /* disable scheduler interrupts */ | ||
| schedule_free(SOF_SCHEDULER_FREE_IRQ_ONLY); | ||
| /* data writeback/invalidate */ | ||
| dcache_writeback_invalidate_all(); | ||
Collaborator There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add a comment, that after this point we aren't "polluting" any more cache lines?.. CollaboratorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do not understand what do you mean by "polluting" here? Collaborator There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. making clean cache lines dirty (is there an official term for this?). I.e. writing to cached memory, without forcing cache write-back. | ||
| schedule_free(); | ||
| /* after writeback/invalidate secondary core is prepared for | ||
| * powered off - prepare_d0ix_core_mask flag can be disabled | ||
| */ | ||
| platform_pm_runtime_prepare_d0ix_dis(cpu_get_id()); | ||
| } else { | ||
| idc_free(0); | ||
| free_system_notify(); | ||
| schedule_free(0); | ||
| /* free entire sys heap, an instance dedicated for this core */ | ||
| free_heap(SOF_MEM_ZONE_SYS); | ||
| free_system_notify(); | ||
| dcache_writeback_invalidate_all(); | ||
| /* free entire sys heap, an instance dedicated for this core */ | ||
| free_heap(SOF_MEM_ZONE_SYS); | ||
| /* Turn off stack memory for core */ | ||
| pm_runtime_put(CORE_MEMORY_POW, cpu_get_id()); | ||
| dcache_writeback_invalidate_all(); | ||
| pm_runtime_put(PM_RUNTIME_DSP, PWRD_BY_TPLG | cpu_get_id()); | ||
| /* Turn off stack memory for core */ | ||
| pm_runtime_put(CORE_MEMORY_POW, cpu_get_id()); | ||
| pm_runtime_put(PM_RUNTIME_DSP, PWRD_BY_TPLG | cpu_get_id()); | ||
| } | ||
| trace_point(0); | ||
| @@ -189,3 +208,50 @@ void cpu_power_down_core(void) | ||
| while (1) | ||
| arch_wait_for_interrupt(0); | ||
| } | ||
| int arch_cpu_restore_secondary_cores(void) | ||
bkokoszx marked this conversation as resolved.
Outdated
Uh oh!There was an error while loading. Please reload this page. | ||
| { | ||
| struct idc_msg power_up = { IDC_MSG_POWER_UP, IDC_MSG_POWER_UP_EXT }; | ||
| int ret, id; | ||
| for (id = 0; id < CONFIG_CORE_COUNT; id++) { | ||
| if (arch_cpu_is_core_enabled(id) && id != PLATFORM_PRIMARY_CORE_ID) { | ||
| power_up.core = id; | ||
| /* Power up secondary core */ | ||
| pm_runtime_get(PM_RUNTIME_DSP, id); | ||
| /* enable IDC interrupt for the secondary core */ | ||
| idc_enable_interrupts(id, cpu_get_id()); | ||
| /* send IDC power up message */ | ||
| ret = idc_send_msg(&power_up, IDC_POWER_UP); | ||
| if (ret < 0) | ||
| return ret; | ||
| } | ||
| } | ||
| return 0; | ||
| } | ||
| int arch_cpu_secondary_cores_prepare_d0ix(void) | ||
| { | ||
| struct idc_msg prepare_msg = { IDC_MSG_PREPARE_D0ix, | ||
| IDC_MSG_PREPARE_D0ix_EXT }; | ||
| int ret, id; | ||
| for (id = 0; id < CONFIG_CORE_COUNT; id++) { | ||
| if (arch_cpu_is_core_enabled(id) && id != PLATFORM_PRIMARY_CORE_ID) { | ||
| prepare_msg.core = id; | ||
| /* send IDC prepare message to all enabled secondary | ||
| * cores. | ||
| */ | ||
| ret = idc_send_msg(&prepare_msg, IDC_BLOCKING); | ||
| if (ret < 0) | ||
| return ret; | ||
| } | ||
| } | ||
| return 0; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -243,10 +243,43 @@ int platform_idc_init(void) | ||
| return 0; | ||
| } | ||
| /** | ||
| * \brief Restores IDC interrupt. During D0->D0ix/D0ix->D0 flow primary core | ||
| * disables all secondary cores - this is not cold boot process, because | ||
| * memory has not been powered off. In that case, we should only enable | ||
| * idc interrupts, because all required structures alreade exist. | ||
| */ | ||
lgirdwood marked this conversation as resolved.
Outdated
Uh oh!There was an error while loading. Please reload this page. | ||
| int platform_idc_restore(void) | ||
| { | ||
| struct idc *idc = *idc_get(); | ||
| int core = cpu_get_id(); | ||
| int ret; | ||
| idc->irq = interrupt_get_irq(PLATFORM_IDC_INTERRUPT, | ||
| PLATFORM_IDC_INTERRUPT_NAME); | ||
| if (idc->irq < 0) { | ||
| tr_err(&idc_tr, "platform_idc_restore(): getting irq failed."); | ||
| return idc->irq; | ||
| } | ||
| ret = interrupt_register(idc->irq, idc_irq_handler, idc); | ||
| if (ret < 0) { | ||
| tr_err(&idc_tr, "platform_idc_restore(): registering irq failed."); | ||
| return ret; | ||
| } | ||
| interrupt_enable(idc->irq, idc); | ||
| /* enable BUSY interrupt */ | ||
| idc_write(IPC_IDCCTL, core, idc->busy_bit_mask); | ||
| return 0; | ||
| } | ||
| /** | ||
| * \brief Frees IDC data and unregisters interrupt. | ||
| */ | ||
| void idc_free(void) | ||
| void idc_free(uint32_t flags) | ||
| { | ||
| struct idc *idc = *idc_get(); | ||
| int core = cpu_get_id(); | ||
| @@ -266,5 +299,8 @@ void idc_free(void) | ||
| idc_write(IPC_IDCTFC(i), core, idctfc); | ||
| } | ||
| if (flags & IDC_FREE_IRQ_ONLY) | ||
| return; | ||
| schedule_task_free(&idc->idc_task); | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.