Linux Audio
Check our new training course
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
/* * Copyright (c) 2022 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include <zephyr/device.h> #include <adsp-clk.h> #include <adsp_shim.h> static struct cavs_clock_info platform_clocks[CONFIG_MP_NUM_CPUS]; static struct k_spinlock lock; int cavs_clock_freq_enc[] = CAVS_CLOCK_FREQ_ENC; #ifndef CONFIG_SOC_INTEL_CAVS_V15 int cavs_clock_freq_mask[] = CAVS_CLOCK_FREQ_MASK; #endif #ifdef CONFIG_SOC_INTEL_CAVS_V15 static void select_cpu_clock_hw(uint32_t freq) { uint8_t cpu_id = _current_cpu->id; uint32_t enc = cavs_clock_freq_enc[freq] << (8 + cpu_id * 2); uint32_t mask = CAVS_CLKCTL_DPCS_MASK(cpu_id); CAVS_SHIM_CLKCTL &= ~CAVS_CLKCTL_HDCS; CAVS_SHIM_CLKCTL = (CAVS_SHIM_CLKCTL & ~mask) | (enc & mask); } #else static void select_cpu_clock_hw(uint32_t freq_idx) { uint32_t enc = cavs_clock_freq_enc[freq_idx]; uint32_t status_mask = cavs_clock_freq_mask[freq_idx]; /* Request clock */ CAVS_SHIM_CLKCTL |= enc; /* Wait for requested clock to be on */ while ((CAVS_SHIM_CLKCTL & status_mask) != status_mask) { k_busy_wait(10); } /* Switch to requested clock */ CAVS_SHIM_CLKCTL = (CAVS_SHIM_CLKCTL & ~CAVS_CLKCTL_OSC_SOURCE_MASK) | enc; /* Release other clocks */ CAVS_SHIM_CLKCTL &= ~CAVS_CLKCTL_OSC_REQUEST_MASK | enc; } #endif int cavs_clock_set_freq(uint32_t freq_idx) { k_spinlock_key_t k; int i; if (freq_idx >= CAVS_CLOCK_FREQ_LEN) { return -EINVAL; } k = k_spin_lock(&lock); select_cpu_clock_hw(freq_idx); for (i = 0; i < CONFIG_MP_NUM_CPUS; i++) { platform_clocks[i].current_freq = freq_idx; } k_spin_unlock(&lock, k); return 0; } struct cavs_clock_info *cavs_clocks_get(void) { return platform_clocks; } void cavs_clock_init(void) { uint32_t platform_lowest_freq_idx = CAVS_CLOCK_FREQ_LOWEST; int i; #ifdef CAVS_CLOCK_HAS_WOVCRO CAVS_SHIM.clkctl |= CAVS_CLKCTL_WOVCRO; if (CAVS_SHIM.clkctl & CAVS_CLKCTL_WOVCRO) { CAVS_SHIM.clkctl = CAVS_SHIM.clkctl & ~CAVS_CLKCTL_WOVCRO; } else { platform_lowest_freq_idx = CAVS_CLOCK_FREQ_LPRO; } #endif for (i = 0; i < CONFIG_MP_NUM_CPUS; i++) { platform_clocks[i].default_freq = CAVS_CLOCK_FREQ_DEFAULT; platform_clocks[i].current_freq = CAVS_CLOCK_FREQ_DEFAULT; platform_clocks[i].lowest_freq = platform_lowest_freq_idx; } }