ipq806x: add LPASS clock control driver
Add a clock control driver to initialize the clock tree inside the low-power audio subsystem. Depthcharge builds up on this to enable audio function on storm. The clock is hardcoded for 48KHz frame rate, two 16 bit channels. BRANCH=storm BUG=chrome-os-partner:35247 TEST=with depthcharge patches applied and Using depthcharge CLI audio test program verified that the target generates sensible sounds audio 100 100 audio 1000 5000 Change-Id: I56513fc782657ade99b6e43b2d5d3141d27ecc4e Signed-off-by: Patrick Georgi <pgeorgi@chromium.org> Original-Commit-Id: 0d4f408408aa38b2f0ee19b83ed490de39074760 Original-Change-Id: If8ffc326698fcea17e05d536930d927ca553481f Original-Signed-off-by: Kenneth Westfield <kwestfie@codeaurora.org> Original-Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Original-Reviewed-on: https://chromium-review.googlesource.com/248830 Original-Reviewed-by: Dylan Reid <dgreid@chromium.org> Reviewed-on: http://review.coreboot.org/9758 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
parent
7f70ad610b
commit
3cfb6a066b
|
@ -98,6 +98,14 @@ static void mainboard_init(device_t dev)
|
|||
/* Copy WIFI calibration data into CBMEM. */
|
||||
cbmem_add_vpd_calibration_data();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Make sure bootloader can issue sounds The frequency is calculated
|
||||
* as "<frame_rate> * <bit_width> * <channels> * 4", i.e.
|
||||
*
|
||||
* 48000 * 2 * 16 * 4 = 6144000
|
||||
*/
|
||||
audio_clock_config(6144000);
|
||||
}
|
||||
|
||||
static void mainboard_enable(device_t dev)
|
||||
|
|
|
@ -44,6 +44,7 @@ ramstage-y += blobs_init.c
|
|||
ramstage-y += cbmem.c
|
||||
ramstage-y += clock.c
|
||||
ramstage-y += gpio.c
|
||||
ramstage-y += lcc.c
|
||||
ramstage-y += soc.c
|
||||
ramstage-$(CONFIG_SPI_FLASH) += spi.c
|
||||
ramstage-y += timer.c
|
||||
|
|
|
@ -192,5 +192,6 @@ void uart_clock_config(unsigned int gsbi_port, unsigned int m, unsigned int n,
|
|||
unsigned int d, unsigned int clk_dummy);
|
||||
void nand_clock_config(void);
|
||||
void usb_clock_config(void);
|
||||
int audio_clock_config(unsigned frequency);
|
||||
|
||||
#endif /* __PLATFORM_IPQ860X_CLOCK_H_ */
|
||||
|
|
|
@ -0,0 +1,341 @@
|
|||
/*
|
||||
* Copyright (c) 2015, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of The Linux Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __DRIVERS_CLOCK_IPQ806X_LCC_REG_H__
|
||||
#define __DRIVERS_CLOCK_IPQ806X_LCC_REG_H__
|
||||
|
||||
#define MSM_GCC_BASE 0x00900000
|
||||
#define MSM_LPASS_LCC_BASE 0x28000000
|
||||
|
||||
/* GCC APCS Configuration/Control */
|
||||
|
||||
#define GCC_PLL_APCS_REG 0x34C0
|
||||
|
||||
#define GCC_PLL_APCS_PLL4_MASK 0x10
|
||||
#define GCC_PLL_APCS_PLL4_SHIFT 4
|
||||
#define GCC_PLL_APCS_PLL4_ENABLE (1 << GCC_PLL_APCS_PLL4_SHIFT)
|
||||
|
||||
/* LCC PLL0 Configuration/Control */
|
||||
|
||||
#define LCC_PLL0_MODE_REG 0x00
|
||||
#define LCC_PLL0_L_REG 0x04
|
||||
#define LCC_PLL0_M_REG 0x08
|
||||
#define LCC_PLL0_N_REG 0x0C
|
||||
#define LCC_PLL0_CFG_REG 0x14
|
||||
#define LCC_PLL0_STAT_REG 0x18
|
||||
|
||||
#define LCC_PLL0_MODE_FSM_RESET_MASK 0x200000
|
||||
#define LCC_PLL0_MODE_FSM_RESET_SHIFT 21
|
||||
#define LCC_PLL0_MODE_FSM_RESET_ASSERT (1 << LCC_PLL0_MODE_FSM_RESET_SHIFT)
|
||||
|
||||
#define LCC_PLL0_MODE_FSM_VOTE_MASK 0x100000
|
||||
#define LCC_PLL0_MODE_FSM_VOTE_SHIFT 20
|
||||
#define LCC_PLL0_MODE_FSM_VOTE_ENABLE (1 << LCC_PLL0_MODE_FSM_VOTE_SHIFT)
|
||||
|
||||
#define LCC_PLL0_MODE_BIAS_CNT_MASK 0xFC000
|
||||
#define LCC_PLL0_MODE_BIAS_CNT_SHIFT 14
|
||||
|
||||
#define LCC_PLL0_MODE_LOCK_CNT_MASK 0x3F00
|
||||
#define LCC_PLL0_MODE_LOCK_CNT_SHIFT 8
|
||||
|
||||
#define LCC_PLL0_MODE_XO_SEL_MASK 0x30
|
||||
#define LCC_PLL0_MODE_XO_SEL_SHIFT 4
|
||||
#define LCC_PLL0_MODE_XO_SEL_PXO (0 << LCC_PLL0_MODE_XO_SEL_SHIFT)
|
||||
#define LCC_PLL0_MODE_XO_SEL_MXO (1 << LCC_PLL0_MODE_XO_SEL_SHIFT)
|
||||
#define LCC_PLL0_MODE_XO_SEL_CXO (2 << LCC_PLL0_MODE_XO_SEL_SHIFT)
|
||||
|
||||
#define LCC_PLL0_MODE_TEST_MASK 0x8
|
||||
#define LCC_PLL0_MODE_TEST_SHIFT 3
|
||||
#define LCC_PLL0_MODE_TEST_ENABLE (1 << LCC_PLL0_MODE_TEST_SHIFT)
|
||||
|
||||
#define LCC_PLL0_MODE_RESET_MASK 0x4
|
||||
#define LCC_PLL0_MODE_RESET_SHIFT 2
|
||||
#define LCC_PLL0_MODE_RESET_DEASSERT (1 << LCC_PLL0_MODE_RESET_SHIFT)
|
||||
|
||||
#define LCC_PLL0_MODE_BYPASS_MASK 0x2
|
||||
#define LCC_PLL0_MODE_BYPASS_SHIFT 1
|
||||
#define LCC_PLL0_MODE_BYPASS_DISABLE (1 << LCC_PLL0_MODE_BYPASS_SHIFT)
|
||||
|
||||
#define LCC_PLL0_MODE_OUTPUT_MASK 0x1
|
||||
#define LCC_PLL0_MODE_OUTPUT_SHIFT 0
|
||||
#define LCC_PLL0_MODE_OUTPUT_ENABLE (1 << LCC_PLL0_MODE_OUTPUT_SHIFT)
|
||||
|
||||
#define LCC_PLL0_L_MASK 0x3FF
|
||||
#define LCC_PLL0_L_SHIFT 0
|
||||
|
||||
#define LCC_PLL0_M_MASK 0x7FFFF
|
||||
#define LCC_PLL0_M_SHIFT 0
|
||||
|
||||
#define LCC_PLL0_N_MASK 0x7FFFF
|
||||
#define LCC_PLL0_N_SHIFT 0
|
||||
|
||||
#define LCC_PLL0_CFG_LV_MAIN_MASK 0x800000
|
||||
#define LCC_PLL0_CFG_LV_MAIN_SHIFT 23
|
||||
#define LCC_PLL0_CFG_LV_MAIN_ENABLE (1 << LCC_PLL0_CFG_LV_MAIN_SHIFT)
|
||||
|
||||
#define LCC_PLL0_CFG_FRAC_MASK 0x400000
|
||||
#define LCC_PLL0_CFG_FRAC_SHIFT 22
|
||||
#define LCC_PLL0_CFG_FRAC_ENABLE (1 << LCC_PLL0_CFG_FRAC_SHIFT)
|
||||
|
||||
#define LCC_PLL0_CFG_POSTDIV_MASK 0x300000
|
||||
#define LCC_PLL0_CFG_POSTDIV_SHIFT 20
|
||||
#define LCC_PLL0_CFG_POSTDIV_DIV1 (0 << LCC_PLL0_CFG_POSTDIV_SHIFT)
|
||||
#define LCC_PLL0_CFG_POSTDIV_DIV2 (1 << LCC_PLL0_CFG_POSTDIV_SHIFT)
|
||||
#define LCC_PLL0_CFG_POSTDIV_DIV4 (2 << LCC_PLL0_CFG_POSTDIV_SHIFT)
|
||||
|
||||
#define LCC_PLL0_CFG_PREDIV_MASK 0x80000
|
||||
#define LCC_PLL0_CFG_PREDIV_SHIFT 19
|
||||
#define LCC_PLL0_CFG_PREDIV_DIV1 (0 << LCC_PLL0_CFG_PREDIV_SHIFT)
|
||||
#define LCC_PLL0_CFG_PREDIV_DIV2 (1 << LCC_PLL0_CFG_PREDIV_SHIFT)
|
||||
|
||||
#define LCC_PLL0_CFG_VCO_SEL_MASK 0x30000
|
||||
#define LCC_PLL0_CFG_VCO_SEL_SHIFT 16
|
||||
#define LCC_PLL0_CFG_VCO_SEL_LOW (0 << LCC_PLL0_CFG_VCO_SEL_SHIFT)
|
||||
#define LCC_PLL0_CFG_VCO_SEL_MED (1 << LCC_PLL0_CFG_VCO_SEL_SHIFT)
|
||||
#define LCC_PLL0_CFG_VCO_SEL_HIGH (2 << LCC_PLL0_CFG_VCO_SEL_SHIFT)
|
||||
|
||||
#define LCC_PLL0_STAT_ACTIVE_MASK 0x10000
|
||||
#define LCC_PLL0_STAT_ACTIVE_SHIFT 16
|
||||
#define LCC_PLL0_STAT_ACTIVE_SET (1 << LCC_PLL0_STAT_ACTIVE_SHIFT)
|
||||
|
||||
#define LCC_PLL0_STAT_NOCLK_MASK 0x1
|
||||
#define LCC_PLL0_STAT_NOCLK_SHIFT 0
|
||||
#define LCC_PLL0_STAT_NOCLK_SET (1 << LCC_PLL0_STAT_NOCLK_SHIFT)
|
||||
|
||||
/* LCC AHBIX Configuration/Control */
|
||||
|
||||
#define LCC_AHBIX_NS_REG 0x38
|
||||
#define LCC_AHBIX_MD_REG 0x3C
|
||||
#define LCC_AHBIX_STAT_REG 0x44
|
||||
|
||||
#define LCC_AHBIX_NS_N_VAL_MASK 0xFF000000
|
||||
#define LCC_AHBIX_NS_N_VAL_SHIFT 24
|
||||
|
||||
#define LCC_AHBIX_NS_CRC_MASK 0x800
|
||||
#define LCC_AHBIX_NS_CRC_SHIFT 11
|
||||
#define LCC_AHBIX_NS_CRC_ENABLE (1 << LCC_AHBIX_NS_CRC_SHIFT)
|
||||
|
||||
#define LCC_AHBIX_NS_GFM_SEL_MASK 0x400
|
||||
#define LCC_AHBIX_NS_GFM_SEL_SHIFT 10
|
||||
#define LCC_AHBIX_NS_GFM_SEL_PXO (0 << LCC_AHBIX_NS_GFM_SEL_SHIFT)
|
||||
#define LCC_AHBIX_NS_GFM_SEL_MNC (1 << LCC_AHBIX_NS_GFM_SEL_SHIFT)
|
||||
|
||||
#define LCC_AHBIX_NS_MNC_CLK_MASK 0x200
|
||||
#define LCC_AHBIX_NS_MNC_CLK_SHIFT 9
|
||||
#define LCC_AHBIX_NS_MNC_CLK_ENABLE (1 << LCC_AHBIX_NS_MNC_CLK_SHIFT)
|
||||
|
||||
#define LCC_AHBIX_NS_MNC_MASK 0x100
|
||||
#define LCC_AHBIX_NS_MNC_SHIFT 8
|
||||
#define LCC_AHBIX_NS_MNC_ENABLE (1 << LCC_AHBIX_NS_MNC_SHIFT)
|
||||
|
||||
#define LCC_AHBIX_NS_MNC_RESET_MASK 0x80
|
||||
#define LCC_AHBIX_NS_MNC_RESET_SHIFT 7
|
||||
#define LCC_AHBIX_NS_MNC_RESET_ASSERT (1 << LCC_AHBIX_NS_MNC_RESET_SHIFT)
|
||||
|
||||
#define LCC_AHBIX_NS_MNC_MODE_MASK 0x60
|
||||
#define LCC_AHBIX_NS_MNC_MODE_SHIFT 5
|
||||
#define LCC_AHBIX_NS_MNC_MODE_BYPASS (0 << LCC_AHBIX_NS_MNC_MODE_SHIFT)
|
||||
#define LCC_AHBIX_NS_MNC_MODE_SWALLOW (1 << LCC_AHBIX_NS_MNC_MODE_SHIFT)
|
||||
#define LCC_AHBIX_NS_MNC_MODE_DUAL (2 << LCC_AHBIX_NS_MNC_MODE_SHIFT)
|
||||
#define LCC_AHBIX_NS_MNC_MODE_SINGLE (3 << LCC_AHBIX_NS_MNC_MODE_SHIFT)
|
||||
|
||||
#define LCC_AHBIX_NS_PREDIV_MASK 0x18
|
||||
#define LCC_AHBIX_NS_PREDIV_SHIFT 3
|
||||
#define LCC_AHBIX_NS_PREDIV_BYPASS (0 << LCC_AHBIX_NS_PREDIV_SHIFT)
|
||||
#define LCC_AHBIX_NS_PREDIV_DIV2 (1 << LCC_AHBIX_NS_PREDIV_SHIFT)
|
||||
#define LCC_AHBIX_NS_PREDIV_DIV4 (3 << LCC_AHBIX_NS_PREDIV_SHIFT)
|
||||
|
||||
#define LCC_AHBIX_NS_MN_SRC_MASK 0x7
|
||||
#define LCC_AHBIX_NS_MN_SRC_SHIFT 0
|
||||
#define LCC_AHBIX_NS_MN_SRC_PXO (0 << LCC_AHBIX_NS_MN_SRC_SHIFT)
|
||||
#define LCC_AHBIX_NS_MN_SRC_CXO (1 << LCC_AHBIX_NS_MN_SRC_SHIFT)
|
||||
#define LCC_AHBIX_NS_MN_SRC_LPA (2 << LCC_AHBIX_NS_MN_SRC_SHIFT)
|
||||
#define LCC_AHBIX_NS_MN_SRC_SEC (3 << LCC_AHBIX_NS_MN_SRC_SHIFT)
|
||||
#define LCC_AHBIX_NS_MN_SRC_CTEST (6 << LCC_AHBIX_NS_MN_SRC_SHIFT)
|
||||
#define LCC_AHBIX_NS_MN_SRC_PTEST (7 << LCC_AHBIX_NS_MN_SRC_SHIFT)
|
||||
|
||||
#define LCC_AHBIX_MD_M_VAL_MASK 0xFF00
|
||||
#define LCC_AHBIX_MD_M_VAL_SHIFT 8
|
||||
|
||||
#define LCC_AHBIX_MD_NOT_2D_VAL_MASK 0xFF
|
||||
#define LCC_AHBIX_MD_NOT_2D_VAL_SHIFT 0
|
||||
|
||||
#define LCC_AHBIX_STAT_AHB_CLK_MASK 0x400
|
||||
#define LCC_AHBIX_STAT_AHB_CLK_SHIFT 10
|
||||
#define LCC_AHBIX_STAT_AHB_CLK_ON (1 << LCC_AHBIX_STAT_AHB_CLK_SHIFT)
|
||||
|
||||
#define LCC_AHBIX_STAT_AIF_CLK_MASK 0x200
|
||||
#define LCC_AHBIX_STAT_AIF_CLK_SHIFT 9
|
||||
#define LCC_AHBIX_STAT_AIF_CLK_ON (1 << LCC_AHBIX_STAT_AIF_CLK_SHIFT)
|
||||
|
||||
#define LCC_AHBIX_STAT_FAB2_CLK_MASK 0x40
|
||||
#define LCC_AHBIX_STAT_FAB2_CLK_SHIFT 6
|
||||
#define LCC_AHBIX_STAT_FAB2_CLK_ON (1 << LCC_AHBIX_STAT_FAB2_CLK_SHIFT)
|
||||
|
||||
#define LCC_AHBIX_STAT_2FAB_CLK_MASK 0x20
|
||||
#define LCC_AHBIX_STAT_2FAB_CLK_SHIFT 5
|
||||
#define LCC_AHBIX_STAT_2FAB_CLK_ON (1 << LCC_AHBIX_STAT_2FAB_CLK_SHIFT)
|
||||
|
||||
/* LCC MI2S Configuration/Control */
|
||||
|
||||
#define LCC_MI2S_NS_REG 0x48
|
||||
#define LCC_MI2S_MD_REG 0x4C
|
||||
#define LCC_MI2S_STAT_REG 0x50
|
||||
|
||||
#define LCC_MI2S_NS_N_VAL_MASK 0xFF000000
|
||||
#define LCC_MI2S_NS_N_VAL_SHIFT 24
|
||||
|
||||
#define LCC_MI2S_NS_RESET_MASK 0x80000
|
||||
#define LCC_MI2S_NS_RESET_SHIFT 19
|
||||
#define LCC_MI2S_NS_RESET_ASSERT (1 << LCC_MI2S_NS_RESET_SHIFT)
|
||||
|
||||
#define LCC_MI2S_NS_OSR_INV_MASK 0x40000
|
||||
#define LCC_MI2S_NS_OSR_INV_SHIFT 18
|
||||
#define LCC_MI2S_NS_OSR_INV_ENABLE (1 << LCC_MI2S_NS_OSR_INV_SHIFT)
|
||||
|
||||
#define LCC_MI2S_NS_OSR_CXC_MASK 0x20000
|
||||
#define LCC_MI2S_NS_OSR_CXC_SHIFT 17
|
||||
#define LCC_MI2S_NS_OSR_CXC_ENABLE (1 << LCC_MI2S_NS_OSR_CXC_SHIFT)
|
||||
|
||||
#define LCC_MI2S_NS_BIT_INV_MASK 0x10000
|
||||
#define LCC_MI2S_NS_BIT_INV_SHIFT 16
|
||||
#define LCC_MI2S_NS_BIT_INV_ENABLE (1 << LCC_MI2S_NS_BIT_INV_SHIFT)
|
||||
|
||||
#define LCC_MI2S_NS_BIT_CXC_MASK 0x8000
|
||||
#define LCC_MI2S_NS_BIT_CXC_SHIFT 15
|
||||
#define LCC_MI2S_NS_BIT_CXC_ENABLE (1 << LCC_MI2S_NS_BIT_CXC_SHIFT)
|
||||
|
||||
#define LCC_MI2S_NS_BIT_SRC_MASK 0x4000
|
||||
#define LCC_MI2S_NS_BIT_SRC_SHIFT 14
|
||||
#define LCC_MI2S_NS_BIT_SRC_MASTER (0 << LCC_MI2S_NS_BIT_SRC_SHIFT)
|
||||
#define LCC_MI2S_NS_BIT_SRC_SLAVE (1 << LCC_MI2S_NS_BIT_SRC_SHIFT)
|
||||
|
||||
#define LCC_MI2S_NS_BIT_DIV_MASK 0x3C00
|
||||
#define LCC_MI2S_NS_BIT_DIV_SHIFT 10
|
||||
#define LCC_MI2S_NS_BIT_DIV_BYPASS (0 << LCC_MI2S_NS_BIT_DIV_SHIFT)
|
||||
#define LCC_MI2S_NS_BIT_DIV_DIV2 (1 << LCC_MI2S_NS_BIT_DIV_SHIFT)
|
||||
#define LCC_MI2S_NS_BIT_DIV_DIV3 (2 << LCC_MI2S_NS_BIT_DIV_SHIFT)
|
||||
#define LCC_MI2S_NS_BIT_DIV_DIV4 (3 << LCC_MI2S_NS_BIT_DIV_SHIFT)
|
||||
#define LCC_MI2S_NS_BIT_DIV_DIV5 (4 << LCC_MI2S_NS_BIT_DIV_SHIFT)
|
||||
#define LCC_MI2S_NS_BIT_DIV_DIV6 (5 << LCC_MI2S_NS_BIT_DIV_SHIFT)
|
||||
#define LCC_MI2S_NS_BIT_DIV_DIV7 (6 << LCC_MI2S_NS_BIT_DIV_SHIFT)
|
||||
#define LCC_MI2S_NS_BIT_DIV_DIV8 (7 << LCC_MI2S_NS_BIT_DIV_SHIFT)
|
||||
#define LCC_MI2S_NS_BIT_DIV_DIV9 (8 << LCC_MI2S_NS_BIT_DIV_SHIFT)
|
||||
#define LCC_MI2S_NS_BIT_DIV_DIV10 (9 << LCC_MI2S_NS_BIT_DIV_SHIFT)
|
||||
#define LCC_MI2S_NS_BIT_DIV_DIV11 (10 << LCC_MI2S_NS_BIT_DIV_SHIFT)
|
||||
#define LCC_MI2S_NS_BIT_DIV_DIV12 (11 << LCC_MI2S_NS_BIT_DIV_SHIFT)
|
||||
#define LCC_MI2S_NS_BIT_DIV_DIV13 (12 << LCC_MI2S_NS_BIT_DIV_SHIFT)
|
||||
#define LCC_MI2S_NS_BIT_DIV_DIV14 (13 << LCC_MI2S_NS_BIT_DIV_SHIFT)
|
||||
#define LCC_MI2S_NS_BIT_DIV_DIV15 (14 << LCC_MI2S_NS_BIT_DIV_SHIFT)
|
||||
#define LCC_MI2S_NS_BIT_DIV_DIV16 (15 << LCC_MI2S_NS_BIT_DIV_SHIFT)
|
||||
|
||||
#define LCC_MI2S_NS_MNC_CLK_MASK 0x200
|
||||
#define LCC_MI2S_NS_MNC_CLK_SHIFT 9
|
||||
#define LCC_MI2S_NS_MNC_CLK_ENABLE (1 << LCC_MI2S_NS_MNC_CLK_SHIFT)
|
||||
|
||||
#define LCC_MI2S_NS_MNC_MASK 0x100
|
||||
#define LCC_MI2S_NS_MNC_SHIFT 8
|
||||
#define LCC_MI2S_NS_MNC_ENABLE (1 << LCC_MI2S_NS_MNC_SHIFT)
|
||||
|
||||
#define LCC_MI2S_NS_MNC_RESET_MASK 0x80
|
||||
#define LCC_MI2S_NS_MNC_RESET_SHIFT 7
|
||||
#define LCC_MI2S_NS_MNC_RESET_ASSERT (1 << LCC_MI2S_NS_MNC_RESET_SHIFT)
|
||||
|
||||
#define LCC_MI2S_NS_MNC_MODE_MASK 0x60
|
||||
#define LCC_MI2S_NS_MNC_MODE_SHIFT 5
|
||||
#define LCC_MI2S_NS_MNC_MODE_BYPASS (0 << LCC_MI2S_NS_MNC_MODE_SHIFT)
|
||||
#define LCC_MI2S_NS_MNC_MODE_SWALLOW (1 << LCC_MI2S_NS_MNC_MODE_SHIFT)
|
||||
#define LCC_MI2S_NS_MNC_MODE_DUAL (2 << LCC_MI2S_NS_MNC_MODE_SHIFT)
|
||||
#define LCC_MI2S_NS_MNC_MODE_SINGLE (3 << LCC_MI2S_NS_MNC_MODE_SHIFT)
|
||||
|
||||
#define LCC_MI2S_NS_PREDIV_MASK 0x18
|
||||
#define LCC_MI2S_NS_PREDIV_SHIFT 3
|
||||
#define LCC_MI2S_NS_PREDIV_BYPASS (0 << LCC_MI2S_NS_PREDIV_SHIFT)
|
||||
#define LCC_MI2S_NS_PREDIV_DIV2 (1 << LCC_MI2S_NS_PREDIV_SHIFT)
|
||||
#define LCC_MI2S_NS_PREDIV_DIV4 (3 << LCC_MI2S_NS_PREDIV_SHIFT)
|
||||
|
||||
#define LCC_MI2S_NS_MN_SRC_MASK 0x7
|
||||
#define LCC_MI2S_NS_MN_SRC_SHIFT 0
|
||||
#define LCC_MI2S_NS_MN_SRC_PXO (0 << LCC_MI2S_NS_MN_SRC_SHIFT)
|
||||
#define LCC_MI2S_NS_MN_SRC_CXO (1 << LCC_MI2S_NS_MN_SRC_SHIFT)
|
||||
#define LCC_MI2S_NS_MN_SRC_LPA (2 << LCC_MI2S_NS_MN_SRC_SHIFT)
|
||||
#define LCC_MI2S_NS_MN_SRC_SEC (3 << LCC_MI2S_NS_MN_SRC_SHIFT)
|
||||
#define LCC_MI2S_NS_MN_SRC_CTEST (6 << LCC_MI2S_NS_MN_SRC_SHIFT)
|
||||
#define LCC_MI2S_NS_MN_SRC_PTEST (7 << LCC_MI2S_NS_MN_SRC_SHIFT)
|
||||
|
||||
#define LCC_MI2S_MD_M_VAL_MASK 0xFF00
|
||||
#define LCC_MI2S_MD_M_VAL_SHIFT 8
|
||||
|
||||
#define LCC_MI2S_MD_NOT_2D_VAL_MASK 0xFF
|
||||
#define LCC_MI2S_MD_NOT_2D_VAL_SHIFT 0
|
||||
|
||||
#define LCC_MI2S_STAT_OSR_CLK_MASK 0x2
|
||||
#define LCC_MI2S_STAT_OSR_CLK_SHIFT 1
|
||||
#define LCC_MI2S_STAT_OSR_CLK_ON (1 << LCC_MI2S_STAT_OSR_CLK_SHIFT)
|
||||
|
||||
#define LCC_MI2S_STAT_BIT_CLK_MASK 0x1
|
||||
#define LCC_MI2S_STAT_BIT_CLK_SHIFT 0
|
||||
#define LCC_MI2S_STAT_BIT_CLK_ON (1 << LCC_MI2S_STAT_BIT_CLK_SHIFT)
|
||||
|
||||
/* LCC PLL Configuration/Control */
|
||||
|
||||
#define LCC_PLL_PCLK_REG 0xC4
|
||||
#define LCC_PLL_SCLK_REG 0xC8
|
||||
|
||||
#define LCC_PLL_PCLK_RESET_MASK 0x2
|
||||
#define LCC_PLL_PCLK_RESET_SHIFT 1
|
||||
#define LCC_PLL_PCLK_RESET_ASSERT (1 << LCC_PLL_PCLK_RESET_SHIFT)
|
||||
|
||||
#define LCC_PLL_PCLK_SRC_MASK 0x1
|
||||
#define LCC_PLL_PCLK_SRC_SHIFT 0
|
||||
#define LCC_PLL_PCLK_SRC_PXO (0 << LCC_PLL_PCLK_SRC_SHIFT)
|
||||
#define LCC_PLL_PCLK_SRC_PRI (1 << LCC_PLL_PCLK_SRC_SHIFT)
|
||||
|
||||
#define LCC_PLL_SCLK_RESET_MASK 0x10
|
||||
#define LCC_PLL_SCLK_RESET_SHIFT 4
|
||||
#define LCC_PLL_SCLK_RESET_ASSERT (1 << LCC_PLL_SCLK_RESET_SHIFT)
|
||||
|
||||
#define LCC_PLL_SCLK_DIV_MASK 0xC
|
||||
#define LCC_PLL_SCLK_DIV_SHIFT 2
|
||||
#define LCC_PLL_SCLK_DIV_BYPASS (0 << LCC_PLL_SCLK_DIV_SHIFT)
|
||||
#define LCC_PLL_SCLK_DIV_DIV2 (1 << LCC_PLL_SCLK_DIV_SHIFT)
|
||||
#define LCC_PLL_SCLK_DIV_DIV3 (2 << LCC_PLL_SCLK_DIV_SHIFT)
|
||||
#define LCC_PLL_SCLK_DIV_DIV4 (3 << LCC_PLL_SCLK_DIV_SHIFT)
|
||||
|
||||
#define LCC_PLL_SCLK_XO_MASK 0x2
|
||||
#define LCC_PLL_SCLK_XO_SHIFT 1
|
||||
#define LCC_PLL_SCLK_XO_PXO (0 << LCC_PLL_SCLK_XO_SHIFT)
|
||||
#define LCC_PLL_SCLK_XO_SEC (1 << LCC_PLL_SCLK_XO_SHIFT)
|
||||
|
||||
#define LCC_PLL_SCLK_MUX_MASK 0x1
|
||||
#define LCC_PLL_SCLK_MUX_SHIFT 0
|
||||
#define LCC_PLL_SCLK_MUX_PLL1 (0 << LCC_PLL_SCLK_MUX_SHIFT)
|
||||
#define LCC_PLL_SCLK_MUX_PLL0 (1 << LCC_PLL_SCLK_MUX_SHIFT)
|
||||
|
||||
#endif /* __DRIVERS_CLOCK_IPQ806X_LCC_REG_H__ */
|
|
@ -0,0 +1,316 @@
|
|||
/*
|
||||
* Copyright (c) 2015, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of The Linux Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <delay.h>
|
||||
#include <console/console.h>
|
||||
#include <soc/clock.h>
|
||||
#include <soc/lcc-reg.h>
|
||||
#include <arch/io.h>
|
||||
|
||||
typedef struct {
|
||||
void *gcc_apcs_regs;
|
||||
void *lcc_pll0_regs;
|
||||
void *lcc_ahbix_regs;
|
||||
void *lcc_mi2s_regs;
|
||||
void *lcc_pll_regs;
|
||||
} Ipq806xLccClocks;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t apcs;
|
||||
} Ipq806xLccGccRegs;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t mode;
|
||||
uint32_t l_val;
|
||||
uint32_t m_val;
|
||||
uint32_t n_val;
|
||||
uint32_t UNUSED;
|
||||
uint32_t config;
|
||||
uint32_t status;
|
||||
} Ipq806xLccPll0Regs;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t ns;
|
||||
uint32_t md;
|
||||
uint32_t UNUSED;
|
||||
uint32_t status;
|
||||
} Ipq806xLccAhbixRegs;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t ns;
|
||||
uint32_t md;
|
||||
uint32_t status;
|
||||
} Ipq806xLccMi2sRegs;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t pri;
|
||||
uint32_t sec;
|
||||
} Ipq806xLccPllRegs;
|
||||
|
||||
struct lcc_freq_tbl {
|
||||
unsigned freq;
|
||||
unsigned pd;
|
||||
unsigned m;
|
||||
unsigned n;
|
||||
unsigned d;
|
||||
};
|
||||
|
||||
static const struct lcc_freq_tbl lcc_mi2s_freq_tbl[] = {
|
||||
{ 1024000, 4, 1, 96, 8 },
|
||||
{ 1411200, 4, 2, 139, 8 },
|
||||
{ 1536000, 4, 1, 64, 8 },
|
||||
{ 2048000, 4, 1, 48, 8 },
|
||||
{ 2116800, 4, 2, 93, 8 },
|
||||
{ 2304000, 4, 2, 85, 8 },
|
||||
{ 2822400, 4, 6, 209, 8 },
|
||||
{ 3072000, 4, 1, 32, 8 },
|
||||
{ 3175200, 4, 1, 31, 8 },
|
||||
{ 4096000, 4, 1, 24, 8 },
|
||||
{ 4233600, 4, 9, 209, 8 },
|
||||
{ 4608000, 4, 3, 64, 8 },
|
||||
{ 5644800, 4, 12, 209, 8 },
|
||||
{ 6144000, 4, 1, 16, 8 },
|
||||
{ 6350400, 4, 2, 31, 8 },
|
||||
{ 8192000, 4, 1, 12, 8 },
|
||||
{ 8467200, 4, 18, 209, 8 },
|
||||
{ 9216000, 4, 3, 32, 8 },
|
||||
{ 11289600, 4, 24, 209, 8 },
|
||||
{ 12288000, 4, 1, 8, 8 },
|
||||
{ 12700800, 4, 27, 209, 8 },
|
||||
{ 13824000, 4, 9, 64, 8 },
|
||||
{ 16384000, 4, 1, 6, 8 },
|
||||
{ 16934400, 4, 41, 238, 8 },
|
||||
{ 18432000, 4, 3, 16, 8 },
|
||||
{ 22579200, 2, 24, 209, 8 },
|
||||
{ 24576000, 4, 1, 4, 8 },
|
||||
{ 27648000, 4, 9, 32, 8 },
|
||||
{ 33868800, 4, 41, 119, 8 },
|
||||
{ 36864000, 4, 3, 8, 8 },
|
||||
{ 45158400, 1, 24, 209, 8 },
|
||||
{ 49152000, 4, 1, 2, 8 },
|
||||
{ 50803200, 1, 27, 209, 8 },
|
||||
{ }
|
||||
};
|
||||
|
||||
static int lcc_init_enable_pll0(Ipq806xLccClocks *bus)
|
||||
{
|
||||
Ipq806xLccGccRegs *gcc_regs = bus->gcc_apcs_regs;
|
||||
Ipq806xLccPll0Regs *pll0_regs = bus->lcc_pll0_regs;
|
||||
Ipq806xLccPllRegs *pll_regs = bus->lcc_pll_regs;
|
||||
uint32_t regval;
|
||||
|
||||
regval = 0;
|
||||
regval = 15 << LCC_PLL0_L_SHIFT & LCC_PLL0_L_MASK;
|
||||
writel(regval, &pll0_regs->l_val);
|
||||
|
||||
regval = 0;
|
||||
regval = 145 << LCC_PLL0_M_SHIFT & LCC_PLL0_M_MASK;
|
||||
writel(regval, &pll0_regs->m_val);
|
||||
|
||||
regval = 0;
|
||||
regval = 199 << LCC_PLL0_N_SHIFT & LCC_PLL0_N_MASK;
|
||||
writel(regval, &pll0_regs->n_val);
|
||||
|
||||
regval = 0;
|
||||
regval |= LCC_PLL0_CFG_LV_MAIN_ENABLE;
|
||||
regval |= LCC_PLL0_CFG_FRAC_ENABLE;
|
||||
writel(regval, &pll0_regs->config);
|
||||
|
||||
regval = 0;
|
||||
regval |= LCC_PLL_PCLK_SRC_PRI;
|
||||
writel(regval, &pll_regs->pri);
|
||||
|
||||
regval = 0;
|
||||
regval |= 1 << LCC_PLL0_MODE_BIAS_CNT_SHIFT &
|
||||
LCC_PLL0_MODE_BIAS_CNT_MASK;
|
||||
regval |= 8 << LCC_PLL0_MODE_LOCK_CNT_SHIFT &
|
||||
LCC_PLL0_MODE_LOCK_CNT_MASK;
|
||||
writel(regval, &pll0_regs->mode);
|
||||
|
||||
regval = readl(&gcc_regs->apcs);
|
||||
regval |= GCC_PLL_APCS_PLL4_ENABLE;
|
||||
writel(regval, &gcc_regs->apcs);
|
||||
|
||||
regval = readl(&pll0_regs->mode);
|
||||
regval |= LCC_PLL0_MODE_FSM_VOTE_ENABLE;
|
||||
writel(regval, &pll0_regs->mode);
|
||||
|
||||
mdelay(1);
|
||||
|
||||
regval = readl(&pll0_regs->status);
|
||||
if (regval & LCC_PLL0_STAT_ACTIVE_MASK)
|
||||
return 0;
|
||||
|
||||
printk(BIOS_ERR, "%s: error enabling PLL4 clock\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lcc_init_enable_ahbix(Ipq806xLccClocks *bus)
|
||||
{
|
||||
Ipq806xLccAhbixRegs *ahbix_regs = bus->lcc_ahbix_regs;
|
||||
uint32_t regval;
|
||||
|
||||
regval = 0;
|
||||
regval |= 1 << LCC_AHBIX_MD_M_VAL_SHIFT & LCC_AHBIX_MD_M_VAL_MASK;
|
||||
regval |= 252 << LCC_AHBIX_MD_NOT_2D_VAL_SHIFT &
|
||||
LCC_AHBIX_MD_NOT_2D_VAL_MASK;
|
||||
writel(regval, &ahbix_regs->md);
|
||||
|
||||
regval = 0;
|
||||
regval |= 253 << LCC_AHBIX_NS_N_VAL_SHIFT & LCC_AHBIX_NS_N_VAL_MASK;
|
||||
regval |= LCC_AHBIX_NS_CRC_ENABLE;
|
||||
regval |= LCC_AHBIX_NS_GFM_SEL_MNC;
|
||||
regval |= LCC_AHBIX_NS_MNC_CLK_ENABLE;
|
||||
regval |= LCC_AHBIX_NS_MNC_ENABLE;
|
||||
regval |= LCC_AHBIX_NS_MNC_MODE_DUAL;
|
||||
regval |= LCC_AHBIX_NS_PREDIV_BYPASS;
|
||||
regval |= LCC_AHBIX_NS_MN_SRC_LPA;
|
||||
writel(regval, &ahbix_regs->ns);
|
||||
|
||||
mdelay(1);
|
||||
|
||||
regval = readl(&ahbix_regs->status);
|
||||
if (regval & LCC_AHBIX_STAT_AIF_CLK_MASK)
|
||||
return 0;
|
||||
|
||||
printk(BIOS_ERR, "%s: error enabling AHBIX clock\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lcc_init_mi2s(Ipq806xLccClocks *bus, unsigned freq)
|
||||
{
|
||||
Ipq806xLccMi2sRegs *mi2s_regs = bus->lcc_mi2s_regs;
|
||||
uint32_t regval;
|
||||
uint8_t pd, m, n, d;
|
||||
unsigned i;
|
||||
|
||||
i = 0;
|
||||
while (lcc_mi2s_freq_tbl[i].freq != 0) {
|
||||
if (lcc_mi2s_freq_tbl[i].freq == freq)
|
||||
break;
|
||||
++i;
|
||||
}
|
||||
if (lcc_mi2s_freq_tbl[i].freq == 0) {
|
||||
printk(BIOS_ERR, "%s: invalid frequency given: %u\n",
|
||||
__func__, freq);
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (lcc_mi2s_freq_tbl[i].pd) {
|
||||
case 1:
|
||||
pd = LCC_MI2S_NS_PREDIV_BYPASS;
|
||||
break;
|
||||
case 2:
|
||||
pd = LCC_MI2S_NS_PREDIV_DIV2;
|
||||
break;
|
||||
case 4:
|
||||
pd = LCC_MI2S_NS_PREDIV_DIV4;
|
||||
break;
|
||||
default:
|
||||
printk(BIOS_ERR, "%s: invalid prediv found: %u\n", __func__,
|
||||
lcc_mi2s_freq_tbl[i].pd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
m = lcc_mi2s_freq_tbl[i].m;
|
||||
n = ~(lcc_mi2s_freq_tbl[i].n - m);
|
||||
d = ~(lcc_mi2s_freq_tbl[i].d * 2);
|
||||
|
||||
regval = 0;
|
||||
regval |= m << LCC_MI2S_MD_M_VAL_SHIFT & LCC_MI2S_MD_M_VAL_MASK;
|
||||
regval |= d << LCC_MI2S_MD_NOT_2D_VAL_SHIFT &
|
||||
LCC_MI2S_MD_NOT_2D_VAL_MASK;
|
||||
writel(regval, &mi2s_regs->md);
|
||||
|
||||
regval = 0;
|
||||
regval |= n << LCC_MI2S_NS_N_VAL_SHIFT & LCC_MI2S_NS_N_VAL_MASK;
|
||||
regval |= LCC_MI2S_NS_BIT_DIV_DIV4;
|
||||
regval |= LCC_MI2S_NS_MNC_CLK_ENABLE;
|
||||
regval |= LCC_MI2S_NS_MNC_ENABLE;
|
||||
regval |= LCC_MI2S_NS_MNC_MODE_DUAL;
|
||||
regval |= pd;
|
||||
regval |= LCC_MI2S_NS_MN_SRC_LPA;
|
||||
writel(regval, &mi2s_regs->ns);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lcc_enable_mi2s(Ipq806xLccClocks *bus)
|
||||
{
|
||||
Ipq806xLccMi2sRegs *mi2s_regs = bus->lcc_mi2s_regs;
|
||||
uint32_t regval;
|
||||
|
||||
regval = readl(&mi2s_regs->ns);
|
||||
regval |= LCC_MI2S_NS_OSR_CXC_ENABLE;
|
||||
regval |= LCC_MI2S_NS_BIT_CXC_ENABLE;
|
||||
writel(regval, &mi2s_regs->ns);
|
||||
|
||||
udelay(10);
|
||||
|
||||
regval = readl(&mi2s_regs->status);
|
||||
if (regval & LCC_MI2S_STAT_OSR_CLK_MASK)
|
||||
if (regval & LCC_MI2S_STAT_BIT_CLK_MASK)
|
||||
return 0;
|
||||
|
||||
printk(BIOS_ERR, "%s: error enabling MI2S clocks: %u\n",
|
||||
__func__, regval);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int audio_clock_config(unsigned frequency)
|
||||
{
|
||||
Ipq806xLccClocks *bus = malloc(sizeof(*bus));
|
||||
|
||||
if (!bus) {
|
||||
printk(BIOS_ERR, "%s: failed to allocate bus structure\n",
|
||||
__func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bus->gcc_apcs_regs = (void *)(MSM_GCC_BASE + GCC_PLL_APCS_REG);
|
||||
bus->lcc_pll0_regs = (void *)(MSM_LPASS_LCC_BASE + LCC_PLL0_MODE_REG);
|
||||
bus->lcc_ahbix_regs = (void *)(MSM_LPASS_LCC_BASE + LCC_AHBIX_NS_REG);
|
||||
bus->lcc_mi2s_regs = (void *)(MSM_LPASS_LCC_BASE + LCC_MI2S_NS_REG);
|
||||
bus->lcc_pll_regs = (void *)(MSM_LPASS_LCC_BASE + LCC_PLL_PCLK_REG);
|
||||
|
||||
|
||||
if (lcc_init_enable_pll0(bus))
|
||||
return 1;
|
||||
if (lcc_init_enable_ahbix(bus))
|
||||
return 1;
|
||||
if (lcc_init_mi2s(bus, frequency))
|
||||
return 1;
|
||||
|
||||
if (lcc_enable_mi2s(bus))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue