diff options
Diffstat (limited to 'cpu')
-rw-r--r-- | cpu/arm_cortexa8/mx6/Makefile | 48 | ||||
-rw-r--r-- | cpu/arm_cortexa8/mx6/crm_regs.h | 530 | ||||
-rw-r--r-- | cpu/arm_cortexa8/mx6/generic.c | 788 | ||||
-rw-r--r-- | cpu/arm_cortexa8/mx6/interrupts.c | 39 | ||||
-rw-r--r-- | cpu/arm_cortexa8/mx6/iomux-v3.c | 76 | ||||
-rw-r--r-- | cpu/arm_cortexa8/mx6/timer.c | 181 |
6 files changed, 1662 insertions, 0 deletions
diff --git a/cpu/arm_cortexa8/mx6/Makefile b/cpu/arm_cortexa8/mx6/Makefile new file mode 100644 index 0000000..2a4337a --- /dev/null +++ b/cpu/arm_cortexa8/mx6/Makefile @@ -0,0 +1,48 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2011 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 generic.o iomux-v3.o timer.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/mx6/crm_regs.h b/cpu/arm_cortexa8/mx6/crm_regs.h new file mode 100644 index 0000000..71e249b --- /dev/null +++ b/cpu/arm_cortexa8/mx6/crm_regs.h @@ -0,0 +1,530 @@ +/* + * Copyright (C) 2010-2011 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_MX6_CRM_REGS_H__ +#define __ARCH_ARM_MACH_MX6_CRM_REGS_H__ + +#define MXC_CCM_BASE CCM_BASE_ADDR + +/* Register addresses of CCM*/ +#define MXC_CCM_CCR (MXC_CCM_BASE + 0x00) +#define MXC_CCM_CCDR (MXC_CCM_BASE + 0x04) +#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) +#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) +#define MXC_CCM_CHSCDR (MXC_CCM_BASE + 0x34) +#define MXC_CCM_CSCDR2 (MXC_CCM_BASE + 0x38) +#define MXC_CCM_CSCDR3 (MXC_CCM_BASE + 0x3C) +#define MXC_CCM_CSCDR4 (MXC_CCM_BASE + 0x40) +#define MXC_CCM_CWDR (MXC_CCM_BASE + 0x44) +#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) +#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 + 0x80) +#define MXC_CCM_CMEOR (MXC_CCM_BASE + 0x88) + +/* Define the bits in register CCR */ +#define MXC_CCM_CCR_RBC_EN (1 << 27) +#define MXC_CCM_CCR_REG_BYPASS_CNT_MASK (0x3F << 21) +#define MXC_CCM_CCR_REG_BYPASS_CNT_OFFSET (21) +#define MXC_CCM_CCR_WB_COUNT_MASK (0x7) +#define MXC_CCM_CCR_WB_COUNT_OFFSET (1 << 16) +#define MXC_CCM_CCR_COSC_EN (1 << 12) +#define MXC_CCM_CCR_OSCNT_MASK (0xFF) +#define MXC_CCM_CCR_OSCNT_OFFSET (0) + +/* Define the bits in register CCDR */ +#define MXC_CCM_CCDR_MMDC_CH1_HS_MASK (1 << 16) +#define MXC_CCM_CCDR_MMDC_CH0_HS_MASK (1 << 17) + +/* Define the bits in register CSR */ +#define MXC_CCM_CSR_COSC_READY (1 << 5) +#define MXC_CCM_CSR_REF_EN_B (1 << 0) + +/* Define the bits in register CCSR */ +#define MXC_CCM_CCSR_PDF_540M_AUTO_DIS (1 << 15) +#define MXC_CCM_CCSR_PDF_720M_AUTO_DIS (1 << 14) +#define MXC_CCM_CCSR_PDF_454M_AUTO_DIS (1 << 13) +#define MXC_CCM_CCSR_PDF_508M_AUTO_DIS (1 << 12) +#define MXC_CCM_CCSR_PDF_594M_AUTO_DIS (1 << 11) +#define MXC_CCM_CCSR_PDF_352M_AUTO_DIS (1 << 10) +#define MXC_CCM_CCSR_PDF_400M_AUTO_DIS (1 << 9) +#define MXC_CCM_CCSR_STEP_SEL (1 << 8) +#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_PERIPH_CLK2_PODF_MASK (0x7 << 27) +#define MXC_CCM_CBCDR_PERIPH_CLK2_PODF_OFFSET (27) +#define MXC_CCM_CBCDR_PERIPH2_CLK2_SEL (1 << 26) +#define MXC_CCM_CBCDR_PERIPH_CLK_SEL (1 << 25) +#define MXC_CCM_CBCDR_MMDC_CH0_PODF_MASK (0x7 << 19) +#define MXC_CCM_CBCDR_MMDC_CH0_PODF_OFFSET (19) +#define MXC_CCM_CBCDR_AXI_PODF_MASK (0x7 << 16) +#define MXC_CCM_CBCDR_AXI_PODF_OFFSET (16) +#define MXC_CCM_CBCDR_AHB_PODF_MASK (0x7 << 10) +#define MXC_CCM_CBCDR_AHB_PODF_OFFSET (10) +#define MXC_CCM_CBCDR_IPG_PODF_MASK (0x3 << 8) +#define MXC_CCM_CBCDR_IPG_PODF_OFFSET (8) +#define MXC_CCM_CBCDR_AXI_ALT_SEL (1 << 7) +#define MXC_CCM_CBCDR_AXI_SEL (1 << 6) +#define MXC_CCM_CBCDR_MMDC_CH1_PODF_MASK (0x7 << 3) +#define MXC_CCM_CBCDR_MMDC_CH1_PODF_OFFSET (3) +#define MXC_CCM_CBCDR_PERIPH2_CLK2_PODF_MASK (0x7 << 0) +#define MXC_CCM_CBCDR_PERIPH2_CLK2_PODF_OFFSET (0) + +/* Define the bits in register CBCMR */ +#define MXC_CCM_CBCMR_GPU3D_SHADER_PODF_MASK (0x7 << 29) +#define MXC_CCM_CBCMR_GPU3D_SHADER_PODF_OFFSET (29) +#define MXC_CCM_CBCMR_GPU3D_CORE_PODF_MASK (0x7 << 26) +#define MXC_CCM_CBCMR_GPU3D_CORE_PODF_OFFSET (26) +#define MXC_CCM_CBCMR_GPU2D_CORE_PODF_MASK (0x7 << 23) +#define MXC_CCM_CBCMR_GPU2D_CORE_PODF_OFFSET (23) +#define MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_MASK (0x3 << 21) +#define MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_OFFSET (21) +#define MXC_CCM_CBCMR_PRE_PERIPH2_CLK2_SEL (1 << 20) +#define MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK (0x3 << 18) +#define MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET (18) +#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK (0x3 << 16) +#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET (16) +#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK (0x3 << 14) +#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET (14) +#define MXC_CCM_CBCMR_PERIPH_CLK2_SEL_MASK (0x3 << 12) +#define MXC_CCM_CBCMR_PERIPH_CLK2_SEL_OFFSET (12) +#define MXC_CCM_CBCMR_VDOAXI_CLK_SEL (1 << 11) +#define MXC_CCM_CBCMR_PCIE_AXI_CLK_SEL (1 << 10) +#define MXC_CCM_CBCMR_GPU3D_SHADER_CLK_SEL_MASK (0x3 << 8) +#define MXC_CCM_CBCMR_GPU3D_SHADER_CLK_SEL_OFFSET (8) +#define MXC_CCM_CBCMR_GPU3D_CORE_CLK_SEL_MASK (0x3 << 4) +#define MXC_CCM_CBCMR_GPU3D_CORE_CLK_SEL_OFFSET (4) +#define MXC_CCM_CBCMR_GPU3D_AXI_CLK_SEL (1 << 1) +#define MXC_CCM_CBCMR_GPU2D_AXI_CLK_SEL (1 << 0) + +/* Define the bits in register CSCMR1 */ +#define MXC_CCM_CSCMR1_ACLK_EMI_SLOW_MASK (0x3 << 29) +#define MXC_CCM_CSCMR1_ACLK_EMI_SLOW_OFFSET (29) +#define MXC_CCM_CSCMR1_ACLK_EMI_MASK (0x3 << 27) +#define MXC_CCM_CSCMR1_ACLK_EMI_OFFSET (27) +#define MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_MASK (0x7 << 23) +#define MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_OFFSET (23) +#define MXC_CCM_CSCMR1_ACLK_EMI_PODF_MASK (0x7 << 20) +#define MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET (20) +#define MXC_CCM_CSCMR1_USDHC4_CLK_SEL (1 << 19) +#define MXC_CCM_CSCMR1_USDHC3_CLK_SEL (1 << 18) +#define MXC_CCM_CSCMR1_USDHC2_CLK_SEL (1 << 17) +#define MXC_CCM_CSCMR1_USDHC1_CLK_SEL (1 << 16) +#define MXC_CCM_CSCMR1_SSI3_CLK_SEL_MASK (0x3 << 14) +#define MXC_CCM_CSCMR1_SSI3_CLK_SEL_OFFSET (14) +#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK (0x3 << 12) +#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET (12) +#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK (0x3 << 10) +#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET (10) +#define MXC_CCM_CSCMR1_PERCLK_PODF_MASK (0x3F) + +/* Define the bits in register CSCMR2 */ +#define MXC_CCM_CSCMR2_ESAI_PRE_SEL_MASK (0x3 << 19) +#define MXC_CCM_CSCMR2_ESAI_PRE_SEL_OFFSET (19) +#define MXC_CCM_CSCMR2_LDB_DI1_IPU_DIV (1 << 11) +#define MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV (1 << 10) +#define MXC_CCM_CSCMR2_CAN_CLK_SEL_MASK (0x3F << 2) +#define MXC_CCM_CSCMR2_CAN_CLK_SEL_OFFSET (2) + +/* Define the bits in register CSCDR1 */ +#define MXC_CCM_CSCDR1_VPU_AXI_PODF_MASK (0x7 << 25) +#define MXC_CCM_CSCDR1_VPU_AXI_PODF_OFFSET (25) +#define MXC_CCM_CSCDR1_USDHC4_PODF_MASK (0x7 << 22) +#define MXC_CCM_CSCDR1_USDHC4_PODF_OFFSET (22) +#define MXC_CCM_CSCDR1_USDHC3_PODF_MASK (0x7 << 19) +#define MXC_CCM_CSCDR1_USDHC3_PODF_OFFSET (19) +#define MXC_CCM_CSCDR1_USDHC2_PODF_MASK (0x7 << 16) +#define MXC_CCM_CSCDR1_USDHC2_PODF_OFFSET (16) +#define MXC_CCM_CSCDR1_USDHC1_PODF_MASK (0x7 << 11) +#define MXC_CCM_CSCDR1_USDHC1_PODF_OFFSET (11) +#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET (8) +#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK (0x7 << 8) +#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET (6) +#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK (0x3 << 6) +#define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK (0x3F) +#define MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET (0) + +/* Define the bits in register CS1CDR */ +#define MXC_CCM_CS1CDR_ESAI_CLK_PODF_MASK (0x3F << 25) +#define MXC_CCM_CS1CDR_ESAI_CLK_PODF_OFFSET (25) +#define MXC_CCM_CS1CDR_SSI3_CLK_PODF_MASK (0x3F << 16) +#define MXC_CCM_CS1CDR_SSI3_CLK_PODF_OFFSET (16) +#define MXC_CCM_CS1CDR_ESAI_CLK_PRED_MASK (0x3 << 9) +#define MXC_CCM_CS1CDR_ESAI_CLK_PRED_OFFSET (9) +#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK (0x7 << 6) +#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET (6) +#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK (0x3F) +#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET (0) + +/* Define the bits in register CS2CDR */ +#define MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK (0x3F << 21) +#define MXC_CCM_CS2CDR_ENFC_CLK_PODF_OFFSET (21) +#define MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK (0x7 << 18) +#define MXC_CCM_CS2CDR_ENFC_CLK_PRED_OFFSET (18) +#define MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK (0x3 << 16) +#define MXC_CCM_CS2CDR_ENFC_CLK_SEL_OFFSET (16) +#define MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK (0x7 << 12) +#define MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET (12) +#define MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK (0x7 << 9) +#define MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET (9) +#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK (0x7 << 6) +#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET (6) +#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK (0x3F) +#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET (0) + +/* Define the bits in register CDCDR */ +#define MXC_CCM_CDCDR_HSI_TX_PODF_MASK (0x7 << 29) +#define MXC_CCM_CDCDR_HSI_TX_PODF_OFFSET (29) +#define MXC_CCM_CDCDR_HSI_TX_CLK_SEL (1 << 28) +#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK (0x7 << 25) +#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET (25) +#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK (0x7 << 19) +#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET (19) +#define MXC_CCM_CDCDR_SPDIF0_CLK_SEL_MASK (0x3 << 20) +#define MXC_CCM_CDCDR_SPDIF0_CLK_SEL_OFFSET (20) +#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK (0x7 << 12) +#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET (12) +#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK (0x7 << 9) +#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET (9) +#define MXC_CCM_CDCDR_SPDIF1_CLK_SEL_MASK (0x3 << 7) +#define MXC_CCM_CDCDR_SPDIF1_CLK_SEL_OFFSET (7) + +/* Define the bits in register CHSCCDR */ +#define MXC_CCM_CHSCCDR_IPU1_DI1_PRE_CLK_SEL_MASK (0x7 << 15) +#define MXC_CCM_CHSCCDR_IPU1_DI1_PRE_CLK_SEL_OFFSET (15) +#define MXC_CCM_CHSCCDR_IPU1_DI1_PODF_MASK (0x7 << 12) +#define MXC_CCM_CHSCCDR_IPU1_DI1_PODF_OFFSET (12) +#define MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_MASK (0x7 << 9) +#define MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_OFFSET (9) +#define MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK (0x7 << 6) +#define MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET (6) +#define MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK (0x7 << 3) +#define MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET (3) +#define MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK (0x7) +#define MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET (0) + +/* Define the bits in register CSCDR2 */ +#define MXC_CCM_CSCDR2_ECSPI_CLK_PODF_MASK (0x3F << 19) +#define MXC_CCM_CSCDR2_ECSPI_CLK_PODF_OFFSET (19) +#define MXC_CCM_CHSCCDR_IPU2_DI1_PRE_CLK_SEL_MASK (0x7 << 15) +#define MXC_CCM_CHSCCDR_IPU2_DI1_PRE_CLK_SEL_OFFSET (15) +#define MXC_CCM_CHSCCDR_IPU2_DI1_PODF_MASK (0x7 << 12) +#define MXC_CCM_CHSCCDR_IPU2_DI1_PODF_OFFSET (12) +#define MXC_CCM_CHSCCDR_IPU2_DI1_CLK_SEL_MASK (0x7 << 9) +#define MXC_CCM_CHSCCDR_IPU2_DI1_CLK_SEL_OFFSET (9) +#define MXC_CCM_CHSCCDR_IPU2_DI0_PRE_CLK_SEL_MASK (0x7 << 6) +#define MXC_CCM_CHSCCDR_IPU2_DI0_PRE_CLK_SEL_OFFSET (6) +#define MXC_CCM_CHSCCDR_IPU2_DI0_PODF_MASK (0x7 << 3) +#define MXC_CCM_CHSCCDR_IPU2_DI0_PODF_OFFSET (3) +#define MXC_CCM_CHSCCDR_IPU2_DI0_CLK_SEL_MASK (0x7) +#define MXC_CCM_CHSCCDR_IPU2_DI0_CLK_SEL_OFFSET (0) + +/* Define the bits in register CSCDR3 */ +#define MXC_CCM_CSCDR3_IPU2_HSP_PODF_MASK (0x7 << 16) +#define MXC_CCM_CSCDR3_IPU2_HSP_PODF_OFFSET (16) +#define MXC_CCM_CSCDR3_IPU2_HSP_CLK_SEL_MASK (0x3 << 14) +#define MXC_CCM_CSCDR3_IPU2_HSP_CLK_SEL_OFFSET (14) +#define MXC_CCM_CSCDR3_IPU1_HSP_PODF_MASK (0x7 << 11) +#define MXC_CCM_CSCDR3_IPU1_HSP_PODF_OFFSET (11) +#define MXC_CCM_CSCDR3_IPU1_HSP_CLK_SEL_MASK (0x3 << 9) +#define MXC_CCM_CSCDR3_IPU1_HSP_CLK_SEL_OFFSET (9) + +/* Define the bits in register CDHIPR */ +#define MXC_CCM_CDHIPR_ARM_PODF_BUSY (1 << 16) +#define MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY (1 << 5) +#define MXC_CCM_CDHIPR_MMDC_CH0_PODF_BUSY (1 << 4) +#define MXC_CCM_CDHIPR_PERIPH2_CLK_SEL_BUSY (1 << 3) +#define MXC_CCM_CDHIPR_MMDC_CH1_PODF_BUSY (1 << 2) +#define MXC_CCM_CDHIPR_AHB_PODF_BUSY (1 << 1) +#define MXC_CCM_CDHIPR_AXI_PODF_BUSY (1) + +/* Define the bits in register CLPCR */ +#define MXC_CCM_CLPCR_MASK_L2CC_IDLE (1 << 27) +#define MXC_CCM_CLPCR_MASK_SCU_IDLE (1 << 26) +#define MXC_CCM_CLPCR_MASK_CORE3_WFI (1 << 25) +#define MXC_CCM_CLPCR_MASK_CORE2_WFI (1 << 24) +#define MXC_CCM_CLPCR_MASK_CORE1_WFI (1 << 23) +#define MXC_CCM_CLPCR_MASK_CORE0_WFI (1 << 22) +#define MXC_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS (1 << 21) +#define MXC_CCM_CLPCR_BYP_MMDC_CH0_LPM_HS (1 << 19) +#define MXC_CCM_CLPCR_WB_CORE_AT_LPM (1 << 17) +#define MXC_CCM_CLPCR_WB_PER_AT_LPM (1 << 17) +#define MXC_CCM_CLPCR_COSC_PWRDOWN (1 << 11) +#define MXC_CCM_CLPCR_STBY_COUNT_MASK (0x3 << 9) +#define MXC_CCM_CLPCR_STBY_COUNT_OFFSET (9) +#define MXC_CCM_CLPCR_VSTBY (1 << 8) +#define MXC_CCM_CLPCR_DIS_REF_OSC (1 << 7) +#define MXC_CCM_CLPCR_SBYOS (1 << 6) +#define MXC_CCM_CLPCR_ARM_CLK_DIS_ON_LPM (1 << 5) +#define MXC_CCM_CLPCR_LPSR_CLK_SEL_MASK (0x3 << 3) +#define MXC_CCM_CLPCR_LPSR_CLK_SEL_OFFSET (3) +#define MXC_CCM_CLPCR_BYPASS_PMIC_VFUNC_READY (1 << 2) +#define MXC_CCM_CLPCR_LPM_MASK (0x3) +#define MXC_CCM_CLPCR_LPM_OFFSET (0) + +/* Define the bits in register CISR */ +#define MXC_CCM_CISR_ARM_PODF_LOADED (1 << 26) +#define MXC_CCM_CISR_MMDC_CH0_PODF_LOADED (1 << 23) +#define MXC_CCM_CISR_PERIPH_CLK_SEL_LOADED (1 << 22) +#define MXC_CCM_CISR_MMDC_CH1_PODF_LOADED (1 << 21) +#define MXC_CCM_CISR_AHB_PODF_LOADED (1 << 20) +#define MXC_CCM_CISR_PERIPH2_CLK_SEL_LOADED (1 << 19) +#define MXC_CCM_CISR_AXI_PODF_LOADED (1 << 17) +#define MXC_CCM_CISR_COSC_READY (1 << 6) +#define MXC_CCM_CISR_LRF_PLL (1) + +/* Define the bits in register CIMR */ +#define MXC_CCM_CIMR_MASK_ARM_PODF_LOADED (1 << 26) +#define MXC_CCM_CIMR_MASK_MMDC_CH0_PODF_LOADED (1 << 23) +#define MXC_CCM_CIMR_MASK_PERIPH_CLK_SEL_LOADED (1 << 22) +#define MXC_CCM_CIMR_MASK_MMDC_CH1_PODF_LOADED (1 << 21) +#define MXC_CCM_CIMR_MASK_AHB_PODF_LOADED (1 << 20) +#define MXC_CCM_CIMR_MASK_PERIPH2_CLK_SEL_LOADED (1 << 22) +#define MXC_CCM_CIMR_MASK_AXI_PODF_LOADED (1 << 17) +#define MXC_CCM_CIMR_MASK_COSC_READY (1 << 6) +#define MXC_CCM_CIMR_MASK_LRF_PLL (1) + +/* Define the bits in register CCOSR */ +#define MXC_CCM_CCOSR_CKO2_EN_OFFSET (1 << 24) +#define MXC_CCM_CCOSR_CKO2_DIV_MASK (0x7 << 21) +#define MXC_CCM_CCOSR_CKO2_DIV_OFFSET (21) +#define MXC_CCM_CCOSR_CKO2_SEL_OFFSET (16) +#define MXC_CCM_CCOSR_CKO2_SEL_MASK (0x1F << 16) +#define MXC_CCM_CCOSR_CKOL_EN (0x1 << 7) +#define MXC_CCM_CCOSR_CKOL_DIV_MASK (0x7 << 4) +#define MXC_CCM_CCOSR_CKOL_DIV_OFFSET (4) +#define MXC_CCM_CCOSR_CKOL_SEL_MASK (0xF) +#define MXC_CCM_CCOSR_CKOL_SEL_OFFSET (0) + +/* Define the bits in registers CGPR */ +#define MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE (1 << 4) +#define MXC_CCM_CGPR_MMDC_EXT_CLK_DIS (1 << 2) +#define MXC_CCM_CGPR_PMIC_DELAY_SCALER (1) + +/* Define the bits in registers CCGRx */ +#define MXC_CCM_CCGR_CG_MASK 3 + +#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 3 + +#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_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_CG4_OFFSET 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 + +#endif /* __ARCH_ARM_MACH_MX6_CRM_REGS_H__ */ diff --git a/cpu/arm_cortexa8/mx6/generic.c b/cpu/arm_cortexa8/mx6/generic.c new file mode 100644 index 0000000..c2540e1 --- /dev/null +++ b/cpu/arm_cortexa8/mx6/generic.c @@ -0,0 +1,788 @@ +/* + * Copyright (C) 2010-2011 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 <common.h> +#include <asm/arch/mx6.h> +#include <asm/arch/regs-anadig.h> +#include <asm/errno.h> +#include <asm/io.h> +#include "crm_regs.h" +#ifdef CONFIG_CMD_CLOCK +#include <asm/clock.h> +#endif +#include <div64.h> +#ifdef CONFIG_ARCH_CPU_INIT +#include <asm/cache-cp15.h> +#endif + +enum pll_clocks { + CPU_PLL1, /* System PLL */ + BUS_PLL2, /* System Bus PLL*/ + USBOTG_PLL3, /* OTG USB PLL */ + AUD_PLL4, /* Audio PLL */ + VID_PLL5, /* Video PLL */ + MLB_PLL6, /* MLB PLL */ + USBHOST_PLL7, /* Host USB PLL */ + ENET_PLL8, /* ENET PLL */ +}; + +#define SZ_DEC_1M 1000000 + +/* Out-of-reset PFDs and clock source definitions */ +#define PLL2_PFD0_FREQ 352000000 +#define PLL2_PFD1_FREQ 594000000 +#define PLL2_PFD2_FREQ 400000000 +#define PLL2_PFD2_DIV_FREQ 200000000 +#define PLL3_PFD0_FREQ 720000000 +#define PLL3_PFD1_FREQ 540000000 +#define PLL3_PFD2_FREQ 508200000 +#define PLL3_PFD3_FREQ 454700000 +#define PLL3_80M 80000000 +#define PLL3_60M 60000000 + +#define AHB_CLK_ROOT 132000000 +#define IPG_CLK_ROOT 66000000 +#define ENET_FREQ_0 25000000 +#define ENET_FREQ_1 50000000 +#define ENET_FREQ_2 100000000 +#define ENET_FREQ_3 125000000 + +#ifdef CONFIG_CMD_CLOCK +#define PLL1_FREQ_MAX 1300000000 +#define PLL1_FREQ_MIN 650000000 +#define PLL2_FREQ_MAX 528000000 +#define PLL2_FREQ_MIN 480000000 +#define MAX_DDR_CLK PLL2_FREQ_MAX +#define AHB_CLK_MAX 132000000 +#define IPG_CLK_MAX (AHB_CLK_MAX >> 1) +#define NFC_CLK_MAX PLL2_FREQ_MAX +#endif + +static u32 __decode_pll(enum pll_clocks pll, u32 infreq) +{ + u32 div; + + switch (pll) { + case CPU_PLL1: + div = REG_RD(ANATOP_BASE_ADDR, HW_ANADIG_PLL_SYS) & + BM_ANADIG_PLL_SYS_DIV_SELECT; + return infreq * (div >> 1); + case BUS_PLL2: + div = REG_RD(ANATOP_BASE_ADDR, HW_ANADIG_PLL_528) & + BM_ANADIG_PLL_528_DIV_SELECT; + return infreq * (20 + (div << 1)); + case USBOTG_PLL3: + div = REG_RD(ANATOP_BASE_ADDR, HW_ANADIG_USB2_PLL_480_CTRL) & + BM_ANADIG_USB2_PLL_480_CTRL_DIV_SELECT; + return infreq * (20 + (div << 1)); + case ENET_PLL8: + div = REG_RD(ANATOP_BASE_ADDR, HW_ANADIG_PLL_ENET) & + BM_ANADIG_PLL_ENET_DIV_SELECT; + switch (div) { + default: + case 0: + return ENET_FREQ_0; + case 1: + return ENET_FREQ_1; + case 2: + return ENET_FREQ_2; + case 3: + return ENET_FREQ_3; + } + case AUD_PLL4: + case VID_PLL5: + case MLB_PLL6: + case USBHOST_PLL7: + default: + return 0; + } +} + +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(CPU_PLL1, CONFIG_MX6_HCLK_FREQ); + return freq / (reg + 1); +} + +static u32 __get_periph_clk(void) +{ + u32 reg; + reg = __REG(MXC_CCM_CBCDR); + if (reg & MXC_CCM_CBCDR_PERIPH_CLK_SEL) { + reg = __REG(MXC_CCM_CBCMR); + switch ((reg & MXC_CCM_CBCMR_PERIPH_CLK2_SEL_MASK) >> + MXC_CCM_CBCMR_PERIPH_CLK2_SEL_OFFSET) { + case 0: + return __decode_pll(USBOTG_PLL3, CONFIG_MX6_HCLK_FREQ); + case 1: + case 2: + return CONFIG_MX6_HCLK_FREQ; + default: + return 0; + } + } else { + reg = __REG(MXC_CCM_CBCMR); + switch ((reg & MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK) >> + MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET) { + default: + case 0: + return __decode_pll(BUS_PLL2, CONFIG_MX6_HCLK_FREQ); + case 1: + return PLL2_PFD2_FREQ; + case 2: + return PLL2_PFD0_FREQ; + case 3: + return PLL2_PFD2_DIV_FREQ; + } + } +} + +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 podf; + u32 clk_root = __get_ipg_clk(); + + podf = __REG(MXC_CCM_CSCMR1) & MXC_CCM_CSCMR1_PERCLK_PODF_MASK; + return clk_root / (podf + 1); +} + +static u32 __get_uart_clk(void) +{ + u32 freq = PLL3_80M, reg, podf; + + reg = __REG(MXC_CCM_CSCDR1); + podf = (reg & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK) >> + MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET; + freq /= (podf + 1); + + return freq; +} + + +static u32 __get_cspi_clk(void) +{ + u32 freq = PLL3_60M, reg, podf; + + reg = __REG(MXC_CCM_CSCDR2); + podf = (reg & MXC_CCM_CSCDR2_ECSPI_CLK_PODF_MASK) >> + MXC_CCM_CSCDR2_ECSPI_CLK_PODF_OFFSET; + freq /= (podf + 1); + + return freq; +} + +static u32 __get_axi_clk(void) +{ + u32 clkroot; + u32 cbcdr = __REG(MXC_CCM_CBCDR); + u32 podf = (cbcdr & MXC_CCM_CBCDR_AXI_PODF_MASK) >> + MXC_CCM_CBCDR_AXI_PODF_OFFSET; + + if (cbcdr & MXC_CCM_CBCDR_AXI_SEL) { + if (cbcdr & MXC_CCM_CBCDR_AXI_ALT_SEL) + clkroot = PLL2_PFD2_FREQ; + else + clkroot = PLL3_PFD1_FREQ;; + } else + clkroot = __get_periph_clk(); + + return clkroot / (podf + 1); +} + +static u32 __get_ahb_clk(void) +{ + u32 cbcdr = __REG(MXC_CCM_CBCDR); + u32 podf = (cbcdr & MXC_CCM_CBCDR_AHB_PODF_MASK) \ + >> MXC_CCM_CBCDR_AHB_PODF_OFFSET; + + return __get_periph_clk() / (podf + 1); +} + +static u32 __get_emi_slow_clk(void) +{ + u32 cscmr1 = __REG(MXC_CCM_CSCMR1); + u32 emi_clk_sel = (cscmr1 & MXC_CCM_CSCMR1_ACLK_EMI_SLOW_MASK) >> + MXC_CCM_CSCMR1_ACLK_EMI_SLOW_OFFSET; + u32 podf = (cscmr1 & MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_MASK) >> + MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET; + + switch (emi_clk_sel) { + default: + case 0: + return __get_axi_clk() / (podf + 1); + case 1: + return __decode_pll(USBOTG_PLL3, CONFIG_MX6_HCLK_FREQ) / + (podf + 1); + case 2: + return PLL2_PFD2_FREQ / (podf + 1); + case 3: + return PLL2_PFD0_FREQ / (podf + 1); + } +} + +static u32 __get_nfc_clk(void) +{ + u32 clkroot; + u32 cs2cdr = __REG(MXC_CCM_CS2CDR); + u32 podf = (cs2cdr & MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK) \ + >> MXC_CCM_CS2CDR_ENFC_CLK_PODF_OFFSET; + u32 pred = (cs2cdr & MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK) \ + >> MXC_CCM_CS2CDR_ENFC_CLK_PRED_OFFSET; + + switch ((cs2cdr & MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK) >> + MXC_CCM_CS2CDR_ENFC_CLK_SEL_OFFSET) { + default: + case 0: + clkroot = PLL2_PFD0_FREQ; + break; + case 1: + clkroot = __decode_pll(BUS_PLL2, CONFIG_MX6_HCLK_FREQ); + break; + case 2: + clkroot = __decode_pll(USBOTG_PLL3, CONFIG_MX6_HCLK_FREQ); + break; + case 3: + clkroot = PLL2_PFD2_FREQ; + break; + } + + return clkroot / pred / podf; +} + +static u32 __get_ddr_clk(void) +{ + u32 cbcdr = __REG(MXC_CCM_CBCDR); + u32 podf = (cbcdr & MXC_CCM_CBCDR_MMDC_CH0_PODF_MASK) >> + MXC_CCM_CBCDR_MMDC_CH0_PODF_OFFSET; + + return __get_periph_clk() / (podf + 1); +} + +static u32 __get_usdhc1_clk(void) +{ + u32 clkroot; + u32 cscmr1 = __REG(MXC_CCM_CSCMR1); + u32 cscdr1 = __REG(MXC_CCM_CSCDR1); + u32 podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC1_PODF_MASK) >> + MXC_CCM_CSCDR1_USDHC1_PODF_OFFSET; + + if (cscmr1 & MXC_CCM_CSCMR1_USDHC1_CLK_SEL) + clkroot = PLL2_PFD0_FREQ; + else + clkroot = PLL2_PFD2_FREQ; + + return clkroot / (podf + 1); +} + +static u32 __get_usdhc2_clk(void) +{ + u32 clkroot; + u32 cscmr1 = __REG(MXC_CCM_CSCMR1); + u32 cscdr1 = __REG(MXC_CCM_CSCDR1); + u32 podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC2_PODF_MASK) >> + MXC_CCM_CSCDR1_USDHC2_PODF_OFFSET; + + if (cscmr1 & MXC_CCM_CSCMR1_USDHC2_CLK_SEL) + clkroot = PLL2_PFD0_FREQ; + else + clkroot = PLL2_PFD2_FREQ; + + return clkroot / (podf + 1); +} + +static u32 __get_usdhc3_clk(void) +{ + u32 clkroot; + u32 cscmr1 = __REG(MXC_CCM_CSCMR1); + u32 cscdr1 = __REG(MXC_CCM_CSCDR1); + u32 podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC3_PODF_MASK) >> + MXC_CCM_CSCDR1_USDHC3_PODF_OFFSET; + + if (cscmr1 & MXC_CCM_CSCMR1_USDHC3_CLK_SEL) + clkroot = PLL2_PFD0_FREQ; + else + clkroot = PLL2_PFD2_FREQ; + + return clkroot / (podf + 1); +} + +static u32 __get_usdhc4_clk(void) +{ + u32 clkroot; + u32 cscmr1 = __REG(MXC_CCM_CSCMR1); + u32 cscdr1 = __REG(MXC_CCM_CSCDR1); + u32 podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC4_PODF_MASK) >> + MXC_CCM_CSCDR1_USDHC4_PODF_OFFSET; + + if (cscmr1 & MXC_CCM_CSCMR1_USDHC4_CLK_SEL) + clkroot = PLL2_PFD0_FREQ; + else + clkroot = PLL2_PFD2_FREQ; + + return clkroot / (podf + 1); +} + +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(); + case MXC_CSPI_CLK: + return __get_cspi_clk(); + case MXC_AXI_CLK: + return __get_axi_clk(); + case MXC_EMI_SLOW_CLK: + return __get_emi_slow_clk(); + case MXC_DDR_CLK: + return __get_ddr_clk(); + case MXC_ESDHC_CLK: + return __get_usdhc1_clk(); + case MXC_ESDHC2_CLK: + return __get_usdhc2_clk(); + case MXC_ESDHC3_CLK: + return __get_usdhc3_clk(); + case MXC_ESDHC4_CLK: + return __get_usdhc4_clk(); + case MXC_SATA_CLK: + return __get_ahb_clk(); + case MXC_NFC_CLK: + return __get_nfc_clk(); + default: + break; + } + return -1; +} + +void mxc_dump_clocks(void) +{ + u32 freq; + freq = __decode_pll(CPU_PLL1, CONFIG_MX6_HCLK_FREQ); + printf("mx6q pll1: %dMHz\n", freq / SZ_DEC_1M); + freq = __decode_pll(BUS_PLL2, CONFIG_MX6_HCLK_FREQ); + printf("mx6q pll2: %dMHz\n", freq / SZ_DEC_1M); + freq = __decode_pll(USBOTG_PLL3, CONFIG_MX6_HCLK_FREQ); + printf("mx6q pll3: %dMHz\n", freq / SZ_DEC_1M); + freq = __decode_pll(ENET_PLL8, CONFIG_MX6_HCLK_FREQ); + printf("mx6q pll8: %dMHz\n", freq / SZ_DEC_1M); + 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)); + printf("cspi clock : %dHz\n", mxc_get_clock(MXC_CSPI_CLK)); + printf("ahb clock : %dHz\n", mxc_get_clock(MXC_AHB_CLK)); + printf("axi clock : %dHz\n", mxc_get_clock(MXC_AXI_CLK)); + printf("emi_slow clock: %dHz\n", mxc_get_clock(MXC_EMI_SLOW_CLK)); + printf("ddr clock : %dHz\n", mxc_get_clock(MXC_DDR_CLK)); + printf("usdhc1 clock : %dHz\n", mxc_get_clock(MXC_ESDHC_CLK)); + printf("usdhc2 clock : %dHz\n", mxc_get_clock(MXC_ESDHC2_CLK)); + printf("usdhc3 clock : %dHz\n", mxc_get_clock(MXC_ESDHC3_CLK)); + printf("usdhc4 clock : %dHz\n", mxc_get_clock(MXC_ESDHC4_CLK)); + printf("nfc clock : %dHz\n", mxc_get_clock(MXC_NFC_CLK)); +} + +#ifdef CONFIG_CMD_CLOCK + +/*! + * This is to calculate divider based on reference clock and + * targeted clock based on the equation for each PLL. + * + * @param pll pll number + * @param ref reference clock freq in Hz + * @param target targeted clock in Hz + * + * @return divider if successful; -1 otherwise. + */ +static int calc_pll_divider(enum pll_clocks pll, u32 ref, u32 target) +{ + int i, div; + + switch (pll) { + case CPU_PLL1: + if (target < PLL1_FREQ_MIN || target > PLL1_FREQ_MAX) { + printf("PLL1 frequency should be" + "within [%d - %d] MHz\n", PLL1_FREQ_MIN / SZ_DEC_1M, + PLL1_FREQ_MAX / SZ_DEC_1M); + return -1; + } + for (i = 54, div = i; i < 109; i++) { + if ((ref * (i >> 1)) > target) + break; + div = i; + } + break; + case BUS_PLL2: + if (target < PLL2_FREQ_MIN || target > PLL2_FREQ_MAX) { + printf("PLL2 frequency should be" + "within [%d - %d] MHz\n", PLL2_FREQ_MIN / SZ_DEC_1M, + PLL2_FREQ_MAX / SZ_DEC_1M); + return -1; + } + for (i = 0, div = i; i < 2; i++) { + if (ref * (20 + (i << 1)) > target) + break; + div = i; + } + break; + default: + printf("Changing this PLL not supported\n"); + return -1; + break; + } + + return div; +} + +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 NFC_CLK: + printf("NFC Clock: %dHz\n", + mxc_get_clock(MXC_NFC_CLK)); + 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; +} + + + +static int config_pll_clk(enum pll_clocks pll, u32 divider) +{ + u32 ccsr = readl(CCM_BASE_ADDR + CLKCTL_CCSR); + + switch (pll) { + case CPU_PLL1: + /* Switch ARM to PLL2 clock */ + writel(ccsr | 0x4, CCM_BASE_ADDR + CLKCTL_CCSR); + + REG_CLR(ANATOP_BASE_ADDR, HW_ANADIG_PLL_SYS, + BM_ANADIG_PLL_SYS_DIV_SELECT); + REG_SET(ANATOP_BASE_ADDR, HW_ANADIG_PLL_SYS, + BF_ANADIG_PLL_SYS_DIV_SELECT(divider)); + /* Enable CPU PLL1 */ + REG_SET(ANATOP_BASE_ADDR, HW_ANADIG_PLL_SYS, + BM_ANADIG_PLL_SYS_ENABLE); + /* Wait for PLL lock */ + while (REG_RD(ANATOP_BASE_ADDR, HW_ANADIG_PLL_SYS) & + BM_ANADIG_PLL_SYS_LOCK) + udelay(10); + /* Clear bypass bit */ + REG_CLR(ANATOP_BASE_ADDR, HW_ANADIG_PLL_SYS, + BM_ANADIG_PLL_SYS_BYPASS); + + /* Switch back */ + writel(ccsr & ~0x4, CCM_BASE_ADDR + CLKCTL_CCSR); + break; + case BUS_PLL2: + /* Switch to pll2 bypass clock */ + writel(ccsr | 0x2, CCM_BASE_ADDR + CLKCTL_CCSR); + + REG_CLR(ANATOP_BASE_ADDR, HW_ANADIG_PLL_528, + BM_ANADIG_PLL_528_DIV_SELECT); + REG_SET(ANATOP_BASE_ADDR, HW_ANADIG_PLL_528, + divider); + /* Enable BUS PLL2 */ + REG_SET(ANATOP_BASE_ADDR, HW_ANADIG_PLL_528, + BM_ANADIG_PLL_528_ENABLE); + /* Wait for PLL lock */ + while (REG_RD(ANATOP_BASE_ADDR, HW_ANADIG_PLL_528) & + BM_ANADIG_PLL_528_LOCK) + udelay(10); + /* Clear bypass bit */ + REG_CLR(ANATOP_BASE_ADDR, HW_ANADIG_PLL_528, + BM_ANADIG_PLL_528_BYPASS); + + /* Switch back */ + writel(ccsr & ~0x2, CCM_BASE_ADDR + CLKCTL_CCSR); + break; + default: + return -1; + } + + return 0; +} + +static int config_core_clk(u32 ref, u32 freq) +{ + int div = calc_pll_divider(CPU_PLL1, ref, freq); + if (div < 0) { + printf("Can't find pll parameters\n"); + return div; + } + + return config_pll_clk(CPU_PLL1, div); +} + +static int config_nfc_clk(u32 nfc_clk) +{ + /* TBD */ + return -1; +} +static int config_periph_clk(u32 ref, u32 freq) +{ + u32 cbcdr = readl(CCM_BASE_ADDR + CLKCTL_CBCDR); + u32 cbcmr = readl(CCM_BASE_ADDR + CLKCTL_CBCMR); + u32 pll2_freq = __decode_pll(BUS_PLL2, CONFIG_MX6_HCLK_FREQ); + u32 pll3_freq = __decode_pll(USBOTG_PLL3, CONFIG_MX6_HCLK_FREQ); + + if (freq >= pll2_freq) { + /* PLL2 */ + writel(cbcmr & ~MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK, + CCM_BASE_ADDR + CLKCTL_CBCMR); + writel(cbcdr & ~MXC_CCM_CBCDR_PERIPH_CLK_SEL, + CCM_BASE_ADDR + CLKCTL_CBCDR); + } else if (freq < pll2_freq && freq >= pll3_freq) { + /* PLL3 */ + writel(cbcmr & ~MXC_CCM_CBCMR_PERIPH_CLK2_SEL_MASK, + CCM_BASE_ADDR + CLKCTL_CBCMR); + writel(cbcdr | MXC_CCM_CBCDR_PERIPH_CLK_SEL, + CCM_BASE_ADDR + CLKCTL_CBCDR); + } else if (freq < pll3_freq && freq >= PLL2_PFD2_FREQ) { + /* 400M PLL2 PFD */ + cbcmr = (cbcmr & ~MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK) | + (1 << MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET); + writel(cbcmr, CCM_BASE_ADDR + CLKCTL_CBCMR); + writel(cbcdr & ~MXC_CCM_CBCDR_PERIPH_CLK_SEL, + CCM_BASE_ADDR + CLKCTL_CBCDR); + } else if (freq < PLL2_PFD2_FREQ && freq >= PLL2_PFD0_FREQ) { + /* 352M PLL2 PFD */ + cbcmr = (cbcmr & ~MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK) | + (2 << MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET); + writel(cbcmr, CCM_BASE_ADDR + CLKCTL_CBCMR); + writel(cbcdr & ~MXC_CCM_CBCDR_PERIPH_CLK_SEL, + CCM_BASE_ADDR + CLKCTL_CBCDR); + } else if (freq == PLL2_PFD2_DIV_FREQ) { + /* 200M PLL2 PFD */ + cbcmr = (cbcmr & ~MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK) | + (3 << MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET); + writel(cbcmr, CCM_BASE_ADDR + CLKCTL_CBCMR); + writel(cbcdr & ~MXC_CCM_CBCDR_PERIPH_CLK_SEL, + CCM_BASE_ADDR + CLKCTL_CBCDR); + } else { + printf("Frequency requested not within range [%d-%d] MHz\n", + PLL2_PFD2_DIV_FREQ / SZ_DEC_1M, pll2_freq / SZ_DEC_1M); + return -1; + } + puts("\n"); + + return 0; +} + +static int config_ddr_clk(u32 ddr_clk) +{ + u32 clk_src = __get_periph_clk(); + u32 i, podf; + u32 cbcdr = readl(CCM_BASE_ADDR + CLKCTL_CBCDR); + + if (ddr_clk > MAX_DDR_CLK) { + printf("DDR clock should be less than" + "%d MHz, assuming max value\n", + (MAX_DDR_CLK / SZ_DEC_1M)); + ddr_clk = MAX_DDR_CLK; + } + + for (i = 1; i < 9; i++) + if ((clk_src / i) <= ddr_clk) + break; + + podf = i - 1; + + cbcdr &= ~MXC_CCM_CBCDR_MMDC_CH0_PODF_MASK; + cbcdr |= podf << MXC_CCM_CBCDR_MMDC_CH0_PODF_OFFSET; + 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 (arm_podf=0) unless the core clock is less than PLL_FREQ_MIN. + * + * @param ref pll input reference clock (24MHz) + * @param freq targeted freq 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; + case NFC_CLK: + if (config_nfc_clk(freq)) + return -1; + break; + default: + printf("Unsupported or invalid clock type! :(\n"); + return -1; + } + + return 0; +} +#endif + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{ + printf("CPU: Freescale i.MX 6 family %d.%dV at %d MHz\n", + (get_board_rev() & 0xFF) >> 4, + (get_board_rev() & 0xF), + __get_mcu_main_clk() / SZ_DEC_1M); + mxc_dump_clocks(); + 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); +void enet_board_init(void); +#endif + +int cpu_eth_init(bd_t *bis) +{ + int rc = -ENODEV; +#if defined(CONFIG_MXC_FEC) + printf("cpu_eth_init\n"); + rc = mxc_fec_initialize(bis); + + /* Set up ENET PLL for 50 MHz */ + + /* Clear power down bit */ + REG_CLR(ANATOP_BASE_ADDR, HW_ANADIG_PLL_ENET, + BM_ANADIG_PLL_ENET_POWERDOWN); + /* Set ENET clock to 50M, Anson need to check */ + REG_SET(ANATOP_BASE_ADDR, HW_ANADIG_PLL_ENET, + BF_ANADIG_PLL_ENET_DIV_SELECT(0x11)); + /* Enable ENET PLL */ + REG_SET(ANATOP_BASE_ADDR, HW_ANADIG_PLL_ENET, + BM_ANADIG_PLL_ENET_ENABLE); + printf("before while\n"); + /* Wait for PLL lock */ + while ((REG_RD(ANATOP_BASE_ADDR, HW_ANADIG_PLL_ENET) & + BM_ANADIG_PLL_ENET_LOCK) == 0) + udelay(100); + /* Clear bypass bit */ + REG_CLR(ANATOP_BASE_ADDR, HW_ANADIG_PLL_ENET, + BM_ANADIG_PLL_ENET_BYPASS); + + printf("before enent_board_init\n"); + + /* Board level init */ + enet_board_init(); + +#endif + return rc; +} + +#if defined(CONFIG_ARCH_CPU_INIT) +int arch_cpu_init(void) +{ + icache_enable(); + dcache_enable(); + +#ifndef CONFIG_L2_OFF + l2_cache_enable(); +#endif + return 0; +} +#endif + diff --git a/cpu/arm_cortexa8/mx6/interrupts.c b/cpu/arm_cortexa8/mx6/interrupts.c new file mode 100644 index 0000000..d5e4fc1 --- /dev/null +++ b/cpu/arm_cortexa8/mx6/interrupts.c @@ -0,0 +1,39 @@ +/* + * (C) Copyright 2007 + * Sascha Hauer, Pengutronix + * + * Copyright (C) 2010-2011 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 <common.h> +#include <asm/io.h> +#include <asm/arch/mx6.h> + +/* 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/mx6/iomux-v3.c b/cpu/arm_cortexa8/mx6/iomux-v3.c new file mode 100644 index 0000000..4f31567 --- /dev/null +++ b/cpu/arm_cortexa8/mx6/iomux-v3.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de> + * Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH, + * <armlinux@phytec.de> + * + * Copyright (C) 2004-2011 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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#include <common.h> +#include <asm/io.h> +#include <asm/arch/mx6.h> +#include <asm/arch/mx6_pins.h> +#include <asm/arch/iomux-v3.h> + +static void *base; + +/* + * configures a single pad in the iomuxer + */ +int mxc_iomux_v3_setup_pad(iomux_v3_cfg_t pad) +{ + u32 mux_ctrl_ofs = (pad & MUX_CTRL_OFS_MASK) >> MUX_CTRL_OFS_SHIFT; + u32 mux_mode = (pad & MUX_MODE_MASK) >> MUX_MODE_SHIFT; + u32 sel_input_ofs = + (pad & MUX_SEL_INPUT_OFS_MASK) >> MUX_SEL_INPUT_OFS_SHIFT; + u32 sel_input = + (pad & MUX_SEL_INPUT_MASK) >> MUX_SEL_INPUT_SHIFT; + u32 pad_ctrl_ofs = + (pad & MUX_PAD_CTRL_OFS_MASK) >> MUX_PAD_CTRL_OFS_SHIFT; + u32 pad_ctrl = (pad & MUX_PAD_CTRL_MASK) >> MUX_PAD_CTRL_SHIFT; + + if (mux_ctrl_ofs) + __raw_writel(mux_mode, base + mux_ctrl_ofs); + + if (sel_input_ofs) + __raw_writel(sel_input, base + sel_input_ofs); + + if (!(pad_ctrl & NO_PAD_CTRL) && pad_ctrl_ofs) + __raw_writel(pad_ctrl, base + pad_ctrl_ofs); + + return 0; +} + +int mxc_iomux_v3_setup_multiple_pads(iomux_v3_cfg_t *pad_list, unsigned count) +{ + iomux_v3_cfg_t *p = pad_list; + int i; + int ret; + + for (i = 0; i < count; i++) { + ret = mxc_iomux_v3_setup_pad(*p); + if (ret) + return ret; + p++; + } + return 0; +} + +void mxc_iomux_v3_init(void *iomux_v3_base) +{ + base = iomux_v3_base; +} + diff --git a/cpu/arm_cortexa8/mx6/timer.c b/cpu/arm_cortexa8/mx6/timer.c new file mode 100644 index 0000000..e4a5a8f --- /dev/null +++ b/cpu/arm_cortexa8/mx6/timer.c @@ -0,0 +1,181 @@ +/* + * (C) Copyright 2007 + * Sascha Hauer, Pengutronix + * + * Copyright (C) 2010-2011 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 <common.h> +#include <asm/arch/mx6.h> +#include <div64.h> + +#define TIMER_BASE GPT_BASE_ADDR /* General purpose timer 1 */ + +/* General purpose timers registers */ +#define GPTCR __REG(TIMER_BASE) /* Control register */ +#define GPTPR __REG(TIMER_BASE + 0x4) /* Prescaler register */ +#define GPTSR __REG(TIMER_BASE + 0x8) /* Status register */ +#define GPTCNT __REG(TIMER_BASE + 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 (4 << 6) /* Clock source */ +#define GPTCR_TEN (1) /* Timer enable */ + +static ulong timestamp; +static ulong lastinc; + +/* "time" is measured in 1 / CONFIG_SYS_HZ seconds, + * "tick" is internal timer period */ +#ifdef CONFIG_TIMER_HIGH_PRECISION +/* ~0.4% error - measured with stop-watch on 100s boot-delay */ +static inline unsigned long long tick_to_time(unsigned long long tick) +{ + tick *= CONFIG_SYS_HZ; + do_div(tick, CONFIG_MX6_CLK32); + return tick; +} + +static inline unsigned long long time_to_tick(unsigned long long time) +{ + time *= CONFIG_MX6_CLK32; + do_div(time, CONFIG_SYS_HZ); + return time; +} + +static inline unsigned long long us_to_tick(unsigned long long us) +{ + us = us * CONFIG_MX6_CLK32 + 999999; + do_div(us, 1000000); + return us; +} +#else +/* ~2% error */ +#define TICK_PER_TIME ((CONFIG_MX6_CLK32 + CONFIG_SYS_HZ / 2) / CONFIG_SYS_HZ) +#define US_PER_TICK (1000000 / CONFIG_MX6_CLK32) + +static inline unsigned long long tick_to_time(unsigned long long tick) +{ + do_div(tick, TICK_PER_TIME); + return tick; +} + +static inline unsigned long long time_to_tick(unsigned long long time) +{ + return time * TICK_PER_TIME; +} + +static inline unsigned long long us_to_tick(unsigned long long us) +{ + us += US_PER_TICK - 1; + do_div(us, US_PER_TICK); + return us; +} +#endif + +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 = 0; /* 32KHz */ + /* Freerun Mode, CLK32 input */ + GPTCR |= GPTCR_CLKSOURCE_32 | GPTCR_TEN; +} + +int timer_init(void) +{ + setup_gpt(); + + return 0; +} + +void reset_timer_masked(void) +{ + /* reset time */ + lastinc = GPTCNT; /* capture current incrementer value time */ + timestamp = 0; /* start "advancing" time stamp from 0 */ +} + +void reset_timer(void) +{ + reset_timer_masked(); +} + +unsigned long long get_ticks(void) +{ + ulong now = GPTCNT; /* current tick value */ + + if (now >= lastinc) /* normal mode (non roll) */ + /* move stamp forward with absolut diff ticks */ + timestamp += (now - lastinc); + else /* we have rollover of incrementer */ + timestamp += (0xFFFFFFFF - lastinc) + now; + lastinc = now; + return timestamp; +} + +ulong get_timer_masked(void) +{ + /* + * get_ticks() returns a long long (64 bit), it wraps in + * 2^64 / CONFIG_MX31_CLK32 = 2^64 / 2^15 = 2^49 ~ 5 * 10^14 (s) ~ + * 5 * 10^9 days... and get_ticks() * CONFIG_SYS_HZ wraps in + * 5 * 10^6 days - long enough. + */ + return tick_to_time(get_ticks()); +} + +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +void set_timer(ulong t) +{ + timestamp = time_to_tick(t); +} + +/* delay x useconds AND perserve advance timstamp value */ +/* GPTCNT is now supposed to tick 1 by 1 us. */ +void udelay(unsigned long usec) +{ + unsigned long long tmp; + ulong tmo; + + setup_gpt(); + + tmo = us_to_tick(usec); + tmp = get_ticks() + tmo; /* get current timestamp */ + + while (get_ticks() < tmp) /* loop till event */ + /*NOP*/; +} |