#include <asm/arch/imx-regs.h>
#include <asm/arch/iomux.h>
#include <asm/arch/mx6-pins.h>
-#include <asm/errno.h>
+#include <asm/arch/mxc_hdmi.h>
+#include <linux/errno.h>
#include <asm/gpio.h>
#include <asm/imx-common/iomux-v3.h>
+#include <asm/imx-common/video.h>
#include <mmc.h>
#include <fsl_esdhc.h>
+#include <malloc.h>
#include <miiphy.h>
#include <netdev.h>
#include <asm/arch/crm_regs.h>
#include <asm/io.h>
#include <asm/arch/sys_proto.h>
#include <spl.h>
+#include <usb.h>
+#include <usb/ehci-ci.h>
DECLARE_GLOBAL_DATA_PTR;
PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST)
#define ETH_PHY_RESET IMX_GPIO_NR(4, 15)
+#define USB_H1_VBUS IMX_GPIO_NR(1, 0)
int dram_init(void)
{
IOMUX_PADS(PAD_EIM_DA4__GPIO3_IO04 | MUX_PAD_CTRL(UART_PAD_CTRL)),
};
+static iomux_v3_cfg_t const usb_pads[] = {
+ IOMUX_PADS(PAD_GPIO_0__GPIO1_IO00 | MUX_PAD_CTRL(NO_PAD_CTRL)),
+};
+
static void setup_iomux_uart(void)
{
SETUP_IOMUX_PADS(uart1_pads);
IOMUX_PADS(PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
IOMUX_PADS(PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
IOMUX_PADS(PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)),
+ IOMUX_PADS(PAD_ENET_RXD0__GPIO1_IO27 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)),
+ IOMUX_PADS(PAD_ENET_RXD1__GPIO1_IO26 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)),
};
static void setup_iomux_enet(void)
SETUP_IOMUX_PADS(enet_pads);
gpio_direction_output(ETH_PHY_RESET, 0);
- mdelay(2);
+ mdelay(10);
gpio_set_value(ETH_PHY_RESET, 1);
+ udelay(100);
}
int board_phy_config(struct phy_device *phydev)
return 0;
}
+/* On Cuboxi Ethernet PHY can be located at addresses 0x0 or 0x4 */
+#define ETH_PHY_MASK ((1 << 0x0) | (1 << 0x4))
+
int board_eth_init(bd_t *bis)
{
struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
+ struct mii_dev *bus;
+ struct phy_device *phydev;
- int ret = enable_fec_anatop_clock(ENET_25MHZ);
+ int ret = enable_fec_anatop_clock(0, ENET_25MHZ);
if (ret)
return ret;
setup_iomux_enet();
- return cpu_eth_init(bis);
+ bus = fec_get_miibus(IMX_FEC_BASE, -1);
+ if (!bus)
+ return -EINVAL;
+
+ phydev = phy_find_by_mask(bus, ETH_PHY_MASK, PHY_INTERFACE_MODE_RGMII);
+ if (!phydev) {
+ ret = -EINVAL;
+ goto free_bus;
+ }
+
+ debug("using phy at address %d\n", phydev->addr);
+ ret = fec_probe(bis, -1, IMX_FEC_BASE, bus, phydev);
+ if (ret)
+ goto free_phydev;
+
+ return 0;
+
+free_phydev:
+ free(phydev);
+free_bus:
+ free(bus);
+ return ret;
+}
+
+#ifdef CONFIG_VIDEO_IPUV3
+static void do_enable_hdmi(struct display_info_t const *dev)
+{
+ imx_enable_hdmi_phy();
+}
+
+struct display_info_t const displays[] = {
+ {
+ .bus = -1,
+ .addr = 0,
+ .pixfmt = IPU_PIX_FMT_RGB24,
+ .detect = detect_hdmi,
+ .enable = do_enable_hdmi,
+ .mode = {
+ .name = "HDMI",
+ /* 1024x768@60Hz (VESA)*/
+ .refresh = 60,
+ .xres = 1024,
+ .yres = 768,
+ .pixclock = 15384,
+ .left_margin = 160,
+ .right_margin = 24,
+ .upper_margin = 29,
+ .lower_margin = 3,
+ .hsync_len = 136,
+ .vsync_len = 6,
+ .sync = FB_SYNC_EXT,
+ .vmode = FB_VMODE_NONINTERLACED
+ }
+ }
+};
+
+size_t display_count = ARRAY_SIZE(displays);
+
+static int setup_display(void)
+{
+ struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+ int reg;
+ int timeout = 100000;
+
+ enable_ipu_clock();
+ imx_setup_hdmi();
+
+ /* set video pll to 455MHz (24MHz * (37+11/12) / 2) */
+ setbits_le32(&ccm->analog_pll_video, BM_ANADIG_PLL_VIDEO_POWERDOWN);
+
+ reg = readl(&ccm->analog_pll_video);
+ reg &= ~BM_ANADIG_PLL_VIDEO_DIV_SELECT;
+ reg |= BF_ANADIG_PLL_VIDEO_DIV_SELECT(37);
+ reg &= ~BM_ANADIG_PLL_VIDEO_POST_DIV_SELECT;
+ reg |= BF_ANADIG_PLL_VIDEO_POST_DIV_SELECT(1);
+ writel(reg, &ccm->analog_pll_video);
+
+ writel(BF_ANADIG_PLL_VIDEO_NUM_A(11), &ccm->analog_pll_video_num);
+ writel(BF_ANADIG_PLL_VIDEO_DENOM_B(12), &ccm->analog_pll_video_denom);
+
+ reg &= ~BM_ANADIG_PLL_VIDEO_POWERDOWN;
+ writel(reg, &ccm->analog_pll_video);
+
+ while (timeout--)
+ if (readl(&ccm->analog_pll_video) & BM_ANADIG_PLL_VIDEO_LOCK)
+ break;
+ if (timeout < 0) {
+ printf("Warning: video pll lock timeout!\n");
+ return -ETIMEDOUT;
+ }
+
+ reg = readl(&ccm->analog_pll_video);
+ reg |= BM_ANADIG_PLL_VIDEO_ENABLE;
+ reg &= ~BM_ANADIG_PLL_VIDEO_BYPASS;
+ writel(reg, &ccm->analog_pll_video);
+
+ /* gate ipu1_di0_clk */
+ clrbits_le32(&ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK);
+
+ /* select video_pll clock / 7 for ipu1_di0_clk -> 65MHz pixclock */
+ reg = readl(&ccm->chsccdr);
+ reg &= ~(MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK |
+ MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK |
+ MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK);
+ reg |= (2 << MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET) |
+ (6 << MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET) |
+ (0 << MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET);
+ writel(reg, &ccm->chsccdr);
+
+ /* enable ipu1_di0_clk */
+ setbits_le32(&ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK);
+
+ return 0;
+}
+#endif /* CONFIG_VIDEO_IPUV3 */
+
+#ifdef CONFIG_USB_EHCI_MX6
+static void setup_usb(void)
+{
+ SETUP_IOMUX_PADS(usb_pads);
}
+int board_ehci_hcd_init(int port)
+{
+ if (port == 1)
+ gpio_direction_output(USB_H1_VBUS, 1);
+
+ return 0;
+}
+#endif
+
int board_early_init_f(void)
{
+ int ret = 0;
setup_iomux_uart();
- return 0;
+
+#ifdef CONFIG_VIDEO_IPUV3
+ ret = setup_display();
+#endif
+
+#ifdef CONFIG_USB_EHCI_MX6
+ setup_usb();
+#endif
+ return ret;
}
int board_init(void)
return 0;
}
-static bool is_mx6q(void)
-{
- if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D))
- return true;
- else
- return false;
-}
-
int board_late_init(void)
{
#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
else
setenv("board_name", "CUBOXI");
- if (is_mx6q())
+ if (is_mx6dq())
setenv("board_rev", "MX6Q");
else
setenv("board_rev", "MX6DL");
.p0_mpdgctrl0 = 0x023C0224,
.p0_mpdgctrl1 = 0x02000220,
.p1_mpdgctrl0 = 0x02200220,
- .p1_mpdgctrl1 = 0x02000220,
+ .p1_mpdgctrl1 = 0x02040208,
.p0_mprddlctl = 0x44444846,
.p1_mprddlctl = 0x4042463C,
.p0_mpwrdlctl = 0x32343032,
writel(0x007F007F, &iomux->gpr[7]);
}
-/*
- * This section requires the differentiation between Solidrun mx6 boards, but
- * for now, it will configure only for the mx6dual hummingboard version.
- */
static void spl_dram_init(int width)
{
struct mx6_ddr_sysinfo sysinfo = {
.bi_on = 1, /* Bank interleaving enabled */
.sde_to_rst = 0x10, /* 14 cycles, 200us (JEDEC default) */
.rst_to_cke = 0x23, /* 33 cycles, 500us (JEDEC default) */
+ .ddr_type = DDR_TYPE_DDR3,
+ .refsel = 1, /* Refresh cycles at 32KHz */
+ .refr = 7, /* 8 refresh commands per refresh cycle */
};
- if (is_cpu_type(MXC_CPU_MX6D) || is_cpu_type(MXC_CPU_MX6Q))
+ if (is_mx6dq())
mx6dq_dram_iocfg(width, &mx6q_ddr_ioregs, &mx6q_grp_ioregs);
else
mx6sdl_dram_iocfg(width, &mx6dl_ddr_ioregs, &mx6sdl_grp_ioregs);
else if (is_cpu_type(MXC_CPU_MX6Q))
mx6_dram_cfg(&sysinfo, &mx6q_2g_mmcd_calib, &mem_ddr_4g);
else if (is_cpu_type(MXC_CPU_MX6DL))
- mx6_dram_cfg(&sysinfo, &mx6q_1g_mmcd_calib, &mem_ddr_2g);
+ mx6_dram_cfg(&sysinfo, &mx6dl_1g_mmcd_calib, &mem_ddr_2g);
else if (is_cpu_type(MXC_CPU_MX6SOLO))
mx6_dram_cfg(&sysinfo, &mx6dl_512m_mmcd_calib, &mem_ddr_2g);
}