/*
 * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
 * Copyright (c) 2024, Altera Corporation. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#ifndef CLOCKMANAGER_H
#define CLOCKMANAGER_H

#include "socfpga_handoff.h"

/* Clock Manager Registers */
#define CLKMGR_BASE				0x10D10000
#define CLKMGR_CTRL				0x00
#define CLKMGR_STAT				0x04
#define CLKMGR_TESTIOCTROL			0x08
#define CLKMGR_INTRGEN				0x0C
#define CLKMGR_INTRMSK				0x10
#define CLKMGR_INTRCLR				0x14
#define CLKMGR_INTRSTS				0x18
#define CLKMGR_INTRSTK				0x1C
#define CLKMGR_INTRRAW				0x20

/* Clock manager control related macros */
#define CLKMGR(_reg)				(CLKMGR_BASE + (CLKMGR_##_reg))
#define CLKMGR_STAT_MAINPLLLOCKED		BIT(8)
#define CLKMGR_STAT_PERPLLLOCKED		BIT(16)

#define CLKMGR_INTRCLR_MAINLOCKLOST		BIT(2)
#define CLKMGR_INTRCLR_PERLOCKLOST		BIT(3)

#define CLKMGR_STAT_ALLPLLLOCKED		(CLKMGR_STAT_MAINPLLLOCKED | \
						CLKMGR_STAT_PERPLLLOCKED)

/* Main PLL Group */
#define CLKMGR_MAINPLL_BASE			0x10D10024
#define CLKMGR_MAINPLL_EN			0x00
#define CLKMGR_MAINPLL_ENS			0x04
#define CLKMGR_MAINPLL_ENR			0x08
#define CLKMGR_MAINPLL_BYPASS			0x0C
#define CLKMGR_MAINPLL_BYPASSS			0x10
#define CLKMGR_MAINPLL_BYPASSR			0x14
#define CLKMGR_MAINPLL_NOCCLK			0x1C
#define CLKMGR_MAINPLL_NOCDIV			0x20
#define CLKMGR_MAINPLL_PLLGLOB			0x24
#define CLKMGR_MAINPLL_FDBCK			0x28
#define CLKMGR_MAINPLL_MEM			0x2C
#define CLKMGR_MAINPLL_MEMSTAT			0x30
#define CLKMGR_MAINPLL_VCOCALIB			0x34
#define CLKMGR_MAINPLL_PLLC0			0x38
#define CLKMGR_MAINPLL_PLLC1			0x3C
#define CLKMGR_MAINPLL_PLLC2			0x40
#define CLKMGR_MAINPLL_PLLC3			0x44
#define CLKMGR_MAINPLL_PLLM			0x48
#define CLKMGR_MAINPLL_FHOP			0x4C
#define CLKMGR_MAINPLL_SSC			0x50
#define CLKMGR_MAINPLL_LOSTLOCK			0x54

