From 81e9e531bba6ed51aa903c21859ff544685ef693 Mon Sep 17 00:00:00 2001 From: Bartosz Kokoszko Date: Tue, 23 Jun 2020 09:55:25 +0200 Subject: [PATCH] mn: clear mclk and bclk source clks in MDIVCTRL We should clear MNDSS and MCDSS bits before setting new mclk and bclks source clocks. This commit is going to fix case when driver want to reconfigure the same SSP (e.g. index = 0). 1. Driver sends ssp_config() and FW configures ssp (index = 0) with MCDSS bits set to e.g. 1. 2. Driver wants to reconfigure the same ssp (index = 0) by sending new ssp_config() and FW tries to configure ssp 0 once again, but firstly it reads MDIVCTRL register: mdivc = mn_reg_read(MN_MDIVCTRL, mclk_id) and then tries to set MCDSS(0): mdivc |= MCDSS(0); , but there is "or" function here - after it MCDSS bits still will be set to 1. That's why we should clear this bits earlier. Signed-off-by: Bartosz Kokoszko --- src/drivers/intel/ssp/mn.c | 15 +++++++++++++-- src/platform/intel/cavs/include/cavs/drivers/mn.h | 3 +++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/drivers/intel/ssp/mn.c b/src/drivers/intel/ssp/mn.c index cc6400d7e3ec..b6d5d2f6b14a 100644 --- a/src/drivers/intel/ssp/mn.c +++ b/src/drivers/intel/ssp/mn.c @@ -140,6 +140,9 @@ static inline int setup_initial_mclk_source(uint32_t mclk_id, /* enable MCLK divider */ mdivc |= MN_MDIVCTRL_M_DIV_ENABLE; + /* clear source mclk clock - bits 17-16 */ + mdivc &= ~MCDSS(MN_SOURCE_CLKS_MASK); + /* select source clock */ mdivc |= MCDSS(ssp_freq_sources[clk_index]); @@ -375,6 +378,7 @@ static inline int setup_initial_bclk_mn_source(uint32_t bclk, uint32_t *scr_div, uint32_t *m, uint32_t *n) { struct mn *mn = mn_get(); + uint32_t mdivc; int clk_index = find_bclk_source(bclk, scr_div, m, n); if (clk_index < 0) { @@ -384,8 +388,15 @@ static inline int setup_initial_bclk_mn_source(uint32_t bclk, uint32_t *scr_div, mn->bclk_source_mn_clock = clk_index; - mn_reg_write(MN_MDIVCTRL, 0, (mn_reg_read(MN_MDIVCTRL, 0) | - MNDSS(ssp_freq_sources[clk_index]))); + mdivc = mn_reg_read(MN_MDIVCTRL, 0); + + /* clear source bclk clock - 21-20 bits */ + mdivc &= ~MNDSS(MN_SOURCE_CLKS_MASK); + + /* select source clock */ + mdivc |= MNDSS(ssp_freq_sources[clk_index]); + + mn_reg_write(MN_MDIVCTRL, 0, mdivc); platform_shared_commit(mn, sizeof(*mn)); diff --git a/src/platform/intel/cavs/include/cavs/drivers/mn.h b/src/platform/intel/cavs/include/cavs/drivers/mn.h index d8ed5c59128f..25ebb88bba40 100644 --- a/src/platform/intel/cavs/include/cavs/drivers/mn.h +++ b/src/platform/intel/cavs/include/cavs/drivers/mn.h @@ -33,6 +33,9 @@ /** \brief Bits for setting M/N source clock. */ #define MNDSS(x) SET_BITS(21, 20, x) +/** \brief Mask for clearing mclk and bclk source in MN_MDIVCTRL */ +#define MN_SOURCE_CLKS_MASK 0x3 + #endif /* __CAVS_DRIVERS_MN_H__ */ #else