From 5d743e40a0164b71edeeed8260c74cbea3484282 Mon Sep 17 00:00:00 2001 From: Zhang Xiaodong Date: Tue, 27 Nov 2012 16:27:07 +0800 Subject: ENGR00223037 fsl: Add new board HDMI dongle for imx6 Q/DL. Add HDMIdongle board for imx6Q/DL under board/freescale. Signed-off-by: Zhang Xiaodong --- board/freescale/common/fsl_sys_rev.c | 1 + board/freescale/mx6q_hdmidongle/Makefile | 47 + board/freescale/mx6q_hdmidongle/config.mk | 7 + board/freescale/mx6q_hdmidongle/flash_header.S | 306 +++++ board/freescale/mx6q_hdmidongle/lowlevel_init.S | 167 +++ board/freescale/mx6q_hdmidongle/mx6q_hdmidongle.c | 1452 +++++++++++++++++++++ board/freescale/mx6q_hdmidongle/u-boot.lds | 74 ++ 7 files changed, 2054 insertions(+) create mode 100644 board/freescale/mx6q_hdmidongle/Makefile create mode 100644 board/freescale/mx6q_hdmidongle/config.mk create mode 100644 board/freescale/mx6q_hdmidongle/flash_header.S create mode 100644 board/freescale/mx6q_hdmidongle/lowlevel_init.S create mode 100644 board/freescale/mx6q_hdmidongle/mx6q_hdmidongle.c create mode 100644 board/freescale/mx6q_hdmidongle/u-boot.lds (limited to 'board') diff --git a/board/freescale/common/fsl_sys_rev.c b/board/freescale/common/fsl_sys_rev.c index ba4c367..0caa859 100644 --- a/board/freescale/common/fsl_sys_rev.c +++ b/board/freescale/common/fsl_sys_rev.c @@ -85,6 +85,7 @@ void fsl_set_system_rev(void) * 0x2 : Smart Device (SD) * 0x3 : Quick-Start Board (QSB) * 0x4 : SoloLite EVK (SL-EVK) + * 0x6 : HDMI Dongle * * bit 8-11: Board Revision ID * 0x0 : Unknown or latest revision diff --git a/board/freescale/mx6q_hdmidongle/Makefile b/board/freescale/mx6q_hdmidongle/Makefile new file mode 100644 index 0000000..1d63462 --- /dev/null +++ b/board/freescale/mx6q_hdmidongle/Makefile @@ -0,0 +1,47 @@ +# +# (C) Copyright 2012 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 $(TOPDIR)/config.mk + +LIB = $(obj)lib$(BOARD).a + +COBJS := $(BOARD).o +SOBJS := lowlevel_init.o flash_header.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/freescale/mx6q_hdmidongle/config.mk b/board/freescale/mx6q_hdmidongle/config.mk new file mode 100644 index 0000000..a0ce2a1 --- /dev/null +++ b/board/freescale/mx6q_hdmidongle/config.mk @@ -0,0 +1,7 @@ +LDSCRIPT := $(SRCTREE)/board/$(VENDOR)/$(BOARD)/u-boot.lds + +sinclude $(OBJTREE)/board/$(VENDOR)/$(BOARD)/config.tmp + +ifndef TEXT_BASE + TEXT_BASE = 0x27800000 +endif diff --git a/board/freescale/mx6q_hdmidongle/flash_header.S b/board/freescale/mx6q_hdmidongle/flash_header.S new file mode 100644 index 0000000..9ca5d0e --- /dev/null +++ b/board/freescale/mx6q_hdmidongle/flash_header.S @@ -0,0 +1,306 @@ +/* + * Copyright (C) 2012 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 +#include + +#ifdef CONFIG_FLASH_HEADER +#ifndef CONFIG_FLASH_HEADER_OFFSET +# error "Must define the offset of flash header" +#endif + +#define CPU_2_BE_32(l) \ + ((((l) & 0x000000FF) << 24) | \ + (((l) & 0x0000FF00) << 8) | \ + (((l) & 0x00FF0000) >> 8) | \ + (((l) & 0xFF000000) >> 24)) + +#define MXC_DCD_ITEM(i, addr, val) \ +dcd_node_##i: \ + .word CPU_2_BE_32(addr) ; \ + .word CPU_2_BE_32(val) ; \ + +.section ".text.flasheader", "x" + b _start + .org CONFIG_FLASH_HEADER_OFFSET + +ivt_header: .word 0x402000D1 /* Tag=0xD1, Len=0x0020, Ver=0x40 */ +app_code_jump_v: .word _start +reserv1: .word 0x0 +dcd_ptr: .word dcd_hdr +boot_data_ptr: .word boot_data +self_ptr: .word ivt_header +app_code_csf: .word 0x0 +reserv2: .word 0x0 + +boot_data: .word TEXT_BASE +image_len: .word _end_of_copy - TEXT_BASE + CONFIG_FLASH_HEADER_OFFSET +plugin: .word 0x0 + +#if defined CONFIG_MX6DL_DDR3 +dcd_hdr: .word 0x40E002D2 /* Tag=0xD2, Len=91*8 + 4 + 4, Ver=0x40 */ +write_dcd_cmd: .word 0x04DC02CC /* Tag=0xCC, Len=91*8 + 4, Param=0x04 */ + +# IOMUXC_BASE_ADDR = 0x20e0000 +# DDR IO TYPE +MXC_DCD_ITEM(1, IOMUXC_BASE_ADDR + 0x774, 0x000c0000) +MXC_DCD_ITEM(2, IOMUXC_BASE_ADDR + 0x754, 0x00000000) +# Clock +MXC_DCD_ITEM(3, IOMUXC_BASE_ADDR + 0x4ac, 0x00000030) +MXC_DCD_ITEM(4, IOMUXC_BASE_ADDR + 0x4b0, 0x00000030) +# Address +MXC_DCD_ITEM(5, IOMUXC_BASE_ADDR + 0x464, 0x00000030) +MXC_DCD_ITEM(6, IOMUXC_BASE_ADDR + 0x490, 0x00000030) +MXC_DCD_ITEM(7, IOMUXC_BASE_ADDR + 0x74c, 0x00000030) +# Control +MXC_DCD_ITEM(8, IOMUXC_BASE_ADDR + 0x494, 0x00000030) +MXC_DCD_ITEM(9, IOMUXC_BASE_ADDR + 0x4a4, 0x00003000) +MXC_DCD_ITEM(10, IOMUXC_BASE_ADDR + 0x4a8, 0x00003000) +MXC_DCD_ITEM(11, IOMUXC_BASE_ADDR + 0x4a0, 0x00000000) +MXC_DCD_ITEM(12, IOMUXC_BASE_ADDR + 0x4b4, 0x00003030) +MXC_DCD_ITEM(13, IOMUXC_BASE_ADDR + 0x4b8, 0x00003030) +MXC_DCD_ITEM(14, IOMUXC_BASE_ADDR + 0x76c, 0x00000030) +# Data Strobe +MXC_DCD_ITEM(15, IOMUXC_BASE_ADDR + 0x750, 0x00020000) + +MXC_DCD_ITEM(16, IOMUXC_BASE_ADDR + 0x4bc, 0x00000030) +MXC_DCD_ITEM(17, IOMUXC_BASE_ADDR + 0x4c0, 0x00000030) +MXC_DCD_ITEM(18, IOMUXC_BASE_ADDR + 0x4c4, 0x00000030) +MXC_DCD_ITEM(19, IOMUXC_BASE_ADDR + 0x4c8, 0x00000030) +MXC_DCD_ITEM(20, IOMUXC_BASE_ADDR + 0x4cc, 0x00000030) +MXC_DCD_ITEM(21, IOMUXC_BASE_ADDR + 0x4d0, 0x00000030) +MXC_DCD_ITEM(22, IOMUXC_BASE_ADDR + 0x4d4, 0x00000030) +MXC_DCD_ITEM(23, IOMUXC_BASE_ADDR + 0x4d8, 0x00000030) +# DATA +MXC_DCD_ITEM(24, IOMUXC_BASE_ADDR + 0x760, 0x00020000) + +MXC_DCD_ITEM(25, IOMUXC_BASE_ADDR + 0x764, 0x00000030) +MXC_DCD_ITEM(26, IOMUXC_BASE_ADDR + 0x770, 0x00000030) +MXC_DCD_ITEM(27, IOMUXC_BASE_ADDR + 0x778, 0x00000030) +MXC_DCD_ITEM(28, IOMUXC_BASE_ADDR + 0x77c, 0x00000030) +MXC_DCD_ITEM(29, IOMUXC_BASE_ADDR + 0x780, 0x00000030) +MXC_DCD_ITEM(30, IOMUXC_BASE_ADDR + 0x784, 0x00000030) +MXC_DCD_ITEM(31, IOMUXC_BASE_ADDR + 0x78c, 0x00000030) +MXC_DCD_ITEM(32, IOMUXC_BASE_ADDR + 0x748, 0x00000030) + +MXC_DCD_ITEM(33, IOMUXC_BASE_ADDR + 0x470, 0x00000030) +MXC_DCD_ITEM(34, IOMUXC_BASE_ADDR + 0x474, 0x00000030) +MXC_DCD_ITEM(35, IOMUXC_BASE_ADDR + 0x478, 0x00000030) +MXC_DCD_ITEM(36, IOMUXC_BASE_ADDR + 0x47c, 0x00000030) +MXC_DCD_ITEM(37, IOMUXC_BASE_ADDR + 0x480, 0x00000030) +MXC_DCD_ITEM(38, IOMUXC_BASE_ADDR + 0x484, 0x00000030) +MXC_DCD_ITEM(39, IOMUXC_BASE_ADDR + 0x488, 0x00000030) +MXC_DCD_ITEM(40, IOMUXC_BASE_ADDR + 0x48c, 0x00000030) + +# MMDC_P0_BASE_ADDR = 0x021b0000 +# MMDC_P1_BASE_ADDR = 0x021b4000 +# Calibrations +# ZQ +MXC_DCD_ITEM(41, MMDC_P0_BASE_ADDR + 0x800, 0xa1390003) +MXC_DCD_ITEM(42, MMDC_P1_BASE_ADDR + 0x800, 0xa1390003) +# write leveling +MXC_DCD_ITEM(43, MMDC_P0_BASE_ADDR + 0x80c, 0x001F001F) +MXC_DCD_ITEM(44, MMDC_P0_BASE_ADDR + 0x810, 0x001F001F) +MXC_DCD_ITEM(45, MMDC_P1_BASE_ADDR + 0x80c, 0x001F001F) +MXC_DCD_ITEM(46, MMDC_P1_BASE_ADDR + 0x810, 0x001F001F) +# DQS gating, read delay, write delay calibration values +# based on calibration compare of 0x00ffff00 +MXC_DCD_ITEM(47, MMDC_P0_BASE_ADDR + 0x83c, 0x420E020E) +MXC_DCD_ITEM(48, MMDC_P0_BASE_ADDR + 0x840, 0x02000200) +MXC_DCD_ITEM(49, MMDC_P1_BASE_ADDR + 0x83C, 0x42020202) +MXC_DCD_ITEM(50, MMDC_P1_BASE_ADDR + 0x840, 0x01720172) +MXC_DCD_ITEM(51, MMDC_P0_BASE_ADDR + 0x848, 0x494C4F4C) +MXC_DCD_ITEM(52, MMDC_P1_BASE_ADDR + 0x848, 0x4A4C4C49) +MXC_DCD_ITEM(53, MMDC_P0_BASE_ADDR + 0x850, 0x3F3F3133) +MXC_DCD_ITEM(54, MMDC_P1_BASE_ADDR + 0x850, 0x39373F2E) +# read data bit delay +MXC_DCD_ITEM(55, MMDC_P0_BASE_ADDR + 0x81c, 0x33333333) +MXC_DCD_ITEM(56, MMDC_P0_BASE_ADDR + 0x820, 0x33333333) +MXC_DCD_ITEM(57, MMDC_P0_BASE_ADDR + 0x824, 0x33333333) +MXC_DCD_ITEM(58, MMDC_P0_BASE_ADDR + 0x828, 0x33333333) +MXC_DCD_ITEM(59, MMDC_P1_BASE_ADDR + 0x81c, 0x33333333) +MXC_DCD_ITEM(60, MMDC_P1_BASE_ADDR + 0x820, 0x33333333) +MXC_DCD_ITEM(61, MMDC_P1_BASE_ADDR + 0x824, 0x33333333) +MXC_DCD_ITEM(62, MMDC_P1_BASE_ADDR + 0x828, 0x33333333) +# Complete calibration by forced measurment +MXC_DCD_ITEM(63, MMDC_P0_BASE_ADDR + 0x8b8, 0x00000800) +MXC_DCD_ITEM(64, MMDC_P1_BASE_ADDR + 0x8b8, 0x00000800) +# MMDC init: +# in DDR3, 64-bit mode, only MMDC0 is initiated: +MXC_DCD_ITEM(65, MMDC_P0_BASE_ADDR + 0x004, 0x0002002d) +MXC_DCD_ITEM(66, MMDC_P0_BASE_ADDR + 0x008, 0x00333030) + +MXC_DCD_ITEM(67, MMDC_P0_BASE_ADDR + 0x00c, 0x40445323) +MXC_DCD_ITEM(68, MMDC_P0_BASE_ADDR + 0x010, 0xb66e8c63) + +MXC_DCD_ITEM(69, MMDC_P0_BASE_ADDR + 0x014, 0x01ff00db) +MXC_DCD_ITEM(70, MMDC_P0_BASE_ADDR + 0x018, 0x00081740) +MXC_DCD_ITEM(71, MMDC_P0_BASE_ADDR + 0x01c, 0x00008000) +MXC_DCD_ITEM(72, MMDC_P0_BASE_ADDR + 0x02c, 0x000026d2) +MXC_DCD_ITEM(73, MMDC_P0_BASE_ADDR + 0x030, 0x00440e21) +MXC_DCD_ITEM(74, MMDC_P0_BASE_ADDR + 0x040, 0x00000027) +MXC_DCD_ITEM(75, MMDC_P0_BASE_ADDR + 0x000, 0xc31a0000) + +# Initialize 2GB DDR3 - Micron MT41J128M +# MR2 +MXC_DCD_ITEM(76, MMDC_P0_BASE_ADDR + 0x01c, 0x04008032) +MXC_DCD_ITEM(77, MMDC_P0_BASE_ADDR + 0x01c, 0x0400803a) +# MR3 +MXC_DCD_ITEM(78, MMDC_P0_BASE_ADDR + 0x01c, 0x00008033) +MXC_DCD_ITEM(79, MMDC_P0_BASE_ADDR + 0x01c, 0x0000803b) +# MR1 +MXC_DCD_ITEM(80, MMDC_P0_BASE_ADDR + 0x01c, 0x00428031) +MXC_DCD_ITEM(81, MMDC_P0_BASE_ADDR + 0x01c, 0x00428039) +# MR0 +MXC_DCD_ITEM(82, MMDC_P0_BASE_ADDR + 0x01c, 0x07208030) +MXC_DCD_ITEM(83, MMDC_P0_BASE_ADDR + 0x01c, 0x07208038) +# ZQ calibration +MXC_DCD_ITEM(84, MMDC_P0_BASE_ADDR + 0x01c, 0x04008040) +MXC_DCD_ITEM(85, MMDC_P0_BASE_ADDR + 0x01c, 0x04008048) +# final DDR setup +MXC_DCD_ITEM(86, MMDC_P0_BASE_ADDR + 0x020, 0x00005800) +MXC_DCD_ITEM(87, MMDC_P0_BASE_ADDR + 0x818, 0x00000007) +MXC_DCD_ITEM(88, MMDC_P1_BASE_ADDR + 0x818, 0x00000007) +MXC_DCD_ITEM(89, MMDC_P0_BASE_ADDR + 0x004, 0x0002556d) +MXC_DCD_ITEM(90, MMDC_P1_BASE_ADDR + 0x404, 0x00011006) +MXC_DCD_ITEM(91, MMDC_P0_BASE_ADDR + 0x01c, 0x00000000) + + +#else +dcd_hdr: .word 0x40D802D2 /* Tag=0xD2, Len=90*8 + 4 + 4, Ver=0x40 */ +write_dcd_cmd: .word 0x04D402CC /* Tag=0xCC, Len=90*8 + 4, Param=0x04 */ + +/* DCD */ + +MXC_DCD_ITEM(1, IOMUXC_BASE_ADDR + 0x5a8, 0x00000030) +MXC_DCD_ITEM(2, IOMUXC_BASE_ADDR + 0x5b0, 0x00000030) +MXC_DCD_ITEM(3, IOMUXC_BASE_ADDR + 0x524, 0x00000030) +MXC_DCD_ITEM(4, IOMUXC_BASE_ADDR + 0x51c, 0x00000030) + +MXC_DCD_ITEM(5, IOMUXC_BASE_ADDR + 0x518, 0x00000030) +MXC_DCD_ITEM(6, IOMUXC_BASE_ADDR + 0x50c, 0x00000030) +MXC_DCD_ITEM(7, IOMUXC_BASE_ADDR + 0x5b8, 0x00000030) +MXC_DCD_ITEM(8, IOMUXC_BASE_ADDR + 0x5c0, 0x00000030) + +MXC_DCD_ITEM(9, IOMUXC_BASE_ADDR + 0x5ac, 0x00020030) +MXC_DCD_ITEM(10, IOMUXC_BASE_ADDR + 0x5b4, 0x00020030) +MXC_DCD_ITEM(11, IOMUXC_BASE_ADDR + 0x528, 0x00020030) +MXC_DCD_ITEM(12, IOMUXC_BASE_ADDR + 0x520, 0x00020030) + +MXC_DCD_ITEM(13, IOMUXC_BASE_ADDR + 0x514, 0x00020030) +MXC_DCD_ITEM(14, IOMUXC_BASE_ADDR + 0x510, 0x00020030) +MXC_DCD_ITEM(15, IOMUXC_BASE_ADDR + 0x5bc, 0x00020030) +MXC_DCD_ITEM(16, IOMUXC_BASE_ADDR + 0x5c4, 0x00020030) + +MXC_DCD_ITEM(17, IOMUXC_BASE_ADDR + 0x56c, 0x00020030) +MXC_DCD_ITEM(18, IOMUXC_BASE_ADDR + 0x578, 0x00020030) +MXC_DCD_ITEM(19, IOMUXC_BASE_ADDR + 0x588, 0x00020030) +MXC_DCD_ITEM(20, IOMUXC_BASE_ADDR + 0x594, 0x00020030) + +MXC_DCD_ITEM(21, IOMUXC_BASE_ADDR + 0x57c, 0x00000030) +MXC_DCD_ITEM(22, IOMUXC_BASE_ADDR + 0x58c, 0x00000000) + +MXC_DCD_ITEM(23, IOMUXC_BASE_ADDR + 0x59c, 0x00000030) +MXC_DCD_ITEM(24, IOMUXC_BASE_ADDR + 0x5a0, 0x00000030) +MXC_DCD_ITEM(25, IOMUXC_BASE_ADDR + 0x784, 0x00000030) +MXC_DCD_ITEM(26, IOMUXC_BASE_ADDR + 0x788, 0x00000030) + +MXC_DCD_ITEM(27, IOMUXC_BASE_ADDR + 0x794, 0x00000030) +MXC_DCD_ITEM(28, IOMUXC_BASE_ADDR + 0x79c, 0x00000030) +MXC_DCD_ITEM(29, IOMUXC_BASE_ADDR + 0x7a0, 0x00000030) +MXC_DCD_ITEM(30, IOMUXC_BASE_ADDR + 0x7a4, 0x00000030) + +MXC_DCD_ITEM(31, IOMUXC_BASE_ADDR + 0x7a8, 0x00000030) +MXC_DCD_ITEM(32, IOMUXC_BASE_ADDR + 0x748, 0x00000030) +MXC_DCD_ITEM(33, IOMUXC_BASE_ADDR + 0x74c, 0x00000030) +MXC_DCD_ITEM(34, IOMUXC_BASE_ADDR + 0x750, 0x00020000) + +MXC_DCD_ITEM(35, IOMUXC_BASE_ADDR + 0x758, 0x00000000) +MXC_DCD_ITEM(36, IOMUXC_BASE_ADDR + 0x774, 0x00020000) +MXC_DCD_ITEM(37, IOMUXC_BASE_ADDR + 0x78c, 0x00000030) +MXC_DCD_ITEM(38, IOMUXC_BASE_ADDR + 0x798, 0x000C0000) + +MXC_DCD_ITEM(39, MMDC_P0_BASE_ADDR + 0x81c, 0x33333333) +MXC_DCD_ITEM(40, MMDC_P0_BASE_ADDR + 0x820, 0x33333333) +MXC_DCD_ITEM(41, MMDC_P0_BASE_ADDR + 0x824, 0x33333333) +MXC_DCD_ITEM(42, MMDC_P0_BASE_ADDR + 0x828, 0x33333333) + +MXC_DCD_ITEM(43, MMDC_P1_BASE_ADDR + 0x81c, 0x33333333) +MXC_DCD_ITEM(44, MMDC_P1_BASE_ADDR + 0x820, 0x33333333) +MXC_DCD_ITEM(45, MMDC_P1_BASE_ADDR + 0x824, 0x33333333) +MXC_DCD_ITEM(46, MMDC_P1_BASE_ADDR + 0x828, 0x33333333) + +MXC_DCD_ITEM(47, MMDC_P0_BASE_ADDR + 0x018, 0x00081740) + +MXC_DCD_ITEM(48, MMDC_P0_BASE_ADDR + 0x01c, 0x00008000) +MXC_DCD_ITEM(49, MMDC_P0_BASE_ADDR + 0x00c, 0x555A7975) +MXC_DCD_ITEM(50, MMDC_P0_BASE_ADDR + 0x010, 0xFF538E64) +MXC_DCD_ITEM(51, MMDC_P0_BASE_ADDR + 0x014, 0x01FF00DB) +MXC_DCD_ITEM(52, MMDC_P0_BASE_ADDR + 0x02c, 0x000026D2) + +MXC_DCD_ITEM(53, MMDC_P0_BASE_ADDR + 0x030, 0x005B0E21) +MXC_DCD_ITEM(54, MMDC_P0_BASE_ADDR + 0x008, 0x09444040) +MXC_DCD_ITEM(55, MMDC_P0_BASE_ADDR + 0x004, 0x00025576) +MXC_DCD_ITEM(56, MMDC_P0_BASE_ADDR + 0x040, 0x00000027) +MXC_DCD_ITEM(57, MMDC_P0_BASE_ADDR + 0x000, 0x831A0000) + +MXC_DCD_ITEM(58, MMDC_P0_BASE_ADDR + 0x01c, 0x04088032) +MXC_DCD_ITEM(59, MMDC_P0_BASE_ADDR + 0x01c, 0x0408803A) +MXC_DCD_ITEM(60, MMDC_P0_BASE_ADDR + 0x01c, 0x00008033) +MXC_DCD_ITEM(61, MMDC_P0_BASE_ADDR + 0x01c, 0x0000803B) +MXC_DCD_ITEM(62, MMDC_P0_BASE_ADDR + 0x01c, 0x00428031) +MXC_DCD_ITEM(63, MMDC_P0_BASE_ADDR + 0x01c, 0x00428039) +MXC_DCD_ITEM(64, MMDC_P0_BASE_ADDR + 0x01c, 0x09408030) +MXC_DCD_ITEM(65, MMDC_P0_BASE_ADDR + 0x01c, 0x09408038) + +MXC_DCD_ITEM(66, MMDC_P0_BASE_ADDR + 0x01c, 0x04008040) +MXC_DCD_ITEM(67, MMDC_P0_BASE_ADDR + 0x01c, 0x04008048) +MXC_DCD_ITEM(68, MMDC_P0_BASE_ADDR + 0x800, 0xA1380003) +MXC_DCD_ITEM(69, MMDC_P1_BASE_ADDR + 0x800, 0xA1380003) +MXC_DCD_ITEM(70, MMDC_P0_BASE_ADDR + 0x020, 0x00005800) +MXC_DCD_ITEM(71, MMDC_P0_BASE_ADDR + 0x818, 0x00000007) +MXC_DCD_ITEM(72, MMDC_P1_BASE_ADDR + 0x818, 0x00000007) + +MXC_DCD_ITEM(73, MMDC_P0_BASE_ADDR + 0x83c, 0x427D0303) +MXC_DCD_ITEM(74, MMDC_P0_BASE_ADDR + 0x840, 0x02740267) +MXC_DCD_ITEM(75, MMDC_P1_BASE_ADDR + 0x83c, 0x43010301) +MXC_DCD_ITEM(76, MMDC_P1_BASE_ADDR + 0x840, 0x02770247) +MXC_DCD_ITEM(77, MMDC_P0_BASE_ADDR + 0x848, 0x44343a36) +MXC_DCD_ITEM(78, MMDC_P1_BASE_ADDR + 0x848, 0x3e3d363d) +MXC_DCD_ITEM(79, MMDC_P0_BASE_ADDR + 0x850, 0x37434644) +MXC_DCD_ITEM(80, MMDC_P1_BASE_ADDR + 0x850, 0x472a4640) +# fine tune SDCLK duty cyc to low - seen to improve measured duty cycle of i.mx6 +MXC_DCD_ITEM(81, MMDC_P0_BASE_ADDR + 0x8c0, 0x24911492) +MXC_DCD_ITEM(82, MMDC_P1_BASE_ADDR + 0x8c0, 0x24911492) + +MXC_DCD_ITEM(83, MMDC_P0_BASE_ADDR + 0x80c, 0x001F001F) +MXC_DCD_ITEM(84, MMDC_P0_BASE_ADDR + 0x810, 0x001F001F) + +MXC_DCD_ITEM(85, MMDC_P1_BASE_ADDR + 0x80c, 0x001F001F) +MXC_DCD_ITEM(86, MMDC_P1_BASE_ADDR + 0x810, 0x001F001F) + +MXC_DCD_ITEM(87, MMDC_P0_BASE_ADDR + 0x8b8, 0x00000800) +MXC_DCD_ITEM(88, MMDC_P1_BASE_ADDR + 0x8b8, 0x00000800) + +MXC_DCD_ITEM(89, MMDC_P0_BASE_ADDR + 0x01c, 0x00000000) +MXC_DCD_ITEM(90, MMDC_P0_BASE_ADDR + 0x404, 0x00011006) + +#endif + +#endif diff --git a/board/freescale/mx6q_hdmidongle/lowlevel_init.S b/board/freescale/mx6q_hdmidongle/lowlevel_init.S new file mode 100644 index 0000000..a299709 --- /dev/null +++ b/board/freescale/mx6q_hdmidongle/lowlevel_init.S @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2012 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 +#include + +/* + Disable L2Cache because ROM turn it on when uboot use plug-in. + If L2Cache is on default, there are cache coherence problem if kernel have + not config L2Cache. +*/ +.macro init_l2cc + ldr r1, =0xa02000 + ldr r0, =0x0 + str r0, [r1, #0x100] +.endm /* init_l2cc */ + +/* invalidate the D-CACHE */ +.macro inv_dcache + mov r0,#0 + mcr p15,2,r0,c0,c0,0 /* cache size selection register, select dcache */ + mrc p15,1,r0,c0,c0,0 /* cache size ID register */ + mov r0,r0,ASR #13 + ldr r3,=0xfff + and r0,r0,r3 + cmp r0,#0x7f + moveq r6,#0x1000 + beq size_done + cmp r0,#0xff + moveq r6,#0x2000 + movne r6,#0x4000 + +size_done: + mov r2,#0 + mov r3,#0x40000000 + mov r4,#0x80000000 + mov r5,#0xc0000000 + +d_inv_loop: + mcr p15,0,r2,c7,c6,2 /* invalidate dcache by set / way */ + mcr p15,0,r3,c7,c6,2 /* invalidate dcache by set / way */ + mcr p15,0,r4,c7,c6,2 /* invalidate dcache by set / way */ + mcr p15,0,r5,c7,c6,2 /* invalidate dcache by set / way */ + add r2,r2,#0x20 + add r3,r3,#0x20 + add r4,r4,#0x20 + add r5,r5,#0x20 + + cmp r2,r6 + bne d_inv_loop +.endm + +/* AIPS setup - Only setup MPROTx registers. + * The PACR default values are good.*/ +.macro init_aips + /* + * Set all MPROTx to be non-bufferable, trusted for R/W, + * not forced to user-mode. + */ + ldr r0, =AIPS1_ON_BASE_ADDR + ldr r1, =0x77777777 + str r1, [r0, #0x0] + str r1, [r0, #0x4] + ldr r1, =0x0 + str r1, [r0, #0x40] + str r1, [r0, #0x44] + str r1, [r0, #0x48] + str r1, [r0, #0x4C] + str r1, [r0, #0x50] + + ldr r0, =AIPS2_ON_BASE_ADDR + ldr r1, =0x77777777 + str r1, [r0, #0x0] + str r1, [r0, #0x4] + ldr r1, =0x0 + str r1, [r0, #0x40] + str r1, [r0, #0x44] + str r1, [r0, #0x48] + str r1, [r0, #0x4C] + str r1, [r0, #0x50] +.endm /* init_aips */ + +.macro setup_pll pll, freq +.endm + +.macro init_clock + +/* PLL1, PLL2, and PLL3 are enabled by ROM */ +#ifdef CONFIG_PLL3 + /* enable PLL3 for UART */ + ldr r0, ANATOP_BASE_ADDR_W + + /* power up PLL */ + ldr r1, [r0, #ANATOP_USB1] + orr r1, r1, #0x1000 + str r1, [r0, #ANATOP_USB1] + + /* enable PLL */ + ldr r1, [r0, #ANATOP_USB1] + orr r1, r1, #0x2000 + str r1, [r0, #ANATOP_USB1] + + /* wait PLL lock */ +100: + ldr r1, [r0, #ANATOP_USB1] + mov r1, r1, lsr #31 + cmp r1, #0x1 + bne 100b + + /* clear bypass bit */ + ldr r1, [r0, #ANATOP_USB1] + and r1, r1, #0xfffeffff + str r1, [r0, #ANATOP_USB1] +#endif + + /* Restore the default values in the Gate registers */ + ldr r0, CCM_BASE_ADDR_W + ldr r1, =0xC0003F + str r1, [r0, #CLKCTL_CCGR0] + ldr r1, =0x30FC00 + str r1, [r0, #CLKCTL_CCGR1] + ldr r1, =0xFFFC000 + str r1, [r0, #CLKCTL_CCGR2] + ldr r1, =0x3FF00000 + str r1, [r0, #CLKCTL_CCGR3] + ldr r1, =0xFFF300 + str r1, [r0, #CLKCTL_CCGR4] + ldr r1, =0xF0000C3 + str r1, [r0, #CLKCTL_CCGR5] + ldr r1, =0x3FC + str r1, [r0, #CLKCTL_CCGR6] +.endm + +.section ".text.init", "x" + +.globl lowlevel_init +lowlevel_init: + + inv_dcache + + init_l2cc + + init_aips + + init_clock + + mov pc, lr + +/* Board level setting value */ +ANATOP_BASE_ADDR_W: .word ANATOP_BASE_ADDR +CCM_BASE_ADDR_W: .word CCM_BASE_ADDR diff --git a/board/freescale/mx6q_hdmidongle/mx6q_hdmidongle.c b/board/freescale/mx6q_hdmidongle/mx6q_hdmidongle.c new file mode 100644 index 0000000..6cfe334 --- /dev/null +++ b/board/freescale/mx6q_hdmidongle/mx6q_hdmidongle.c @@ -0,0 +1,1452 @@ +/* + * Copyright (C) 2012 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 +#include +#include +#include +#ifdef CONFIG_MXC_FEC +#include +#endif +#if defined(CONFIG_VIDEO_MX5) +#include +#include +#include +#include +#include +#endif + +#ifdef CONFIG_IMX_ECSPI +#include +#endif + +#if CONFIG_I2C_MXC +#include +#endif + +#ifdef CONFIG_CMD_MMC +#include +#include +#endif + +#ifdef CONFIG_ARCH_MMU +#include +#include +#endif + +#ifdef CONFIG_CMD_CLOCK +#include +#endif + +#ifdef CONFIG_CMD_IMXOTP +#include +#endif + +#ifdef CONFIG_MXC_GPIO +#include +#include +#endif + +#ifdef CONFIG_ANDROID_RECOVERY +#include +#endif +DECLARE_GLOBAL_DATA_PTR; + +static enum boot_device boot_dev; + +#define GPIO_REVB_POWER_KEY IMX_GPIO_NR(1, 27) +#define USB_OTG_PWR IMX_GPIO_NR(4, 15) +#define USB_H1_POWER IMX_GPIO_NR(4, 14) + +#define HDMIDONGLE_CHG_SYS_ON IMX_GPIO_NR(2, 6) + +#ifdef CONFIG_VIDEO_MX5 +extern unsigned char fsl_bmp_600x400[]; +extern int fsl_bmp_600x400_size; +extern int g_ipu_hw_rev; + +#if defined(CONFIG_BMP_8BPP) +unsigned short colormap[256]; +#elif defined(CONFIG_BMP_16BPP) +unsigned short colormap[65536]; +#else +unsigned short colormap[16777216]; +#endif + +static int di = 1; + +extern int ipuv3_fb_init(struct fb_videomode *mode, int di, + int interface_pix_fmt, + ipu_di_clk_parent_t di_clk_parent, + int di_clk_val); + +static struct fb_videomode lvds_xga = { + "XGA", 60, 1024, 768, 15385, 220, 40, 21, 7, 60, 10, + FB_SYNC_EXT, + FB_VMODE_NONINTERLACED, + 0, +}; + +vidinfo_t panel_info; +#endif + +static inline void setup_boot_device(void) +{ + uint soc_sbmr = readl(SRC_BASE_ADDR + 0x4); + uint bt_mem_ctl = (soc_sbmr & 0x000000FF) >> 4 ; + uint bt_mem_type = (soc_sbmr & 0x00000008) >> 3; + + switch (bt_mem_ctl) { + case 0x0: + if (bt_mem_type) + boot_dev = ONE_NAND_BOOT; + else + boot_dev = WEIM_NOR_BOOT; + break; + case 0x2: + boot_dev = SATA_BOOT; + break; + case 0x3: + if (bt_mem_type) + boot_dev = I2C_BOOT; + else + boot_dev = SPI_NOR_BOOT; + break; + case 0x4: + case 0x5: + boot_dev = SD_BOOT; + break; + case 0x6: + case 0x7: + boot_dev = MMC_BOOT; + break; + case 0x8 ... 0xf: + boot_dev = NAND_BOOT; + break; + default: + boot_dev = UNKNOWN_BOOT; + break; + } +} + +enum boot_device get_boot_device(void) +{ + return boot_dev; +} + +u32 get_board_rev(void) +{ + return fsl_system_rev; +} + +#ifdef CONFIG_ARCH_MMU +void board_mmu_init(void) +{ + unsigned long ttb_base = PHYS_SDRAM_1 + 0x4000; + unsigned long i; + + /* + * Set the TTB register + */ + asm volatile ("mcr p15,0,%0,c2,c0,0" : : "r"(ttb_base) /*:*/); + + /* + * Set the Domain Access Control Register + */ + i = ARM_ACCESS_DACR_DEFAULT; + asm volatile ("mcr p15,0,%0,c3,c0,0" : : "r"(i) /*:*/); + + /* + * First clear all TT entries - ie Set them to Faulting + */ + memset((void *)ttb_base, 0, ARM_FIRST_LEVEL_PAGE_TABLE_SIZE); + /* Actual Virtual Size Attributes Function */ + /* Base Base MB cached? buffered? access permissions */ + /* xxx00000 xxx00000 */ + X_ARM_MMU_SECTION(0x000, 0x000, 0x001, + ARM_UNCACHEABLE, ARM_UNBUFFERABLE, + ARM_ACCESS_PERM_RW_RW); /* ROM, 1M */ + X_ARM_MMU_SECTION(0x001, 0x001, 0x008, + ARM_UNCACHEABLE, ARM_UNBUFFERABLE, + ARM_ACCESS_PERM_RW_RW); /* 8M */ + X_ARM_MMU_SECTION(0x009, 0x009, 0x001, + ARM_UNCACHEABLE, ARM_UNBUFFERABLE, + ARM_ACCESS_PERM_RW_RW); /* IRAM */ + X_ARM_MMU_SECTION(0x00A, 0x00A, 0x0F6, + ARM_UNCACHEABLE, ARM_UNBUFFERABLE, + ARM_ACCESS_PERM_RW_RW); /* 246M */ + + /* 2 GB memory starting at 0x10000000, only map 1.875 GB */ + X_ARM_MMU_SECTION(0x100, 0x100, 0x780, + ARM_CACHEABLE, ARM_BUFFERABLE, + ARM_ACCESS_PERM_RW_RW); + /* uncached alias of the same 1.875 GB memory */ + X_ARM_MMU_SECTION(0x100, 0x880, 0x780, + ARM_UNCACHEABLE, ARM_UNBUFFERABLE, + ARM_ACCESS_PERM_RW_RW); + + /* Enable MMU */ + MMU_ON(); +} +#endif + +#ifdef CONFIG_DWC_AHSATA + +#define ANATOP_PLL_LOCK 0x80000000 +#define ANATOP_PLL_ENABLE_MASK 0x00002000 +#define ANATOP_PLL_BYPASS_MASK 0x00010000 +#define ANATOP_PLL_LOCK 0x80000000 +#define ANATOP_PLL_PWDN_MASK 0x00001000 +#define ANATOP_PLL_HOLD_RING_OFF_MASK 0x00000800 +#define ANATOP_SATA_CLK_ENABLE_MASK 0x00100000 + +int setup_sata(void) +{ + u32 reg = 0; + s32 timeout = 100000; + + /* Enable sata clock */ + reg = readl(CCM_BASE_ADDR + 0x7c); /* CCGR5 */ + reg |= 0x30; + writel(reg, CCM_BASE_ADDR + 0x7c); + + /* Enable PLLs */ + reg = readl(ANATOP_BASE_ADDR + 0xe0); /* ENET PLL */ + reg &= ~ANATOP_PLL_PWDN_MASK; + writel(reg, ANATOP_BASE_ADDR + 0xe0); + reg |= ANATOP_PLL_ENABLE_MASK; + while (timeout--) { + if (readl(ANATOP_BASE_ADDR + 0xe0) & ANATOP_PLL_LOCK) + break; + } + if (timeout <= 0) + return -1; + reg &= ~ANATOP_PLL_BYPASS_MASK; + writel(reg, ANATOP_BASE_ADDR + 0xe0); + reg |= ANATOP_SATA_CLK_ENABLE_MASK; + writel(reg, ANATOP_BASE_ADDR + 0xe0); + + /* Enable sata phy */ + reg = readl(IOMUXC_BASE_ADDR + 0x34); /* GPR13 */ + + reg &= ~0x07ffffff; + /* + * rx_eq_val_0 = 5 [26:24] + * los_lvl = 0x12 [23:19] + * rx_dpll_mode_0 = 0x3 [18:16] + * mpll_ss_en = 0x0 [14] + * tx_atten_0 = 0x4 [13:11] + * tx_boost_0 = 0x0 [10:7] + * tx_lvl = 0x11 [6:2] + * mpll_ck_off_b = 0x1 [1] + * tx_edgerate_0 = 0x0 [0] + * */ + reg |= 0x59124c6; + writel(reg, IOMUXC_BASE_ADDR + 0x34); + + return 0; +} +#endif + +int dram_init(void) +{ + /* + * Switch PL301_FAST2 to DDR Dual-channel mapping + * however this block the boot up, temperory redraw + */ + /* + * u32 reg = 1; + * writel(reg, GPV0_BASE_ADDR); + */ + + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; + gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; + + return 0; +} + +static void setup_uart(void) +{ +#if defined CONFIG_MX6Q + /* UART4 TXD */ + mxc_iomux_v3_setup_pad(MX6Q_PAD_KEY_COL0__UART4_TXD); + + /* UART4 RXD */ + mxc_iomux_v3_setup_pad(MX6Q_PAD_KEY_ROW0__UART4_RXD); +#elif defined CONFIG_MX6DL + /* UART4 TXD */ + mxc_iomux_v3_setup_pad(MX6DL_PAD_KEY_COL0__UART4_TXD); + + /* UART4 RXD */ + mxc_iomux_v3_setup_pad(MX6DL_PAD_KEY_ROW0__UART4_RXD); +#endif +} + +#ifdef CONFIG_VIDEO_MX5 +void setup_lvds_poweron(void) +{ + int reg; + /* AUX_5V_EN: GPIO(6, 10) */ +#ifdef CONFIG_MX6DL + mxc_iomux_v3_setup_pad(MX6DL_PAD_NANDF_RB0__GPIO_6_10); +#else + mxc_iomux_v3_setup_pad(MX6Q_PAD_NANDF_RB0__GPIO_6_10); +#endif + + reg = readl(GPIO6_BASE_ADDR + GPIO_GDIR); + reg |= (1 << 10); + writel(reg, GPIO6_BASE_ADDR + GPIO_GDIR); + + reg = readl(GPIO6_BASE_ADDR + GPIO_DR); + reg |= (1 << 10); + writel(reg, GPIO6_BASE_ADDR + GPIO_DR); +} +#endif + +#ifdef CONFIG_I2C_MXC +#define I2C1_SDA_GPIO5_26_BIT_MASK (1 << 26) +#define I2C1_SCL_GPIO5_27_BIT_MASK (1 << 27) +#define I2C2_SCL_GPIO4_12_BIT_MASK (1 << 12) +#define I2C2_SDA_GPIO4_13_BIT_MASK (1 << 13) +#define I2C3_SCL_GPIO1_3_BIT_MASK (1 << 3) +#define I2C3_SDA_GPIO1_6_BIT_MASK (1 << 6) + +static void setup_i2c(unsigned int module_base) +{ + unsigned int reg; + + switch (module_base) { + case I2C1_BASE_ADDR: +#if defined CONFIG_MX6Q + /* i2c1 SDA */ + mxc_iomux_v3_setup_pad(MX6Q_PAD_CSI0_DAT8__I2C1_SDA); + + /* i2c1 SCL */ + mxc_iomux_v3_setup_pad(MX6Q_PAD_CSI0_DAT9__I2C1_SCL); +#elif defined CONFIG_MX6DL + /* i2c1 SDA */ + mxc_iomux_v3_setup_pad(MX6DL_PAD_CSI0_DAT8__I2C1_SDA); + /* i2c1 SCL */ + mxc_iomux_v3_setup_pad(MX6DL_PAD_CSI0_DAT9__I2C1_SCL); +#endif + + /* Enable i2c clock */ + reg = readl(CCM_BASE_ADDR + CLKCTL_CCGR2); + reg |= 0xC0; + writel(reg, CCM_BASE_ADDR + CLKCTL_CCGR2); + + break; + case I2C2_BASE_ADDR: +#if defined CONFIG_MX6Q + /* i2c2 SDA */ + mxc_iomux_v3_setup_pad(MX6Q_PAD_KEY_ROW3__I2C2_SDA); + + /* i2c2 SCL */ + mxc_iomux_v3_setup_pad(MX6Q_PAD_KEY_COL3__I2C2_SCL); +#elif defined CONFIG_MX6DL + /* i2c2 SDA */ + mxc_iomux_v3_setup_pad(MX6DL_PAD_KEY_ROW3__I2C2_SDA); + + /* i2c2 SCL */ + mxc_iomux_v3_setup_pad(MX6DL_PAD_KEY_COL3__I2C2_SCL); +#endif + + /* Enable i2c clock */ + reg = readl(CCM_BASE_ADDR + CLKCTL_CCGR2); + reg |= 0x300; + writel(reg, CCM_BASE_ADDR + CLKCTL_CCGR2); + + break; + case I2C3_BASE_ADDR: +#if defined CONFIG_MX6Q + /* GPIO_3 for I2C3_SCL */ + mxc_iomux_v3_setup_pad(MX6Q_PAD_GPIO_3__I2C3_SCL); + /* GPIO_6 for I2C3_SDA */ + mxc_iomux_v3_setup_pad(MX6Q_PAD_GPIO_6__I2C3_SDA); + +#elif defined CONFIG_MX6DL + /* GPIO_3 for I2C3_SCL */ + mxc_iomux_v3_setup_pad(MX6DL_PAD_GPIO_3__I2C3_SCL); + /* GPIO_6 for I2C3_SDA */ + mxc_iomux_v3_setup_pad(MX6DL_PAD_GPIO_6__I2C3_SDA); +#endif + /* Enable i2c clock */ + reg = readl(CCM_BASE_ADDR + CLKCTL_CCGR2); + reg |= 0xC00; + writel(reg, CCM_BASE_ADDR + CLKCTL_CCGR2); + + break; + default: + printf("Invalid I2C base: 0x%x\n", module_base); + break; + } +} +/* Note: udelay() is not accurate for i2c timing */ +static void __udelay(int time) +{ + int i, j; + + for (i = 0; i < time; i++) { + for (j = 0; j < 200; j++) { + asm("nop"); + asm("nop"); + } + } +} +static void mx6q_i2c_gpio_scl_direction(int bus, int output) +{ + u32 reg; + + switch (bus) { + case 1: +#if defined CONFIG_MX6Q + mxc_iomux_v3_setup_pad(MX6Q_PAD_CSI0_DAT9__GPIO_5_27); +#elif defined CONFIG_MX6DL + mxc_iomux_v3_setup_pad(MX6DL_PAD_CSI0_DAT9__GPIO_5_27); +#endif + reg = readl(GPIO5_BASE_ADDR + GPIO_GDIR); + if (output) + reg |= I2C1_SCL_GPIO5_27_BIT_MASK; + else + reg &= ~I2C1_SCL_GPIO5_27_BIT_MASK; + writel(reg, GPIO5_BASE_ADDR + GPIO_GDIR); + break; + case 2: +#if defined CONFIG_MX6Q + mxc_iomux_v3_setup_pad(MX6Q_PAD_KEY_COL3__GPIO_4_12); +#elif defined CONFIG_MX6DL + mxc_iomux_v3_setup_pad(MX6DL_PAD_KEY_COL3__GPIO_4_12); +#endif + reg = readl(GPIO4_BASE_ADDR + GPIO_GDIR); + if (output) + reg |= I2C2_SCL_GPIO4_12_BIT_MASK; + else + reg &= ~I2C2_SCL_GPIO4_12_BIT_MASK; + writel(reg, GPIO4_BASE_ADDR + GPIO_GDIR); + break; + case 3: +#if defined CONFIG_MX6Q + mxc_iomux_v3_setup_pad(MX6Q_PAD_GPIO_3__GPIO_1_3); +#elif defined CONFIG_MX6DL + mxc_iomux_v3_setup_pad(MX6DL_PAD_GPIO_3__GPIO_1_3); +#endif + reg = readl(GPIO1_BASE_ADDR + GPIO_GDIR); + if (output) + reg |= I2C3_SCL_GPIO1_3_BIT_MASK; + else + reg &= I2C3_SCL_GPIO1_3_BIT_MASK; + writel(reg, GPIO1_BASE_ADDR + GPIO_GDIR); + break; + } +} + +/* set 1 to output, sent 0 to input */ +static void mx6q_i2c_gpio_sda_direction(int bus, int output) +{ + u32 reg; + + switch (bus) { + case 1: +#if defined CONFIG_MX6Q + mxc_iomux_v3_setup_pad(MX6Q_PAD_CSI0_DAT8__GPIO_5_26); +#elif defined CONFIG_MX6DL + mxc_iomux_v3_setup_pad(MX6DL_PAD_CSI0_DAT8__GPIO_5_26); +#endif + reg = readl(GPIO5_BASE_ADDR + GPIO_GDIR); + if (output) + reg |= I2C1_SDA_GPIO5_26_BIT_MASK; + else + reg &= ~I2C1_SDA_GPIO5_26_BIT_MASK; + writel(reg, GPIO5_BASE_ADDR + GPIO_GDIR); + break; + case 2: +#if defined CONFIG_MX6Q + mxc_iomux_v3_setup_pad(MX6Q_PAD_KEY_ROW3__GPIO_4_13); +#elif defined CONFIG_MX6DL + mxc_iomux_v3_setup_pad(MX6DL_PAD_KEY_ROW3__GPIO_4_13); +#endif + reg = readl(GPIO4_BASE_ADDR + GPIO_GDIR); + if (output) + reg |= I2C2_SDA_GPIO4_13_BIT_MASK; + else + reg &= ~I2C2_SDA_GPIO4_13_BIT_MASK; + writel(reg, GPIO4_BASE_ADDR + GPIO_GDIR); + case 3: +#if defined CONFIG_MX6Q + mxc_iomux_v3_setup_pad(MX6Q_PAD_GPIO_6__GPIO_1_6); +#elif defined CONFIG_MX6DL + mxc_iomux_v3_setup_pad(MX6DL_PAD_GPIO_6__GPIO_1_6); +#endif + reg = readl(GPIO1_BASE_ADDR + GPIO_GDIR); + if (output) + reg |= I2C3_SDA_GPIO1_6_BIT_MASK; + else + reg &= ~I2C3_SDA_GPIO1_6_BIT_MASK; + writel(reg, GPIO1_BASE_ADDR + GPIO_GDIR); + default: + break; + } +} + +/* set 1 to high 0 to low */ +static void mx6q_i2c_gpio_scl_set_level(int bus, int high) +{ + u32 reg; + + switch (bus) { + case 1: + reg = readl(GPIO5_BASE_ADDR + GPIO_DR); + if (high) + reg |= I2C1_SCL_GPIO5_27_BIT_MASK; + else + reg &= ~I2C1_SCL_GPIO5_27_BIT_MASK; + writel(reg, GPIO5_BASE_ADDR + GPIO_DR); + break; + case 2: + reg = readl(GPIO4_BASE_ADDR + GPIO_DR); + if (high) + reg |= I2C2_SCL_GPIO4_12_BIT_MASK; + else + reg &= ~I2C2_SCL_GPIO4_12_BIT_MASK; + writel(reg, GPIO4_BASE_ADDR + GPIO_DR); + break; + case 3: + reg = readl(GPIO1_BASE_ADDR + GPIO_DR); + if (high) + reg |= I2C3_SCL_GPIO1_3_BIT_MASK; + else + reg &= ~I2C3_SCL_GPIO1_3_BIT_MASK; + writel(reg, GPIO1_BASE_ADDR + GPIO_DR); + break; + } +} + +/* set 1 to high 0 to low */ +static void mx6q_i2c_gpio_sda_set_level(int bus, int high) +{ + u32 reg; + + switch (bus) { + case 1: + reg = readl(GPIO5_BASE_ADDR + GPIO_DR); + if (high) + reg |= I2C1_SDA_GPIO5_26_BIT_MASK; + else + reg &= ~I2C1_SDA_GPIO5_26_BIT_MASK; + writel(reg, GPIO5_BASE_ADDR + GPIO_DR); + break; + case 2: + reg = readl(GPIO4_BASE_ADDR + GPIO_DR); + if (high) + reg |= I2C2_SDA_GPIO4_13_BIT_MASK; + else + reg &= ~I2C2_SDA_GPIO4_13_BIT_MASK; + writel(reg, GPIO4_BASE_ADDR + GPIO_DR); + break; + case 3: + reg = readl(GPIO1_BASE_ADDR + GPIO_DR); + if (high) + reg |= I2C3_SDA_GPIO1_6_BIT_MASK; + else + reg &= ~I2C3_SDA_GPIO1_6_BIT_MASK; + writel(reg, GPIO1_BASE_ADDR + GPIO_DR); + break; + } +} + +static int mx6q_i2c_gpio_check_sda(int bus) +{ + u32 reg; + int result = 0; + + switch (bus) { + case 1: + reg = readl(GPIO5_BASE_ADDR + GPIO_PSR); + result = !!(reg & I2C1_SDA_GPIO5_26_BIT_MASK); + break; + case 2: + reg = readl(GPIO4_BASE_ADDR + GPIO_PSR); + result = !!(reg & I2C2_SDA_GPIO4_13_BIT_MASK); + break; + case 3: + reg = readl(GPIO1_BASE_ADDR + GPIO_PSR); + result = !!(reg & I2C3_SDA_GPIO1_6_BIT_MASK); + break; + } + + return result; +} + + /* Random reboot cause i2c SDA low issue: + * the i2c bus busy because some device pull down the I2C SDA + * line. This happens when Host is reading some byte from slave, and + * then host is reset/reboot. Since in this case, device is + * controlling i2c SDA line, the only thing host can do this give the + * clock on SCL and sending NAK, and STOP to finish this + * transaction. + * + * How to fix this issue: + * detect if the SDA was low on bus send 8 dummy clock, and 1 + * clock + NAK, and STOP to finish i2c transaction the pending + * transfer. + */ +int i2c_bus_recovery(void) +{ + int i, bus, result = 0; + + for (bus = 1; bus <= 3; bus++) { + mx6q_i2c_gpio_sda_direction(bus, 0); + + if (mx6q_i2c_gpio_check_sda(bus) == 0) { + printf("i2c: I2C%d SDA is low, start i2c recovery...\n", bus); + mx6q_i2c_gpio_scl_direction(bus, 1); + mx6q_i2c_gpio_scl_set_level(bus, 1); + __udelay(10000); + + for (i = 0; i < 9; i++) { + mx6q_i2c_gpio_scl_set_level(bus, 1); + __udelay(5); + mx6q_i2c_gpio_scl_set_level(bus, 0); + __udelay(5); + } + + /* 9th clock here, the slave should already + release the SDA, we can set SDA as high to + a NAK.*/ + mx6q_i2c_gpio_sda_direction(bus, 1); + mx6q_i2c_gpio_sda_set_level(bus, 1); + __udelay(1); /* Pull up SDA first */ + mx6q_i2c_gpio_scl_set_level(bus, 1); + __udelay(5); /* plus pervious 1 us */ + mx6q_i2c_gpio_scl_set_level(bus, 0); + __udelay(5); + mx6q_i2c_gpio_sda_set_level(bus, 0); + __udelay(5); + mx6q_i2c_gpio_scl_set_level(bus, 1); + __udelay(5); + /* Here: SCL is high, and SDA from low to high, it's a + * stop condition */ + mx6q_i2c_gpio_sda_set_level(bus, 1); + __udelay(5); + + mx6q_i2c_gpio_sda_direction(bus, 0); + if (mx6q_i2c_gpio_check_sda(bus) == 1) + printf("I2C%d Recovery success\n", bus); + else { + printf("I2C%d Recovery failed, I2C1 SDA still low!!!\n", bus); + result |= 1 << bus; + } + } + + /* configure back to i2c */ + switch (bus) { + case 1: + setup_i2c(I2C1_BASE_ADDR); + break; + case 2: + setup_i2c(I2C2_BASE_ADDR); + break; + case 3: + setup_i2c(I2C3_BASE_ADDR); + break; + } + } + + return result; +} + + +void setup_pmic_voltages(void) +{ + unsigned char value = 0 ; + i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); + if (!i2c_probe(0x8)) { + if (i2c_read(0x8, 0, 1, &value, 1)) + printf("%s:i2c_read:error\n", __func__); + printf("Found PFUZE100! device id=%x\n", value); + #if CONFIG_MX6_INTER_LDO_BYPASS + /*VDDCORE 1.1V@800Mhz: SW1AB*/ + value = 0x20; + i2c_write(0x8, 0x20, 1, &value, 1); + + /*VDDSOC 1.2V : SW1C*/ + value = 0x24; + i2c_write(0x8, 0x2e, 1, &value, 1); + + /* Bypass the VDDSOC from Anatop */ + val = REG_RD(ANATOP_BASE_ADDR, HW_ANADIG_REG_CORE); + val &= ~BM_ANADIG_REG_CORE_REG2_TRG; + val |= BF_ANADIG_REG_CORE_REG2_TRG(0x1f); + REG_WR(ANATOP_BASE_ADDR, HW_ANADIG_REG_CORE, val); + + /* Bypass the VDDCORE from Anatop */ + val = REG_RD(ANATOP_BASE_ADDR, HW_ANADIG_REG_CORE); + val &= ~BM_ANADIG_REG_CORE_REG0_TRG; + val |= BF_ANADIG_REG_CORE_REG0_TRG(0x1f); + REG_WR(ANATOP_BASE_ADDR, HW_ANADIG_REG_CORE, val); + + /* Bypass the VDDPU from Anatop */ + val = REG_RD(ANATOP_BASE_ADDR, HW_ANADIG_REG_CORE); + val &= ~BM_ANADIG_REG_CORE_REG1_TRG; + val |= BF_ANADIG_REG_CORE_REG1_TRG(0x1f); + REG_WR(ANATOP_BASE_ADDR, HW_ANADIG_REG_CORE, val); + + /*clear PowerDown Enable bit of WDOG1_WMCR*/ + writew(0, WDOG1_BASE_ADDR + 0x08); + printf("hw_anadig_reg_core=%x\n", + REG_RD(ANATOP_BASE_ADDR, HW_ANADIG_REG_CORE)); + #endif + + } +} +#endif + +#ifdef CONFIG_IMX_ECSPI +s32 spi_get_cfg(struct imx_spi_dev_t *dev) +{ + switch (dev->slave.cs) { + case 0: + /* SPI-NOR */ + dev->base = ECSPI2_BASE_ADDR; + dev->freq = 25000000; + dev->ss_pol = IMX_SPI_ACTIVE_LOW; + dev->ss = 0; + dev->fifo_sz = 64 * 4; + dev->us_delay = 0; + break; + case 1: + /* SPI-NOR */ + dev->base = ECSPI2_BASE_ADDR; + dev->freq = 25000000; + dev->ss_pol = IMX_SPI_ACTIVE_LOW; + dev->ss = 1; + dev->fifo_sz = 64 * 4; + dev->us_delay = 0; + break; + default: + printf("Invalid Bus ID!\n"); + } + + return 0; +} + +void spi_io_init(struct imx_spi_dev_t *dev) +{ + u32 reg; + + switch (dev->base) { + case ECSPI2_BASE_ADDR: + /* Enable clock */ + reg = readl(CCM_BASE_ADDR + CLKCTL_CCGR1); + reg |= 0xC; + writel(reg, CCM_BASE_ADDR + CLKCTL_CCGR1); + +#if defined CONFIG_MX6Q + /* SCLK */ + mxc_iomux_v3_setup_pad(MX6Q_PAD_EIM_CS0__ECSPI2_SCLK); + + /* MISO */ + mxc_iomux_v3_setup_pad(MX6Q_PAD_EIM_OE__ECSPI2_MISO); + + /* MOSI */ + mxc_iomux_v3_setup_pad(MX6Q_PAD_EIM_CS1__ECSPI2_MOSI); + + mxc_iomux_v3_setup_pad(MX6Q_PAD_EIM_RW__ECSPI2_SS0); +#elif defined CONFIG_MX6DL + /* SCLK */ + mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_OE__ECSPI2_MISO); + + /* MISO */ + mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_OE__ECSPI2_MISO); + + /* MOSI */ + mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_CS1__ECSPI2_MOSI); + + mxc_iomux_v3_setup_pad(MX6DL_PAD_EIM_RW__ECSPI2_SS0); +#endif + break; + case ECSPI1_BASE_ADDR: + case ECSPI3_BASE_ADDR: + /* ecspi1,3 fall through */ + break; + default: + break; + } +} +#endif +#ifdef CONFIG_NAND_GPMI +#if defined CONFIG_MX6Q +iomux_v3_cfg_t nfc_pads[] = { + MX6Q_PAD_NANDF_CLE__RAWNAND_CLE, + MX6Q_PAD_NANDF_ALE__RAWNAND_ALE, + MX6Q_PAD_NANDF_WP_B__RAWNAND_RESETN, + MX6Q_PAD_NANDF_RB0__RAWNAND_READY0, + MX6Q_PAD_NANDF_CS0__RAWNAND_CE0N, + MX6Q_PAD_NANDF_CS1__RAWNAND_CE1N, + MX6Q_PAD_NANDF_CS2__RAWNAND_CE2N, + MX6Q_PAD_NANDF_CS3__RAWNAND_CE3N, + MX6Q_PAD_SD4_CMD__RAWNAND_RDN, + MX6Q_PAD_SD4_CLK__RAWNAND_WRN, + MX6Q_PAD_NANDF_D0__RAWNAND_D0, + MX6Q_PAD_NANDF_D1__RAWNAND_D1, + MX6Q_PAD_NANDF_D2__RAWNAND_D2, + MX6Q_PAD_NANDF_D3__RAWNAND_D3, + MX6Q_PAD_NANDF_D4__RAWNAND_D4, + MX6Q_PAD_NANDF_D5__RAWNAND_D5, + MX6Q_PAD_NANDF_D6__RAWNAND_D6, + MX6Q_PAD_NANDF_D7__RAWNAND_D7, + MX6Q_PAD_SD4_DAT0__RAWNAND_DQS, +}; +#elif defined CONFIG_MX6DL +iomux_v3_cfg_t nfc_pads[] = { + MX6DL_PAD_NANDF_CLE__RAWNAND_CLE, + MX6DL_PAD_NANDF_ALE__RAWNAND_ALE, + MX6DL_PAD_NANDF_WP_B__RAWNAND_RESETN, + MX6DL_PAD_NANDF_RB0__RAWNAND_READY0, + MX6DL_PAD_NANDF_CS0__RAWNAND_CE0N, + MX6DL_PAD_NANDF_CS1__RAWNAND_CE1N, + MX6DL_PAD_NANDF_CS2__RAWNAND_CE2N, + MX6DL_PAD_NANDF_CS3__RAWNAND_CE3N, + MX6DL_PAD_SD4_CMD__RAWNAND_RDN, + MX6DL_PAD_SD4_CLK__RAWNAND_WRN, + MX6DL_PAD_NANDF_D0__RAWNAND_D0, + MX6DL_PAD_NANDF_D1__RAWNAND_D1, + MX6DL_PAD_NANDF_D2__RAWNAND_D2, + MX6DL_PAD_NANDF_D3__RAWNAND_D3, + MX6DL_PAD_NANDF_D4__RAWNAND_D4, + MX6DL_PAD_NANDF_D5__RAWNAND_D5, + MX6DL_PAD_NANDF_D6__RAWNAND_D6, + MX6DL_PAD_NANDF_D7__RAWNAND_D7, + MX6DL_PAD_SD4_DAT0__RAWNAND_DQS, +}; +#endif + +int setup_gpmi_nand(void) +{ + unsigned int reg; + + /* config gpmi nand iomux */ + mxc_iomux_v3_setup_multiple_pads(nfc_pads, + ARRAY_SIZE(nfc_pads)); + + + /* config gpmi and bch clock to 11Mhz*/ + reg = readl(CCM_BASE_ADDR + CLKCTL_CS2CDR); + reg &= 0xF800FFFF; + reg |= 0x01E40000; + writel(reg, CCM_BASE_ADDR + CLKCTL_CS2CDR); + + /* enable gpmi and bch clock gating */ + reg = readl(CCM_BASE_ADDR + CLKCTL_CCGR4); + reg |= 0xFF003000; + writel(reg, CCM_BASE_ADDR + CLKCTL_CCGR4); + + /* enable apbh clock gating */ + reg = readl(CCM_BASE_ADDR + CLKCTL_CCGR0); + reg |= 0x0030; + writel(reg, CCM_BASE_ADDR + CLKCTL_CCGR0); + +} +#endif + +#ifdef CONFIG_NET_MULTI +int board_eth_init(bd_t *bis) +{ + int rc = -ENODEV; + + return rc; +} +#endif + +#ifdef CONFIG_CMD_MMC + +/* On this board, only SD3 can support 1.8V signalling + * that is required for UHS-I mode of operation. + * Last element in struct is used to indicate 1.8V support. + */ +struct fsl_esdhc_cfg usdhc_cfg[4] = { + {USDHC1_BASE_ADDR, 1, 1, 1, 0}, + {USDHC2_BASE_ADDR, 1, 1, 1, 0}, + {USDHC3_BASE_ADDR, 1, 1, 1, 0}, + {USDHC4_BASE_ADDR, 1, 1, 1, 0}, +}; + +#ifdef CONFIG_DYNAMIC_MMC_DEVNO +int get_mmc_env_devno(void) +{ + uint soc_sbmr = readl(SRC_BASE_ADDR + 0x4); + + if (SD_BOOT == boot_dev || MMC_BOOT == boot_dev) { + /* BOOT_CFG2[3] and BOOT_CFG2[4] */ + return (soc_sbmr & 0x00001800) >> 11; + } else + return -1; + +} +#endif + +#if defined CONFIG_MX6Q +iomux_v3_cfg_t usdhc1_pads[] = { + MX6Q_PAD_SD1_CLK__USDHC1_CLK, + MX6Q_PAD_SD1_CMD__USDHC1_CMD, + MX6Q_PAD_SD1_DAT0__USDHC1_DAT0, + MX6Q_PAD_SD1_DAT1__USDHC1_DAT1, + MX6Q_PAD_SD1_DAT2__USDHC1_DAT2, + MX6Q_PAD_SD1_DAT3__USDHC1_DAT3, +}; + +iomux_v3_cfg_t usdhc2_pads[] = { + MX6Q_PAD_SD2_CLK__USDHC2_CLK, + MX6Q_PAD_SD2_CMD__USDHC2_CMD, + MX6Q_PAD_SD2_DAT0__USDHC2_DAT0, + MX6Q_PAD_SD2_DAT1__USDHC2_DAT1, + MX6Q_PAD_SD2_DAT2__USDHC2_DAT2, + MX6Q_PAD_SD2_DAT3__USDHC2_DAT3, +}; + +iomux_v3_cfg_t usdhc3_pads[] = { + MX6Q_PAD_SD3_CLK__USDHC3_CLK, + MX6Q_PAD_SD3_CMD__USDHC3_CMD, + MX6Q_PAD_SD3_DAT0__USDHC3_DAT0, + MX6Q_PAD_SD3_DAT1__USDHC3_DAT1, + MX6Q_PAD_SD3_DAT2__USDHC3_DAT2, + MX6Q_PAD_SD3_DAT3__USDHC3_DAT3, + MX6Q_PAD_SD3_DAT4__USDHC3_DAT4, + MX6Q_PAD_SD3_DAT5__USDHC3_DAT5, + MX6Q_PAD_SD3_DAT6__USDHC3_DAT6, + MX6Q_PAD_SD3_DAT7__USDHC3_DAT7, +}; + +iomux_v3_cfg_t usdhc4_pads[] = { + MX6Q_PAD_SD4_CLK__USDHC4_CLK, + MX6Q_PAD_SD4_CMD__USDHC4_CMD, + MX6Q_PAD_SD4_DAT0__USDHC4_DAT0, + MX6Q_PAD_SD4_DAT1__USDHC4_DAT1, + MX6Q_PAD_SD4_DAT2__USDHC4_DAT2, + MX6Q_PAD_SD4_DAT3__USDHC4_DAT3, + MX6Q_PAD_SD4_DAT4__USDHC4_DAT4, + MX6Q_PAD_SD4_DAT5__USDHC4_DAT5, + MX6Q_PAD_SD4_DAT6__USDHC4_DAT6, + MX6Q_PAD_SD4_DAT7__USDHC4_DAT7, +}; +#elif defined CONFIG_MX6DL +iomux_v3_cfg_t usdhc1_pads[] = { + MX6DL_PAD_SD1_CLK__USDHC1_CLK, + MX6DL_PAD_SD1_CMD__USDHC1_CMD, + MX6DL_PAD_SD1_DAT0__USDHC1_DAT0, + MX6DL_PAD_SD1_DAT1__USDHC1_DAT1, + MX6DL_PAD_SD1_DAT2__USDHC1_DAT2, + MX6DL_PAD_SD1_DAT3__USDHC1_DAT3, +}; + +iomux_v3_cfg_t usdhc2_pads[] = { + MX6DL_PAD_SD2_CLK__USDHC2_CLK, + MX6DL_PAD_SD2_CMD__USDHC2_CMD, + MX6DL_PAD_SD2_DAT0__USDHC2_DAT0, + MX6DL_PAD_SD2_DAT1__USDHC2_DAT1, + MX6DL_PAD_SD2_DAT2__USDHC2_DAT2, + MX6DL_PAD_SD2_DAT3__USDHC2_DAT3, +}; + +iomux_v3_cfg_t usdhc3_pads[] = { + MX6DL_PAD_SD3_CLK__USDHC3_CLK, + MX6DL_PAD_SD3_CMD__USDHC3_CMD, + MX6DL_PAD_SD3_DAT0__USDHC3_DAT0, + MX6DL_PAD_SD3_DAT1__USDHC3_DAT1, + MX6DL_PAD_SD3_DAT2__USDHC3_DAT2, + MX6DL_PAD_SD3_DAT3__USDHC3_DAT3, + MX6DL_PAD_SD3_DAT4__USDHC3_DAT4, + MX6DL_PAD_SD3_DAT5__USDHC3_DAT5, + MX6DL_PAD_SD3_DAT6__USDHC3_DAT6, + MX6DL_PAD_SD3_DAT7__USDHC3_DAT7, +}; + +iomux_v3_cfg_t usdhc4_pads[] = { + MX6DL_PAD_SD4_CLK__USDHC4_CLK, + MX6DL_PAD_SD4_CMD__USDHC4_CMD, + MX6DL_PAD_SD4_DAT0__USDHC4_DAT0, + MX6DL_PAD_SD4_DAT1__USDHC4_DAT1, + MX6DL_PAD_SD4_DAT2__USDHC4_DAT2, + MX6DL_PAD_SD4_DAT3__USDHC4_DAT3, + MX6DL_PAD_SD4_DAT4__USDHC4_DAT4, + MX6DL_PAD_SD4_DAT5__USDHC4_DAT5, + MX6DL_PAD_SD4_DAT6__USDHC4_DAT6, + MX6DL_PAD_SD4_DAT7__USDHC4_DAT7, +}; +#endif + +int usdhc_gpio_init(bd_t *bis) +{ + s32 status = 0; + u32 index = 0; + + for (index = 0; index < CONFIG_SYS_FSL_USDHC_NUM; + ++index) { + switch (index) { + case 0: + mxc_iomux_v3_setup_multiple_pads(usdhc1_pads, + sizeof(usdhc1_pads) / + sizeof(usdhc1_pads[0])); + break; + case 1: + mxc_iomux_v3_setup_multiple_pads(usdhc2_pads, + sizeof(usdhc2_pads) / + sizeof(usdhc2_pads[0])); + break; + case 2: + mxc_iomux_v3_setup_multiple_pads(usdhc3_pads, + sizeof(usdhc3_pads) / + sizeof(usdhc3_pads[0])); + break; + case 3: + mxc_iomux_v3_setup_multiple_pads(usdhc4_pads, + sizeof(usdhc4_pads) / + sizeof(usdhc4_pads[0])); + break; + default: + printf("Warning: you configured more USDHC controllers" + "(%d) then supported by the board (%d)\n", + index+1, CONFIG_SYS_FSL_USDHC_NUM); + return status; + } + status |= fsl_esdhc_initialize(bis, &usdhc_cfg[index]); + } + + return status; +} + +int board_mmc_init(bd_t *bis) +{ + if (!usdhc_gpio_init(bis)) + return 0; + else + return -1; +} + +/* For DDR mode operation, provide target delay parameter for each SD port. + * Use cfg->esdhc_base to distinguish the SD port #. The delay for each port + * is dependent on signal layout for that particular port. If the following + * CONFIG is not defined, then the default target delay value will be used. + */ +#ifdef CONFIG_GET_DDR_TARGET_DELAY +u32 get_ddr_delay(struct fsl_esdhc_cfg *cfg) +{ + /* No delay required on SABRESD board SD ports */ + return 0; +} +#endif + +#endif + +#ifdef CONFIG_LCD +void lcd_enable(void) +{ + char *s; + int ret; + unsigned int reg; + + s = getenv("lvds_num"); + di = simple_strtol(s, NULL, 10); + + /* + * hw_rev 2: IPUV3DEX + * hw_rev 3: IPUV3M + * hw_rev 4: IPUV3H + */ + g_ipu_hw_rev = IPUV3_HW_REV_IPUV3H; + +#if defined CONFIG_MX6Q + mxc_iomux_v3_setup_pad(MX6Q_PAD_SD1_DAT3__GPIO_1_21); +#elif defined CONFIG_MX6DL + mxc_iomux_v3_setup_pad(MX6DL_PAD_SD1_DAT3__GPIO_1_21); +#endif + + reg = readl(GPIO1_BASE_ADDR + GPIO_GDIR); + reg |= (1 << 21); + writel(reg, GPIO1_BASE_ADDR + GPIO_GDIR); + + reg = readl(GPIO1_BASE_ADDR + GPIO_DR); + reg |= (1 << 21); + writel(reg, GPIO1_BASE_ADDR + GPIO_DR); + + /* Enable IPU clock */ + if (di == 1) { + reg = readl(CCM_BASE_ADDR + CLKCTL_CCGR3); + reg |= 0xC033; + writel(reg, CCM_BASE_ADDR + CLKCTL_CCGR3); + } else { + reg = readl(CCM_BASE_ADDR + CLKCTL_CCGR3); + reg |= 0x300F; + writel(reg, CCM_BASE_ADDR + CLKCTL_CCGR3); + } + + ret = ipuv3_fb_init(&lvds_xga, di, IPU_PIX_FMT_RGB666, + DI_PCLK_LDB, 65000000); + if (ret) + puts("LCD cannot be configured\n"); + + reg = readl(ANATOP_BASE_ADDR + 0xF0); + reg &= ~0x00003F00; + reg |= 0x00001300; + writel(reg, ANATOP_BASE_ADDR + 0xF4); + + reg = readl(CCM_BASE_ADDR + CLKCTL_CS2CDR); + reg &= ~0x00007E00; + reg |= 0x00003600; + writel(reg, CCM_BASE_ADDR + CLKCTL_CS2CDR); + + reg = readl(CCM_BASE_ADDR + CLKCTL_CSCMR2); + reg |= 0x00000C00; + writel(reg, CCM_BASE_ADDR + CLKCTL_CSCMR2); + + reg = 0x0002A953; + writel(reg, CCM_BASE_ADDR + CLKCTL_CHSCCDR); + + if (di == 1) + writel(0x40C, IOMUXC_BASE_ADDR + 0x8); + else + writel(0x201, IOMUXC_BASE_ADDR + 0x8); +} +#endif + +#ifdef CONFIG_VIDEO_MX5 +void panel_info_init(void) +{ + panel_info.vl_bpix = LCD_BPP; + panel_info.vl_col = lvds_xga.xres; + panel_info.vl_row = lvds_xga.yres; + panel_info.cmap = colormap; +} +#endif + +#ifdef CONFIG_SPLASH_SCREEN +void setup_splash_image(void) +{ + char *s; + ulong addr; + + s = getenv("splashimage"); + + if (s != NULL) { + addr = simple_strtoul(s, NULL, 16); + +#if defined(CONFIG_ARCH_MMU) + addr = ioremap_nocache(iomem_to_phys(addr), + fsl_bmp_600x400_size); +#endif + memcpy((char *)addr, (char *)fsl_bmp_600x400, + fsl_bmp_600x400_size); + } +} +#endif + +int board_init(void) +{ +/* need set Power Supply Glitch to 0x41736166 +*and need clear Power supply Glitch Detect bit +* when POR or reboot or power on Otherwise system +*could not be power off anymore*/ + u32 reg; + writel(0x41736166, SNVS_BASE_ADDR + 0x64);/*set LPPGDR*/ + udelay(10); + reg = readl(SNVS_BASE_ADDR + 0x4c); + reg |= (1 << 3); + writel(reg, SNVS_BASE_ADDR + 0x4c);/*clear LPSR*/ + + mxc_iomux_v3_init((void *)IOMUXC_BASE_ADDR); +#if defined CONFIG_MX6Q + mxc_iomux_v3_setup_pad(MX6Q_PAD_NANDF_D6__GPIO_2_6); +#elif defined CONFIG_MX6DL + mxc_iomux_v3_setup_pad(MX6DL_PAD_NANDF_D6__GPIO_2_6); +#endif + gpio_direction_output(HDMIDONGLE_CHG_SYS_ON, 1); + setup_boot_device(); + fsl_set_system_rev(); + + /* board id for linux */ + gd->bd->bi_arch_number = MACH_TYPE_MX6Q_HDMIDONGLE; + + /* address of boot parameters */ + gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100; + + setup_uart(); + +#ifdef CONFIG_DWC_AHSATA + setup_sata(); +#endif + +#ifdef CONFIG_VIDEO_MX5 + /* Enable lvds power */ + setup_lvds_poweron(); + + panel_info_init(); + + gd->fb_base = CONFIG_FB_BASE; +#ifdef CONFIG_ARCH_MMU + gd->fb_base = ioremap_nocache(iomem_to_phys(gd->fb_base), 0); +#endif +#endif + +#ifdef CONFIG_NAND_GPMI + setup_gpmi_nand(); +#endif + return 0; +} + + +#ifdef CONFIG_ANDROID_RECOVERY +int check_recovery_cmd_file(void) +{ + int button_pressed = 0; + int recovery_mode = 0; + + recovery_mode = check_and_clean_recovery_flag(); + + /* Check Recovery Combo Button press or not. */ + mxc_iomux_v3_setup_pad(MX6X_IOMUX(PAD_ENET_RXD0__GPIO_1_27)); + + gpio_direction_input(GPIO_REVB_POWER_KEY); + + if (gpio_get_value(GPIO_REVB_POWER_KEY) == 0) { /* VOL_DN key is low assert */ + button_pressed = 1; + printf("Recovery key pressed\n"); + } + + return recovery_mode || button_pressed; +} +#endif + +int board_late_init(void) +{ + #ifdef CONFIG_I2C_MXC + setup_i2c(CONFIG_SYS_I2C_PORT); + i2c_bus_recovery(); + setup_pmic_voltages(); + #endif + return 0; +} + +#ifdef CONFIG_MXC_FEC +static int phy_read(char *devname, unsigned char addr, unsigned char reg, + unsigned short *pdata) +{ + int ret = miiphy_read(devname, addr, reg, pdata); + if (ret) + printf("Error reading from %s PHY addr=%02x reg=%02x\n", + devname, addr, reg); + return ret; +} + +static int phy_write(char *devname, unsigned char addr, unsigned char reg, + unsigned short value) +{ + int ret = miiphy_write(devname, addr, reg, value); + if (ret) + printf("Error writing to %s PHY addr=%02x reg=%02x\n", devname, + addr, reg); + return ret; +} + +int mx6_rgmii_rework(char *devname, int phy_addr) +{ + unsigned short val; + + /* To enable AR8031 ouput a 125MHz clk from CLK_25M */ + phy_write(devname, phy_addr, 0xd, 0x7); + phy_write(devname, phy_addr, 0xe, 0x8016); + phy_write(devname, phy_addr, 0xd, 0x4007); + phy_read(devname, phy_addr, 0xe, &val); + + val &= 0xffe3; + val |= 0x18; + phy_write(devname, phy_addr, 0xe, val); + + /* introduce tx clock delay */ + phy_write(devname, phy_addr, 0x1d, 0x5); + phy_read(devname, phy_addr, 0x1e, &val); + val |= 0x0100; + phy_write(devname, phy_addr, 0x1e, val); + + return 0; +} + +#if defined CONFIG_MX6Q +iomux_v3_cfg_t enet_pads[] = { + MX6Q_PAD_ENET_MDIO__ENET_MDIO, + MX6Q_PAD_ENET_MDC__ENET_MDC, + MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC, + MX6Q_PAD_RGMII_TD0__ENET_RGMII_TD0, + MX6Q_PAD_RGMII_TD1__ENET_RGMII_TD1, + MX6Q_PAD_RGMII_TD2__ENET_RGMII_TD2, + MX6Q_PAD_RGMII_TD3__ENET_RGMII_TD3, + MX6Q_PAD_RGMII_TX_CTL__ENET_RGMII_TX_CTL, + MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK, + MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC, + MX6Q_PAD_RGMII_RD0__ENET_RGMII_RD0, + MX6Q_PAD_RGMII_RD1__ENET_RGMII_RD1, + MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2, + MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3, + MX6Q_PAD_RGMII_RX_CTL__ENET_RGMII_RX_CTL, + MX6Q_PAD_GPIO_0__CCM_CLKO, + MX6Q_PAD_GPIO_3__CCM_CLKO2, +}; +#elif defined CONFIG_MX6DL +iomux_v3_cfg_t enet_pads[] = { + MX6DL_PAD_ENET_MDIO__ENET_MDIO, + MX6DL_PAD_ENET_MDC__ENET_MDC, + MX6DL_PAD_RGMII_TXC__ENET_RGMII_TXC, + MX6DL_PAD_RGMII_TD0__ENET_RGMII_TD0, + MX6DL_PAD_RGMII_TD1__ENET_RGMII_TD1, + MX6DL_PAD_RGMII_TD2__ENET_RGMII_TD2, + MX6DL_PAD_RGMII_TD3__ENET_RGMII_TD3, + MX6DL_PAD_RGMII_TX_CTL__ENET_RGMII_TX_CTL, + MX6DL_PAD_ENET_REF_CLK__ENET_TX_CLK, + MX6DL_PAD_RGMII_RXC__ENET_RGMII_RXC, + MX6DL_PAD_RGMII_RD0__ENET_RGMII_RD0, + MX6DL_PAD_RGMII_RD1__ENET_RGMII_RD1, + MX6DL_PAD_RGMII_RD2__ENET_RGMII_RD2, + MX6DL_PAD_RGMII_RD3__ENET_RGMII_RD3, + MX6DL_PAD_RGMII_RX_CTL__ENET_RGMII_RX_CTL, + MX6DL_PAD_GPIO_0__CCM_CLKO, +}; +#endif + +void enet_board_init(void) +{ + unsigned int reg; +#if defined CONFIG_MX6Q + iomux_v3_cfg_t enet_reset = + (_MX6Q_PAD_ENET_CRS_DV__GPIO_1_25 & + ~MUX_PAD_CTRL_MASK) | + MUX_PAD_CTRL(0x88); +#elif defined CONFIG_MX6DL + iomux_v3_cfg_t enet_reset = + (MX6DL_PAD_ENET_CRS_DV__GPIO_1_25 & + ~MUX_PAD_CTRL_MASK) | + MUX_PAD_CTRL(0x88); +#endif + + mxc_iomux_v3_setup_multiple_pads(enet_pads, + ARRAY_SIZE(enet_pads)); + mxc_iomux_v3_setup_pad(enet_reset); + + /* phy reset: gpio1-25 */ + reg = readl(GPIO1_BASE_ADDR + 0x0); + reg &= ~0x2000000; + writel(reg, GPIO1_BASE_ADDR + 0x0); + + reg = readl(GPIO1_BASE_ADDR + 0x4); + reg |= 0x2000000; + writel(reg, GPIO1_BASE_ADDR + 0x4); + + udelay(500); + + reg = readl(GPIO1_BASE_ADDR + 0x0); + reg |= 0x2000000; + writel(reg, GPIO1_BASE_ADDR + 0x0); +} +#endif + +int checkboard(void) +{ + printf("Board: %s-HDMIDONGLE: %s Board: 0x%x [", + mx6_chip_name(), + mx6_board_rev_name(), + fsl_system_rev); + + switch (__REG(SRC_BASE_ADDR + 0x8)) { + case 0x0001: + printf("POR"); + break; + case 0x0009: + printf("RST"); + break; + case 0x0010: + case 0x0011: + printf("WDOG"); + break; + default: + printf("unknown"); + } + printf(" ]\n"); + + printf("Boot Device: "); + switch (get_boot_device()) { + case WEIM_NOR_BOOT: + printf("NOR\n"); + break; + case ONE_NAND_BOOT: + printf("ONE NAND\n"); + break; + case PATA_BOOT: + printf("PATA\n"); + break; + case SATA_BOOT: + printf("SATA\n"); + break; + case I2C_BOOT: + printf("I2C\n"); + break; + case SPI_NOR_BOOT: + printf("SPI NOR\n"); + break; + case SD_BOOT: + printf("SD\n"); + break; + case MMC_BOOT: + printf("MMC\n"); + break; + case NAND_BOOT: + printf("NAND\n"); + break; + case UNKNOWN_BOOT: + default: + printf("UNKNOWN\n"); + break; + } + return 0; +} + +#ifdef CONFIG_IMX_UDC + +void udc_pins_setting(void) +{ + mxc_iomux_v3_setup_pad(MX6X_IOMUX(PAD_GPIO_1__USBOTG_ID)); + mxc_iomux_v3_setup_pad(MX6X_IOMUX(PAD_KEY_ROW4__GPIO_4_15)); + if (mx6_board_is_reva()) + mxc_iomux_v3_setup_pad(MX6X_IOMUX(PAD_KEY_COL4__GPIO_4_14)); + + /* set USB_OTG_PWR to 0 */ + gpio_direction_output(USB_OTG_PWR, 0); + + /* set USB_H1_POWER to 1 */ + if (mx6_board_is_reva()) + gpio_direction_output(USB_H1_POWER, 1); + + mxc_iomux_set_gpr_register(1, 13, 1, 0); + +} +#endif diff --git a/board/freescale/mx6q_hdmidongle/u-boot.lds b/board/freescale/mx6q_hdmidongle/u-boot.lds new file mode 100644 index 0000000..fe2bda1 --- /dev/null +++ b/board/freescale/mx6q_hdmidongle/u-boot.lds @@ -0,0 +1,74 @@ +/* + * January 2004 - Changed to support H4 device + * Copyright (c) 2004 Texas Instruments + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * (C) Copyright 2012 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 + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + /* WARNING - the following is hand-optimized to fit within */ + /* the sector layout of our flash chips! XXX FIXME XXX */ + board/freescale/mx6q_hdmidongle/flash_header.o (.text.flasheader) + cpu/arm_cortexa8/start.o + board/freescale/mx6q_hdmidongle/libmx6q_hdmidongle.a (.text) + lib_arm/libarm.a (.text) + net/libnet.a (.text) + drivers/mtd/libmtd.a (.text) + drivers/mmc/libmmc.a (.text) + + . = DEFINED(env_offset) ? env_offset : .; + common/env_embedded.o(.text) + + *(.text) + } + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + .got : { *(.got) } + + . = .; + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = ALIGN(4); + _end_of_copy = .; /* end_of ROM copy code here */ + __bss_start = .; + .bss : { *(.bss) } + _end = .; +} -- cgit v1.1