#define CLKMGR_MAINPLL(_reg)			(CLKMGR_MAINPLL_BASE + \
							(CLKMGR_MAINPLL_##_reg))

#define CLKMGR_XPLL_LOSTLOCK_BYPASSCLEAR	BIT(0)
#define CLKMGR_XPLLGLOB_CLR_LOSTLOCK_BYPASS	BIT(29)

/* Peripheral PLL Group */
#define CLKMGR_PERPLL_BASE			0x10D1007C
#define CLKMGR_PERPLL_EN			0x00
#define CLKMGR_PERPLL_ENS			0x04
#define CLKMGR_PERPLL_ENR			0x08
#define CLKMGR_PERPLL_BYPASS			0x0C
#define CLKMGR_PERPLL_BYPASSS			0x10
#define CLKMGR_PERPLL_BYPASSR			0x14
#define CLKMGR_PERPLL_EMACCTL			0x18
#define CLKMGR_PERPLL_GPIODIV			0x1C
#define CLKMGR_PERPLL_PLLGLOB			0x20
#define CLKMGR_PERPLL_FDBCK			0x24
#define CLKMGR_PERPLL_MEM			0x28
#define CLKMGR_PERPLL_MEMSTAT			0x2C
#define CLKMGR_PERPLL_VCOCALIB			0x30
#define CLKMGR_PERPLL_PLLC0			0x34
#define CLKMGR_PERPLL_PLLC1			0x38
#define CLKMGR_PERPLL_PLLC2			0x3C
#define CLKMGR_PERPLL_PLLC3			0x40
#define CLKMGR_PERPLL_PLLM			0x44
#define CLKMGR_PERPLL_FHOP			0x48
#define CLKMGR_PERPLL_SSC			0x4C
#define CLKMGR_PERPLL_LOSTLOCK			0x50

#define CLKMGR_PERPLL(_reg)			(CLKMGR_PERPLL_BASE + \
							(CLKMGR_PERPLL_##_reg))

/* Altera Group */
#define CLKMGR_ALTERA_BASE			0x10D100D0
#define CLKMGR_ALTERA_JTAG			0x00
#define CLKMGR_ALTERA_EMACACTR			0x04
#define CLKMGR_ALTERA_EMACBCTR			0x08
#define CLKMGR_ALTERA_EMACPTPCTR		0x0C
#define CLKMGR_ALTERA_GPIODBCTR			0x10
#define CLKMGR_ALTERA_S2FUSER0CTR		0x18
#define CLKMGR_ALTERA_S2FUSER1CTR		0x1C
#define CLKMGR_ALTERA_PSIREFCTR			0x20
#define CLKMGR_ALTERA_EXTCNTRST			0x24
#define CLKMGR_ALTERA_USB31CTR			0x28
#define CLKMGR_ALTERA_DSUCTR			0x2C
#define CLKMGR_ALTERA_CORE01CTR			0x30
#define CLKMGR_ALTERA_CORE23CTR			0x34
#define CLKMGR_ALTERA_CORE2CTR			0x38
#define CLKMGR_ALTERA_CORE3CTR			0x3C
#define CLKMGR_ALTERA_SERIAL_CON_PLL_CTR	0x40

#define CLKMGR_ALTERA(_reg)			(CLKMGR_ALTERA_BASE + \
							(CLKMGR_ALTERA_##_reg))

#define CLKMGR_ALTERA_EXTCNTRST_EMACACNTRST	BIT(0)
#define CLKMGR_ALTERA_EXTCNTRST_EMACBCNTRST	BIT(1)
#define CLKMGR_ALTERA_EXTCNTRST_EMACPTPCNTRST	BIT(2)
#define CLKMGR_ALTERA_EXTCNTRST_GPIODBCNTRST	BIT(3)
#define CLKMGR_ALTERA_EXTCNTRST_S2FUSER0CNTRST	BIT(5)
#define CLKMGR_ALTERA_EXTCNTRST_S2FUSER1CNTRST	BIT(6)
#define CLKMGR_ALTERA_EXTCNTRST_PSIREFCNTRST	BIT(7)
#define CLKMGR_ALTERA_EXTCNTRST_USB31REFCNTRST	BIT(8)
#define CLKMGR_ALTERA_EXTCNTRST_DSUCNTRST	BIT(10)
#define CLKMGR_ALTERA_EXTCNTRST_CORE01CNTRST	BIT(11)
#define CLKMGR_ALTERA_EXTCNTRST_CORE2CNTRST	BIT(12)
#define CLKMGR_ALTERA_EXTCNTRST_CORE3CNTRST	BIT(13)

#define CLKMGR_ALTERA_EXTCNTRST_ALLCNTRST	\
						(CLKMGR_ALTERA_EXTCNTRST_EMACACNTRST |	\
						CLKMGR_ALTERA_EXTCNTRST_EMACBCNTRST |	\
						CLKMGR_ALTERA_EXTCNTRST_EMACPTPCNTRST |	\
						CLKMGR_ALTERA_EXTCNTRST_GPIODBCNTRST |	\
						CLKMGR_ALTERA_EXTCNTRST_S2FUSER0CNTRST |\
						CLKMGR_ALTERA_EXTCNTRST_S2FUSER1CNTRST |\
						CLKMGR_ALTERA_EXTCNTRST_PSIREFCNTRST |	\
						CLKMGR_ALTERA_EXTCNTRST_USB31REFCNTRST |\
						CLKMGR_ALTERA_EXTCNTRST_DSUCNTRST |	\
						CLKMGR_ALTERA_EXTCNTRST_CORE01CNTRST |	\
						CLKMGR_ALTERA_EXTCNTRST_CORE2CNTRST |	\
						CLKMGR_ALTERA_EXTCNTRST_CORE3CNTRST)

#define CLKMGR_ALTERA_CORE0			0
#define CLKMGR_ALTERA_CORE1			1
#define CLKMGR_ALTERA_CORE2			2
#define CLKMGR_ALTERA_CORE3			3

/* PLL membus configuration macros */
#define CLKMGR_MEM_REQ				BIT(24)
#define CLKMGR_MEM_WR				BIT(25)
#define CLKMGR_MEM_ERR				BIT(26)
#define CLKMGR_MEM_WDAT_OFFSET			16
#define CLKMGR_MEM_ADDR_MASK			GENMASK(15, 0)
#define CLKMGR_MEM_ADDR_START			0x00004000
#define CLKMGR_PLLCFG_SRC_SYNC_MODE		0x27
#define CLKMGR_PLLCFG_OVRSHOOT_FREQ_LOCK	0xB3
#define CLKMGR_PLLCFG_LOCK_SETTLE_TIME		0xE6
#define CLKMGR_PLLCFG_DUTYCYCLE_CLKSLICE0	0x03
#define CLKMGR_PLLCFG_DUTYCYCLE_CLKSLICE1	0x07

/* Clock Manager Macros */
#define CLKMGR_CTRL_BOOTMODE_SET_MSK		0x00000001
#define CLKMGR_STAT_BUSY_E_BUSY			0x1
#define CLKMGR_STAT_BUSY(x)			(((x) & 0x00000001) >> 0)
#define CLKMGR_INTRCLR_MAINLOCKLOST_SET_MSK	0x00000004
#define CLKMGR_INTRCLR_PERLOCKLOST_SET_MSK	0x00000008
#define CLKMGR_INTOSC_HZ			460000000
#define CLKMGR_CTRL_BOOTMODE			BIT(0)
#define CLKMGR_STAT_MAINPLL_LOCKED		BIT(8)
#define CLKMGR_STAT_MAIN_TRANS			BIT(9)
#define CLKMGR_STAT_PERPLL_LOCKED		BIT(16)
#define CLKMGR_STAT_PERF_TRANS			BIT(17)
#define CLKMGR_STAT_BOOTMODE			BIT(24)
#define CLKMGR_STAT_BOOTCLKSRC			BIT(25)

#define CLKMGR_STAT_ALLPLL_LOCKED_MASK		(CLKMGR_STAT_MAINPLL_LOCKED | \
						 CLKMGR_STAT_PERPLL_LOCKED)
/* Main PLL Macros */
#define CLKMGR_MAINPLL_EN_RESET			0x0000005E
#define CLKMGR_MAINPLL_ENS_RESET		0x0000005E
#define CLKMGR_MAINPLL_PLLGLOB_PD_N		BIT(0)
#define CLKMGR_MAINPLL_PLLGLOB_RST_N		BIT(1)
#define CLKMGR_MAINPLL_PLLCX_EN			BIT(27)
#define CLKMGR_MAINPLL_PLLCX_MUTE		BIT(28)

#define CLKMGR_PERPLL_EN_SDMMCCLK		BIT(5)
#define CLKMGR_PERPLL_GPIODIV_GPIODBCLK_SET(x)	(((x) << 0) & 0x0000FFFF)
#define CLKMGR_PERPLL_PLLGLOB_PD_N		BIT(0)
#define CLKMGR_PERPLL_PLLGLOB_RST_N		BIT(1)
#define CLKMGR_PERPLL_PLLCX_EN			BIT(27)
#define CLKMGR_PERPLL_PLLCX_MUTE		BIT(28)

/* Altera Macros */
#define CLKMGR_ALTERA_EXTCNTRST_RESET		0xFF

/* Shared Macros */
#define CLKMGR_PLLGLOB_PSRC(x)			(((x) & 0x00030000) >> 16)
#define CLKMGR_PSRC_MAIN			0
#define CLKMGR_PSRC_PER				1

#define CLKMGR_PLLGLOB_PSRC_EOSC1		0x0
#define CLKMGR_PLLGLOB_PSRC_INTOSC		0x1
#define CLKMGR_PLLGLOB_PSRC_F2S			0x2

#define CLKMGR_PLLM_MDIV(x)			((x) & 0x000003FF)
#define CLKMGR_PLLGLOB_PD_SET_MSK		0x00000001
#define CLKMGR_PLLGLOB_RST_SET_MSK		0x00000002

#define CLKMGR_PLLGLOB_REFCLKDIV(x)		(((x) & 0x00003F00) >> 8)
#define CLKMGR_PLLGLOB_AREFCLKDIV(x)		(((x) & 0x00000F00) >> 8)
#define CLKMGR_PLLGLOB_DREFCLKDIV(x)		(((x) & 0x00003000) >> 12)

#define CLKMGR_VCOCALIB_HSCNT_SET(x)		(((x) << 0) & 0x000003FF)
#define CLKMGR_VCOCALIB_MSCNT_SET(x)		(((x) << 16) & 0x00FF0000)

#define CLKMGR_CLR_LOSTLOCK_BYPASS		0x20000000

#define CLKMGR_CLKSRC_MASK			GENMASK(18, 16)
#define CLKMGR_CLKSRC_OFFSET			16
#define CLKMGR_CLKSRC_MAIN			0
#define CLKMGR_CLKSRC_PER			1
#define CLKMGR_CLKSRC_OSC1			2
#define CLKMGR_CLKSRC_INTOSC			3
#define CLKMGR_CLKSRC_FPGA			4
#define CLKMGR_PLLCX_DIV_MSK			GENMASK(10, 0)

#define GET_CLKMGR_CLKSRC(x)			(((x) & CLKMGR_CLKSRC_MASK) >> \
							CLKMGR_CLKSRC_OFFSET)

#define CLKMGR_MAINPLL_NOCDIV_L4MP_MASK		GENMASK(5, 4)
#define CLKMGR_MAINPLL_NOCDIV_L4MP_OFFSET	4
#define GET_CLKMGR_MAINPLL_NOCDIV_L4MP(x)	(((x) & CLKMGR_MAINPLL_NOCDIV_L4MP_MASK) >> \
						CLKMGR_MAINPLL_NOCDIV_L4MP_OFFSET)

