summaryrefslogtreecommitdiff
path: root/arch/arm/cpu/armv7/am33xx/clock.c
diff options
context:
space:
mode:
authorWolfgang Denk <wd@denx.de>2011-10-28 00:15:19 +0200
committerWolfgang Denk <wd@denx.de>2011-10-28 00:15:19 +0200
commit87a5d601031652293ec4b729fdb7ee01bbd940a8 (patch)
tree91ede3ee45b228736c1876a700024782d7bc2032 /arch/arm/cpu/armv7/am33xx/clock.c
parent606a76f8ef479e42ae4d06f8f3ce87e9a1c72acf (diff)
parent37fc0ed268dc5acacd3a83adafa26eb1a84e90af (diff)
downloadu-boot-imx-87a5d601031652293ec4b729fdb7ee01bbd940a8.zip
u-boot-imx-87a5d601031652293ec4b729fdb7ee01bbd940a8.tar.gz
u-boot-imx-87a5d601031652293ec4b729fdb7ee01bbd940a8.tar.bz2
Merge branch 'master' of git://git.denx.de/u-boot-arm
* 'master' of git://git.denx.de/u-boot-arm: ARM: Add Calxeda Highbank platform dkb: make mmc command as default enabled Marvell: dkb: add mmc support ARM: pantheon: add mmc definition davinci: remove config.mk file from the sources ARM:AM33XX: Add support for TI AM335X EVM ARM:AM33XX: Added timer support ARM:AM33XX: Add emif/ddr support ARM:AM33XX: Add clock definitions ARM:AM33XX: Added support for AM33xx omap3/emif4: fix registers definition davinci: remove obsolete macro CONFIG_EMAC_MDIO_PHY_NUM davinci: emac: add support for more than 1 PHYs davinci: emac: add new features to autonegotiate for EMAC da850evm: Move LPSC configuration to board_early_init_f() omap4_panda: Build in cmd_gpio support on panda omap: Don't use gpio_free to change direction to input mmc: omap: Allow OMAP_HSMMC[23]_BASE to be unset OMAP3: overo : Add environment variable optargs to bootargs OMAP3: overo: Move ethernet CS4 configuration to execute based on board id OMAP3: overo : Use ttyO2 instead of ttyS2. da830: add support for NAND boot mode dm36x: revert cache disable patch dm644X: revert cache disable patch devkit8000: Add malloc space omap: spl: fix build break due to changes in FAT OMAP3 SPL: Provide weak omap_rev_string omap: beagle: Use ubifs instead of jffs2 for nand boot omap: overo: Disable pull-ups on camera PCLK, HS and VS signals omap: overo: Configure mux for gpio10 SPL: Add DMA library omap3: Add interface for omap3 DMA omap3: Add DMA register accessors omap3: Add Base register for DMA arm, davinci: add missing LSPC define for MMC/SD1 U-Boot/SPL: omap4: Make ddr pre-calculated timings as default. DaVinci: correct MDSTAT.STATE mask omap4: splitting padconfs into common, 4430 and 4460 omap4: adding revision detection for 4460 ES1.1 omap4: replacing OMAP4_CONTROL with OMAP4430_CONTROL gplug: fixed build error as a result of code cleanup patch kirkwood_spi: add dummy spi_init() gpio: mvmfp: reduce include platform file ARM: orion5x: reduce dependence of including platform file serial: reduce include platform file for marvell chip ARM: kirkwood: reduce dependence of including platform file ARM: armada100: reduce dependence of including platform file ARM: pantheon: reduce dependence of including platform file Armada100: Add env storage support for Marvell gplugD Armada100: Add SPI flash support for Marvell gplugD Armada100: Add SPI support for Marvell gplugD SPI: Add SPI driver support for Marvell Armada100 dreamplug: initial board support. imx: fix coding style misc: pmic: drop old Freescale's pmic driver MX31: mx31pdk: use new pmic driver MX31: mx31ads: use new pmic driver MX31: mx31_litekit: use new pmic driver MX5: mx53evk: use new pmic driver MX5: mx51evk: use new pmic driver MX35: mx35pdk: use new pmic driver misc: pmic: addI2C support to pmic_fsl driver misc: pmic: use I2C_SET_BUS in pmic I2C MX5: efikamx/efikasb: use new pmic driver MX3: qong: use new pmic driver RTC: Switch mc13783 to generic pmic code MX5: vision2: use new pmic driver misc: pmic: Freescale PMIC switches to generic PMIC driver misc:pmic:samsung Enable PMIC driver at GONI target misc:pmic:max8998 MAX8998 support at a new PMIC driver. misc:pmic:core New generic PMIC driver mx31pdk: Remove unneeded config mx31: provide readable WEIM CS accessor MX51: vision2: Set global macros I2C: Add i2c_get/set_speed() to mxc_i2c.c ARM: Update mach-types devkit8000: Add config to enable SPL MMC boot devkit8000: protect board_mmc_init arm, post: add missing post_time_ms for arm cosmetic, post: Codingstyle cleanup arm, logbuffer: make it compileclean tegra2: Enable MMC for Seaboard tegra2: Add more pinmux functions tegra2: Rename PIN_ to PINGRP_ tegra2: Add more clock functions tegra2: Clean up board code a little tegra2: Rename CLOCK_PLL_ID to CLOCK_ID
Diffstat (limited to 'arch/arm/cpu/armv7/am33xx/clock.c')
-rw-r--r--arch/arm/cpu/armv7/am33xx/clock.c273
1 files changed, 273 insertions, 0 deletions
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();
+}