diff options
Diffstat (limited to 'arch/arm/cpu/armv7/am33xx/clock_am33xx.c')
| -rw-r--r-- | arch/arm/cpu/armv7/am33xx/clock_am33xx.c | 475 | 
1 files changed, 106 insertions, 369 deletions
| diff --git a/arch/arm/cpu/armv7/am33xx/clock_am33xx.c b/arch/arm/cpu/armv7/am33xx/clock_am33xx.c index fb3fb43dc..e5f287b33 100644 --- a/arch/arm/cpu/armv7/am33xx/clock_am33xx.c +++ b/arch/arm/cpu/armv7/am33xx/clock_am33xx.c @@ -14,392 +14,129 @@  #include <asm/arch/hardware.h>  #include <asm/io.h> -#define PRCM_MOD_EN		0x2 -#define PRCM_FORCE_WAKEUP	0x2 -#define PRCM_FUNCTL		0x0 - -#define PRCM_EMIF_CLK_ACTIVITY	BIT(2) -#define PRCM_L3_GCLK_ACTIVITY	BIT(4) - -#define PLL_BYPASS_MODE		0x4 -#define ST_MN_BYPASS		0x00000100 -#define ST_DPLL_CLK		0x00000001 -#define CLK_SEL_MASK		0x7ffff -#define CLK_DIV_MASK		0x1f -#define CLK_DIV2_MASK		0x7f -#define CLK_SEL_SHIFT		0x8 -#define CLK_MODE_SEL		0x7 -#define CLK_MODE_MASK		0xfffffff8 -#define CLK_DIV_SEL		0xFFFFFFE0 -#define CPGMAC0_IDLE		0x30000 -#define DPLL_CLKDCOLDO_GATE_CTRL        0x300 -  #define OSC	(V_OSCK/1000000) -#define MPUPLL_M	CONFIG_SYS_MPUCLK -#define MPUPLL_N	(OSC-1) -#define MPUPLL_M2	1 +struct cm_perpll *const cmper = (struct cm_perpll *)CM_PER; +struct cm_wkuppll *const cmwkup = (struct cm_wkuppll *)CM_WKUP; +struct cm_dpll *const cmdpll = (struct cm_dpll *)CM_DPLL; +struct cm_rtc *const cmrtc = (struct cm_rtc *)CM_RTC; -/* Core PLL Fdll = 1 GHZ, */ -#define COREPLL_M	1000 -#define COREPLL_N	(OSC-1) +const struct dpll_regs dpll_mpu_regs = { +	.cm_clkmode_dpll	= CM_WKUP + 0x88, +	.cm_idlest_dpll		= CM_WKUP + 0x20, +	.cm_clksel_dpll		= CM_WKUP + 0x2C, +	.cm_div_m2_dpll		= CM_WKUP + 0xA8, +}; -#define COREPLL_M4	10	/* CORE_CLKOUTM4 = 200 MHZ */ -#define COREPLL_M5	8	/* CORE_CLKOUTM5 = 250 MHZ */ -#define COREPLL_M6	4	/* CORE_CLKOUTM6 = 500 MHZ */ +const struct dpll_regs dpll_core_regs = { +	.cm_clkmode_dpll	= CM_WKUP + 0x90, +	.cm_idlest_dpll		= CM_WKUP + 0x5C, +	.cm_clksel_dpll		= CM_WKUP + 0x68, +	.cm_div_m4_dpll		= CM_WKUP + 0x80, +	.cm_div_m5_dpll		= CM_WKUP + 0x84, +	.cm_div_m6_dpll		= CM_WKUP + 0xD8, +}; -/* - * USB PHY clock is 960 MHZ. Since, this comes directly from Fdll, Fdll - * frequency needs to be set to 960 MHZ. Hence, - * For clkout = 192 MHZ, Fdll = 960 MHZ, divider values are given below - */ -#define PERPLL_M	960 -#define PERPLL_N	(OSC-1) -#define PERPLL_M2	5 +const struct dpll_regs dpll_per_regs = { +	.cm_clkmode_dpll	= CM_WKUP + 0x8C, +	.cm_idlest_dpll		= CM_WKUP + 0x70, +	.cm_clksel_dpll		= CM_WKUP + 0x9C, +	.cm_div_m2_dpll		= CM_WKUP + 0xAC, +}; -/* DDR Freq is 266 MHZ for now */ -/* Set Fdll = 400 MHZ , Fdll = M * 2 * CLKINP/ N + 1; clkout = Fdll /(2 * M2) */ -#define DDRPLL_M	266 -#define DDRPLL_N	(OSC-1) -#define DDRPLL_M2	1 +const struct dpll_regs dpll_ddr_regs = { +	.cm_clkmode_dpll	= CM_WKUP + 0x94, +	.cm_idlest_dpll		= CM_WKUP + 0x34, +	.cm_clksel_dpll		= CM_WKUP + 0x40, +	.cm_div_m2_dpll		= CM_WKUP + 0xA0, +}; -const struct cm_perpll *cmper = (struct cm_perpll *)CM_PER; -const struct cm_wkuppll *cmwkup = (struct cm_wkuppll *)CM_WKUP; -const struct cm_dpll *cmdpll = (struct cm_dpll *)CM_DPLL; -const struct cm_rtc *cmrtc = (struct cm_rtc *)CM_RTC; +const struct dpll_params dpll_mpu = { +		CONFIG_SYS_MPUCLK, OSC-1, 1, -1, -1, -1, -1}; +const struct dpll_params dpll_core = { +		1000, OSC-1, -1, -1, 10, 8, 4}; +const struct dpll_params dpll_per = { +		960, OSC-1, 5, -1, -1, -1, -1}; -static void enable_interface_clocks(void) +void setup_clocks_for_console(void)  { -	/* Enable all the Interconnect Modules */ -	writel(PRCM_MOD_EN, &cmper->l3clkctrl); -	while (readl(&cmper->l3clkctrl) != PRCM_MOD_EN) -		; - -	writel(PRCM_MOD_EN, &cmper->l4lsclkctrl); -	while (readl(&cmper->l4lsclkctrl) != PRCM_MOD_EN) -		; +	clrsetbits_le32(&cmwkup->wkclkstctrl, CD_CLKCTRL_CLKTRCTRL_MASK, +			CD_CLKCTRL_CLKTRCTRL_SW_WKUP << +			CD_CLKCTRL_CLKTRCTRL_SHIFT); -	writel(PRCM_MOD_EN, &cmper->l4fwclkctrl); -	while (readl(&cmper->l4fwclkctrl) != PRCM_MOD_EN) -		; +	clrsetbits_le32(&cmper->l4hsclkstctrl, CD_CLKCTRL_CLKTRCTRL_MASK, +			CD_CLKCTRL_CLKTRCTRL_SW_WKUP << +			CD_CLKCTRL_CLKTRCTRL_SHIFT); -	writel(PRCM_MOD_EN, &cmwkup->wkl4wkclkctrl); -	while (readl(&cmwkup->wkl4wkclkctrl) != PRCM_MOD_EN) -		; - -	writel(PRCM_MOD_EN, &cmper->l3instrclkctrl); -	while (readl(&cmper->l3instrclkctrl) != PRCM_MOD_EN) -		; - -	writel(PRCM_MOD_EN, &cmper->l4hsclkctrl); -	while (readl(&cmper->l4hsclkctrl) != PRCM_MOD_EN) -		; - -	writel(PRCM_MOD_EN, &cmwkup->wkgpio0clkctrl); -	while (readl(&cmwkup->wkgpio0clkctrl) != PRCM_MOD_EN) -		; +	clrsetbits_le32(&cmwkup->wkup_uart0ctrl, +			MODULE_CLKCTRL_MODULEMODE_MASK, +			MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << +			MODULE_CLKCTRL_MODULEMODE_SHIFT); +	clrsetbits_le32(&cmper->uart1clkctrl, +			MODULE_CLKCTRL_MODULEMODE_MASK, +			MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << +			MODULE_CLKCTRL_MODULEMODE_SHIFT); +	clrsetbits_le32(&cmper->uart2clkctrl, +			MODULE_CLKCTRL_MODULEMODE_MASK, +			MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << +			MODULE_CLKCTRL_MODULEMODE_SHIFT); +	clrsetbits_le32(&cmper->uart3clkctrl, +			MODULE_CLKCTRL_MODULEMODE_MASK, +			MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << +			MODULE_CLKCTRL_MODULEMODE_SHIFT); +	clrsetbits_le32(&cmper->uart4clkctrl, +			MODULE_CLKCTRL_MODULEMODE_MASK, +			MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << +			MODULE_CLKCTRL_MODULEMODE_SHIFT); +	clrsetbits_le32(&cmper->uart5clkctrl, +			MODULE_CLKCTRL_MODULEMODE_MASK, +			MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << +			MODULE_CLKCTRL_MODULEMODE_SHIFT);  } -/* - * Force power domain wake up transition - * Ensure that the corresponding interface clock is active before - * using the peripheral - */ -static void power_domain_wkup_transition(void) +void enable_basic_clocks(void)  { -	writel(PRCM_FORCE_WAKEUP, &cmper->l3clkstctrl); -	writel(PRCM_FORCE_WAKEUP, &cmper->l4lsclkstctrl); -	writel(PRCM_FORCE_WAKEUP, &cmwkup->wkclkstctrl); -	writel(PRCM_FORCE_WAKEUP, &cmper->l4fwclkstctrl); -	writel(PRCM_FORCE_WAKEUP, &cmper->l3sclkstctrl); -} +	u32 *const clk_domains[] = { +		&cmper->l3clkstctrl, +		&cmper->l4fwclkstctrl, +		&cmper->l3sclkstctrl, +		&cmper->l4lsclkstctrl, +		&cmwkup->wkclkstctrl, +		&cmper->emiffwclkctrl, +		&cmrtc->clkstctrl, +		0 +	}; -/* - * Enable the peripheral clock for required peripherals - */ -static void enable_per_clocks(void) -{ -	/* Enable the control module though RBL would have done it*/ -	writel(PRCM_MOD_EN, &cmwkup->wkctrlclkctrl); -	while (readl(&cmwkup->wkctrlclkctrl) != PRCM_MOD_EN) -		; +	u32 *const clk_modules_explicit_en[] = { +		&cmper->l3clkctrl, +		&cmper->l4lsclkctrl, +		&cmper->l4fwclkctrl, +		&cmwkup->wkl4wkclkctrl, +		&cmper->l3instrclkctrl, +		&cmper->l4hsclkctrl, +		&cmwkup->wkgpio0clkctrl, +		&cmwkup->wkctrlclkctrl, +		&cmper->timer2clkctrl, +		&cmper->gpmcclkctrl, +		&cmper->elmclkctrl, +		&cmper->mmc0clkctrl, +		&cmper->mmc1clkctrl, +		&cmwkup->wkup_i2c0ctrl, +		&cmper->gpio1clkctrl, +		&cmper->gpio2clkctrl, +		&cmper->gpio3clkctrl, +		&cmper->i2c1clkctrl, +		&cmper->cpgmac0clkctrl, +		&cmper->spi0clkctrl, +		&cmrtc->rtcclkctrl, +		&cmper->usb0clkctrl, +		&cmper->emiffwclkctrl, +		&cmper->emifclkctrl, +		0 +	}; -	/* Enable the module clock */ -	writel(PRCM_MOD_EN, &cmper->timer2clkctrl); -	while (readl(&cmper->timer2clkctrl) != PRCM_MOD_EN) -		; +	do_enable_clocks(clk_domains, clk_modules_explicit_en, 1);  	/* Select the Master osc 24 MHZ as Timer2 clock source */  	writel(0x1, &cmdpll->clktimer2clk); - -	/* UART0 */ -	writel(PRCM_MOD_EN, &cmwkup->wkup_uart0ctrl); -	while (readl(&cmwkup->wkup_uart0ctrl) != PRCM_MOD_EN) -		; - -	/* UART1 */ -#ifdef CONFIG_SERIAL2 -	writel(PRCM_MOD_EN, &cmper->uart1clkctrl); -	while (readl(&cmper->uart1clkctrl) != PRCM_MOD_EN) -		; -#endif /* CONFIG_SERIAL2 */ - -	/* UART2 */ -#ifdef CONFIG_SERIAL3 -	writel(PRCM_MOD_EN, &cmper->uart2clkctrl); -	while (readl(&cmper->uart2clkctrl) != PRCM_MOD_EN) -		; -#endif /* CONFIG_SERIAL3 */ - -	/* UART3 */ -#ifdef CONFIG_SERIAL4 -	writel(PRCM_MOD_EN, &cmper->uart3clkctrl); -	while (readl(&cmper->uart3clkctrl) != PRCM_MOD_EN) -		; -#endif /* CONFIG_SERIAL4 */ - -	/* UART4 */ -#ifdef CONFIG_SERIAL5 -	writel(PRCM_MOD_EN, &cmper->uart4clkctrl); -	while (readl(&cmper->uart4clkctrl) != PRCM_MOD_EN) -		; -#endif /* CONFIG_SERIAL5 */ - -	/* UART5 */ -#ifdef CONFIG_SERIAL6 -	writel(PRCM_MOD_EN, &cmper->uart5clkctrl); -	while (readl(&cmper->uart5clkctrl) != PRCM_MOD_EN) -		; -#endif /* CONFIG_SERIAL6 */ - -	/* GPMC */ -	writel(PRCM_MOD_EN, &cmper->gpmcclkctrl); -	while (readl(&cmper->gpmcclkctrl) != PRCM_MOD_EN) -		; - -	/* ELM */ -	writel(PRCM_MOD_EN, &cmper->elmclkctrl); -	while (readl(&cmper->elmclkctrl) != PRCM_MOD_EN) -		; - -	/* MMC0*/ -	writel(PRCM_MOD_EN, &cmper->mmc0clkctrl); -	while (readl(&cmper->mmc0clkctrl) != PRCM_MOD_EN) -		; - -	/* MMC1 */ -	writel(PRCM_MOD_EN, &cmper->mmc1clkctrl); -	while (readl(&cmper->mmc1clkctrl) != PRCM_MOD_EN) -		; - -	/* i2c0 */ -	writel(PRCM_MOD_EN, &cmwkup->wkup_i2c0ctrl); -	while (readl(&cmwkup->wkup_i2c0ctrl) != PRCM_MOD_EN) -		; - -	/* gpio1 module */ -	writel(PRCM_MOD_EN, &cmper->gpio1clkctrl); -	while (readl(&cmper->gpio1clkctrl) != PRCM_MOD_EN) -		; - -	/* gpio2 module */ -	writel(PRCM_MOD_EN, &cmper->gpio2clkctrl); -	while (readl(&cmper->gpio2clkctrl) != PRCM_MOD_EN) -		; - -	/* gpio3 module */ -	writel(PRCM_MOD_EN, &cmper->gpio3clkctrl); -	while (readl(&cmper->gpio3clkctrl) != PRCM_MOD_EN) -		; - -	/* i2c1 */ -	writel(PRCM_MOD_EN, &cmper->i2c1clkctrl); -	while (readl(&cmper->i2c1clkctrl) != PRCM_MOD_EN) -		; - -	/* Ethernet */ -	writel(PRCM_MOD_EN, &cmper->cpgmac0clkctrl); -	while ((readl(&cmper->cpgmac0clkctrl) & CPGMAC0_IDLE) != PRCM_FUNCTL) -		; - -	/* spi0 */ -	writel(PRCM_MOD_EN, &cmper->spi0clkctrl); -	while (readl(&cmper->spi0clkctrl) != PRCM_MOD_EN) -		; - -	/* RTC */ -	writel(PRCM_MOD_EN, &cmrtc->rtcclkctrl); -	while (readl(&cmrtc->rtcclkctrl) != PRCM_MOD_EN) -		; - -	/* MUSB */ -	writel(PRCM_MOD_EN, &cmper->usb0clkctrl); -	while (readl(&cmper->usb0clkctrl) != PRCM_MOD_EN) -		; -} - -void mpu_pll_config_val(int mpull_m) -{ -	u32 clkmode, clksel, div_m2; - -	clkmode = readl(&cmwkup->clkmoddpllmpu); -	clksel = readl(&cmwkup->clkseldpllmpu); -	div_m2 = readl(&cmwkup->divm2dpllmpu); - -	/* Set the PLL to bypass Mode */ -	writel(PLL_BYPASS_MODE, &cmwkup->clkmoddpllmpu); -	while (readl(&cmwkup->idlestdpllmpu) != ST_MN_BYPASS) -		; - -	clksel = clksel & (~CLK_SEL_MASK); -	clksel = clksel | ((mpull_m << CLK_SEL_SHIFT) | MPUPLL_N); -	writel(clksel, &cmwkup->clkseldpllmpu); - -	div_m2 = div_m2 & ~CLK_DIV_MASK; -	div_m2 = div_m2 | MPUPLL_M2; -	writel(div_m2, &cmwkup->divm2dpllmpu); - -	clkmode = clkmode | CLK_MODE_SEL; -	writel(clkmode, &cmwkup->clkmoddpllmpu); - -	while (readl(&cmwkup->idlestdpllmpu) != ST_DPLL_CLK) -		; -} - -static void mpu_pll_config(void) -{ -	mpu_pll_config_val(CONFIG_SYS_MPUCLK); -} - -static void core_pll_config(void) -{ -	u32 clkmode, clksel, div_m4, div_m5, div_m6; - -	clkmode = readl(&cmwkup->clkmoddpllcore); -	clksel = readl(&cmwkup->clkseldpllcore); -	div_m4 = readl(&cmwkup->divm4dpllcore); -	div_m5 = readl(&cmwkup->divm5dpllcore); -	div_m6 = readl(&cmwkup->divm6dpllcore); - -	/* Set the PLL to bypass Mode */ -	writel(PLL_BYPASS_MODE, &cmwkup->clkmoddpllcore); - -	while (readl(&cmwkup->idlestdpllcore) != ST_MN_BYPASS) -		; - -	clksel = clksel & (~CLK_SEL_MASK); -	clksel = clksel | ((COREPLL_M << CLK_SEL_SHIFT) | COREPLL_N); -	writel(clksel, &cmwkup->clkseldpllcore); - -	div_m4 = div_m4 & ~CLK_DIV_MASK; -	div_m4 = div_m4 | COREPLL_M4; -	writel(div_m4, &cmwkup->divm4dpllcore); - -	div_m5 = div_m5 & ~CLK_DIV_MASK; -	div_m5 = div_m5 | COREPLL_M5; -	writel(div_m5, &cmwkup->divm5dpllcore); - -	div_m6 = div_m6 & ~CLK_DIV_MASK; -	div_m6 = div_m6 | COREPLL_M6; -	writel(div_m6, &cmwkup->divm6dpllcore); - -	clkmode = clkmode | CLK_MODE_SEL; -	writel(clkmode, &cmwkup->clkmoddpllcore); - -	while (readl(&cmwkup->idlestdpllcore) != ST_DPLL_CLK) -		; -} - -static void per_pll_config(void) -{ -	u32 clkmode, clksel, div_m2; - -	clkmode = readl(&cmwkup->clkmoddpllper); -	clksel = readl(&cmwkup->clkseldpllper); -	div_m2 = readl(&cmwkup->divm2dpllper); - -	/* Set the PLL to bypass Mode */ -	writel(PLL_BYPASS_MODE, &cmwkup->clkmoddpllper); - -	while (readl(&cmwkup->idlestdpllper) != ST_MN_BYPASS) -		; - -	clksel = clksel & (~CLK_SEL_MASK); -	clksel = clksel | ((PERPLL_M << CLK_SEL_SHIFT) | PERPLL_N); -	writel(clksel, &cmwkup->clkseldpllper); - -	div_m2 = div_m2 & ~CLK_DIV2_MASK; -	div_m2 = div_m2 | PERPLL_M2; -	writel(div_m2, &cmwkup->divm2dpllper); - -	clkmode = clkmode | CLK_MODE_SEL; -	writel(clkmode, &cmwkup->clkmoddpllper); - -	while (readl(&cmwkup->idlestdpllper) != ST_DPLL_CLK) -		; - -	writel(DPLL_CLKDCOLDO_GATE_CTRL, &cmwkup->clkdcoldodpllper); -} - -void ddr_pll_config(unsigned int ddrpll_m) -{ -	u32 clkmode, clksel, div_m2; - -	clkmode = readl(&cmwkup->clkmoddpllddr); -	clksel = readl(&cmwkup->clkseldpllddr); -	div_m2 = readl(&cmwkup->divm2dpllddr); - -	/* Set the PLL to bypass Mode */ -	clkmode = (clkmode & CLK_MODE_MASK) | PLL_BYPASS_MODE; -	writel(clkmode, &cmwkup->clkmoddpllddr); - -	/* Wait till bypass mode is enabled */ -	while ((readl(&cmwkup->idlestdpllddr) & ST_MN_BYPASS) -				!= ST_MN_BYPASS) -		; - -	clksel = clksel & (~CLK_SEL_MASK); -	clksel = clksel | ((ddrpll_m << CLK_SEL_SHIFT) | DDRPLL_N); -	writel(clksel, &cmwkup->clkseldpllddr); - -	div_m2 = div_m2 & CLK_DIV_SEL; -	div_m2 = div_m2 | DDRPLL_M2; -	writel(div_m2, &cmwkup->divm2dpllddr); - -	clkmode = (clkmode & CLK_MODE_MASK) | CLK_MODE_SEL; -	writel(clkmode, &cmwkup->clkmoddpllddr); - -	/* Wait till dpll is locked */ -	while ((readl(&cmwkup->idlestdpllddr) & ST_DPLL_CLK) != ST_DPLL_CLK) -		; -} - -void enable_emif_clocks(void) -{ -	/* Enable the  EMIF_FW Functional clock */ -	writel(PRCM_MOD_EN, &cmper->emiffwclkctrl); -	/* Enable EMIF0 Clock */ -	writel(PRCM_MOD_EN, &cmper->emifclkctrl); -	/* Poll if module is functional */ -	while ((readl(&cmper->emifclkctrl)) != PRCM_MOD_EN) -		; -} - -/* - * Configure the PLL/PRCM for necessary peripherals - */ -void pll_init() -{ -	mpu_pll_config(); -	core_pll_config(); -	per_pll_config(); - -	/* Enable the required interconnect clocks */ -	enable_interface_clocks(); - -	/* Power domain wake up transition */ -	power_domain_wkup_transition(); - -	/* Enable the required peripherals */ -	enable_per_clocks();  } |