#define CLKMGR_MAINPLL_NOCDIV_L4SP_MASK		GENMASK(7, 6)
#define CLKMGR_MAINPLL_NOCDIV_L4SP_OFFSET	6
#define GET_CLKMGR_MAINPLL_NOCDIV_L4SP(x)	(((x) & CLKMGR_MAINPLL_NOCDIV_L4SP_MASK) >> \
						CLKMGR_MAINPLL_NOCDIV_L4SP_OFFSET)

#define CLKMGR_MAINPLL_NOCDIV_SPHY_MASK		GENMASK(17, 16)
#define CLKMGR_MAINPLL_NOCDIV_SPHY_OFFSET	16
#define GET_CLKMGR_MAINPLL_NOCDIV_SPHY(x)	(((x) & CLKMGR_MAINPLL_NOCDIV_SPHY_MASK) >> \
						CLKMGR_MAINPLL_NOCDIV_SPHY_OFFSET)


#define CLKMGR_MAINPLL_NOCDIV_L4SYSFREE_MASK	GENMASK(3, 2)
#define CLKMGR_MAINPLL_NOCDIV_L4SYSFREE_OFFSET	2
#define GET_CLKMGR_MAINPLL_NOCDIV_L4SYSFREE(x)	(((x) & CLKMGR_MAINPLL_NOCDIV_L4SYSFREE_MASK) >> \
						CLKMGR_MAINPLL_NOCDIV_L4SYSFREE_OFFSET)

