Merge git://git.denx.de/u-boot-arc
[oweals/u-boot.git] / board / ge / bx50v3 / bx50v3.c
index 70c298d2d0cf33ab3bd4ff5470b4bf7917e04db4..0acf655c0e5b86686ea1d32471ba1ab1c4122f2a 100644 (file)
@@ -10,7 +10,7 @@
 #include <asm/arch/imx-regs.h>
 #include <asm/arch/iomux.h>
 #include <asm/arch/mx6-pins.h>
-#include <asm/errno.h>
+#include <linux/errno.h>
 #include <asm/gpio.h>
 #include <asm/imx-common/mxc_i2c.h>
 #include <asm/imx-common/iomux-v3.h>
 #include <asm/io.h>
 #include <asm/arch/sys_proto.h>
 #include <i2c.h>
+#include <pwm.h>
 DECLARE_GLOBAL_DATA_PTR;
 
+#define NC_PAD_CTRL (PAD_CTL_PUS_100K_UP |     \
+       PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \
+       PAD_CTL_HYS)
+
 #define UART_PAD_CTRL  (PAD_CTL_PUS_100K_UP |                  \
        PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm |                 \
        PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
@@ -55,7 +60,7 @@ DECLARE_GLOBAL_DATA_PTR;
 
 int dram_init(void)
 {
-       gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
+       gd->ram_size = imx_ddr_size();
 
        return 0;
 }
@@ -98,8 +103,9 @@ static void setup_iomux_enet(void)
 
        /* Reset AR8033 PHY */
        gpio_direction_output(IMX_GPIO_NR(1, 28), 0);
-       udelay(500);
+       mdelay(10);
        gpio_set_value(IMX_GPIO_NR(1, 28), 1);
+       mdelay(1);
 }
 
 static iomux_v3_cfg_t const usdhc2_pads[] = {
@@ -301,7 +307,8 @@ static int mx6_rgmii_rework(struct phy_device *phydev)
        /* set debug port address: SerDes Test and System Mode Control */
        phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05);
        /* enable rgmii tx clock delay */
-       phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100);
+       /* set the reserved bits to avoid board specific voltage peak issue*/
+       phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x3D47);
 
        return 0;
 }
@@ -324,6 +331,8 @@ static iomux_v3_cfg_t const backlight_pads[] = {
        /* Backlight enable for LVDS display */
        MX6_PAD_GPIO_0__GPIO1_IO00 | MUX_PAD_CTRL(NO_PAD_CTRL),
 #define LVDS_BACKLIGHT_GP IMX_GPIO_NR(1, 0)
+       /* backlight PWM brightness control */
+       MX6_PAD_SD1_DAT3__PWM1_OUT | MUX_PAD_CTRL(NO_PAD_CTRL),
 };
 
 static void do_enable_hdmi(struct display_info_t const *dev)
@@ -390,55 +399,117 @@ struct display_info_t const displays[] = {{
 } } };
 size_t display_count = ARRAY_SIZE(displays);
 
