From 315847875c915dc4ee666743bf99235a4f9a4b8d Mon Sep 17 00:00:00 2001 From: Jason Liu Date: Wed, 7 Jul 2010 05:33:19 +0800 Subject: ENGR00124359 Add uboot support for MX50 Add initial support for MX50 -Support mddr200Mhz, lpddr2266Mhz ARM2 board, -Support boot from SD/MMC, -Support boot from SPI-NOR, -Support FEC, UART, -Support SD/MMC/SPI command within UBOOT Signed-off-by: Anish Trivedi Signed-off-by: Terry Lv Signed-off-by: Jason Liu --- cpu/arm_cortexa8/mx50/Makefile | 48 ++ cpu/arm_cortexa8/mx50/cache.c | 44 ++ cpu/arm_cortexa8/mx50/crm_regs.h | 646 +++++++++++++++++++++++ cpu/arm_cortexa8/mx50/generic.c | 1019 ++++++++++++++++++++++++++++++++++++ cpu/arm_cortexa8/mx50/interrupts.c | 39 ++ cpu/arm_cortexa8/mx50/iomux.c | 137 +++++ cpu/arm_cortexa8/mx50/serial.c | 226 ++++++++ cpu/arm_cortexa8/mx50/timer.c | 127 +++++ 8 files changed, 2286 insertions(+) create mode 100644 cpu/arm_cortexa8/mx50/Makefile create mode 100644 cpu/arm_cortexa8/mx50/cache.c create mode 100644 cpu/arm_cortexa8/mx50/crm_regs.h create mode 100644 cpu/arm_cortexa8/mx50/generic.c create mode 100644 cpu/arm_cortexa8/mx50/interrupts.c create mode 100644 cpu/arm_cortexa8/mx50/iomux.c create mode 100644 cpu/arm_cortexa8/mx50/serial.c create mode 100644 cpu/arm_cortexa8/mx50/timer.c (limited to 'cpu') diff --git a/cpu/arm_cortexa8/mx50/Makefile b/cpu/arm_cortexa8/mx50/Makefile new file mode 100644 index 0000000..460bdd9 --- /dev/null +++ b/cpu/arm_cortexa8/mx50/Makefile @@ -0,0 +1,48 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2010 Freescale Semiconductor, Inc. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(SOC).a + +COBJS = interrupts.o serial.o generic.o iomux.o timer.o cache.o +COBJS += $(COBJS-y) + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/cpu/arm_cortexa8/mx50/cache.c b/cpu/arm_cortexa8/mx50/cache.c new file mode 100644 index 0000000..60df92f --- /dev/null +++ b/cpu/arm_cortexa8/mx50/cache.c @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2010 Freescale Semiconductor, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include + +void l2_cache_enable(void) +{ + asm("mrc 15, 0, r0, c1, c0, 1"); + asm("orr r0, r0, #0x2"); + asm("mcr 15, 0, r0, c1, c0, 1"); +} + +void l2_cache_disable(void) +{ + asm("mrc 15, 0, r0, c1, c0, 1"); + asm("bic r0, r0, #0x2"); + asm("mcr 15, 0, r0, c1, c0, 1"); +} + +/*dummy function for L2 ON*/ +u32 get_device_type(void) +{ + return 0; +} diff --git a/cpu/arm_cortexa8/mx50/crm_regs.h b/cpu/arm_cortexa8/mx50/crm_regs.h new file mode 100644 index 0000000..eb94bbe --- /dev/null +++ b/cpu/arm_cortexa8/mx50/crm_regs.h @@ -0,0 +1,646 @@ +/* + * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. + * + * 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. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef __ARCH_ARM_MACH_MX50_CRM_REGS_H__ +#define __ARCH_ARM_MACH_MX50_CRM_REGS_H__ + +#define MXC_CCM_BASE CCM_BASE_ADDR +#define MXC_DPLL1_BASE PLL1_BASE_ADDR +#define MXC_DPLL2_BASE PLL2_BASE_ADDR +#define MXC_DPLL3_BASE PLL3_BASE_ADDR + +/* PLL Register Offsets */ +#define MXC_PLL_DP_CTL 0x00 +#define MXC_PLL_DP_CONFIG 0x04 +#define MXC_PLL_DP_OP 0x08 +#define MXC_PLL_DP_MFD 0x0C +#define MXC_PLL_DP_MFN 0x10 +#define MXC_PLL_DP_MFNMINUS 0x14 +#define MXC_PLL_DP_MFNPLUS 0x18 +#define MXC_PLL_DP_HFS_OP 0x1C +#define MXC_PLL_DP_HFS_MFD 0x20 +#define MXC_PLL_DP_HFS_MFN 0x24 +#define MXC_PLL_DP_MFN_TOGC 0x28 +#define MXC_PLL_DP_DESTAT 0x2c + +/* PLL Register Bit definitions */ +#define MXC_PLL_DP_CTL_MUL_CTRL 0x2000 +#define MXC_PLL_DP_CTL_DPDCK0_2_EN 0x1000 +#define MXC_PLL_DP_CTL_DPDCK0_2_OFFSET 12 +#define MXC_PLL_DP_CTL_ADE 0x800 +#define MXC_PLL_DP_CTL_REF_CLK_DIV 0x400 +#define MXC_PLL_DP_CTL_REF_CLK_SEL_MASK (3 << 8) +#define MXC_PLL_DP_CTL_REF_CLK_SEL_OFFSET 8 +#define MXC_PLL_DP_CTL_HFSM 0x80 +#define MXC_PLL_DP_CTL_PRE 0x40 +#define MXC_PLL_DP_CTL_UPEN 0x20 +#define MXC_PLL_DP_CTL_RST 0x10 +#define MXC_PLL_DP_CTL_RCP 0x8 +#define MXC_PLL_DP_CTL_PLM 0x4 +#define MXC_PLL_DP_CTL_BRM0 0x2 +#define MXC_PLL_DP_CTL_LRF 0x1 + +#define MXC_PLL_DP_CONFIG_BIST 0x8 +#define MXC_PLL_DP_CONFIG_SJC_CE 0x4 +#define MXC_PLL_DP_CONFIG_AREN 0x2 +#define MXC_PLL_DP_CONFIG_LDREQ 0x1 + +#define MXC_PLL_DP_OP_MFI_OFFSET 4 +#define MXC_PLL_DP_OP_MFI_MASK (0xF << 4) +#define MXC_PLL_DP_OP_PDF_OFFSET 0 +#define MXC_PLL_DP_OP_PDF_MASK 0xF + +#define MXC_PLL_DP_MFD_OFFSET 0 +#define MXC_PLL_DP_MFD_MASK 0x07FFFFFF + +#define MXC_PLL_DP_MFN_OFFSET 0x0 +#define MXC_PLL_DP_MFN_MASK 0x07FFFFFF + +#define MXC_PLL_DP_MFN_TOGC_TOG_DIS (1 << 17) +#define MXC_PLL_DP_MFN_TOGC_TOG_EN (1 << 16) +#define MXC_PLL_DP_MFN_TOGC_CNT_OFFSET 0x0 +#define MXC_PLL_DP_MFN_TOGC_CNT_MASK 0xFFFF + +#define MXC_PLL_DP_DESTAT_TOG_SEL (1 << 31) +#define MXC_PLL_DP_DESTAT_MFN 0x07FFFFFF + +/* Register addresses of CCM*/ +#define MXC_CCM_CCR (MXC_CCM_BASE + 0x00) +#define MXC_CCM_CCDR (MXC_CCM_BASE + 0x04) /* Reserved */ +#define MXC_CCM_CSR (MXC_CCM_BASE + 0x08) +#define MXC_CCM_CCSR (MXC_CCM_BASE + 0x0C) +#define MXC_CCM_CACRR (MXC_CCM_BASE + 0x10) +#define MXC_CCM_CBCDR (MXC_CCM_BASE + 0x14) +#define MXC_CCM_CBCMR (MXC_CCM_BASE + 0x18) +#define MXC_CCM_CSCMR1 (MXC_CCM_BASE + 0x1C) +#define MXC_CCM_CSCMR2 (MXC_CCM_BASE + 0x20) /* Reserved */ +#define MXC_CCM_CSCDR1 (MXC_CCM_BASE + 0x24) +#define MXC_CCM_CS1CDR (MXC_CCM_BASE + 0x28) +#define MXC_CCM_CS2CDR (MXC_CCM_BASE + 0x2C) +#define MXC_CCM_CDCDR (MXC_CCM_BASE + 0x30) /* Reserved */ +#define MXC_CCM_CHSCDR (MXC_CCM_BASE + 0x34) /* Reserved */ +#define MXC_CCM_CSCDR2 (MXC_CCM_BASE + 0x38) +#define MXC_CCM_CSCDR3 (MXC_CCM_BASE + 0x3C) /* Reserved */ +#define MXC_CCM_CSCDR4 (MXC_CCM_BASE + 0x40) /* Reserved */ +#define MXC_CCM_CWDR (MXC_CCM_BASE + 0x44) /* Reserved */ +#define MXC_CCM_CDHIPR (MXC_CCM_BASE + 0x48) +#define MXC_CCM_CDCR (MXC_CCM_BASE + 0x4C) +#define MXC_CCM_CTOR (MXC_CCM_BASE + 0x50) +#define MXC_CCM_CLPCR (MXC_CCM_BASE + 0x54) +#define MXC_CCM_CISR (MXC_CCM_BASE + 0x58) +#define MXC_CCM_CIMR (MXC_CCM_BASE + 0x5C) +#define MXC_CCM_CCOSR (MXC_CCM_BASE + 0x60) +#define MXC_CCM_CGPR (MXC_CCM_BASE + 0x64) /* Reserved */ +#define MXC_CCM_CCGR0 (MXC_CCM_BASE + 0x68) +#define MXC_CCM_CCGR1 (MXC_CCM_BASE + 0x6C) +#define MXC_CCM_CCGR2 (MXC_CCM_BASE + 0x70) +#define MXC_CCM_CCGR3 (MXC_CCM_BASE + 0x74) +#define MXC_CCM_CCGR4 (MXC_CCM_BASE + 0x78) +#define MXC_CCM_CCGR5 (MXC_CCM_BASE + 0x7C) +#define MXC_CCM_CCGR6 (MXC_CCM_BASE + 0x80) +#define MXC_CCM_CCGR7 (MXC_CCM_BASE + 0x84) +#define MXC_CCM_CMEOR (MXC_CCM_BASE + 0x88) +#define MXC_CCM_CSR2 (MXC_CCM_BASE + 0x8C) +#define MXC_CCM_CLKSEQ_BYPASS (MXC_CCM_BASE + 0x90) +#define MXC_CCM_CLK_SYS (MXC_CCM_BASE + 0x94) +#define MXC_CCM_CLK_DDR (MXC_CCM_BASE + 0x98) + +/* Define the bits in register CCR */ +#define MXC_CCM_CCR_COSC_EN (1 << 12) +#define MXC_CCM_CCR_CAMP1_EN (1 << 9) +#define MXC_CCM_CCR_OSCNT_OFFSET (0) +#define MXC_CCM_CCR_OSCNT_MASK (0xFF) + +/* Define the bits in register CSR */ +#define MXC_CCM_CSR_COSR_READY (1 << 5) +#define MXC_CCM_CSR_LVS_VALUE (1 << 4) +#define MXC_CCM_CSR_CAMP1_READY (1 << 2) +#define MXC_CCM_CSR_TEMP_MON_ALARM (1 << 1) +#define MXC_CCM_CSR_REF_EN_B (1 << 0) + +/* Define the bits in register CCSR */ +#define MXC_CCM_CCSR_PLL3_PFD_EN (0x1 << 13) +#define MXC_CCM_CCSR_PLL2_PFD_EN (0x1 << 12) +#define MXC_CCM_CCSR_PLL1_PFD_EN (0x1 << 11) +#define MXC_CCM_CCSR_LP_APM_SEL (0x1 << 10) +#define MXC_CCM_CCSR_LP_APM_SEL_OFFSET (1) +#define MXC_CCM_CCSR_STEP_SEL_OFFSET (7) +#define MXC_CCM_CCSR_STEP_SEL_MASK (0x3 << 7) +#define MXC_CCM_CCSR_PLL2_PODF_OFFSET (5) +#define MXC_CCM_CCSR_PLL2_PODF_MASK (0x3 << 5) +#define MXC_CCM_CCSR_PLL3_PODF_OFFSET (3) +#define MXC_CCM_CCSR_PLL3_PODF_MASK (0x3 << 3) +#define MXC_CCM_CCSR_PLL1_SW_CLK_SEL (1 << 2) +#define MXC_CCM_CCSR_PLL2_SW_CLK_SEL (1 << 1) +#define MXC_CCM_CCSR_PLL3_SW_CLK_SEL (1 << 0) + +/* Define the bits in register CACRR */ +#define MXC_CCM_CACRR_ARM_PODF_OFFSET (0) +#define MXC_CCM_CACRR_ARM_PODF_MASK (0x7) + +/* Define the bits in register CBCDR */ +#define MXC_CCM_CBCDR_WEIM_CLK_SEL (0x1 << 27) +#define MXC_CCM_CBCDR_PERIPH_CLK_SEL_OFFSET (25) +#define MXC_CCM_CBCDR_PERIPH_CLK_SEL_MASK (0x3 << 25) +#define MXC_CCM_CBCDR_WEIM_PODF_OFFSET (22) +#define MXC_CCM_CBCDR_WEIM_PODF_MASK (7 << 22) +#define MXC_CCM_CBCDR_AXI_B_PODF_OFFSET (19) +#define MXC_CCM_CBCDR_AXI_B_PODF_MASK (0x7 << 19) +#define MXC_CCM_CBCDR_AXI_A_PODF_OFFSET (16) +#define MXC_CCM_CBCDR_AXI_A_PODF_MASK (0x7 << 16) +#define MXC_CCM_CBCDR_AHB_PODF_OFFSET (10) +#define MXC_CCM_CBCDR_AHB_PODF_MASK (0x7 << 10) +#define MXC_CCM_CBCDR_IPG_PODF_OFFSET (8) +#define MXC_CCM_CBCDR_IPG_PODF_MASK (0x3 << 8) +#define MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET (6) +#define MXC_CCM_CBCDR_PERCLK_PRED1_MASK (0x3 << 6) +#define MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET (3) +#define MXC_CCM_CBCDR_PERCLK_PRED2_MASK (0x7 << 3) +#define MXC_CCM_CBCDR_PERCLK_PODF_OFFSET (0) +#define MXC_CCM_CBCDR_PERCLK_PODF_MASK (0x7) + +/* Define the bits in register CBCMR */ +#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET (16) +#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK (0x3 << 16) +#define MXC_CCM_CBCMR_DBG_APB_CLK_SEL_OFFSET (2) +#define MXC_CCM_CBCMR_DBG_APB_CLK_SEL_MASK (0x3 << 2) +#define MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL (0x1 << 1) +#define MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL (0x1 << 0) +#define MXC_CCM_CBCMR_LP_APM_SEL_OFFSET (0x1) + +/* Define the bits in register CSCMR1 */ +#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_OFFSET (30) +#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_MASK (0x3 << 30) +#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_OFFSET (28) +#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_MASK (0x3 << 28) +#define MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET (24) +#define MXC_CCM_CSCMR1_UART_CLK_SEL_MASK (0x3 << 24) +#define MXC_CCM_CSCMR1_ESDHC1_CLK_SEL_OFFSET (21) +#define MXC_CCM_CSCMR1_ESDHC1_CLK_SEL_MASK (0x3 << 21) +#define MXC_CCM_CSCMR1_ESDHC2_CLK_SEL (0x1 << 20) +#define MXC_CCM_CSCMR1_ESDHC4_CLK_SEL (0x1 << 19) +#define MXC_CCM_CSCMR1_ESDHC3_CLK_SEL_OFFSET (16) +#define MXC_CCM_CSCMR1_ESDHC3_CLK_SEL_MASK (0x7 << 16) +#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET (14) +#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK (0x3 << 14) +#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET (12) +#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK (0x3 << 12) +#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_OFFSET (8) +#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_MASK (0x3 << 8) +#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET (4) +#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK (0x3 << 4) +#define MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL (0x1 << 1) +#define MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL (0x1) + +/* Define the bits in register CSCDR1 */ +#define MXC_CCM_CSCDR1_ESDHC3_CLK_PRED_OFFSET (22) +#define MXC_CCM_CSCDR1_ESDHC3_CLK_PRED_MASK (0x7 << 22) +#define MXC_CCM_CSCDR1_ESDHC3_CLK_PODF_OFFSET (19) +#define MXC_CCM_CSCDR1_ESDHC3_CLK_PODF_MASK (0x7 << 19) +#define MXC_CCM_CSCDR1_ESDHC1_CLK_PRED_OFFSET (16) +#define MXC_CCM_CSCDR1_ESDHC1_CLK_PRED_MASK (0x7 << 16) +#define MXC_CCM_CSCDR1_PGC_CLK_PODF_OFFSET (14) +#define MXC_CCM_CSCDR1_PGC_CLK_PODF_MASK (0x3 << 14) +#define MXC_CCM_CSCDR1_ESDHC1_CLK_PODF_OFFSET (11) +#define MXC_CCM_CSCDR1_ESDHC1_CLK_PODF_MASK (0x7 << 11) +#define MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET (3) +#define MXC_CCM_CSCDR1_UART_CLK_PRED_MASK (0x7 << 3) +#define MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET (0) +#define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK (0x7) + +/* Define the bits in register CS1CDR and CS2CDR */ +#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_OFFSET (22) +#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_MASK (0x7 << 22) +#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_OFFSET (16) +#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_MASK (0x3F << 16) +#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET (6) +#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK (0x7 << 6) +#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET (0) +#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK (0x3F) + +#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_OFFSET (22) +#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_MASK (0x7 << 22) +#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_OFFSET (16) +#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_MASK (0x3F << 16) +#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET (6) +#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK (0x7 << 6) +#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET (0) +#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK (0x3F) + +/* Define the bits in register CSCDR2 */ +#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET (25) +#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK (0x7 << 25) +#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET (19) +#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK (0x3F << 19) + +/* Define the bits in register CDHIPR */ +#define MXC_CCM_CDHIPR_ARM_PODF_BUSY (1 << 16) +#define MXC_CCM_CDHIPR_WEIM_CLK_SEL_BUSY (1 << 6) +#define MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY (1 << 5) +#define MXC_CCM_CDHIPR_AHB_PODF_BUSY (1 << 3) +#define MXC_CCM_CDHIPR_WEIM_PODF_BUSY (1 << 2) +#define MXC_CCM_CDHIPR_AXI_B_PODF_BUSY (1 << 1) +#define MXC_CCM_CDHIPR_AXI_A_PODF_BUSY (1 << 0) + +/* Define the bits in register CDCR */ + +#define MXC_CCM_CDCR_SW_PERIPH_CLK_DIV_REQ_STATUS (0x1 << 7) +#define MXC_CCM_CDCR_SW_PERIPH_CLK_DIV_REQ (0x1 << 6) +#define MXC_CCM_CDCR_SW_DVFS_EN (0x1 << 5) +#define MXC_CCM_CDCR_ARM_FREQ_SHIFT_DIVIDER (0x1 << 2) +#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_OFFSET (0) +#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_MASK (0x3) + +/* Define the bits in register CLPCR */ +#define MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS (0x1 << 25) +#define MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS (0x1 << 24) +#define MXC_CCM_CLPCR_BYPASS_RNGB_LPM_HS (0x1 << 23) +#define MXC_CCM_CLPCR_BYPASS_WEIM_LPM_HS (0x1 << 19) +#define MXC_CCM_CLPCR_COSC_PWRDOWN (0x1 << 11) +#define MXC_CCM_CLPCR_STBY_COUNT_OFFSET (9) +#define MXC_CCM_CLPCR_STBY_COUNT_MASK (0x3 << 9) +#define MXC_CCM_CLPCR_VSTBY (0x1 << 8) +#define MXC_CCM_CLPCR_DIS_REF_OSC (0x1 << 7) +#define MXC_CCM_CLPCR_SBYOS (0x1 << 6) +#define MXC_CCM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5) +#define MXC_CCM_CLPCR_BYPASS_PMIC_VFUNC_READY (0x1 << 2) +#define MXC_CCM_CLPCR_LPM_OFFSET (0) +#define MXC_CCM_CLPCR_LPM_MASK (0x3) + +/* Define the bits in register CISR */ +#define MXC_CCM_CISR_ARM_PODF_LOADED (0x1 << 26) +#define MXC_CCM_CISR_TEMP_MON_ALARM (0x1 << 25) +#define MXC_CCM_CISR_WEIM_CLK_SEL_LOADED (0x1 << 23) +#define MXC_CCM_CISR_PER_CLK_SEL_LOADED (0x1 << 22) +#define MXC_CCM_CISR_AHB_PODF_LOADED (0x1 << 20) +#define MXC_CCM_CISR_WEIM_PODF_LOADED (0x1 << 19) +#define MXC_CCM_CISR_AXI_B_PODF_LOADED (0x1 << 18) +#define MXC_CCM_CISR_AXI_A_PODF_LOADED (0x1 << 17) +#define MXC_CCM_CISR_DIVIDER_LOADED (0x1 << 16) +#define MXC_CCM_CISR_COSC_READY (0x1 << 6) +#define MXC_CCM_CISR_CAMP1_READY (0x1 << 4) +#define MXC_CCM_CISR_LRF_PLL3 (0x1 << 2) +#define MXC_CCM_CISR_LRF_PLL2 (0x1 << 1) +#define MXC_CCM_CISR_LRF_PLL1 (0x1) + +/* Define the bits in register CIMR */ +#define MXC_CCM_CIMR_MASK_ARM_PODF_LOADED (0x1 << 26) +#define MXC_CCM_CIMR_MASK_TEMP_MON_ALARM (0x1 << 25) +#define MXC_CCM_CIMR_MASK_WEIM_CLK_SEL_LOADED (0x1 << 23) +#define MXC_CCM_CIMR_MASK_PER_CLK_SEL_LOADED (0x1 << 22) +#define MXC_CCM_CIMR_MASK_AHB_PODF_LOADED (0x1 << 20) +#define MXC_CCM_CIMR_MASK_WEIM_PODF_LOADED (0x1 << 19) +#define MXC_CCM_CIMR_MASK_AXI_B_PODF_LOADED (0x1 << 18) +#define MXC_CCM_CIMR_MASK_AXI_A_PODF_LOADED (0x1 << 17) +#define MXC_CCM_CIMR_MASK_DIVIDER_LOADED (0x1 << 16) +#define MXC_CCM_CIMR_MASK_COSC_READY (0x1 << 6) +#define MXC_CCM_CIMR_MASK_CAMP1_READY (0x1 << 4) +#define MXC_CCM_CIMR_MASK_LRF_PLL3 (0x1 << 2) +#define MXC_CCM_CIMR_MASK_LRF_PLL2 (0x1 << 1) +#define MXC_CCM_CIMR_MASK_LRF_PLL1 (0x1) + +/* Define the bits in register CCOSR */ +#define MXC_CCM_CCOSR_CKO2_EN_OFFSET (0x1 << 24) +#define MXC_CCM_CCOSR_CKO2_DIV_OFFSET (21) +#define MXC_CCM_CCOSR_CKO2_DIV_MASK (0x7 << 21) +#define MXC_CCM_CCOSR_CKO2_SEL_OFFSET (16) +#define MXC_CCM_CCOSR_CKO2_SEL_MASK (0x1F << 16) +#define MXC_CCM_CCOSR_CKO1_SLOW_SEL (0x1 << 8) +#define MXC_CCM_CCOSR_CKO1_EN (0x1 << 7) +#define MXC_CCM_CCOSR_CKO1_DIV_OFFSET (4) +#define MXC_CCM_CCOSR_CKO1_DIV_MASK (0x7 << 4) +#define MXC_CCM_CCOSR_CKO1_SEL_OFFSET (0) +#define MXC_CCM_CCOSR_CKO1_SEL_MASK (0xF) + +/* Define the bits in registers CCGRx */ +#define MXC_CCM_CCGR_CG_MASK 0x3 + +#define MXC_CCM_CCGR0_CG15_OFFSET 30 +#define MXC_CCM_CCGR0_CG15_MASK (0x3 << 30) +#define MXC_CCM_CCGR0_CG14_OFFSET 28 +#define MXC_CCM_CCGR0_CG14_MASK (0x3 << 28) +#define MXC_CCM_CCGR0_CG13_OFFSET 26 +#define MXC_CCM_CCGR0_CG13_MASK (0x3 << 26) +#define MXC_CCM_CCGR0_CG12_OFFSET 24 +#define MXC_CCM_CCGR0_CG12_MASK (0x3 << 24) +#define MXC_CCM_CCGR0_CG11_OFFSET 22 +#define MXC_CCM_CCGR0_CG11_MASK (0x3 << 22) +#define MXC_CCM_CCGR0_CG10_OFFSET 20 +#define MXC_CCM_CCGR0_CG10_MASK (0x3 << 20) +#define MXC_CCM_CCGR0_CG9_OFFSET 18 +#define MXC_CCM_CCGR0_CG9_MASK (0x3 << 18) +#define MXC_CCM_CCGR0_CG8_OFFSET 16 +#define MXC_CCM_CCGR0_CG8_MASK (0x3 << 16) +#define MXC_CCM_CCGR0_CG7_OFFSET 14 +#define MXC_CCM_CCGR0_CG6_OFFSET 12 +#define MXC_CCM_CCGR0_CG5_OFFSET 10 +#define MXC_CCM_CCGR0_CG5_MASK (0x3 << 10) +#define MXC_CCM_CCGR0_CG4_OFFSET 8 +#define MXC_CCM_CCGR0_CG4_MASK (0x3 << 8) +#define MXC_CCM_CCGR0_CG3_OFFSET 6 +#define MXC_CCM_CCGR0_CG3_MASK (0x3 << 6) +#define MXC_CCM_CCGR0_CG2_OFFSET 4 +#define MXC_CCM_CCGR0_CG2_MASK (0x3 << 4) +#define MXC_CCM_CCGR0_CG1_OFFSET 2 +#define MXC_CCM_CCGR0_CG1_MASK (0x3 << 2) +#define MXC_CCM_CCGR0_CG0_OFFSET 0 +#define MXC_CCM_CCGR0_CG0_MASK 0x3 + +#define MXC_CCM_CCGR1_CG15_OFFSET 30 +#define MXC_CCM_CCGR1_CG14_OFFSET 28 +#define MXC_CCM_CCGR1_CG13_OFFSET 26 +#define MXC_CCM_CCGR1_CG12_OFFSET 24 +#define MXC_CCM_CCGR1_CG11_OFFSET 22 +#define MXC_CCM_CCGR1_CG10_OFFSET 20 +#define MXC_CCM_CCGR1_CG9_OFFSET 18 +#define MXC_CCM_CCGR1_CG8_OFFSET 16 +#define MXC_CCM_CCGR1_CG7_OFFSET 14 +#define MXC_CCM_CCGR1_CG6_OFFSET 12 +#define MXC_CCM_CCGR1_CG5_OFFSET 10 +#define MXC_CCM_CCGR1_CG4_OFFSET 8 +#define MXC_CCM_CCGR1_CG3_OFFSET 6 +#define MXC_CCM_CCGR1_CG2_OFFSET 4 +#define MXC_CCM_CCGR1_CG1_OFFSET 2 +#define MXC_CCM_CCGR1_CG0_OFFSET 0 + +#define MXC_CCM_CCGR2_CG15_OFFSET 30 +#define MXC_CCM_CCGR2_CG14_OFFSET 28 +#define MXC_CCM_CCGR2_CG13_OFFSET 26 +#define MXC_CCM_CCGR2_CG12_OFFSET 24 +#define MXC_CCM_CCGR2_CG11_OFFSET 22 +#define MXC_CCM_CCGR2_CG10_OFFSET 20 +#define MXC_CCM_CCGR2_CG9_OFFSET 18 +#define MXC_CCM_CCGR2_CG8_OFFSET 16 +#define MXC_CCM_CCGR2_CG7_OFFSET 14 +#define MXC_CCM_CCGR2_CG6_OFFSET 12 +#define MXC_CCM_CCGR2_CG5_OFFSET 10 +#define MXC_CCM_CCGR2_CG4_OFFSET 8 +#define MXC_CCM_CCGR2_CG3_OFFSET 6 +#define MXC_CCM_CCGR2_CG2_OFFSET 4 +#define MXC_CCM_CCGR2_CG1_OFFSET 2 +#define MXC_CCM_CCGR2_CG0_OFFSET 0 + +#define MXC_CCM_CCGR3_CG15_OFFSET 30 +#define MXC_CCM_CCGR3_CG14_OFFSET 28 +#define MXC_CCM_CCGR3_CG13_OFFSET 26 +#define MXC_CCM_CCGR3_CG12_OFFSET 24 +#define MXC_CCM_CCGR3_CG11_OFFSET 22 +#define MXC_CCM_CCGR3_CG10_OFFSET 20 +#define MXC_CCM_CCGR3_CG9_OFFSET 18 +#define MXC_CCM_CCGR3_CG8_OFFSET 16 +#define MXC_CCM_CCGR3_CG7_OFFSET 14 +#define MXC_CCM_CCGR3_CG6_OFFSET 12 +#define MXC_CCM_CCGR3_CG5_OFFSET 10 +#define MXC_CCM_CCGR3_CG4_OFFSET 8 +#define MXC_CCM_CCGR3_CG3_OFFSET 6 +#define MXC_CCM_CCGR3_CG2_OFFSET 4 +#define MXC_CCM_CCGR3_CG1_OFFSET 2 +#define MXC_CCM_CCGR3_CG0_OFFSET 0 + +#define MXC_CCM_CCGR4_CG15_OFFSET 30 +#define MXC_CCM_CCGR4_CG14_OFFSET 28 +#define MXC_CCM_CCGR4_CG13_OFFSET 26 +#define MXC_CCM_CCGR4_CG12_OFFSET 24 +#define MXC_CCM_CCGR4_CG11_OFFSET 22 +#define MXC_CCM_CCGR4_CG10_OFFSET 20 +#define MXC_CCM_CCGR4_CG9_OFFSET 18 +#define MXC_CCM_CCGR4_CG8_OFFSET 16 +#define MXC_CCM_CCGR4_CG7_OFFSET 14 +#define MXC_CCM_CCGR4_CG6_OFFSET 12 +#define MXC_CCM_CCGR4_CG5_OFFSET 10 +#define MXC_CCM_CCGR4_CG4_OFFSET 8 +#define MXC_CCM_CCGR4_CG3_OFFSET 6 +#define MXC_CCM_CCGR4_CG2_OFFSET 4 +#define MXC_CCM_CCGR4_CG1_OFFSET 2 +#define MXC_CCM_CCGR4_CG0_OFFSET 0 + +#define MXC_CCM_CCGR5_CG15_OFFSET 30 +#define MXC_CCM_CCGR5_CG14_OFFSET 28 +#define MXC_CCM_CCGR5_CG14_MASK (0x3 << 28) +#define MXC_CCM_CCGR5_CG13_OFFSET 26 +#define MXC_CCM_CCGR5_CG13_MASK (0x3 << 26) +#define MXC_CCM_CCGR5_CG12_OFFSET 24 +#define MXC_CCM_CCGR5_CG12_MASK (0x3 << 24) +#define MXC_CCM_CCGR5_CG11_OFFSET 22 +#define MXC_CCM_CCGR5_CG11_MASK (0x3 << 22) +#define MXC_CCM_CCGR5_CG10_OFFSET 20 +#define MXC_CCM_CCGR5_CG10_MASK (0x3 << 20) +#define MXC_CCM_CCGR5_CG9_OFFSET 18 +#define MXC_CCM_CCGR5_CG9_MASK (0x3 << 18) +#define MXC_CCM_CCGR5_CG8_OFFSET 16 +#define MXC_CCM_CCGR5_CG8_MASK (0x3 << 16) +#define MXC_CCM_CCGR5_CG7_OFFSET 14 +#define MXC_CCM_CCGR5_CG7_MASK (0x3 << 14) +#define MXC_CCM_CCGR5_CG6_1_OFFSET 12 +#define MXC_CCM_CCGR5_CG6_2_OFFSET 13 +#define MXC_CCM_CCGR5_CG6_OFFSET 12 +#define MXC_CCM_CCGR5_CG6_MASK (0x3 << 12) +#define MXC_CCM_CCGR5_CG5_OFFSET 10 +#define MXC_CCM_CCGR5_CG4_OFFSET 8 +#define MXC_CCM_CCGR5_CG3_OFFSET 6 +#define MXC_CCM_CCGR5_CG2_OFFSET 4 +#define MXC_CCM_CCGR5_CG2_MASK (0x3 << 4) +#define MXC_CCM_CCGR5_CG1_OFFSET 2 +#define MXC_CCM_CCGR5_CG0_OFFSET 0 + +#define MXC_CCM_CCGR6_CG15_OFFSET 30 +#define MXC_CCM_CCGR6_CG14_OFFSET 28 +#define MXC_CCM_CCGR6_CG14_MASK (0x3 << 28) +#define MXC_CCM_CCGR6_CG13_OFFSET 26 +#define MXC_CCM_CCGR6_CG13_MASK (0x3 << 26) +#define MXC_CCM_CCGR6_CG12_OFFSET 24 +#define MXC_CCM_CCGR6_CG12_MASK (0x3 << 24) +#define MXC_CCM_CCGR6_CG11_OFFSET 22 +#define MXC_CCM_CCGR6_CG11_MASK (0x3 << 22) +#define MXC_CCM_CCGR6_CG10_OFFSET 20 +#define MXC_CCM_CCGR6_CG10_MASK (0x3 << 20) +#define MXC_CCM_CCGR6_CG9_OFFSET 18 +#define MXC_CCM_CCGR6_CG9_MASK (0x3 << 18) +#define MXC_CCM_CCGR6_CG8_OFFSET 16 +#define MXC_CCM_CCGR6_CG8_MASK (0x3 << 16) +#define MXC_CCM_CCGR6_CG7_OFFSET 14 +#define MXC_CCM_CCGR6_CG7_MASK (0x3 << 14) +#define MXC_CCM_CCGR6_CG6_OFFSET 12 +#define MXC_CCM_CCGR6_CG6_MASK (0x3 << 12) +#define MXC_CCM_CCGR6_CG5_OFFSET 10 +#define MXC_CCM_CCGR6_CG5_MASK (0x3 << 10) +#define MXC_CCM_CCGR6_CG4_OFFSET 8 +#define MXC_CCM_CCGR6_CG4_MASK (0x3 << 8) +#define MXC_CCM_CCGR6_CG3_OFFSET 6 +#define MXC_CCM_CCGR6_CG2_OFFSET 4 +#define MXC_CCM_CCGR6_CG2_MASK (0x3 << 4) +#define MXC_CCM_CCGR6_CG1_OFFSET 2 +#define MXC_CCM_CCGR6_CG0_OFFSET 0 + +#define MXC_CCM_CCGR7_CG15_OFFSET 30 +#define MXC_CCM_CCGR7_CG14_OFFSET 28 +#define MXC_CCM_CCGR7_CG14_MASK (0x3 << 28) +#define MXC_CCM_CCGR7_CG13_OFFSET 26 +#define MXC_CCM_CCGR7_CG13_MASK (0x3 << 26) +#define MXC_CCM_CCGR7_CG12_OFFSET 24 +#define MXC_CCM_CCGR7_CG12_MASK (0x3 << 24) +#define MXC_CCM_CCGR7_CG11_OFFSET 22 +#define MXC_CCM_CCGR7_CG11_MASK (0x3 << 22) +#define MXC_CCM_CCGR7_CG10_OFFSET 20 +#define MXC_CCM_CCGR7_CG10_MASK (0x3 << 20) +#define MXC_CCM_CCGR7_CG9_OFFSET 18 +#define MXC_CCM_CCGR7_CG9_MASK (0x3 << 18) +#define MXC_CCM_CCGR7_CG8_OFFSET 16 +#define MXC_CCM_CCGR7_CG8_MASK (0x3 << 16) +#define MXC_CCM_CCGR7_CG7_OFFSET 14 +#define MXC_CCM_CCGR7_CG7_MASK (0x3 << 14) +#define MXC_CCM_CCGR7_CG6_OFFSET 12 +#define MXC_CCM_CCGR7_CG6_MASK (0x3 << 12) +#define MXC_CCM_CCGR7_CG5_OFFSET 10 +#define MXC_CCM_CCGR7_CG4_OFFSET 8 +#define MXC_CCM_CCGR7_CG3_OFFSET 6 +#define MXC_CCM_CCGR7_CG2_OFFSET 4 +#define MXC_CCM_CCGR7_CG2_MASK (0x3 << 4) +#define MXC_CCM_CCGR7_CG1_OFFSET 2 +#define MXC_CCM_CCGR7_CG0_OFFSET 0 + +/* Define the bits in registers CLKSEQ_BYPASS */ +#define MXC_CCM_CLKSEQ_BYPASS_ELCDIF_PIX_OFFSET 14 +#define MXC_CCM_CLKSEQ_BYPASS_ELCDIF_PIX_MASK (0x3 << 14) +#define MXC_CCM_CLKSEQ_BYPASS_EPDC_PIX_OFFSET 12 +#define MXC_CCM_CLKSEQ_BYPASS_EPDC_PIX_MASK (0x3 << 12) +#define MXC_CCM_CLKSEQ_BYPASS_MSHCX_OFFSET 10 +#define MXC_CCM_CLKSEQ_BYPASS_MSHCX_MASK (0x3 << 10) +#define MXC_CCM_CLKSEQ_BYPASS_BCH_OFFSET 8 +#define MXC_CCM_CLKSEQ_BYPASS_BCH_MASK (0x3 << 8) +#define MXC_CCM_CLKSEQ_BYPASS_GPMI_OFFSET 6 +#define MXC_CCM_CLKSEQ_BYPASS_GPMI_MASK (0x3 << 6) +#define MXC_CCM_CLKSEQ_BYPASS_EPDC_OFFSET 4 +#define MXC_CCM_CLKSEQ_BYPASS_EPDC_MASK (0x3 << 4) +#define MXC_CCM_CLKSEQ_BYPASS_DISPLY_AXI_OFFSET 2 +#define MXC_CCM_CLKSEQ_BYPASS_DISPLY_AXI_MASK (0x3 << 2) +#define MXC_CCM_CLKSEQ_BYPASS_SYS_CLK_1 (0x1 << 1) +#define MXC_CCM_CLKSEQ_BYPASS_SYS_CLK_0 (0x1 << 0) + +/* Define the bits in registers CLK_SYS */ +#define MXC_CCM_CLK_SYS_XTAL_CLKGATE_OFFSET 30 +#define MXC_CCM_CLK_SYS_XTAL_CLKGATE_MASK (0x3 << 30) +#define MXC_CCM_CLK_SYS_PLL_CLKGATE_OFFSET 28 +#define MXC_CCM_CLK_SYS_PLL_CLKGATE_MASK (0x3 << 28) +#define MXC_CCM_CLK_SYS_DIV_XTAL_OFFSET 6 +#define MXC_CCM_CLK_SYS_DIV_XTAL_MASK (0xf << 6) +#define MXC_CCM_CLK_SYS_DIV_PLL_OFFSET 0 +#define MXC_CCM_CLK_SYS_DIV_PLL_MASK (0x3f << 0) + +/* Define the bits in registers CLK_DDR */ +#define MXC_CCM_CLK_DDR_DDR_CLKGATE_OFFSET (30) +#define MXC_CCM_CLK_DDR_DDR_CLKGATE_MASK (0x3 << 30) +#define MXC_CCM_CLK_DDR_DDR_PFD_SEL (1 << 6) +#define MXC_CCM_CLK_DDR_DDR_DIV_PLL_OFFSET (0) +#define MXC_CCM_CLK_DDR_DDR_DIV_PLL_MASK (0x3F) + + +#define MXC_GPC_BASE (IO_ADDRESS(GPC_BASE_ADDR)) +#define MXC_DPTC_LP_BASE (MXC_GPC_BASE + 0x80) +#define MXC_DPTC_GP_BASE (MXC_GPC_BASE + 0x100) +#define MXC_DVFS_CORE_BASE (MXC_GPC_BASE + 0x180) +#define MXC_DVFS_PER_BASE (MXC_GPC_BASE + 0x1C4) +#define MXC_PGC_IPU_BASE (MXC_GPC_BASE + 0x220) +#define MXC_PGC_VPU_BASE (MXC_GPC_BASE + 0x240) +#define MXC_PGC_GPU_BASE (MXC_GPC_BASE + 0x260) +#define MXC_SRPG_NEON_BASE (MXC_GPC_BASE + 0x280) +#define MXC_SRPG_ARM_BASE (MXC_GPC_BASE + 0x2A0) +#define MXC_SRPG_EMPGC0_BASE (MXC_GPC_BASE + 0x2C0) +#define MXC_SRPG_EMPGC1_BASE (MXC_GPC_BASE + 0x2D0) +#define MXC_SRPG_MEGAMIX_BASE (MXC_GPC_BASE + 0x2E0) +#define MXC_SRPG_EMI_BASE (MXC_GPC_BASE + 0x300) + +/* DVFS CORE */ +#define MXC_DVFSTHRS (MXC_DVFS_CORE_BASE + 0x00) +#define MXC_DVFSCOUN (MXC_DVFS_CORE_BASE + 0x04) +#define MXC_DVFSSIG1 (MXC_DVFS_CORE_BASE + 0x08) +#define MXC_DVFSSIG0 (MXC_DVFS_CORE_BASE + 0x0C) +#define MXC_DVFSGPC0 (MXC_DVFS_CORE_BASE + 0x10) +#define MXC_DVFSGPC1 (MXC_DVFS_CORE_BASE + 0x14) +#define MXC_DVFSGPBT (MXC_DVFS_CORE_BASE + 0x18) +#define MXC_DVFSEMAC (MXC_DVFS_CORE_BASE + 0x1C) +#define MXC_DVFSCNTR (MXC_DVFS_CORE_BASE + 0x20) +#define MXC_DVFSLTR0_0 (MXC_DVFS_CORE_BASE + 0x24) +#define MXC_DVFSLTR0_1 (MXC_DVFS_CORE_BASE + 0x28) +#define MXC_DVFSLTR1_0 (MXC_DVFS_CORE_BASE + 0x2C) +#define MXC_DVFSLTR1_1 (MXC_DVFS_CORE_BASE + 0x30) +#define MXC_DVFSPT0 (MXC_DVFS_CORE_BASE + 0x34) +#define MXC_DVFSPT1 (MXC_DVFS_CORE_BASE + 0x38) +#define MXC_DVFSPT2 (MXC_DVFS_CORE_BASE + 0x3C) +#define MXC_DVFSPT3 (MXC_DVFS_CORE_BASE + 0x40) + +/* DVFS PER */ +#define MXC_DVFSPER_LTR0 (MXC_DVFS_PER_BASE) +#define MXC_DVFSPER_LTR1 (MXC_DVFS_PER_BASE + 0x04) +#define MXC_DVFSPER_LTR2 (MXC_DVFS_PER_BASE + 0x08) +#define MXC_DVFSPER_LTR3 (MXC_DVFS_PER_BASE + 0x0C) +#define MXC_DVFSPER_LTBR0 (MXC_DVFS_PER_BASE + 0x10) +#define MXC_DVFSPER_LTBR1 (MXC_DVFS_PER_BASE + 0x14) +#define MXC_DVFSPER_PMCR0 (MXC_DVFS_PER_BASE + 0x18) +#define MXC_DVFSPER_PMCR1 (MXC_DVFS_PER_BASE + 0x1C) + +/* GPC */ +#define MXC_GPC_CNTR (MXC_GPC_BASE + 0x0) +#define MXC_GPC_PGR (MXC_GPC_BASE + 0x4) +#define MXC_GPC_VCR (MXC_GPC_BASE + 0x8) +#define MXC_GPC_ALL_PU (MXC_GPC_BASE + 0xC) +#define MXC_GPC_NEON (MXC_GPC_BASE + 0x10) + +/* PGC */ +#define MXC_PGC_IPU_PGCR (MXC_PGC_IPU_BASE + 0x0) +#define MXC_PGC_IPU_PGSR (MXC_PGC_IPU_BASE + 0xC) +#define MXC_PGC_VPU_PGCR (MXC_PGC_VPU_BASE + 0x0) +#define MXC_PGC_VPU_PGSR (MXC_PGC_VPU_BASE + 0xC) +#define MXC_PGC_GPU_PGCR (MXC_PGC_GPU_BASE + 0x0) +#define MXC_PGC_GPU_PGSR (MXC_PGC_GPU_BASE + 0xC) + +#define MXC_PGCR_PCR 1 +#define MXC_SRPGCR_PCR 1 +#define MXC_EMPGCR_PCR 1 +#define MXC_PGSR_PSR 1 + + +#define MXC_CORTEXA8_PLAT_LPC_DSM (1 << 0) +#define MXC_CORTEXA8_PLAT_LPC_DBG_DSM (1 << 1) + +/* SRPG */ +#define MXC_SRPG_NEON_SRPGCR (MXC_SRPG_NEON_BASE + 0x0) +#define MXC_SRPG_NEON_PUPSCR (MXC_SRPG_NEON_BASE + 0x4) +#define MXC_SRPG_NEON_PDNSCR (MXC_SRPG_NEON_BASE + 0x8) + +#define MXC_SRPG_ARM_SRPGCR (MXC_SRPG_ARM_BASE + 0x0) +#define MXC_SRPG_ARM_PUPSCR (MXC_SRPG_ARM_BASE + 0x4) +#define MXC_SRPG_ARM_PDNSCR (MXC_SRPG_ARM_BASE + 0x8) + +#define MXC_SRPG_EMPGC0_SRPGCR (MXC_SRPG_EMPGC0_BASE + 0x0) +#define MXC_SRPG_EMPGC0_PUPSCR (MXC_SRPG_EMPGC0_BASE + 0x4) +#define MXC_SRPG_EMPGC0_PDNSCR (MXC_SRPG_EMPGC0_BASE + 0x8) + +#define MXC_SRPG_EMPGC1_SRPGCR (MXC_SRPG_EMPGC1_BASE + 0x0) +#define MXC_SRPG_EMPGC1_PUPSCR (MXC_SRPG_EMPGC1_BASE + 0x4) +#define MXC_SRPG_EMPGC1_PDNSCR (MXC_SRPG_EMPGC1_BASE + 0x8) + +#define MXC_SRPG_MEGAMIX_SRPGCR (MXC_SRPG_MEGAMIX_BASE + 0x0) +#define MXC_SRPG_MEGAMIX_PUPSCR (MXC_SRPG_MEGAMIX_BASE + 0x4) +#define MXC_SRPG_MEGAMIX_PDNSCR (MXC_SRPG_MEGAMIX_BASE + 0x8) + +#define MXC_SRPGC_EMI_SRPGCR (MXC_SRPGC_EMI_BASE + 0x0) +#define MXC_SRPGC_EMI_PUPSCR (MXC_SRPGC_EMI_BASE + 0x4) +#define MXC_SRPGC_EMI_PDNSCR (MXC_SRPGC_EMI_BASE + 0x8) + +#endif /* __ARCH_ARM_MACH_MX50_CRM_REGS_H__ */ diff --git a/cpu/arm_cortexa8/mx50/generic.c b/cpu/arm_cortexa8/mx50/generic.c new file mode 100644 index 0000000..79a803c --- /dev/null +++ b/cpu/arm_cortexa8/mx50/generic.c @@ -0,0 +1,1019 @@ +/* + * Copyright (C) 2010 Freescale Semiconductor, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include "crm_regs.h" +#ifdef CONFIG_CMD_CLOCK +#include +#endif +#include +#ifdef CONFIG_ARCH_CPU_INIT +#include +#endif + +enum pll_clocks { + PLL1_CLK = MXC_DPLL1_BASE, + PLL2_CLK = MXC_DPLL2_BASE, + PLL3_CLK = MXC_DPLL3_BASE, +}; + +enum pll_sw_clocks { + PLL1_SW_CLK, + PLL2_SW_CLK, + PLL3_SW_CLK, +}; + +#define AHB_CLK_ROOT 133333333 +#define IPG_CLK_ROOT 66666666 +#define IPG_PER_CLK_ROOT 40000000 + +#ifdef CONFIG_CMD_CLOCK +#define SZ_DEC_1M 1000000 +#define PLL_PD_MAX 16 /* Actual pd+1 */ +#define PLL_MFI_MAX 15 +#define PLL_MFI_MIN 5 +#define ARM_DIV_MAX 8 +#define IPG_DIV_MAX 4 +#define AHB_DIV_MAX 8 +#define EMI_DIV_MAX 8 +#define NFC_DIV_MAX 8 + +struct fixed_pll_mfd { + u32 ref_clk_hz; + u32 mfd; +}; + +const struct fixed_pll_mfd fixed_mfd[4] = { + {0, 0}, /* reserved */ + {0, 0}, /* reserved */ + {CONFIG_MX50_HCLK_FREQ, 24 * 16}, /* 384 */ + {0, 0}, /* reserved */ +}; + +struct pll_param { + u32 pd; + u32 mfi; + u32 mfn; + u32 mfd; +}; + +#define PLL_FREQ_MAX(_ref_clk_) \ + (4 * _ref_clk_ * PLL_MFI_MAX) +#define PLL_FREQ_MIN(_ref_clk_) \ + ((2 * _ref_clk_ * (PLL_MFI_MIN - 1)) / PLL_PD_MAX) +#define MAX_DDR_CLK 420000000 +#define AHB_CLK_MAX 133333333 +#define IPG_CLK_MAX (AHB_CLK_MAX / 2) +#define NFC_CLK_MAX 25000000 +#define HSP_CLK_MAX 133333333 +#endif + +static u32 __decode_pll(enum pll_clocks pll, u32 infreq) +{ + long mfi, mfn, mfd, pdf, ref_clk, mfn_abs; + unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, pll_hfsm, dbl; + s64 temp; + + dp_ctl = __REG(pll + MXC_PLL_DP_CTL); + pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM; + dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN; + + if (pll_hfsm == 0) { + dp_op = __REG(pll + MXC_PLL_DP_OP); + dp_mfd = __REG(pll + MXC_PLL_DP_MFD); + dp_mfn = __REG(pll + MXC_PLL_DP_MFN); + } else { + dp_op = __REG(pll + MXC_PLL_DP_HFS_OP); + dp_mfd = __REG(pll + MXC_PLL_DP_HFS_MFD); + dp_mfn = __REG(pll + MXC_PLL_DP_HFS_MFN); + } + pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK; + mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET; + mfi = (mfi <= 5) ? 5 : mfi; + mfd = dp_mfd & MXC_PLL_DP_MFD_MASK; + mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK; + /* Sign extend to 32-bits */ + if (mfn >= 0x04000000) { + mfn |= 0xFC000000; + mfn_abs = -mfn; + } + + ref_clk = 2 * infreq; + if (dbl != 0) + ref_clk *= 2; + + ref_clk /= (pdf + 1); + temp = (u64) ref_clk * mfn_abs; + do_div(temp, mfd + 1); + if (mfn < 0) + temp = -temp; + temp = (ref_clk * mfi) + temp; + + return temp; +} + +static u32 __get_mcu_main_clk(void) +{ + u32 reg, freq; + reg = (__REG(MXC_CCM_CACRR) & MXC_CCM_CACRR_ARM_PODF_MASK) >> + MXC_CCM_CACRR_ARM_PODF_OFFSET; + freq = __decode_pll(PLL1_CLK, CONFIG_MX50_HCLK_FREQ); + return freq / (reg + 1); +} + +/* + * This function returns the low power audio clock. + */ +u32 __get_lp_apm(void) +{ + u32 ret_val = 0; + u32 cbcmr = __REG(MXC_CCM_CBCMR); + + if (((cbcmr >> MXC_CCM_CBCMR_LP_APM_SEL_OFFSET) & 0x1) == 0) + ret_val = CONFIG_MX50_HCLK_FREQ; + else + ret_val = ((32768 * 1024)); + + return ret_val; +} + +static u32 __get_periph_clk(void) +{ + u32 reg; + reg = __REG(MXC_CCM_CBCDR); + + switch ((reg & MXC_CCM_CBCDR_PERIPH_CLK_SEL_MASK) >> + MXC_CCM_CBCDR_PERIPH_CLK_SEL_OFFSET) { + case 0: + return __decode_pll(PLL1_CLK, CONFIG_MX50_HCLK_FREQ); + case 1: + return __decode_pll(PLL2_CLK, CONFIG_MX50_HCLK_FREQ); + case 2: + return __decode_pll(PLL3_CLK, CONFIG_MX50_HCLK_FREQ); + default: + return __get_lp_apm(); + } +} + +static u32 __get_ipg_clk(void) +{ + u32 ahb_podf, ipg_podf; + + ahb_podf = __REG(MXC_CCM_CBCDR); + ipg_podf = (ahb_podf & MXC_CCM_CBCDR_IPG_PODF_MASK) >> + MXC_CCM_CBCDR_IPG_PODF_OFFSET; + ahb_podf = (ahb_podf & MXC_CCM_CBCDR_AHB_PODF_MASK) >> + MXC_CCM_CBCDR_AHB_PODF_OFFSET; + return __get_periph_clk() / ((ahb_podf + 1) * (ipg_podf + 1)); +} + +static u32 __get_ipg_per_clk(void) +{ + u32 pred1, pred2, podf, clk; + if (__REG(MXC_CCM_CBCMR) & MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL) + return __get_ipg_clk(); + + clk = __REG(MXC_CCM_CBCMR) & MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL ? + __get_lp_apm() : __get_periph_clk(); + + podf = __REG(MXC_CCM_CBCDR); + pred1 = (podf & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >> + MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET; + pred2 = (podf & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >> + MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET; + podf = (podf & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >> + MXC_CCM_CBCDR_PERCLK_PODF_OFFSET; + + return clk / ((pred1 + 1) * (pred2 + 1) * (podf + 1)); +} + +static u32 __get_uart_clk(void) +{ + u32 freq = 0, reg, pred, podf; + reg = __REG(MXC_CCM_CSCMR1); + switch ((reg & MXC_CCM_CSCMR1_UART_CLK_SEL_MASK) >> + MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET) { + case 0x0: + freq = __decode_pll(PLL1_CLK, CONFIG_MX50_HCLK_FREQ); + break; + case 0x1: + freq = __decode_pll(PLL2_CLK, CONFIG_MX50_HCLK_FREQ); + break; + case 0x2: + freq = __decode_pll(PLL3_CLK, CONFIG_MX50_HCLK_FREQ); + break; + case 0x3: + freq = __get_lp_apm(); + break; + default: + break; + } + + reg = __REG(MXC_CCM_CSCDR1); + + pred = (reg & MXC_CCM_CSCDR1_UART_CLK_PRED_MASK) >> + MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET; + + podf = (reg & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK) >> + MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET; + freq /= (pred + 1) * (podf + 1); + + return freq; +} + + +static u32 __get_cspi_clk(void) +{ + u32 ret_val = 0, pdf, pre_pdf, clk_sel, div; + u32 cscmr1 = __REG(MXC_CCM_CSCMR1); + u32 cscdr2 = __REG(MXC_CCM_CSCDR2); + + pre_pdf = (cscdr2 & MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK) \ + >> MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET; + pdf = (cscdr2 & MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK) \ + >> MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET; + clk_sel = (cscmr1 & MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK) \ + >> MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET; + + div = (pre_pdf + 1) * (pdf + 1); + + switch (clk_sel) { + case 0: + ret_val = __decode_pll(PLL1_CLK, CONFIG_MX50_HCLK_FREQ) / div; + break; + case 1: + ret_val = __decode_pll(PLL2_CLK, CONFIG_MX50_HCLK_FREQ) / div; + break; + case 2: + ret_val = __decode_pll(PLL3_CLK, CONFIG_MX50_HCLK_FREQ) / div; + break; + default: + ret_val = __get_lp_apm() / div; + break; + } + + return ret_val; +} + +static u32 __get_axi_a_clk(void) +{ + u32 cbcdr = __REG(MXC_CCM_CBCDR); + u32 pdf = (cbcdr & MXC_CCM_CBCDR_AXI_A_PODF_MASK) \ + >> MXC_CCM_CBCDR_AXI_A_PODF_OFFSET; + + return __get_periph_clk() / (pdf + 1); +} + +static u32 __get_axi_b_clk(void) +{ + u32 cbcdr = __REG(MXC_CCM_CBCDR); + u32 pdf = (cbcdr & MXC_CCM_CBCDR_AXI_B_PODF_MASK) \ + >> MXC_CCM_CBCDR_AXI_B_PODF_OFFSET; + + return __get_periph_clk() / (pdf + 1); +} + +static u32 __get_ahb_clk(void) +{ + u32 cbcdr = __REG(MXC_CCM_CBCDR); + u32 pdf = (cbcdr & MXC_CCM_CBCDR_AHB_PODF_MASK) \ + >> MXC_CCM_CBCDR_AHB_PODF_OFFSET; + + return __get_periph_clk() / (pdf + 1); +} + + +static u32 __get_emi_slow_clk(void) +{ + u32 cbcdr = __REG(MXC_CCM_CBCDR); + u32 emi_clk_sel = cbcdr & MXC_CCM_CBCDR_WEIM_CLK_SEL; + u32 pdf = (cbcdr & MXC_CCM_CBCDR_WEIM_PODF_MASK) \ + >> MXC_CCM_CBCDR_WEIM_PODF_OFFSET; + + if (emi_clk_sel) + return __get_ahb_clk() / (pdf + 1); + + return __get_periph_clk() / (pdf + 1); +} + +static u32 __get_sys_clk(void) +{ + u32 ret_val = 0, clk, sys_pll_div; + u32 clkseq_bypass = __REG(MXC_CCM_CLKSEQ_BYPASS); + + /* Fixme Not handle OSC and PFD1 mux */ + if ((clkseq_bypass & MXC_CCM_CLKSEQ_BYPASS_SYS_CLK_1) && + clkseq_bypass & MXC_CCM_CLKSEQ_BYPASS_SYS_CLK_0) { + sys_pll_div = __REG(MXC_CCM_CLK_SYS) \ + & MXC_CCM_CLK_SYS_DIV_PLL_MASK; + clk = __decode_pll(PLL1_CLK, CONFIG_MX50_HCLK_FREQ); + if (sys_pll_div) + clk /= sys_pll_div; + ret_val = clk; + } else if ((clkseq_bypass & MXC_CCM_CLKSEQ_BYPASS_SYS_CLK_0) == 0) { + ret_val = CONFIG_MX50_HCLK_FREQ; /* OSC */ + } else { + + printf("Warning, Fixme Not handle PFD1 mux\n"); + } + + return ret_val; + +} +static u32 __get_ddr_clk(void) +{ + u32 ret_val = 0, clk, ddr_pll_div; + u32 clk_ddr = __REG(MXC_CCM_CLK_DDR); + u32 ddr_clk_sel = clk_ddr & MXC_CCM_CLK_DDR_DDR_PFD_SEL; + + if (!ddr_clk_sel) { + ddr_pll_div = clk_ddr & \ + MXC_CCM_CLK_DDR_DDR_DIV_PLL_MASK; + clk = __decode_pll(PLL1_CLK, CONFIG_MX50_HCLK_FREQ); + if (ddr_pll_div) + clk /= ddr_pll_div; + ret_val = clk; + } else { + + printf("Warning, Fixme Not handle PFD1 mux\n"); + } + + return ret_val; +} + +#ifdef CONFIG_CMD_MMC +static u32 __get_esdhc1_clk(void) +{ + u32 ret_val = 0, div, pre_pdf, pdf; + u32 cscmr1 = __REG(MXC_CCM_CSCMR1); + u32 cscdr1 = __REG(MXC_CCM_CSCDR1); + u32 esdh1_clk_sel; + + esdh1_clk_sel = (cscmr1 & MXC_CCM_CSCMR1_ESDHC1_CLK_SEL_MASK) \ + >> MXC_CCM_CSCMR1_ESDHC1_CLK_SEL_OFFSET; + pre_pdf = (cscdr1 & MXC_CCM_CSCDR1_ESDHC1_CLK_PRED_MASK) \ + >> MXC_CCM_CSCDR1_ESDHC1_CLK_PRED_OFFSET; + pdf = (cscdr1 & MXC_CCM_CSCDR1_ESDHC1_CLK_PODF_MASK) \ + >> MXC_CCM_CSCDR1_ESDHC1_CLK_PODF_OFFSET ; + + div = (pre_pdf + 1) * (pdf + 1); + + switch (esdh1_clk_sel) { + case 0: + ret_val = __decode_pll(PLL1_CLK, CONFIG_MX50_HCLK_FREQ); + break; + case 1: + ret_val = __decode_pll(PLL2_CLK, CONFIG_MX50_HCLK_FREQ); + break; + case 2: + ret_val = __decode_pll(PLL3_CLK, CONFIG_MX50_HCLK_FREQ); + break; + case 3: + ret_val = __get_lp_apm(); + break; + default: + break; + } + + ret_val /= div; + + return ret_val; +} + +static u32 __get_esdhc3_clk(void) +{ + u32 ret_val = 0, div, pre_pdf, pdf; + u32 esdh3_clk_sel; + u32 cscmr1 = __REG(MXC_CCM_CSCMR1); + u32 cscdr1 = __REG(MXC_CCM_CSCDR1); + esdh3_clk_sel = (cscmr1 & MXC_CCM_CSCMR1_ESDHC3_CLK_SEL_MASK) \ + >> MXC_CCM_CSCMR1_ESDHC3_CLK_SEL_OFFSET; + pre_pdf = (cscdr1 & MXC_CCM_CSCDR1_ESDHC3_CLK_PRED_MASK) \ + >> MXC_CCM_CSCDR1_ESDHC3_CLK_PRED_OFFSET; + pdf = (cscdr1 & MXC_CCM_CSCDR1_ESDHC3_CLK_PODF_MASK) \ + >> MXC_CCM_CSCDR1_ESDHC3_CLK_PODF_OFFSET ; + + div = (pre_pdf + 1) * (pdf + 1); + + switch (esdh3_clk_sel) { + case 0: + ret_val = __decode_pll(PLL1_CLK, CONFIG_MX50_HCLK_FREQ); + break; + case 1: + ret_val = __decode_pll(PLL2_CLK, CONFIG_MX50_HCLK_FREQ); + break; + case 2: + ret_val = __decode_pll(PLL3_CLK, CONFIG_MX50_HCLK_FREQ); + break; + case 3: + ret_val = __get_lp_apm(); + break; + case 5 ... 8: + puts("Warning, Fixme,not handle PFD mux\n"); + + break; + default: + break; + } + + ret_val /= div; + + return ret_val; +} + +static u32 __get_esdhc2_clk(void) +{ + u32 cscmr1 = __REG(MXC_CCM_CSCMR1); + u32 esdh2_clk_sel = cscmr1 & MXC_CCM_CSCMR1_ESDHC2_CLK_SEL; + if (esdh2_clk_sel) + return __get_esdhc3_clk(); + + return __get_esdhc1_clk(); +} + +static u32 __get_esdhc4_clk(void) +{ + u32 cscmr1 = __REG(MXC_CCM_CSCMR1); + u32 esdh4_clk_sel = cscmr1 & MXC_CCM_CSCMR1_ESDHC4_CLK_SEL; + if (esdh4_clk_sel) + return __get_esdhc3_clk(); + + return __get_esdhc1_clk(); +} +#endif + +unsigned int mxc_get_clock(enum mxc_clock clk) +{ + switch (clk) { + case MXC_ARM_CLK: + return __get_mcu_main_clk(); + case MXC_PER_CLK: + return __get_periph_clk(); + case MXC_AHB_CLK: + return __get_ahb_clk(); + case MXC_IPG_CLK: + return __get_ipg_clk(); + case MXC_IPG_PERCLK: + return __get_ipg_per_clk(); + case MXC_UART_CLK: + return __get_uart_clk(); +#ifdef CONFIG_IMX_CSPI + case MXC_CSPI_CLK: + return __get_cspi_clk(); +#endif + case MXC_AXI_A_CLK: + return __get_axi_a_clk(); + case MXC_AXI_B_CLK: + return __get_axi_b_clk(); + case MXC_EMI_SLOW_CLK: + return __get_emi_slow_clk(); + case MXC_DDR_CLK: + return __get_ddr_clk(); +#ifdef CONFIG_CMD_MMC + case MXC_ESDHC_CLK: + return __get_esdhc1_clk(); + case MXC_ESDHC2_CLK: + return __get_esdhc2_clk(); + case MXC_ESDHC3_CLK: + return __get_esdhc3_clk(); + case MXC_ESDHC4_CLK: + return __get_esdhc4_clk(); +#endif + default: + break; + } + return -1; +} + +void mxc_dump_clocks(void) +{ + u32 freq; + freq = __decode_pll(PLL1_CLK, CONFIG_MX50_HCLK_FREQ); + printf("mx50 pll1: %dMHz\n", freq / 1000000); + freq = __decode_pll(PLL2_CLK, CONFIG_MX50_HCLK_FREQ); + printf("mx50 pll2: %dMHz\n", freq / 1000000); + freq = __decode_pll(PLL3_CLK, CONFIG_MX50_HCLK_FREQ); + printf("mx50 pll3: %dMHz\n", freq / 1000000); + printf("ipg clock : %dHz\n", mxc_get_clock(MXC_IPG_CLK)); + printf("ipg per clock : %dHz\n", mxc_get_clock(MXC_IPG_PERCLK)); + printf("uart clock : %dHz\n", mxc_get_clock(MXC_UART_CLK)); +#ifdef CONFIG_IMX_ECSPI + printf("cspi clock : %dHz\n", mxc_get_clock(MXC_CSPI_CLK)); +#endif + printf("ahb clock : %dHz\n", mxc_get_clock(MXC_AHB_CLK)); + printf("axi_a clock : %dHz\n", mxc_get_clock(MXC_AXI_A_CLK)); + printf("axi_b clock : %dHz\n", mxc_get_clock(MXC_AXI_B_CLK)); + printf("weim_clock : %dHz\n", mxc_get_clock(MXC_EMI_SLOW_CLK)); + printf("ddr clock : %dHz\n", mxc_get_clock(MXC_DDR_CLK)); +#ifdef CONFIG_CMD_MMC + printf("esdhc1 clock : %dHz\n", mxc_get_clock(MXC_ESDHC_CLK)); + printf("esdhc2 clock : %dHz\n", mxc_get_clock(MXC_ESDHC2_CLK)); + printf("esdhc3 clock : %dHz\n", mxc_get_clock(MXC_ESDHC3_CLK)); + printf("esdhc4 clock : %dHz\n", mxc_get_clock(MXC_ESDHC4_CLK)); +#endif +} + +#ifdef CONFIG_CMD_CLOCK +/* precondition: m>0 and n>0. Let g=gcd(m,n). */ +static int gcd(int m, int n) +{ + int t; + while (m > 0) { + if (n > m) { + t = m; + m = n; + n = t; + } /* swap */ + m -= n; + } + return n; +} + +/*! + * This is to calculate various parameters based on reference clock and + * targeted clock based on the equation: + * t_clk = 2*ref_freq*(mfi + mfn/(mfd+1))/(pd+1) + * This calculation is based on a fixed MFD value for simplicity. + * + * @param ref reference clock freq in Hz + * @param target targeted clock in Hz + * @param pll pll_param structure. + * + * @return 0 if successful; non-zero otherwise. + */ +static int calc_pll_params(u32 ref, u32 target, struct pll_param *pll) +{ + u64 pd, mfi = 1, mfn, mfd, t1; + u32 n_target = target; + u32 n_ref = ref, i; + + /* + * Make sure targeted freq is in the valid range. + * Otherwise the following calculation might be wrong!!! + */ + if (n_target < PLL_FREQ_MIN(ref) || + n_target > PLL_FREQ_MAX(ref)) { + printf("Targeted peripheral clock should be" + "within [%d - %d]\n", + PLL_FREQ_MIN(ref) / SZ_DEC_1M, + PLL_FREQ_MAX(ref) / SZ_DEC_1M); + return -1; + } + + for (i = 0; i < ARRAY_SIZE(fixed_mfd); i++) { + if (fixed_mfd[i].ref_clk_hz == ref) { + mfd = fixed_mfd[i].mfd; + break; + } + } + + if (i == ARRAY_SIZE(fixed_mfd)) + return -1; + + /* Use n_target and n_ref to avoid overflow */ + for (pd = 1; pd <= PLL_PD_MAX; pd++) { + t1 = n_target * pd; + do_div(t1, (4 * n_ref)); + mfi = t1; + if (mfi > PLL_MFI_MAX) + return -1; + else if (mfi < 5) + continue; + break; + } + /* Now got pd and mfi already */ + /* + mfn = (((n_target * pd) / 4 - n_ref * mfi) * mfd) / n_ref; + */ + t1 = n_target * pd; + do_div(t1, 4); + t1 -= n_ref * mfi; + t1 *= mfd; + do_div(t1, n_ref); + mfn = t1; +#ifdef CMD_CLOCK_DEBUG + printf("%d: ref=%d, target=%d, pd=%d," + "mfi=%d,mfn=%d, mfd=%d\n", + __LINE__, ref, (u32)n_target, + (u32)pd, (u32)mfi, (u32)mfn, + (u32)mfd); +#endif + i = 1; + if (mfn != 0) + i = gcd(mfd, mfn); + pll->pd = (u32)pd; + pll->mfi = (u32)mfi; + do_div(mfn, i); + pll->mfn = (u32)mfn; + do_div(mfd, i); + pll->mfd = (u32)mfd; + + return 0; +} + +int clk_info(u32 clk_type) +{ + switch (clk_type) { + case CPU_CLK: + printf("CPU Clock: %dHz\n", + mxc_get_clock(MXC_ARM_CLK)); + break; + case PERIPH_CLK: + printf("Peripheral Clock: %dHz\n", + mxc_get_clock(MXC_PER_CLK)); + break; + case AHB_CLK: + printf("AHB Clock: %dHz\n", + mxc_get_clock(MXC_AHB_CLK)); + break; + case IPG_CLK: + printf("IPG Clock: %dHz\n", + mxc_get_clock(MXC_IPG_CLK)); + break; + case IPG_PERCLK: + printf("IPG_PER Clock: %dHz\n", + mxc_get_clock(MXC_IPG_PERCLK)); + break; + case UART_CLK: + printf("UART Clock: %dHz\n", + mxc_get_clock(MXC_UART_CLK)); + break; + case CSPI_CLK: + printf("CSPI Clock: %dHz\n", + mxc_get_clock(MXC_CSPI_CLK)); + break; + case DDR_CLK: + printf("DDR Clock: %dHz\n", + mxc_get_clock(MXC_DDR_CLK)); + break; + case ALL_CLK: + printf("cpu clock: %dMHz\n", + mxc_get_clock(MXC_ARM_CLK) / SZ_DEC_1M); + mxc_dump_clocks(); + break; + default: + printf("Unsupported clock type! :(\n"); + } + + return 0; +} + +#define calc_div(target_clk, src_clk, limit) ({ \ + u32 tmp = 0; \ + if ((src_clk % target_clk) <= 100) \ + tmp = src_clk / target_clk; \ + else \ + tmp = (src_clk / target_clk) + 1; \ + if (tmp > limit) \ + tmp = limit; \ + (tmp - 1); \ + }) + +u32 calc_per_cbcdr_val(u32 per_clk, u32 cbcmr) +{ + u32 cbcdr = __REG(MXC_CCM_CBCDR); + u32 tmp_clk = 0, div = 0, clk_sel = 0; + + cbcdr &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL; + + /* emi_slow_podf divider */ + tmp_clk = __get_emi_slow_clk(); + clk_sel = cbcdr & MXC_CCM_CBCDR_EMI_CLK_SEL; + if (clk_sel) { + div = calc_div(tmp_clk, per_clk, 8); + cbcdr &= ~MXC_CCM_CBCDR_EMI_PODF_MASK; + cbcdr |= (div << MXC_CCM_CBCDR_EMI_PODF_OFFSET); + } + + /* axi_b_podf divider */ + tmp_clk = __get_axi_b_clk(); + div = calc_div(tmp_clk, per_clk, 8); + cbcdr &= ~MXC_CCM_CBCDR_AXI_B_PODF_MASK; + cbcdr |= (div << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET); + + /* axi_b_podf divider */ + tmp_clk = __get_axi_a_clk(); + div = calc_div(tmp_clk, per_clk, 8); + cbcdr &= ~MXC_CCM_CBCDR_AXI_A_PODF_MASK; + cbcdr |= (div << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET); + + /* ahb podf divider */ + tmp_clk = AHB_CLK_ROOT; + div = calc_div(tmp_clk, per_clk, 8); + cbcdr &= ~MXC_CCM_CBCDR_AHB_PODF_MASK; + cbcdr |= (div << MXC_CCM_CBCDR_AHB_PODF_OFFSET); + + return cbcdr; +} + +#define CHANGE_PLL_SETTINGS(base, pd, mfi, mfn, mfd) \ + { \ + writel(0x1232, base + PLL_DP_CTL); \ + writel(0x2, base + PLL_DP_CONFIG); \ + writel(((pd - 1) << 0) | (mfi << 4), \ + base + PLL_DP_OP); \ + writel(mfn, base + PLL_DP_MFN); \ + writel(mfd - 1, base + PLL_DP_MFD); \ + writel(((pd - 1) << 0) | (mfi << 4), \ + base + PLL_DP_HFS_OP); \ + writel(mfn, base + PLL_DP_HFS_MFN); \ + writel(mfd - 1, base + PLL_DP_HFS_MFD); \ + writel(0x1232, base + PLL_DP_CTL); \ + while (!readl(base + PLL_DP_CTL) & 0x1) \ + ; \ + } + +int config_pll_clk(enum pll_clocks pll, struct pll_param *pll_param) +{ + u32 ccsr = readl(CCM_BASE_ADDR + CLKCTL_CCSR); + u32 pll_base = pll; + + switch (pll) { + case PLL1_CLK: + /* Switch ARM to PLL2 clock */ + writel(ccsr | 0x4, CCM_BASE_ADDR + CLKCTL_CCSR); + CHANGE_PLL_SETTINGS(pll_base, pll_param->pd, + pll_param->mfi, pll_param->mfn, + pll_param->mfd); + /* Switch back */ + writel(ccsr & ~0x4, CCM_BASE_ADDR + CLKCTL_CCSR); + break; + case PLL2_CLK: + /* Switch to pll2 bypass clock */ + writel(ccsr | 0x2, CCM_BASE_ADDR + CLKCTL_CCSR); + CHANGE_PLL_SETTINGS(pll_base, pll_param->pd, + pll_param->mfi, pll_param->mfn, + pll_param->mfd); + /* Switch back */ + writel(ccsr & ~0x2, CCM_BASE_ADDR + CLKCTL_CCSR); + break; + case PLL3_CLK: + /* Switch to pll3 bypass clock */ + writel(ccsr | 0x1, CCM_BASE_ADDR + CLKCTL_CCSR); + CHANGE_PLL_SETTINGS(pll_base, pll_param->pd, + pll_param->mfi, pll_param->mfn, + pll_param->mfd); + /* Switch back */ + writel(ccsr & ~0x1, CCM_BASE_ADDR + CLKCTL_CCSR); + break; + default: + return -1; + } + + return 0; +} + +int config_core_clk(u32 ref, u32 freq) +{ + int ret = 0; + u32 pll = 0; + struct pll_param pll_param; + + memset(&pll_param, 0, sizeof(struct pll_param)); + + /* The case that periph uses PLL1 is not considered here */ + pll = freq; + ret = calc_pll_params(ref, pll, &pll_param); + if (ret != 0) { + printf("Can't find pll parameters: %d\n", + ret); + return ret; + } + + return config_pll_clk(PLL1_CLK, &pll_param); +} + +int config_periph_clk(u32 ref, u32 freq) +{ + int ret = 0; + u32 pll = freq; + struct pll_param pll_param; + + memset(&pll_param, 0, sizeof(struct pll_param)); + + if (__REG(MXC_CCM_CBCDR) & MXC_CCM_CBCDR_PERIPH_CLK_SEL) { + /* Actually this case is not considered here */ + ret = calc_pll_params(ref, pll, &pll_param); + if (ret != 0) { + printf("Can't find pll parameters: %d\n", + ret); + return ret; + } + switch ((__REG(MXC_CCM_CBCMR) & \ + MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK) >> + MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET) { + case 0: + return config_pll_clk(PLL1_CLK, &pll_param); + break; + case 1: + return config_pll_clk(PLL3_CLK, &pll_param); + break; + default: + return -1; + } + } else { + u32 old_cbcmr = readl(CCM_BASE_ADDR + CLKCTL_CBCMR); + u32 new_cbcdr = calc_per_cbcdr_val(pll, old_cbcmr); + + /* Switch peripheral to PLL3 */ + writel(0x00015154, CCM_BASE_ADDR + CLKCTL_CBCMR); + writel(0x02888945, CCM_BASE_ADDR + CLKCTL_CBCDR); + + /* Make sure change is effective */ + while (readl(CCM_BASE_ADDR + CLKCTL_CDHIPR) != 0) + ; + + /* Setup PLL2 */ + ret = calc_pll_params(ref, pll, &pll_param); + if (ret != 0) { + printf("Can't find pll parameters: %d\n", + ret); + return ret; + } + config_pll_clk(PLL2_CLK, &pll_param); + + /* Switch peripheral back */ + writel(new_cbcdr, CCM_BASE_ADDR + CLKCTL_CBCDR); + writel(old_cbcmr, CCM_BASE_ADDR + CLKCTL_CBCMR); + + /* Make sure change is effective */ + while (readl(CCM_BASE_ADDR + CLKCTL_CDHIPR) != 0) + ; + puts("\n"); + } + + return 0; +} + +int config_ddr_clk(u32 emi_clk) +{ + u32 clk_src; + s32 shift = 0, clk_sel, div = 1; + u32 cbcmr = readl(CCM_BASE_ADDR + CLKCTL_CBCMR); + u32 cbcdr = readl(CCM_BASE_ADDR + CLKCTL_CBCDR); + + if (emi_clk > MAX_DDR_CLK) { + printf("DDR clock should be less than" + "%d MHz, assuming max value \n", + (MAX_DDR_CLK / SZ_DEC_1M)); + emi_clk = MAX_DDR_CLK; + } + + clk_src = __get_periph_clk(); + /* Find DDR clock input */ + clk_sel = (cbcmr >> 10) & 0x3; + switch (clk_sel) { + case 0: + shift = 16; + break; + case 1: + shift = 19; + break; + case 2: + shift = 22; + break; + case 3: + shift = 10; + break; + default: + return -1; + } + + if ((clk_src % emi_clk) == 0) + div = clk_src / emi_clk; + else + div = (clk_src / emi_clk) + 1; + if (div > 8) + div = 8; + + cbcdr = cbcdr & ~(0x7 << shift); + cbcdr |= ((div - 1) << shift); + writel(cbcdr, CCM_BASE_ADDR + CLKCTL_CBCDR); + while (readl(CCM_BASE_ADDR + CLKCTL_CDHIPR) != 0) + ; + writel(0x0, CCM_BASE_ADDR + CLKCTL_CCDR); + + return 0; +} + +/*! + * This function assumes the expected core clock has to be changed by + * modifying the PLL. This is NOT true always but for most of the times, + * it is. So it assumes the PLL output freq is the same as the expected + * core clock (presc=1) unless the core clock is less than PLL_FREQ_MIN. + * In the latter case, it will try to increase the presc value until + * (presc*core_clk) is greater than PLL_FREQ_MIN. It then makes call to + * calc_pll_params() and obtains the values of PD, MFI,MFN, MFD based + * on the targeted PLL and reference input clock to the PLL. Lastly, + * it sets the register based on these values along with the dividers. + * Note 1) There is no value checking for the passed-in divider values + * so the caller has to make sure those values are sensible. + * 2) Also adjust the NFC divider such that the NFC clock doesn't + * exceed NFC_CLK_MAX. + * 3) IPU HSP clock is independent of AHB clock. Even it can go up to + * 177MHz for higher voltage, this function fixes the max to 133MHz. + * 4) This function should not have allowed diag_printf() calls since + * the serial driver has been stoped. But leave then here to allow + * easy debugging by NOT calling the cyg_hal_plf_serial_stop(). + * + * @param ref pll input reference clock (24MHz) + * @param freq core clock in Hz + * @param clk_type clock type, e.g CPU_CLK, DDR_CLK, etc. + * @return 0 if successful; non-zero otherwise + */ +int clk_config(u32 ref, u32 freq, u32 clk_type) +{ + freq *= SZ_DEC_1M; + + switch (clk_type) { + case CPU_CLK: + if (config_core_clk(ref, freq)) + return -1; + break; + case PERIPH_CLK: + if (config_periph_clk(ref, freq)) + return -1; + break; + case DDR_CLK: + if (config_ddr_clk(freq)) + return -1; + break; + default: + printf("Unsupported or invalid clock type! :(\n"); + } + + return 0; +} +#endif + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{ + printf("CPU: Freescale i.MX50 family %d.%dV at %d MHz\n", + (get_board_rev() & 0xFF) >> 4, + (get_board_rev() & 0xF), + __get_mcu_main_clk() / 1000000); +#ifndef CONFIG_CMD_CLOCK + mxc_dump_clocks(); +#endif + return 0; +} +#endif + +#if defined(CONFIG_MXC_FEC) +extern int mxc_fec_initialize(bd_t *bis); +extern void mxc_fec_set_mac_from_env(char *mac_addr); +#endif + +int cpu_eth_init(bd_t *bis) +{ + int rc = -ENODEV; +#if defined(CONFIG_MXC_FEC) + char *env = NULL; + + rc = mxc_fec_initialize(bis); + + env = getenv("fec_addr"); + if (env) + mxc_fec_set_mac_from_env(env); +#endif + return rc; +} + +#if defined(CONFIG_ARCH_CPU_INIT) +int arch_cpu_init(void) +{ + icache_enable(); + dcache_enable(); + +#ifdef CONFIG_L2_OFF + l2_cache_disable(); +#else + l2_cache_enable(); +#endif + return 0; +} +#endif + diff --git a/cpu/arm_cortexa8/mx50/interrupts.c b/cpu/arm_cortexa8/mx50/interrupts.c new file mode 100644 index 0000000..4576507 --- /dev/null +++ b/cpu/arm_cortexa8/mx50/interrupts.c @@ -0,0 +1,39 @@ +/* + * (C) Copyright 2007 + * Sascha Hauer, Pengutronix + * + * Copyright (C) 2010 Freescale Semiconductor, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include + +/* nothing really to do with interrupts, just starts up a counter. */ +int interrupt_init(void) +{ + return 0; +} + +void reset_cpu(ulong addr) +{ + __REG16(WDOG1_BASE_ADDR) = 4; +} diff --git a/cpu/arm_cortexa8/mx50/iomux.c b/cpu/arm_cortexa8/mx50/iomux.c new file mode 100644 index 0000000..66f1bf7 --- /dev/null +++ b/cpu/arm_cortexa8/mx50/iomux.c @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include + +/*! + * IOMUX register (base) addresses + */ +enum iomux_reg_addr { + IOMUXGPR0 = IOMUXC_BASE_ADDR, + IOMUXGPR1 = IOMUXC_BASE_ADDR + 0x004, + IOMUXGPR2 = IOMUXC_BASE_ADDR + 0x008, + IOMUXSW_MUX_CTL = IOMUXC_BASE_ADDR, + IOMUXSW_MUX_END = IOMUXC_BASE_ADDR + MUX_I_END, + IOMUXSW_PAD_CTL = IOMUXC_BASE_ADDR + PAD_I_START, + IOMUXSW_INPUT_CTL = IOMUXC_BASE_ADDR + INPUT_CTL_START, +}; + +static inline u32 _get_mux_reg(iomux_pin_name_t pin) +{ + u32 mux_reg = PIN_TO_IOMUX_MUX(pin); + + mux_reg += IOMUXSW_MUX_CTL; + + return mux_reg; +} + +static inline u32 _get_pad_reg(iomux_pin_name_t pin) +{ + u32 pad_reg = PIN_TO_IOMUX_PAD(pin); + + pad_reg += IOMUXSW_PAD_CTL; + + return pad_reg; +} + +static inline u32 _get_mux_end(void) +{ + return IOMUXSW_MUX_END; +} + +/*! + * This function is used to configure a pin through the IOMUX module. + * FIXED ME: for backward compatible. Will be static function! + * @param pin a pin number as defined in \b #iomux_pin_name_t + * @param cfg an output function as defined in \b #iomux_pin_cfg_t + * + * @return 0 if successful; Non-zero otherwise + */ +static int iomux_config_mux(iomux_pin_name_t pin, iomux_pin_cfg_t cfg) +{ + u32 mux_reg = _get_mux_reg(pin); + + if ((mux_reg > _get_mux_end()) || (mux_reg < IOMUXSW_MUX_CTL)) + return -1; + if (cfg == IOMUX_CONFIG_GPIO) + writel(PIN_TO_ALT_GPIO(pin), mux_reg); + else + writel(cfg, mux_reg); + + return 0; +} + +/*! + * Request ownership for an IO pin. This function has to be the first one + * being called before that pin is used. The caller has to check the + * return value to make sure it returns 0. + * + * @param pin a name defined by \b iomux_pin_name_t + * @param cfg an input function as defined in \b #iomux_pin_cfg_t + * + * @return 0 if successful; Non-zero otherwise + */ +int mxc_request_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t cfg) +{ + int ret = iomux_config_mux(pin, cfg); + + return ret; +} + +/*! + * Release ownership for an IO pin + * + * @param pin a name defined by \b iomux_pin_name_t + * @param cfg an input function as defined in \b #iomux_pin_cfg_t + */ +void mxc_free_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t cfg) +{ +} + +/*! + * This function configures the pad value for a IOMUX pin. + * + * @param pin a pin number as defined in \b #iomux_pin_name_t + * @param config the ORed value of elements defined in \b #iomux_pad_config_t + */ +void mxc_iomux_set_pad(iomux_pin_name_t pin, u32 config) +{ + u32 pad_reg = _get_pad_reg(pin); + + writel(config, pad_reg); +} + +unsigned int mxc_iomux_get_pad(iomux_pin_name_t pin) +{ + u32 pad_reg = _get_pad_reg(pin); + + return readl(pad_reg); +} +/*! + * This function configures input path. + * + * @param input index of input select register as defined in \b + * #iomux_input_select_t + * @param config the binary value of elements defined in \b + * #iomux_input_config_t + */ +void mxc_iomux_set_input(iomux_input_select_t input, u32 config) +{ + u32 reg = IOMUXSW_INPUT_CTL + (input << 2); + + writel(config, reg); +} diff --git a/cpu/arm_cortexa8/mx50/serial.c b/cpu/arm_cortexa8/mx50/serial.c new file mode 100644 index 0000000..a0cef25 --- /dev/null +++ b/cpu/arm_cortexa8/mx50/serial.c @@ -0,0 +1,226 @@ +/* + * (c) 2007 Sascha Hauer + * + * Copyright (C) 2010 Freescale Semiconductor, Inc. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include + +#if defined CONFIG_MX50_UART + +#include + +#ifdef CONFIG_MX50_UART1 +#define UART_PHYS UART1_BASE_ADDR +#elif defined(CONFIG_MX50_UART2) +#define UART_PHYS UART2_BASE_ADDR +#elif defined(CONFIG_MX50_UART3) +#define UART_PHYS UART3_BASE_ADDR +#else +#error "define CFG_MX50_UARTx to use the mx50 UART driver" +#endif + +/* Register definitions */ +#define URXD 0x0 /* Receiver Register */ +#define UTXD 0x40 /* Transmitter Register */ +#define UCR1 0x80 /* Control Register 1 */ +#define UCR2 0x84 /* Control Register 2 */ +#define UCR3 0x88 /* Control Register 3 */ +#define UCR4 0x8c /* Control Register 4 */ +#define UFCR 0x90 /* FIFO Control Register */ +#define USR1 0x94 /* Status Register 1 */ +#define USR2 0x98 /* Status Register 2 */ +#define UESC 0x9c /* Escape Character Register */ +#define UTIM 0xa0 /* Escape Timer Register */ +#define UBIR 0xa4 /* BRM Incremental Register */ +#define UBMR 0xa8 /* BRM Modulator Register */ +#define UBRC 0xac /* Baud Rate Count Register */ +#define UTS 0xb4 /* UART Test Register (mx31) */ + +/* UART Control Register Bit Fields.*/ +#define URXD_CHARRDY (1<<15) +#define URXD_ERR (1<<14) +#define URXD_OVRRUN (1<<13) +#define URXD_FRMERR (1<<12) +#define URXD_BRK (1<<11) +#define URXD_PRERR (1<<10) +#define UCR1_ADEN (1<<15) /* Auto dectect interrupt */ +#define UCR1_ADBR (1<<14) /* Auto detect baud rate */ +#define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */ +#define UCR1_IDEN (1<<12) /* Idle condition interrupt */ +#define UCR1_RRDYEN (1<<9) /* Recv ready interrupt enable */ +#define UCR1_RDMAEN (1<<8) /* Recv ready DMA enable */ +#define UCR1_IREN (1<<7) /* Infrared interface enable */ +#define UCR1_TXMPTYEN (1<<6) /* Transimitter empty interrupt enable */ +#define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */ +#define UCR1_SNDBRK (1<<4) /* Send break */ +#define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */ +#define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */ +#define UCR1_DOZE (1<<1) /* Doze */ +#define UCR1_UARTEN (1<<0) /* UART enabled */ +#define UCR2_ESCI (1<<15) /* Escape seq interrupt enable */ +#define UCR2_IRTS (1<<14) /* Ignore RTS pin */ +#define UCR2_CTSC (1<<13) /* CTS pin control */ +#define UCR2_CTS (1<<12) /* Clear to send */ +#define UCR2_ESCEN (1<<11) /* Escape enable */ +#define UCR2_PREN (1<<8) /* Parity enable */ +#define UCR2_PROE (1<<7) /* Parity odd/even */ +#define UCR2_STPB (1<<6) /* Stop */ +#define UCR2_WS (1<<5) /* Word size */ +#define UCR2_RTSEN (1<<4) /* Request to send interrupt enable */ +#define UCR2_TXEN (1<<2) /* Transmitter enabled */ +#define UCR2_RXEN (1<<1) /* Receiver enabled */ +#define UCR2_SRST (1<<0) /* SW reset */ +#define UCR3_DTREN (1<<13) /* DTR interrupt enable */ +#define UCR3_PARERREN (1<<12) /* Parity enable */ +#define UCR3_FRAERREN (1<<11) /* Frame error interrupt enable */ +#define UCR3_DSR (1<<10) /* Data set ready */ +#define UCR3_DCD (1<<9) /* Data carrier detect */ +#define UCR3_RI (1<<8) /* Ring indicator */ +#define UCR3_TIMEOUTEN (1<<7) /* Timeout interrupt enable */ +#define UCR3_RXDSEN (1<<6) /* Receive status interrupt enable */ +#define UCR3_AIRINTEN (1<<5) /* Async IR wake interrupt enable */ +#define UCR3_AWAKEN (1<<4) /* Async wake interrupt enable */ +#define UCR3_REF25 (1<<3) /* Ref freq 25 MHz */ +#define UCR3_REF30 (1<<2) /* Ref Freq 30 MHz */ +#define UCR3_INVT (1<<1) /* Inverted Infrared transmission */ +#define UCR3_BPEN (1<<0) /* Preset registers enable */ +#define UCR4_CTSTL_32 (32<<10) /* CTS trigger level (32 chars) */ +#define UCR4_INVR (1<<9) /* Inverted infrared reception */ +#define UCR4_ENIRI (1<<8) /* Serial infrared interrupt enable */ +#define UCR4_WKEN (1<<7) /* Wake interrupt enable */ +#define UCR4_REF16 (1<<6) /* Ref freq 16 MHz */ +#define UCR4_IRSC (1<<5) /* IR special case */ +#define UCR4_TCEN (1<<3) /* Transmit complete interrupt enable */ +#define UCR4_BKEN (1<<2) /* Break condition interrupt enable */ +#define UCR4_OREN (1<<1) /* Receiver overrun interrupt enable */ +#define UCR4_DREN (1<<0) /* Recv data ready interrupt enable */ +#define UFCR_RXTL_SHF 0 /* Receiver trigger level shift */ +#define UFCR_RFDIV (7<<7) /* Reference freq divider mask */ +#define UFCR_TXTL_SHF 10 /* Transmitter trigger level shift */ +#define USR1_PARITYERR (1<<15) /* Parity error interrupt flag */ +#define USR1_RTSS (1<<14) /* RTS pin status */ +#define USR1_TRDY (1<<13)/* Transmitter ready interrupt/dma flag */ +#define USR1_RTSD (1<<12) /* RTS delta */ +#define USR1_ESCF (1<<11) /* Escape seq interrupt flag */ +#define USR1_FRAMERR (1<<10) /* Frame error interrupt flag */ +#define USR1_RRDY (1<<9) /* Receiver ready interrupt/dma flag */ +#define USR1_TIMEOUT (1<<7) /* Receive timeout interrupt status */ +#define USR1_RXDS (1<<6) /* Receiver idle interrupt flag */ +#define USR1_AIRINT (1<<5) /* Async IR wake interrupt flag */ +#define USR1_AWAKE (1<<4) /* Aysnc wake interrupt flag */ +#define USR2_ADET (1<<15) /* Auto baud rate detect complete */ +#define USR2_TXFE (1<<14) /* Transmit buffer FIFO empty */ +#define USR2_DTRF (1<<13) /* DTR edge interrupt flag */ +#define USR2_IDLE (1<<12) /* Idle condition */ +#define USR2_IRINT (1<<8) /* Serial infrared interrupt flag */ +#define USR2_WAKE (1<<7) /* Wake */ +#define USR2_RTSF (1<<4) /* RTS edge interrupt flag */ +#define USR2_TXDC (1<<3) /* Transmitter complete */ +#define USR2_BRCD (1<<2) /* Break condition */ +#define USR2_ORE (1<<1) /* Overrun error */ +#define USR2_RDR (1<<0) /* Recv data ready */ +#define UTS_FRCPERR (1<<13) /* Force parity error */ +#define UTS_LOOP (1<<12) /* Loop tx and rx */ +#define UTS_TXEMPTY (1<<6) /* TxFIFO empty */ +#define UTS_RXEMPTY (1<<5) /* RxFIFO empty */ +#define UTS_TXFULL (1<<4) /* TxFIFO full */ +#define UTS_RXFULL (1<<3) /* RxFIFO full */ +#define UTS_SOFTRST (1<<0) /* Software reset */ + +DECLARE_GLOBAL_DATA_PTR; + +void serial_setbrg(void) +{ + u32 clk = mxc_get_clock(MXC_UART_CLK); + + if (!gd->baudrate) + gd->baudrate = CONFIG_BAUDRATE; + __REG(UART_PHYS + UFCR) = 0x4 << 7; /* divide input clock by 2 */ + __REG(UART_PHYS + UBIR) = 0xf; + __REG(UART_PHYS + UBMR) = clk / (2 * gd->baudrate); +} + +int serial_getc(void) +{ + while (__REG(UART_PHYS + UTS) & UTS_RXEMPTY) + ; + return __REG(UART_PHYS + URXD); +} + +void serial_putc(const char c) +{ + __REG(UART_PHYS + UTXD) = c; + + /* wait for transmitter to be ready */ + while (!(__REG(UART_PHYS + UTS) & UTS_TXEMPTY)) + ; + + /* If \n, also do \r */ + if (c == '\n') + serial_putc('\r'); +} + +/* + * Test whether a character is in the RX buffer + */ +int serial_tstc(void) +{ + /* If receive fifo is empty, return false */ + if (__REG(UART_PHYS + UTS) & UTS_RXEMPTY) + return 0; + return 1; +} + +void serial_puts(const char *s) +{ + while (*s) + serial_putc(*s++); +} + +/* + * Initialise the serial port with the given baudrate. The settings + * are always 8 data bits, no parity, 1 stop bit, no start bits. + * + */ +int serial_init(void) +{ + __REG(UART_PHYS + UCR1) = 0x0; + __REG(UART_PHYS + UCR2) = 0x0; + + while (!(__REG(UART_PHYS + UCR2) & UCR2_SRST)) + ; + + __REG(UART_PHYS + UCR3) = 0x0704; + __REG(UART_PHYS + UCR4) = 0x8000; + __REG(UART_PHYS + UESC) = 0x002b; + __REG(UART_PHYS + UTIM) = 0x0; + + __REG(UART_PHYS + UTS) = 0x0; + + serial_setbrg(); + + __REG(UART_PHYS + UCR2) = + UCR2_WS | UCR2_IRTS | UCR2_RXEN | UCR2_TXEN | UCR2_SRST; + + __REG(UART_PHYS + UCR1) = UCR1_UARTEN; + + return 0; +} + +#endif /* CONFIG_MX50_UART */ diff --git a/cpu/arm_cortexa8/mx50/timer.c b/cpu/arm_cortexa8/mx50/timer.c new file mode 100644 index 0000000..00150ab --- /dev/null +++ b/cpu/arm_cortexa8/mx50/timer.c @@ -0,0 +1,127 @@ +/* + * (C) Copyright 2007 + * Sascha Hauer, Pengutronix + * + * Copyright (C) 2010 Freescale Semiconductor, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include + +/* General purpose timers registers */ +#define GPTCR __REG(GPT1_BASE_ADDR) /* Control register */ +#define GPTPR __REG(GPT1_BASE_ADDR + 0x4) /* Prescaler register */ +#define GPTSR __REG(GPT1_BASE_ADDR + 0x8) /* Status register */ +#define GPTCNT __REG(GPT1_BASE_ADDR + 0x24) /* Counter register */ + +/* General purpose timers bitfields */ +#define GPTCR_SWR (1<<15) /* Software reset */ +#define GPTCR_FRR (1<<9) /* Freerun / restart */ +#define GPTCR_CLKSOURCE_32 (0x100<<6) /* Clock source */ +#define GPTCR_CLKSOURCE_IPG (0x001<<6) /* Clock source */ +#define GPTCR_TEN (1) /* Timer enable */ +#define GPTPR_VAL (50) + +static inline void setup_gpt(void) +{ + int i; + static int init_done; + + if (init_done) + return; + + init_done = 1; + + /* setup GP Timer 1 */ + GPTCR = GPTCR_SWR; + for (i = 0; i < 100; i++) + GPTCR = 0; /* We have no udelay by now */ + GPTPR = GPTPR_VAL; /* 50Mhz / 50 */ + /* Freerun Mode, PERCLK1 input */ + GPTCR |= GPTCR_CLKSOURCE_IPG | GPTCR_TEN; +} + +int timer_init(void) +{ + setup_gpt(); + + return 0; +} + +void reset_timer_masked(void) +{ + GPTCR = 0; + /* Freerun Mode, PERCLK1 input */ + GPTCR = GPTCR_CLKSOURCE_IPG | GPTCR_TEN; +} + +inline ulong get_timer_masked(void) +{ + ulong val = GPTCNT; + + return val; +} + +void reset_timer(void) +{ + reset_timer_masked(); +} + +ulong get_timer(ulong base) +{ + ulong tmp; + + tmp = get_timer_masked(); + + if (tmp <= (base * 1000)) { + /* Overflow */ + tmp += (0xffffffff - base); + } + + return (tmp / 1000) - base; +} + +void set_timer(ulong t) +{ +} + +/* delay x useconds AND perserve advance timstamp value */ +/* GPTCNT is now supposed to tick 1 by 1 us. */ +void udelay(unsigned long usec) +{ + ulong tmp; + + setup_gpt(); + + tmp = get_timer_masked(); /* get current timestamp */ + + /* if setting this forward will roll time stamp */ + if ((usec + tmp + 1) < tmp) { + /* reset "advancing" timestamp to 0, set lastinc value */ + reset_timer_masked(); + } else { + /* else, set advancing stamp wake up time */ + tmp += usec; + } + + while (get_timer_masked() < tmp) /* loop till event */ + /*NOP*/; +} -- cgit v1.1