#define CLKMGR_PERPLL_EMAC0_CLK_SRC_MASK	BIT(26)
#define CLKMGR_PERPLL_EMAC0_CLK_SRC_OFFSET	26
#define GET_CLKMGR_PERPLL_EMAC0_CLK_SRC(x)	(((x) & CLKMGR_PERPLL_EMAC0_CLK_SRC_MASK) >> \
						CLKMGR_PERPLL_EMAC0_CLK_SRC_OFFSET)

#define CLKMGR_ALTERA_EMACACTR_CLK_SRC_MASK	GENMASK(18, 16)
#define CLKMGR_ALTERA_EMACACTR_CLK_SRC_OFFSET	16
#define GET_CLKMGR_EMACACTR_CLK_SRC(x)		(((x) & CLKMGR_ALTERA_EMACACTR_CLK_SRC_MASK) >> \
						CLKMGR_ALTERA_EMACACTR_CLK_SRC_OFFSET)

#define CLKMGR_MPU_CLK_ID			0
#define CLKMGR_MPU_PERIPH_CLK_ID		1
#define CLKMGR_L4_MAIN_CLK_ID			2
#define CLKMGR_L4_MP_CLK_ID			3
#define CLKMGR_L4_SP_CLK_ID			4
#define CLKMGR_WDT_CLK_ID			5
#define CLKMGR_UART_CLK_ID			6
#define CLKMGR_EMAC0_CLK_ID			7
#define CLKMGR_EMAC1_CLK_ID			8
#define CLKMGR_EMAC2_CLK_ID			9
#define CLKMGR_EMAC_PTP_CLK_ID			10
#define CLKMGR_SDMMC_CLK_ID			11

