1 /* 2 * Copyright (c) 2022 Intel Corporation 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #include <errno.h> 8 9 #include <zephyr/device.h> 10 #include <zephyr/kernel.h> 11 #include <zephyr/spinlock.h> 12 13 #include <adsp_clk.h> 14 #include <adsp_shim.h> 15 16 static struct adsp_clock_info platform_clocks[CONFIG_MP_MAX_NUM_CPUS]; 17 static struct k_spinlock lock; 18 19 int adsp_clock_freq_enc[] = ADSP_CLOCK_FREQ_ENC; 20 int adsp_clock_freq_mask[] = ADSP_CLOCK_FREQ_MASK; 21 select_cpu_clock_hw(uint32_t freq_idx)22static void select_cpu_clock_hw(uint32_t freq_idx) 23 { 24 uint32_t enc = adsp_clock_freq_enc[freq_idx]; 25 uint32_t status_mask = adsp_clock_freq_mask[freq_idx]; 26 27 /* Request clock */ 28 ADSP_CLKCTL |= enc; 29 30 /* Wait for requested clock to be on */ 31 while ((ADSP_CLKCTL & status_mask) != status_mask) { 32 k_busy_wait(10); 33 } 34 35 /* Switch to requested clock */ 36 ADSP_CLKCTL = (ADSP_CLKCTL & ~ADSP_CLKCTL_OSC_SOURCE_MASK) | 37 enc; 38 39 /* Release other clocks */ 40 ADSP_CLKCTL &= ~ADSP_CLKCTL_OSC_REQUEST_MASK | enc; 41 } 42 adsp_clock_set_freq(uint32_t freq_idx)43int adsp_clock_set_freq(uint32_t freq_idx) 44 { 45 k_spinlock_key_t k; 46 int i; 47 48 if (freq_idx >= ADSP_CLOCK_FREQ_LEN) { 49 return -EINVAL; 50 } 51 52 k = k_spin_lock(&lock); 53 54 select_cpu_clock_hw(freq_idx); 55 56 unsigned int num_cpus = arch_num_cpus(); 57 58 for (i = 0; i < num_cpus; i++) { 59 platform_clocks[i].current_freq = freq_idx; 60 } 61 62 k_spin_unlock(&lock, k); 63 64 return 0; 65 } 66 adsp_clocks_get(void)67struct adsp_clock_info *adsp_clocks_get(void) 68 { 69 return platform_clocks; 70 } 71 adsp_clock_init(void)72void adsp_clock_init(void) 73 { 74 uint32_t platform_lowest_freq_idx = ADSP_CLOCK_FREQ_LOWEST; 75 int i; 76 77 #ifdef ADSP_CLOCK_HAS_WOVCRO 78 #ifdef CONFIG_SOC_SERIES_INTEL_ACE 79 ACE_DfPMCCU.dfclkctl |= ACE_CLKCTL_WOVCRO; 80 if (ACE_DfPMCCU.dfclkctl & ACE_CLKCTL_WOVCRO) { 81 ACE_DfPMCCU.dfclkctl = ACE_DfPMCCU.dfclkctl & ~ACE_CLKCTL_WOVCRO; 82 } else { 83 platform_lowest_freq_idx = ADSP_CLOCK_FREQ_LPRO; 84 } 85 #else 86 CAVS_SHIM.clkctl |= CAVS_CLKCTL_WOVCRO; 87 if (CAVS_SHIM.clkctl & CAVS_CLKCTL_WOVCRO) { 88 CAVS_SHIM.clkctl = CAVS_SHIM.clkctl & ~CAVS_CLKCTL_WOVCRO; 89 } else { 90 platform_lowest_freq_idx = ADSP_CLOCK_FREQ_LPRO; 91 } 92 #endif /* CONFIG_SOC_SERIES_INTEL_ACE */ 93 #endif /* ADSP_CLOCK_HAS_WOVCRO */ 94 95 unsigned int num_cpus = arch_num_cpus(); 96 97 for (i = 0; i < num_cpus; i++) { 98 platform_clocks[i].default_freq = ADSP_CLOCK_FREQ_DEFAULT; 99 platform_clocks[i].current_freq = ADSP_CLOCK_FREQ_DEFAULT; 100 platform_clocks[i].lowest_freq = platform_lowest_freq_idx; 101 } 102 } 103