-static void setup_display(void)
+static void enable_videopll(void)
+{
+       struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+       s32 timeout = 100000;
+
+       setbits_le32(&ccm->analog_pll_video, BM_ANADIG_PLL_VIDEO_POWERDOWN);
+
+       /* set video pll to 910MHz (24MHz * (37+11/12))
+       * video pll post div to 910/4 = 227.5MHz
+       */
+       clrsetbits_le32(&ccm->analog_pll_video,
+                       BM_ANADIG_PLL_VIDEO_DIV_SELECT |
+                       BM_ANADIG_PLL_VIDEO_POST_DIV_SELECT,
+                       BF_ANADIG_PLL_VIDEO_DIV_SELECT(37) |
+                       BF_ANADIG_PLL_VIDEO_POST_DIV_SELECT(0));
+
+       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);
+
+       clrbits_le32(&ccm->analog_pll_video, BM_ANADIG_PLL_VIDEO_POWERDOWN);
+
+       while (timeout--)
+               if (readl(&ccm->analog_pll_video) & BM_ANADIG_PLL_VIDEO_LOCK)
+                       break;
+
+       if (timeout < 0)
+               printf("Warning: video pll lock timeout!\n");
+
+       clrsetbits_le32(&ccm->analog_pll_video,
+                       BM_ANADIG_PLL_VIDEO_BYPASS,
+                       BM_ANADIG_PLL_VIDEO_ENABLE);
+}
+
+static void setup_display_b850v3(void)
 {
        struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
        struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
-       int reg;
 
-       enable_ipu_clock();
+       enable_videopll();
+
+       /* IPU1 D0 clock is 227.5 / 3.5 = 65MHz */
+       clrbits_le32(&mxc_ccm->cscmr2, MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV);
+
        imx_setup_hdmi();
 
-       reg = readl(&mxc_ccm->CCGR3);
-       reg |=  MXC_CCM_CCGR3_LDB_DI0_MASK;
-       writel(reg, &mxc_ccm->CCGR3);
-
-       reg = readl(&mxc_ccm->cs2cdr);
-       reg &= ~(MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK |
-                MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK);
-       reg |= (3 << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET) |
-              (3 << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET);
-       writel(reg, &mxc_ccm->cs2cdr);
-
-       reg = readl(&mxc_ccm->cscmr2);
-       reg |= (MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV);
-       writel(reg, &mxc_ccm->cscmr2);
-
-       reg = readl(&mxc_ccm->chsccdr);
-       reg |= (CHSCCDR_CLK_SEL_LDB_DI0
-               << MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET);
-       writel(reg, &mxc_ccm->chsccdr);
-
-       reg = IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES
-            | IOMUXC_GPR2_DI1_VS_POLARITY_ACTIVE_HIGH
-            | IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW
-            | IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG
-            | IOMUXC_GPR2_DATA_WIDTH_CH1_24BIT
-            | IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG
-            | IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT
-            | IOMUXC_GPR2_LVDS_CH1_MODE_ENABLED_DI0
-            | IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0;
-       writel(reg, &iomux->gpr[2]);
-
-       reg = readl(&iomux->gpr[3]);
-       reg = (reg & ~(IOMUXC_GPR3_LVDS0_MUX_CTL_MASK |
-                      IOMUXC_GPR3_LVDS1_MUX_CTL_MASK |
-                      IOMUXC_GPR3_HDMI_MUX_CTL_MASK))
-           | (IOMUXC_GPR3_MUX_SRC_IPU1_DI0
-              << IOMUXC_GPR3_LVDS0_MUX_CTL_OFFSET)
-           | (IOMUXC_GPR3_MUX_SRC_IPU1_DI0
-              << IOMUXC_GPR3_LVDS1_MUX_CTL_OFFSET);
-       writel(reg, &iomux->gpr[3]);
+       /* Set LDB_DI0 as clock source for IPU_DI0 */
+       clrsetbits_le32(&mxc_ccm->chsccdr,
+                       MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK,
+                       (CHSCCDR_CLK_SEL_LDB_DI0 <<
+                        MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET));
+
+       /* Turn on IPU LDB DI0 clocks */
+       setbits_le32(&mxc_ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK);
+
+       enable_ipu_clock();
+
+       writel(IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES |
+              IOMUXC_GPR2_DI1_VS_POLARITY_ACTIVE_LOW |
+              IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW |
+              IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG |
+              IOMUXC_GPR2_DATA_WIDTH_CH1_24BIT |
+              IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG |
+              IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT |
+              IOMUXC_GPR2_SPLIT_MODE_EN_MASK |
+              IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0 |
+              IOMUXC_GPR2_LVDS_CH1_MODE_ENABLED_DI0,
+              &iomux->gpr[2]);
+
+       clrbits_le32(&iomux->gpr[3],
+                    IOMUXC_GPR3_LVDS0_MUX_CTL_MASK |
+                    IOMUXC_GPR3_LVDS1_MUX_CTL_MASK |
+                    IOMUXC_GPR3_HDMI_MUX_CTL_MASK);
+}
+
+static void setup_display_bx50v3(void)
+{
+       struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+       struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
+
+       /* When a reset/reboot is performed the display power needs to be turned
+        * off for atleast 500ms. The boot time is ~300ms, we need to wait for
+        * an additional 200ms here. Unfortunately we use external PMIC for
+        * doing the reset, so can not differentiate between POR vs soft reset
+        */
+       mdelay(200);
+
+       /* IPU1 DI0 clock is 480/7 = 68.5 MHz */
+       setbits_le32(&mxc_ccm->cscmr2, MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV);
+
+       /* Set LDB_DI0 as clock source for IPU_DI0 */
+       clrsetbits_le32(&mxc_ccm->chsccdr,
+                       MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK,
+                       (CHSCCDR_CLK_SEL_LDB_DI0 <<
+                       MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET));
+
+       /* Turn on IPU LDB DI0 clocks */
+       setbits_le32(&mxc_ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK);
+
+       enable_ipu_clock();
+
+       writel(IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES |
+              IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW |
+              IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG |
+              IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT |
+              IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0,
+              &iomux->gpr[2]);
+
+       clrsetbits_le32(&iomux->gpr[3],
+                       IOMUXC_GPR3_LVDS0_MUX_CTL_MASK,
+                      (IOMUXC_GPR3_MUX_SRC_IPU1_DI0 <<
+                       IOMUXC_GPR3_LVDS0_MUX_CTL_OFFSET));
 
        /* backlights off until needed */
        imx_iomux_v3_setup_multiple_pads(backlight_pads,
@@ -467,6 +538,12 @@ int board_eth_init(bd_t *bis)
 
 static iomux_v3_cfg_t const misc_pads[] = {
        MX6_PAD_KEY_ROW2__GPIO4_IO11    | MUX_PAD_CTRL(NO_PAD_CTRL),
+       MX6_PAD_EIM_A25__GPIO5_IO02     | MUX_PAD_CTRL(NC_PAD_CTRL),
+       MX6_PAD_EIM_CS0__GPIO2_IO23     | MUX_PAD_CTRL(NC_PAD_CTRL),
+       MX6_PAD_EIM_CS1__GPIO2_IO24     | MUX_PAD_CTRL(NC_PAD_CTRL),
+       MX6_PAD_EIM_OE__GPIO2_IO25      | MUX_PAD_CTRL(NC_PAD_CTRL),
+       MX6_PAD_EIM_BCLK__GPIO6_IO31    | MUX_PAD_CTRL(NC_PAD_CTRL),
+       MX6_PAD_GPIO_1__GPIO1_IO01      | MUX_PAD_CTRL(NC_PAD_CTRL),
 };
 #define SUS_S3_OUT     IMX_GPIO_NR(4, 11)
 #define WIFI_EN        IMX_GPIO_NR(6, 14)
@@ -478,7 +555,14 @@ int board_early_init_f(void)
 
        setup_iomux_uart();
 
-
+#if defined(CONFIG_VIDEO_IPUV3)
+       if (IS_ENABLED(CONFIG_TARGET_GE_B850V3))
+               /* Set LDB clock to Video PLL */
+               select_ldb_di_clock_source(MXC_PLL5_CLK);
+       else
+               /* Set LDB clock to USB PLL */
+               select_ldb_di_clock_source(MXC_PLL3_SW_CLK);
+#endif
        return 0;
 }
 
@@ -487,7 +571,10 @@ int board_init(void)
        gpio_direction_output(SUS_S3_OUT, 1);
        gpio_direction_output(WIFI_EN, 1);
 #if defined(CONFIG_VIDEO_IPUV3)
-       setup_display();
+       if (IS_ENABLED(CONFIG_TARGET_GE_B850V3))
+               setup_display_b850v3();
+       else
+               setup_display_bx50v3();
 #endif
        /* address of boot parameters */
        gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
@@ -511,18 +598,83 @@ static const struct boot_mode board_boot_modes[] = {
 };
 #endif
 
+void pmic_init(void)
+{
+#define I2C_PMIC                0x2
+#define DA9063_I2C_ADDR         0x58
+#define DA9063_REG_BCORE2_CFG   0x9D
+#define DA9063_REG_BCORE1_CFG   0x9E
+#define DA9063_REG_BPRO_CFG     0x9F
+#define DA9063_REG_BIO_CFG      0xA0
+#define DA9063_REG_BMEM_CFG     0xA1
+#define DA9063_REG_BPERI_CFG    0xA2
+#define DA9063_BUCK_MODE_MASK   0xC0
+#define DA9063_BUCK_MODE_MANUAL 0x00
+#define DA9063_BUCK_MODE_SLEEP  0x40
+#define DA9063_BUCK_MODE_SYNC   0x80
+#define DA9063_BUCK_MODE_AUTO   0xC0
+
+       uchar val;
+
+       i2c_set_bus_num(I2C_PMIC);
+
+       i2c_read(DA9063_I2C_ADDR, DA9063_REG_BCORE2_CFG, 1, &val, 1);
+       val &= ~DA9063_BUCK_MODE_MASK;
+       val |= DA9063_BUCK_MODE_SYNC;
+       i2c_write(DA9063_I2C_ADDR, DA9063_REG_BCORE2_CFG, 1, &val, 1);
+
+       i2c_read(DA9063_I2C_ADDR, DA9063_REG_BCORE1_CFG, 1, &val, 1);
+       val &= ~DA9063_BUCK_MODE_MASK;
+       val |= DA9063_BUCK_MODE_SYNC;
+       i2c_write(DA9063_I2C_ADDR, DA9063_REG_BCORE1_CFG, 1, &val, 1);
+
+       i2c_read(DA9063_I2C_ADDR, DA9063_REG_BPRO_CFG, 1, &val, 1);
+       val &= ~DA9063_BUCK_MODE_MASK;
+       val |= DA9063_BUCK_MODE_SYNC;
+       i2c_write(DA9063_I2C_ADDR, DA9063_REG_BPRO_CFG, 1, &val, 1);
+
+       i2c_read(DA9063_I2C_ADDR, DA9063_REG_BIO_CFG, 1, &val, 1);
+       val &= ~DA9063_BUCK_MODE_MASK;
+       val |= DA9063_BUCK_MODE_SYNC;
+       i2c_write(DA9063_I2C_ADDR, DA9063_REG_BIO_CFG, 1, &val, 1);
+
+       i2c_read(DA9063_I2C_ADDR, DA9063_REG_BMEM_CFG, 1, &val, 1);
+       val &= ~DA9063_BUCK_MODE_MASK;
+       val |= DA9063_BUCK_MODE_SYNC;
+       i2c_write(DA9063_I2C_ADDR, DA9063_REG_BMEM_CFG, 1, &val, 1);
+
+       i2c_read(DA9063_I2C_ADDR, DA9063_REG_BPERI_CFG, 1, &val, 1);
+       val &= ~DA9063_BUCK_MODE_MASK;
+       val |= DA9063_BUCK_MODE_SYNC;
+       i2c_write(DA9063_I2C_ADDR, DA9063_REG_BPERI_CFG, 1, &val, 1);
+}
+
 int board_late_init(void)
 {
 #ifdef CONFIG_CMD_BMODE
        add_board_boot_modes(board_boot_modes);
 #endif
+
+#ifdef CONFIG_VIDEO_IPUV3
        /* We need at least 200ms between power on and backlight on
         * as per specifications from CHI MEI */
        mdelay(250);
 
+       /* enable backlight PWM 1 */
+       pwm_init(0, 0, 0);
+
+       /* duty cycle 5000000ns, period: 5000000ns */
+       pwm_config(0, 5000000, 5000000);
+
        /* Backlight Power */
        gpio_direction_output(LVDS_BACKLIGHT_GP, 1);
 
+       pwm_enable(0);
+#endif
+
+       /* board specific pmic init */
+       pmic_init();
+
        return 0;
 }