[U-Boot] [PATCH 2/5] ARM:AM33XX: Add clock definitions

Chandan Nath chandan.nath at ti.com
Tue Oct 11 15:51:10 CEST 2011


This patch adds basic clock definition of am33xx SoC.

Signed-off-by: Chandan Nath <chandan.nath at ti.com>
---
 arch/arm/cpu/armv7/am33xx/Makefile               |    1 +
 arch/arm/cpu/armv7/am33xx/clock.c                |  273 ++++++++++++++++++++++
 arch/arm/include/asm/arch-am33xx/clock.h         |   24 ++
 arch/arm/include/asm/arch-am33xx/clocks_am33xx.h |   55 +++++
 4 files changed, 353 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/cpu/armv7/am33xx/clock.c
 create mode 100644 arch/arm/include/asm/arch-am33xx/clock.h
 create mode 100644 arch/arm/include/asm/arch-am33xx/clocks_am33xx.h

diff --git a/arch/arm/cpu/armv7/am33xx/Makefile b/arch/arm/cpu/armv7/am33xx/Makefile
index 498df78..fc25587 100644
--- a/arch/arm/cpu/armv7/am33xx/Makefile
+++ b/arch/arm/cpu/armv7/am33xx/Makefile
@@ -18,6 +18,7 @@ LIB	= $(obj)lib$(SOC).o
 
 SOBJS	:= lowlevel_init.o
 
+COBJS	+= clock.o
 COBJS	+= sys_info.o
 
 SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
diff --git a/arch/arm/cpu/armv7/am33xx/clock.c b/arch/arm/cpu/armv7/am33xx/clock.c
new file mode 100644
index 0000000..4ca6c45
--- /dev/null
+++ b/arch/arm/cpu/armv7/am33xx/clock.c
@@ -0,0 +1,273 @@
+/*
+ * clock.c
+ *
+ * clocks for AM33XX based boards
+ *
+ * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <common.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/hardware.h>
+#include <asm/io.h>
+
+#define PRCM_MOD_EN		0x2
+#define PRCM_FORCE_WAKEUP	0x2
+
+#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
+
+
+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;
+
+static void enable_interface_clocks(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)
+		;
+
+	writel(PRCM_MOD_EN, &cmper->l4fwclkctrl);
+	while (readl(&cmper->l4fwclkctrl) != PRCM_MOD_EN)
+		;
+
+	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)
+		;
+}
+
+/*
+ * 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)
+{
+	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);
+}
+
+/*
+ * 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)
+		;
+
+	/* Enable the module clock */
+	writel(PRCM_MOD_EN, &cmper->timer2clkctrl);
+	while (readl(&cmper->timer2clkctrl) != PRCM_MOD_EN)
+		;
+
+	/* UART0 */
+	writel(PRCM_MOD_EN, &cmwkup->wkup_uart0ctrl);
+	while (readl(&cmwkup->wkup_uart0ctrl) != PRCM_MOD_EN)
+		;
+}
+
+static void mpu_pll_config(void)
+{
+	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 | ((MPUPLL_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 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)
+		;
+}
+
+static void ddr_pll_config(void)
+{
+	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 for emif_gclk  & L3_G clock  are active */
+	while ((readl(&cmper->l3clkstctrl) & (PRCM_EMIF_CLK_ACTIVITY |
+			PRCM_L3_GCLK_ACTIVITY)) != (PRCM_EMIF_CLK_ACTIVITY |
+			PRCM_L3_GCLK_ACTIVITY))
+		;
+	/* 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();
+	ddr_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();
+}
diff --git a/arch/arm/include/asm/arch-am33xx/clock.h b/arch/arm/include/asm/arch-am33xx/clock.h
new file mode 100644
index 0000000..872ff82
--- /dev/null
+++ b/arch/arm/include/asm/arch-am33xx/clock.h
@@ -0,0 +1,24 @@
+/*
+ * clock.h
+ *
+ * clock header
+ *
+ * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CLOCKS_H_
+#define _CLOCKS_H_
+
+#include <asm/arch/clocks_am33xx.h>
+
+#endif
diff --git a/arch/arm/include/asm/arch-am33xx/clocks_am33xx.h b/arch/arm/include/asm/arch-am33xx/clocks_am33xx.h
new file mode 100644
index 0000000..abc5b6b
--- /dev/null
+++ b/arch/arm/include/asm/arch-am33xx/clocks_am33xx.h
@@ -0,0 +1,55 @@
+/*
+ * clocks_am33xx.h
+ *
+ * AM33xx clock define
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CLOCKS_AM33XX_H_
+#define _CLOCKS_AM33XX_H_
+
+#define OSC	24
+
+/* MAIN PLL Fdll = 550 MHZ, */
+#define MPUPLL_M	550
+#define MPUPLL_N	23
+#define MPUPLL_M2	1
+
+/* Core PLL Fdll = 1 GHZ, */
+#define COREPLL_M	1000
+#define COREPLL_N	23
+
+#define COREPLL_M4	10	/* CORE_CLKOUTM4 = 200 MHZ */
+#define COREPLL_M5	8	/* CORE_CLKOUTM5 = 250 MHZ */
+#define COREPLL_M6	4	/* CORE_CLKOUTM6 = 500 MHZ */
+
+/*
+ * 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	23
+#define PERPLL_M2	5
+
+/* 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	23
+#define DDRPLL_M2	1
+
+extern void pll_init(void);
+extern void enable_emif_clocks(void);
+
+#endif	/* endif _CLOCKS_AM33XX_H_ */
-- 
1.7.1



More information about the U-Boot mailing list