#define CLKMGR_MAINPLL_BYPASS_ALL		(0xF6)
#define CLKMGR_PERPLL_BYPASS_ALL		(0xEF)
#define CLKMGR_PLLCX_STAT			BIT(29)
#define GET_PLLCX_STAT(x)			((x) & CLKMGR_PLLCX_STAT)

#define CLKMGR_MAINPLL_TYPE			(0)
#define CLKMGR_PERPLL_TYPE			(1)

#define CLKMGR_MAX_RETRY_COUNT			1000

#define CLKMGR_PLLM_MDIV_MASK			GENMASK(9, 0)
#define CLKMGR_PLLGLOB_PD_MASK			BIT(0)
#define CLKMGR_PLLGLOB_RST_MASK			BIT(1)
#define CLKMGR_PLLGLOB_AREFCLKDIV_MASK		GENMASK(11, 8)
#define CLKMGR_PLLGLOB_DREFCLKDIV_MASK		GENMASK(13, 12)
#define CLKMGR_PLLGLOB_REFCLKDIV_MASK		GENMASK(13, 8)
#define CLKMGR_PLLGLOB_MODCLKDIV_MASK		GENMASK(24, 27)
#define CLKMGR_PLLGLOB_AREFCLKDIV_OFFSET	8
#define CLKMGR_PLLGLOB_DREFCLKDIV_OFFSET	12
#define CLKMGR_PLLGLOB_REFCLKDIV_OFFSET		8
#define CLKMGR_PLLGLOB_MODCLKDIV_OFFSET		24
#define CLKMGR_PLLGLOB_VCO_PSRC_MASK		GENMASK(17, 16)
#define CLKMGR_PLLGLOB_VCO_PSRC_OFFSET		16
#define CLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK	BIT(29)

#define CLKMGR_VCOCALIB_MSCNT_MASK		GENMASK(23, 16)
#define CLKMGR_VCOCALIB_MSCNT_OFFSET		16
#define CLKMGR_VCOCALIB_HSCNT_MASK		GENMASK(9, 0)
#define CLKMGR_VCOCALIB_MSCNT_CONST		100
#define CLKMGR_VCOCALIB_HSCNT_CONST		4

int config_clkmgr_handoff(handoff *hoff_ptr);
uint32_t clkmgr_get_rate(uint32_t clk_id);

/* PLL configuration data structure in power-down state */
typedef struct pll_cfg {
	uint32_t addr;
	uint32_t data;
	uint32_t mask;
} pll_cfg_t;

#endif
