treewide: replace #include <asm/errno.h> with <linux/errno.h>
[oweals/u-boot.git] / board / solidrun / mx6cuboxi / mx6cuboxi.c
index d3a32c1663954394e18d6c822acca77f4c5e6954..285588d80a3aa46e440a479e2b14c7eb440af763 100644 (file)
 #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;
 
@@ -50,6 +55,7 @@ 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)
 {
@@ -77,6 +83,10 @@ static iomux_v3_cfg_t const hb_cbi_sense[] = {
        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);
@@ -124,6 +134,8 @@ static iomux_v3_cfg_t const enet_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)
@@ -131,8 +143,9 @@ 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)
@@ -143,11 +156,16 @@ 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;
 
@@ -156,13 +174,150 @@ int board_eth_init(bd_t *bis)
 
        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)
@@ -212,14 +367,6 @@ int checkboard(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
@@ -228,7 +375,7 @@ int board_late_init(void)
        else
                setenv("board_name", "CUBOXI");
 
-       if (is_mx6q())
+       if (is_mx6dq())
                setenv("board_rev", "MX6Q");
        else
                setenv("board_rev", "MX6DL");
@@ -382,7 +529,7 @@ static const struct mx6_mmdc_calibration mx6dl_1g_mmcd_calib = {
        .p0_mpdgctrl0 =    0x023C0224,
        .p0_mpdgctrl1 =    0x02000220,
        .p1_mpdgctrl0 =    0x02200220,
-       .p1_mpdgctrl1 =    0x02000220,
+       .p1_mpdgctrl1 =    0x02040208,
        .p0_mprddlctl =    0x44444846,
        .p1_mprddlctl =    0x4042463C,
        .p0_mpwrdlctl =    0x32343032,
@@ -440,10 +587,6 @@ static void gpr_init(void)
        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 = {
@@ -461,9 +604,12 @@ static void spl_dram_init(int width)
                .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);
@@ -473,7 +619,7 @@ static void spl_dram_init(int width)
        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);
 }