Merge branch 'master' of git://www.denx.de/git/u-boot-uniphier
authorTom Rini <trini@konsulko.com>
Mon, 25 Apr 2016 17:45:32 +0000 (13:45 -0400)
committerTom Rini <trini@konsulko.com>
Mon, 25 Apr 2016 17:45:32 +0000 (13:45 -0400)
24 files changed:
arch/arm/cpu/armv7/mx6/Kconfig
arch/arm/cpu/armv7/mx6/clock.c
arch/arm/imx-common/Makefile
arch/arm/include/asm/arch-mx6/clock.h
arch/arm/include/asm/arch-mx6/imx-regs.h
board/ge/bx50v3/bx50v3.c
board/technexion/pico-imx6ul/Kconfig [new file with mode: 0644]
board/technexion/pico-imx6ul/MAINTAINERS [new file with mode: 0644]
board/technexion/pico-imx6ul/Makefile [new file with mode: 0644]
board/technexion/pico-imx6ul/imximage.cfg [new file with mode: 0644]
board/technexion/pico-imx6ul/pico-imx6ul.c [new file with mode: 0644]
configs/pico-imx6ul_defconfig [new file with mode: 0644]
drivers/core/device.c
drivers/dfu/dfu_ram.c
drivers/i2c/designware_i2c.c
drivers/i2c/designware_i2c.h
drivers/mtd/ubi/wl.c
drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c
drivers/usb/gadget/f_fastboot.c
fs/ubifs/super.c
include/configs/ge_bx50v3.h
include/configs/pico-imx6ul.h [new file with mode: 0644]
include/dm/device.h
test/py/tests/test_dfu.py

index 1bcd3990933670987e06c59c619f79b38aa8768b..663f970c4c9f88fa66d269d980ebed63f1d81e5a 100644 (file)
@@ -136,6 +136,10 @@ config TARGET_OT1200
        bool "Bachmann OT1200"
        select SUPPORT_SPL
 
+config TARGET_PICO_IMX6UL
+       bool "PICO-IMX6UL-EMMC"
+       select MX6UL
+
 config TARGET_PLATINUM_PICON
        bool "platinum-picon"
        select SUPPORT_SPL
@@ -200,6 +204,7 @@ source "board/gateworks/gw_ventana/Kconfig"
 source "board/kosagi/novena/Kconfig"
 source "board/seco/Kconfig"
 source "board/solidrun/mx6cuboxi/Kconfig"
+source "board/technexion/pico-imx6ul/Kconfig"
 source "board/tbs/tbs2910/Kconfig"
 source "board/tqc/tqma6/Kconfig"
 source "board/udoo/Kconfig"
index 3b53842e4072d1639171387c840f5522130be418..e6f227548afeae90487a3f8353daadb51adf7130 100644 (file)
@@ -1217,6 +1217,157 @@ void enable_ipu_clock(void)
        }
 }
 #endif
+
+#if defined(CONFIG_MX6Q) || defined(CONFIG_MX6D) || defined(CONFIG_MX6DL) || \
+       defined(CONFIG_MX6S)
+static void disable_ldb_di_clock_sources(void)
+{
+       struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+       int reg;
+
+       /* Make sure PFDs are disabled at boot. */
+       reg = readl(&mxc_ccm->analog_pfd_528);
+       /* Cannot disable pll2_pfd2_396M, as it is the MMDC clock in iMX6DL */
+       if (is_cpu_type(MXC_CPU_MX6DL))
+               reg |= 0x80008080;
+       else
+               reg |= 0x80808080;
+       writel(reg, &mxc_ccm->analog_pfd_528);
+
+       /* Disable PLL3 PFDs */
+       reg = readl(&mxc_ccm->analog_pfd_480);
+       reg |= 0x80808080;
+       writel(reg, &mxc_ccm->analog_pfd_480);
+
+       /* Disable PLL5 */
+       reg = readl(&mxc_ccm->analog_pll_video);
+       reg &= ~(1 << 13);
+       writel(reg, &mxc_ccm->analog_pll_video);
+}
+
+static void enable_ldb_di_clock_sources(void)
+{
+       struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+       int reg;
+
+       reg = readl(&mxc_ccm->analog_pfd_528);
+       if (is_cpu_type(MXC_CPU_MX6DL))
+               reg &= ~(0x80008080);
+       else
+               reg &= ~(0x80808080);
+       writel(reg, &mxc_ccm->analog_pfd_528);
+
+       reg = readl(&mxc_ccm->analog_pfd_480);
+       reg &= ~(0x80808080);
+       writel(reg, &mxc_ccm->analog_pfd_480);
+}
+
+/*
+ * Try call this function as early in the boot process as possible since the
+ * function temporarily disables PLL2 PFD's, PLL3 PFD's and PLL5.
+ */
+void select_ldb_di_clock_source(enum ldb_di_clock clk)
+{
+       struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+       int reg;
+
+       /*
+        * Need to follow a strict procedure when changing the LDB
+        * clock, else we can introduce a glitch. Things to keep in
+        * mind:
+        * 1. The current and new parent clocks must be disabled.
+        * 2. The default clock for ldb_dio_clk is mmdc_ch1 which has
+        * no CG bit.
+        * 3. In the RTL implementation of the LDB_DI_CLK_SEL mux
+        * the top four options are in one mux and the PLL3 option along
+        * with another option is in the second mux. There is third mux
+        * used to decide between the first and second mux.
+        * The code below switches the parent to the bottom mux first
+        * and then manipulates the top mux. This ensures that no glitch
+        * will enter the divider.
+        *
+        * Need to disable MMDC_CH1 clock manually as there is no CG bit
+        * for this clock. The only way to disable this clock is to move
+        * it to pll3_sw_clk and then to disable pll3_sw_clk
+        * Make sure periph2_clk2_sel is set to pll3_sw_clk
+        */
+
+       /* Disable all ldb_di clock parents */
+       disable_ldb_di_clock_sources();
+
+       /* Set MMDC_CH1 mask bit */
+       reg = readl(&mxc_ccm->ccdr);
+       reg |= MXC_CCM_CCDR_MMDC_CH1_HS_MASK;
+       writel(reg, &mxc_ccm->ccdr);
+
+       /* Set periph2_clk2_sel to be sourced from PLL3_sw_clk */
+       reg = readl(&mxc_ccm->cbcmr);
+       reg &= ~MXC_CCM_CBCMR_PERIPH2_CLK2_SEL;
+       writel(reg, &mxc_ccm->cbcmr);
+
+       /*
+        * Set the periph2_clk_sel to the top mux so that
+        * mmdc_ch1 is from pll3_sw_clk.
+        */
+       reg = readl(&mxc_ccm->cbcdr);
+       reg |= MXC_CCM_CBCDR_PERIPH2_CLK_SEL;
+       writel(reg, &mxc_ccm->cbcdr);
+
+       /* Wait for the clock switch */
+       while (readl(&mxc_ccm->cdhipr))
+               ;
+       /* Disable pll3_sw_clk by selecting bypass clock source */
+       reg = readl(&mxc_ccm->ccsr);
+       reg |= MXC_CCM_CCSR_PLL3_SW_CLK_SEL;
+       writel(reg, &mxc_ccm->ccsr);
+
+       /* Set the ldb_di0_clk and ldb_di1_clk to 111b */
+       reg = readl(&mxc_ccm->cs2cdr);
+       reg |= ((7 << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET)
+             | (7 << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET));
+       writel(reg, &mxc_ccm->cs2cdr);
+
+       /* Set the ldb_di0_clk and ldb_di1_clk to 100b */
+       reg = readl(&mxc_ccm->cs2cdr);
+       reg &= ~(MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK
+             | MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK);
+       reg |= ((4 << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET)
+             | (4 << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET));
+       writel(reg, &mxc_ccm->cs2cdr);
+
+       /* Set the ldb_di0_clk and ldb_di1_clk to desired source */
+       reg = readl(&mxc_ccm->cs2cdr);
+       reg &= ~(MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK
+             | MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK);
+       reg |= ((clk << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET)
+             | (clk << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET));
+       writel(reg, &mxc_ccm->cs2cdr);
+
+       /* Unbypass pll3_sw_clk */
+       reg = readl(&mxc_ccm->ccsr);
+       reg &= ~MXC_CCM_CCSR_PLL3_SW_CLK_SEL;
+       writel(reg, &mxc_ccm->ccsr);
+
+       /*
+        * Set the periph2_clk_sel back to the bottom mux so that
+        * mmdc_ch1 is from its original parent.
+        */
+       reg = readl(&mxc_ccm->cbcdr);
+       reg &= ~MXC_CCM_CBCDR_PERIPH2_CLK_SEL;
+       writel(reg, &mxc_ccm->cbcdr);
+
+       /* Wait for the clock switch */
+       while (readl(&mxc_ccm->cdhipr))
+               ;
+       /* Clear MMDC_CH1 mask bit */
+       reg = readl(&mxc_ccm->ccdr);
+       reg &= ~MXC_CCM_CCDR_MMDC_CH1_HS_MASK;
+       writel(reg, &mxc_ccm->ccdr);
+
+       enable_ldb_di_clock_sources();
+}
+#endif
+
 /***************************************************/
 
 U_BOOT_CMD(
index 30e66ba9a48de0750ed58e31b862554b035b8975..c208628f35e1269fe06e7f56e639f8470228a287 100644 (file)
@@ -86,7 +86,7 @@ u-boot-with-nand-spl.imx: spl/u-boot-nand-spl.imx u-boot.uim FORCE
        $(call if_changed,pad_cat)
 
 quiet_cmd_u-boot-nand-spl_imx = GEN     $@
-cmd_u-boot-nand-spl_imx = (echo -ne '\x00\x00\x00\x00\x46\x43\x42\x20\x01' && \
+cmd_u-boot-nand-spl_imx = (printf '\000\000\000\000\106\103\102\040\001' && \
        dd bs=1015 count=1 if=/dev/zero 2>/dev/null) | cat - $< > $@
 
 spl/u-boot-nand-spl.imx: SPL FORCE
index 14505239e856b415f7f0a943a56aea269c089f6c..82f9f92b83ddf925817489aa88cd7bed2932d426 100644 (file)
@@ -42,6 +42,14 @@ enum mxc_clock {
        MXC_I2C_CLK,
 };
 
+enum ldb_di_clock {
+       MXC_PLL5_CLK = 0,
+       MXC_PLL2_PFD0_CLK,
+       MXC_PLL2_PFD2_CLK,
+       MXC_MMDC_CH1_CLK,
+       MXC_PLL3_SW_CLK,
+};
+
 enum enet_freq {
        ENET_25MHZ,
        ENET_50MHZ,
@@ -70,4 +78,5 @@ int enable_lcdif_clock(u32 base_addr);
 void enable_qspi_clk(int qspi_num);
 void enable_thermal_clk(void);
 void mxs_set_lcdclk(u32 base_addr, u32 freq);
+void select_ldb_di_clock_source(enum ldb_di_clock clk);
 #endif /* __ASM_ARCH_CLOCK_H */
index 53488bef552683f6d231763f004ed4d18fb1b8dd..3ab04bf998deb66bb7b32a56f500af97eee01352 100644 (file)
 #define IP2APB_TZASC1_BASE_ADDR     (AIPS2_OFF_BASE_ADDR + 0x50000)
 #ifdef CONFIG_MX6UL
 #define QSPI0_BASE_ADDR             (AIPS2_OFF_BASE_ADDR + 0x60000)
+#define UART6_BASE_ADDR             (AIPS2_OFF_BASE_ADDR + 0x7C000)
 #elif defined(CONFIG_MX6SX)
 #define SAI1_BASE_ADDR              (AIPS2_OFF_BASE_ADDR + 0x54000)
 #define AUDMUX_BASE_ADDR            (AIPS2_OFF_BASE_ADDR + 0x58000)
index 70c298d2d0cf33ab3bd4ff5470b4bf7917e04db4..ff8f4d7b972e842c6990afce8aa6fd95a4056953 100644 (file)
 #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)
@@ -324,6 +329,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 +397,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 +536,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 +553,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 +569,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;
@@ -520,9 +605,17 @@ int board_late_init(void)
         * 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);
+
        return 0;
 }
 
diff --git a/board/technexion/pico-imx6ul/Kconfig b/board/technexion/pico-imx6ul/Kconfig
new file mode 100644 (file)
index 0000000..81acd61
--- /dev/null
@@ -0,0 +1,15 @@
+if TARGET_PICO_IMX6UL
+
+config SYS_BOARD
+       default "pico-imx6ul"
+
+config SYS_VENDOR
+       default "technexion"
+
+config SYS_SOC
+       default "mx6"
+
+config SYS_CONFIG_NAME
+       default "pico-imx6ul"
+
+endif
diff --git a/board/technexion/pico-imx6ul/MAINTAINERS b/board/technexion/pico-imx6ul/MAINTAINERS
new file mode 100644 (file)
index 0000000..594a883
--- /dev/null
@@ -0,0 +1,7 @@
+Technexion PICO-IMX6UL board
+M:     Richard Hu <richard.hu@technexion.com>
+M:     Fabio Estevam <fabio.estevam@nxp.com>
+S:     Maintained
+F:     board/technexion/pico-imx6ul/
+F:     include/configs/pico-imx6ul.h
+F:     configs/pico-imx6ul_defconfig
diff --git a/board/technexion/pico-imx6ul/Makefile b/board/technexion/pico-imx6ul/Makefile
new file mode 100644 (file)
index 0000000..ac8ff9e
--- /dev/null
@@ -0,0 +1,7 @@
+# (C) Copyright 2015 Technexion Ltd.
+# (C) Copyright 2015 Freescale Semiconductor, Inc.
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y  := pico-imx6ul.o
diff --git a/board/technexion/pico-imx6ul/imximage.cfg b/board/technexion/pico-imx6ul/imximage.cfg
new file mode 100644 (file)
index 0000000..9145b44
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ *
+ * Refer docs/README.imxmage for more details about how-to configure
+ * and create imximage boot image
+ *
+ * The syntax is taken as close as possible with the kwbimage
+ */
+
+#define __ASSEMBLY__
+#include <config.h>
+
+/* image version */
+
+IMAGE_VERSION 2
+
+/*
+ * Boot Device : one of
+ * spi/sd/nand/onenand, qspi/nor
+ */
+BOOT_FROM      sd
+
+/*
+ * Device Configuration Data (DCD)
+ *
+ * Each entry must have the format:
+ * Addr-type           Address        Value
+ *
+ * where:
+ *     Addr-type register length (1,2 or 4 bytes)
+ *     Address   absolute address of the register
+ *     value     value to be stored in the register
+ */
+
+/* Enable all clocks */
+DATA 4 0x020c4068 0xffffffff
+DATA 4 0x020c406c 0xffffffff
+DATA 4 0x020c4070 0xffffffff
+DATA 4 0x020c4074 0xffffffff
+DATA 4 0x020c4078 0xffffffff
+DATA 4 0x020c407c 0xffffffff
+DATA 4 0x020c4080 0xffffffff
+
+DATA 4 0x020E04B4 0x000C0000
+DATA 4 0x020E04AC 0x00000000
+DATA 4 0x020E027C 0x00000030
+DATA 4 0x020E0250 0x00000030
+DATA 4 0x020E024C 0x00000030
+DATA 4 0x020E0490 0x00000030
+DATA 4 0x020E0288 0x00000030
+DATA 4 0x020E0270 0x00000000
+DATA 4 0x020E0260 0x00000030
+DATA 4 0x020E0264 0x00000030
+DATA 4 0x020E04A0 0x00000030
+DATA 4 0x020E0494 0x00020000
+DATA 4 0x020E0280 0x00000030
+DATA 4 0x020E0284 0x00000030
+DATA 4 0x020E04B0 0x00020000
+DATA 4 0x020E0498 0x00000030
+DATA 4 0x020E04A4 0x00000030
+DATA 4 0x020E0244 0x00000030
+DATA 4 0x020E0248 0x00000030
+DATA 4 0x021B001C 0x00008000
+DATA 4 0x021B0800 0xA1390003
+DATA 4 0x021B080C 0x00000000
+DATA 4 0x021B083C 0x01380134
+DATA 4 0x021B0848 0x40404244
+DATA 4 0x021B0850 0x40405050
+DATA 4 0x021B081C 0x33333333
+DATA 4 0x021B0820 0x33333333
+DATA 4 0x021B082C 0xf3333333
+DATA 4 0x021B0830 0xf3333333
+DATA 4 0x021B08C0 0x00921012
+DATA 4 0x021B08b8 0x00000800
+DATA 4 0x021B0004 0x0002002D
+DATA 4 0x021B0008 0x00333030
+DATA 4 0x021B000C 0x676B52F3
+DATA 4 0x021B0010 0xB66D8B63
+DATA 4 0x021B0014 0x01FF00DB
+DATA 4 0x021B0018 0x00201740
+DATA 4 0x021B001C 0x00008000
+DATA 4 0x021B002C 0x000026D2
+DATA 4 0x021B0030 0x006B1023
+DATA 4 0x021B0040 0x00000047
+DATA 4 0x021B0000 0x83180000
+DATA 4 0x021B001C 0x02008032
+DATA 4 0x021B001C 0x00008033
+DATA 4 0x021B001C 0x00048031
+DATA 4 0x021B001C 0x15208030
+DATA 4 0x021B001C 0x04008040
+DATA 4 0x021B0020 0x00000800
+DATA 4 0x021B0818 0x00000227
+DATA 4 0x021B0004 0x0002552D
+DATA 4 0x021B0404 0x00011006
+DATA 4 0x021B001C 0x00000000
diff --git a/board/technexion/pico-imx6ul/pico-imx6ul.c b/board/technexion/pico-imx6ul/pico-imx6ul.c
new file mode 100644 (file)
index 0000000..c038d43
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2015 Technexion Ltd.
+ *
+ * Author: Richard Hu <richard.hu@technexion.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <asm/arch/clock.h>
+#include <asm/arch/iomux.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/crm_regs.h>
+#include <asm/arch/mx6-pins.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/gpio.h>
+#include <asm/imx-common/iomux-v3.h>
+#include <asm/io.h>
+#include <common.h>
+#include <fsl_esdhc.h>
+#include <linux/sizes.h>
+#include <usb.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define UART_PAD_CTRL  (PAD_CTL_PKE | PAD_CTL_PUE |            \
+       PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED |               \
+       PAD_CTL_DSE_40ohm   | PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
+
+#define USDHC_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE |            \
+       PAD_CTL_PUS_22K_UP  | PAD_CTL_SPEED_LOW |               \
+       PAD_CTL_DSE_80ohm   | PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
+
+#define OTG_ID_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE |           \
+       PAD_CTL_PUS_47K_UP  | PAD_CTL_SPEED_LOW |               \
+       PAD_CTL_DSE_80ohm   | PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
+
+int dram_init(void)
+{
+       gd->ram_size = imx_ddr_size();
+
+       return 0;
+}
+
+static iomux_v3_cfg_t const uart6_pads[] = {
+       MX6_PAD_CSI_MCLK__UART6_DCE_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
+       MX6_PAD_CSI_PIXCLK__UART6_DCE_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+
+static iomux_v3_cfg_t const usdhc1_pads[] = {
+       MX6_PAD_SD1_CLK__USDHC1_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+       MX6_PAD_SD1_CMD__USDHC1_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+       MX6_PAD_SD1_DATA0__USDHC1_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+       MX6_PAD_SD1_DATA1__USDHC1_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+       MX6_PAD_SD1_DATA2__USDHC1_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+       MX6_PAD_SD1_DATA3__USDHC1_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+       MX6_PAD_NAND_READY_B__USDHC1_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+       MX6_PAD_NAND_CE0_B__USDHC1_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+       MX6_PAD_NAND_CE1_B__USDHC1_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+       MX6_PAD_NAND_CLE__USDHC1_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+};
+
+static iomux_v3_cfg_t const usb_otg_pad[] = {
+       MX6_PAD_GPIO1_IO00__ANATOP_OTG1_ID | MUX_PAD_CTRL(OTG_ID_PAD_CTRL),
+};
+
+static void setup_iomux_uart(void)
+{
+       imx_iomux_v3_setup_multiple_pads(uart6_pads, ARRAY_SIZE(uart6_pads));
+}
+
+static void setup_usb(void)
+{
+       imx_iomux_v3_setup_multiple_pads(usb_otg_pad, ARRAY_SIZE(usb_otg_pad));
+}
+
+static struct fsl_esdhc_cfg usdhc_cfg[1] = {
+       {USDHC1_BASE_ADDR},
+};
+
+int board_mmc_getcd(struct mmc *mmc)
+{
+       return 1;
+}
+
+int board_mmc_init(bd_t *bis)
+{
+       imx_iomux_v3_setup_multiple_pads(usdhc1_pads, ARRAY_SIZE(usdhc1_pads));
+       usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
+       return fsl_esdhc_initialize(bis, &usdhc_cfg[0]);
+}
+
+int board_early_init_f(void)
+{
+       setup_iomux_uart();
+
+       return 0;
+}
+
+int board_usb_phy_mode(int port)
+{
+       return USB_INIT_DEVICE;
+}
+
+int board_init(void)
+{
+       /* Address of boot parameters */
+       gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
+
+       setup_usb();
+
+       return 0;
+}
+
+int checkboard(void)
+{
+       puts("Board: PICO-IMX6UL-EMMC\n");
+
+       return 0;
+}
diff --git a/configs/pico-imx6ul_defconfig b/configs/pico-imx6ul_defconfig
new file mode 100644 (file)
index 0000000..9157faa
--- /dev/null
@@ -0,0 +1,5 @@
+CONFIG_ARM=y
+CONFIG_ARCH_MX6=y
+CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/technexion/pico-imx6ul/imximage.cfg"
+CONFIG_TARGET_PICO_IMX6UL=y
+CONFIG_OF_LIBFDT=y
index 269087a084cf6edbf1637de12602b5773c79e394..1322991d6c7b6e0599679518543da7c5cdb7c5ad 100644 (file)
@@ -673,6 +673,11 @@ fdt_addr_t dev_get_addr(struct udevice *dev)
        return dev_get_addr_index(dev, 0);
 }
 
+void *dev_get_addr_ptr(struct udevice *dev)
+{
+       return (void *)(uintptr_t)dev_get_addr_index(dev, 0);
+}
+
 bool device_has_children(struct udevice *dev)
 {
        return !list_empty(&dev->child_head);
index e094a946f6be708dfc31a23fdaf48bc7d13f7b9b..c1b00217c911bb265df23445a50177cf7dc88eb8 100644 (file)
@@ -54,19 +54,26 @@ static int dfu_read_medium_ram(struct dfu_entity *dfu, u64 offset,
 
 int dfu_fill_entity_ram(struct dfu_entity *dfu, char *devstr, char *s)
 {
-       char *st;
+       const char *argv[3];
+       const char **parg = argv;
+
+       for (; parg < argv + sizeof(argv) / sizeof(*argv); ++parg) {
+               *parg = strsep(&s, " ");
+               if (*parg == NULL) {
+                       error("Invalid number of arguments.\n");
+                       return -ENODEV;
+               }
+       }
 
        dfu->dev_type = DFU_DEV_RAM;
-       st = strsep(&s, " ");
-       if (strcmp(st, "ram")) {
-               error("unsupported device: %s\n", st);
+       if (strcmp(argv[0], "ram")) {
+               error("unsupported device: %s\n", argv[0]);
                return -ENODEV;
        }
 
        dfu->layout = DFU_RAM_ADDR;
-       dfu->data.ram.start = (void *)simple_strtoul(s, &s, 16);
-       s++;
-       dfu->data.ram.size = simple_strtoul(s, &s, 16);
+       dfu->data.ram.start = (void *)simple_strtoul(argv[1], NULL, 16);
+       dfu->data.ram.size = simple_strtoul(argv[2], NULL, 16);
 
        dfu->write_medium = dfu_write_medium_ram;
        dfu->get_medium_size = dfu_get_medium_size_ram;
index e768cdedb0db99530eb9c9a34da290cf1191e0a4..0c7cd0ba727921e2dc49acaf761036bc7e511a86 100644 (file)
  */
 
 #include <common.h>
+#include <dm.h>
 #include <i2c.h>
+#include <pci.h>
 #include <asm/io.h>
 #include "designware_i2c.h"
 
-static struct i2c_regs *i2c_get_base(struct i2c_adapter *adap)
-{
-       switch (adap->hwadapnr) {
-#if CONFIG_SYS_I2C_BUS_MAX >= 4
-       case 3:
-               return (struct i2c_regs *)CONFIG_SYS_I2C_BASE3;
+struct dw_scl_sda_cfg {
+       u32 ss_hcnt;
+       u32 fs_hcnt;
+       u32 ss_lcnt;
+       u32 fs_lcnt;
+       u32 sda_hold;
+};
+
+#ifdef CONFIG_X86
+/* BayTrail HCNT/LCNT/SDA hold time */
+static struct dw_scl_sda_cfg byt_config = {
+       .ss_hcnt = 0x200,
+       .fs_hcnt = 0x55,
+       .ss_lcnt = 0x200,
+       .fs_lcnt = 0x99,
+       .sda_hold = 0x6,
+};
 #endif
-#if CONFIG_SYS_I2C_BUS_MAX >= 3
-       case 2:
-               return (struct i2c_regs *)CONFIG_SYS_I2C_BASE2;
-#endif
-#if CONFIG_SYS_I2C_BUS_MAX >= 2
-       case 1:
-               return (struct i2c_regs *)CONFIG_SYS_I2C_BASE1;
-#endif
-       case 0:
-               return (struct i2c_regs *)CONFIG_SYS_I2C_BASE;
-       default:
-               printf("Wrong I2C-adapter number %d\n", adap->hwadapnr);
-       }
 
-       return NULL;
+struct dw_i2c {
+       struct i2c_regs *regs;
+       struct dw_scl_sda_cfg *scl_sda_cfg;
+};
+
+static void dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
+{
+       u32 ena = enable ? IC_ENABLE_0B : 0;
+       int timeout = 100;
+
+       do {
+               writel(ena, &i2c_base->ic_enable);
+               if ((readl(&i2c_base->ic_enable_status) & IC_ENABLE_0B) == ena)
+                       return;
+
+               /*
+                * Wait 10 times the signaling period of the highest I2C
+                * transfer supported by the driver (for 400KHz this is
+                * 25us) as described in the DesignWare I2C databook.
+                */
+               udelay(25);
+       } while (timeout--);
+
+       printf("timeout in %sabling I2C adapter\n", enable ? "en" : "dis");
 }
 
 /*
- * set_speed - Set the i2c speed mode (standard, high, fast)
- * @i2c_spd:   required i2c speed mode
+ * i2c_set_bus_speed - Set the i2c speed
+ * @speed:     required i2c speed
  *
- * Set the i2c speed mode (standard, high, fast)
+ * Set the i2c speed.
  */
-static void set_speed(struct i2c_adapter *adap, int i2c_spd)
+static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base,
+                                          struct dw_scl_sda_cfg *scl_sda_cfg,
+                                          unsigned int speed)
 {
-       struct i2c_regs *i2c_base = i2c_get_base(adap);
        unsigned int cntl;
        unsigned int hcnt, lcnt;
-       unsigned int enbl;
+       int i2c_spd;
+
+       if (speed >= I2C_MAX_SPEED)
+               i2c_spd = IC_SPEED_MODE_MAX;
+       else if (speed >= I2C_FAST_SPEED)
+               i2c_spd = IC_SPEED_MODE_FAST;
+       else
+               i2c_spd = IC_SPEED_MODE_STANDARD;
 
        /* to set speed cltr must be disabled */
-       enbl = readl(&i2c_base->ic_enable);
-       enbl &= ~IC_ENABLE_0B;
-       writel(enbl, &i2c_base->ic_enable);
+       dw_i2c_enable(i2c_base, false);
 
        cntl = (readl(&i2c_base->ic_con) & (~IC_CON_SPD_MSK));
 
        switch (i2c_spd) {
+#ifndef CONFIG_X86 /* No High-speed for BayTrail yet */
        case IC_SPEED_MODE_MAX:
-               cntl |= IC_CON_SPD_HS;
-               hcnt = (IC_CLK * MIN_HS_SCL_HIGHTIME) / NANO_TO_MICRO;
+               cntl |= IC_CON_SPD_SS;
+               if (scl_sda_cfg) {
+                       hcnt = scl_sda_cfg->fs_hcnt;
+                       lcnt = scl_sda_cfg->fs_lcnt;
+               } else {
+                       hcnt = (IC_CLK * MIN_HS_SCL_HIGHTIME) / NANO_TO_MICRO;
+                       lcnt = (IC_CLK * MIN_HS_SCL_LOWTIME) / NANO_TO_MICRO;
+               }
                writel(hcnt, &i2c_base->ic_hs_scl_hcnt);
-               lcnt = (IC_CLK * MIN_HS_SCL_LOWTIME) / NANO_TO_MICRO;
                writel(lcnt, &i2c_base->ic_hs_scl_lcnt);
                break;
+#endif
 
        case IC_SPEED_MODE_STANDARD:
                cntl |= IC_CON_SPD_SS;
-               hcnt = (IC_CLK * MIN_SS_SCL_HIGHTIME) / NANO_TO_MICRO;
+               if (scl_sda_cfg) {
+                       hcnt = scl_sda_cfg->ss_hcnt;
+                       lcnt = scl_sda_cfg->ss_lcnt;
+               } else {
+                       hcnt = (IC_CLK * MIN_SS_SCL_HIGHTIME) / NANO_TO_MICRO;
+                       lcnt = (IC_CLK * MIN_SS_SCL_LOWTIME) / NANO_TO_MICRO;
+               }
                writel(hcnt, &i2c_base->ic_ss_scl_hcnt);
-               lcnt = (IC_CLK * MIN_SS_SCL_LOWTIME) / NANO_TO_MICRO;
                writel(lcnt, &i2c_base->ic_ss_scl_lcnt);
                break;
 
        case IC_SPEED_MODE_FAST:
        default:
                cntl |= IC_CON_SPD_FS;
-               hcnt = (IC_CLK * MIN_FS_SCL_HIGHTIME) / NANO_TO_MICRO;
+               if (scl_sda_cfg) {
+                       hcnt = scl_sda_cfg->fs_hcnt;
+                       lcnt = scl_sda_cfg->fs_lcnt;
+               } else {
+                       hcnt = (IC_CLK * MIN_FS_SCL_HIGHTIME) / NANO_TO_MICRO;
+                       lcnt = (IC_CLK * MIN_FS_SCL_LOWTIME) / NANO_TO_MICRO;
+               }
                writel(hcnt, &i2c_base->ic_fs_scl_hcnt);
-               lcnt = (IC_CLK * MIN_FS_SCL_LOWTIME) / NANO_TO_MICRO;
                writel(lcnt, &i2c_base->ic_fs_scl_lcnt);
                break;
        }
 
        writel(cntl, &i2c_base->ic_con);
 
-       /* Enable back i2c now speed set */
-       enbl |= IC_ENABLE_0B;
-       writel(enbl, &i2c_base->ic_enable);
-}
-
-/*
- * i2c_set_bus_speed - Set the i2c speed
- * @speed:     required i2c speed
- *
- * Set the i2c speed.
- */
-static unsigned int dw_i2c_set_bus_speed(struct i2c_adapter *adap,
-                                        unsigned int speed)
-{
-       int i2c_spd;
-
-       if (speed >= I2C_MAX_SPEED)
-               i2c_spd = IC_SPEED_MODE_MAX;
-       else if (speed >= I2C_FAST_SPEED)
-               i2c_spd = IC_SPEED_MODE_FAST;
-       else
-               i2c_spd = IC_SPEED_MODE_STANDARD;
+       /* Configure SDA Hold Time if required */
+       if (scl_sda_cfg)
+               writel(scl_sda_cfg->sda_hold, &i2c_base->ic_sda_hold);
 
-       set_speed(adap, i2c_spd);
-       adap->speed = speed;
+       /* Enable back i2c now speed set */
+       dw_i2c_enable(i2c_base, true);
 
        return 0;
 }
 
-/*
- * i2c_init - Init function
- * @speed:     required i2c speed
- * @slaveaddr: slave address for the device
- *
- * Initialization function.
- */
-static void dw_i2c_init(struct i2c_adapter *adap, int speed,
-                       int slaveaddr)
-{
-       struct i2c_regs *i2c_base = i2c_get_base(adap);
-       unsigned int enbl;
-
-       /* Disable i2c */
-       enbl = readl(&i2c_base->ic_enable);
-       enbl &= ~IC_ENABLE_0B;
-       writel(enbl, &i2c_base->ic_enable);
-
-       writel((IC_CON_SD | IC_CON_SPD_FS | IC_CON_MM), &i2c_base->ic_con);
-       writel(IC_RX_TL, &i2c_base->ic_rx_tl);
-       writel(IC_TX_TL, &i2c_base->ic_tx_tl);
-       dw_i2c_set_bus_speed(adap, speed);
-       writel(IC_STOP_DET, &i2c_base->ic_intr_mask);
-       writel(slaveaddr, &i2c_base->ic_sar);
-
-       /* Enable i2c */
-       enbl = readl(&i2c_base->ic_enable);
-       enbl |= IC_ENABLE_0B;
-       writel(enbl, &i2c_base->ic_enable);
-}
-
 /*
  * i2c_setaddress - Sets the target slave address
  * @i2c_addr:  target i2c address
  *
  * Sets the target slave address.
  */
-static void i2c_setaddress(struct i2c_adapter *adap, unsigned int i2c_addr)
+static void i2c_setaddress(struct i2c_regs *i2c_base, unsigned int i2c_addr)
 {
-       struct i2c_regs *i2c_base = i2c_get_base(adap);
-       unsigned int enbl;
-
        /* Disable i2c */
-       enbl = readl(&i2c_base->ic_enable);
-       enbl &= ~IC_ENABLE_0B;
-       writel(enbl, &i2c_base->ic_enable);
+       dw_i2c_enable(i2c_base, false);
 
        writel(i2c_addr, &i2c_base->ic_tar);
 
        /* Enable i2c */
-       enbl = readl(&i2c_base->ic_enable);
-       enbl |= IC_ENABLE_0B;
-       writel(enbl, &i2c_base->ic_enable);
+       dw_i2c_enable(i2c_base, true);
 }
 
 /*
@@ -172,10 +161,8 @@ static void i2c_setaddress(struct i2c_adapter *adap, unsigned int i2c_addr)
  *
  * Flushes the i2c RX FIFO
  */
-static void i2c_flush_rxfifo(struct i2c_adapter *adap)
+static void i2c_flush_rxfifo(struct i2c_regs *i2c_base)
 {
-       struct i2c_regs *i2c_base = i2c_get_base(adap);
-
        while (readl(&i2c_base->ic_status) & IC_STATUS_RFNE)
                readl(&i2c_base->ic_cmd_data);
 }
@@ -185,9 +172,8 @@ static void i2c_flush_rxfifo(struct i2c_adapter *adap)
  *
  * Waits for bus busy
  */
-static int i2c_wait_for_bb(struct i2c_adapter *adap)
+static int i2c_wait_for_bb(struct i2c_regs *i2c_base)
 {
-       struct i2c_regs *i2c_base = i2c_get_base(adap);
        unsigned long start_time_bb = get_timer(0);
 
        while ((readl(&i2c_base->ic_status) & IC_STATUS_MA) ||
@@ -201,15 +187,13 @@ static int i2c_wait_for_bb(struct i2c_adapter *adap)
        return 0;
 }
 
-static int i2c_xfer_init(struct i2c_adapter *adap, uchar chip, uint addr,
+static int i2c_xfer_init(struct i2c_regs *i2c_base, uchar chip, uint addr,
                         int alen)
 {
-       struct i2c_regs *i2c_base = i2c_get_base(adap);
-
-       if (i2c_wait_for_bb(adap))
+       if (i2c_wait_for_bb(i2c_base))
                return 1;
 
-       i2c_setaddress(adap, chip);
+       i2c_setaddress(i2c_base, chip);
        while (alen) {
                alen--;
                /* high byte address going out first */
@@ -219,9 +203,8 @@ static int i2c_xfer_init(struct i2c_adapter *adap, uchar chip, uint addr,
        return 0;
 }
 
-static int i2c_xfer_finish(struct i2c_adapter *adap)
+static int i2c_xfer_finish(struct i2c_regs *i2c_base)
 {
-       struct i2c_regs *i2c_base = i2c_get_base(adap);
        ulong start_stop_det = get_timer(0);
 
        while (1) {
@@ -233,12 +216,12 @@ static int i2c_xfer_finish(struct i2c_adapter *adap)
                }
        }
 
-       if (i2c_wait_for_bb(adap)) {
+       if (i2c_wait_for_bb(i2c_base)) {
                printf("Timed out waiting for bus\n");
                return 1;
        }
 
-       i2c_flush_rxfifo(adap);
+       i2c_flush_rxfifo(i2c_base);
 
        return 0;
 }
@@ -253,10 +236,9 @@ static int i2c_xfer_finish(struct i2c_adapter *adap)
  *
  * Read from i2c memory.
  */
-static int dw_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr,
-                      int alen, u8 *buffer, int len)
+static int __dw_i2c_read(struct i2c_regs *i2c_base, u8 dev, uint addr,
+                        int alen, u8 *buffer, int len)
 {
-       struct i2c_regs *i2c_base = i2c_get_base(adap);
        unsigned long start_time_rx;
 
 #ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
@@ -278,7 +260,7 @@ static int dw_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr,
              addr);
 #endif
 
-       if (i2c_xfer_init(adap, dev, addr, alen))
+       if (i2c_xfer_init(i2c_base, dev, addr, alen))
                return 1;
 
        start_time_rx = get_timer(0);
@@ -298,7 +280,7 @@ static int dw_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr,
                }
        }
 
-       return i2c_xfer_finish(adap);
+       return i2c_xfer_finish(i2c_base);
 }
 
 /*
@@ -311,10 +293,9 @@ static int dw_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr,
  *
  * Write to i2c memory.
  */
-static int dw_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr,
-                       int alen, u8 *buffer, int len)
+static int __dw_i2c_write(struct i2c_regs *i2c_base, u8 dev, uint addr,
+                         int alen, u8 *buffer, int len)
 {
-       struct i2c_regs *i2c_base = i2c_get_base(adap);
        int nb = len;
        unsigned long start_time_tx;
 
@@ -337,7 +318,7 @@ static int dw_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr,
              addr);
 #endif
 
-       if (i2c_xfer_init(adap, dev, addr, alen))
+       if (i2c_xfer_init(i2c_base, dev, addr, alen))
                return 1;
 
        start_time_tx = get_timer(0);
@@ -358,21 +339,98 @@ static int dw_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr,
                }
        }
 
-       return i2c_xfer_finish(adap);
+       return i2c_xfer_finish(i2c_base);
+}
+
+/*
+ * __dw_i2c_init - Init function
+ * @speed:     required i2c speed
+ * @slaveaddr: slave address for the device
+ *
+ * Initialization function.
+ */
+static void __dw_i2c_init(struct i2c_regs *i2c_base, int speed, int slaveaddr)
+{
+       /* Disable i2c */
+       dw_i2c_enable(i2c_base, false);
+
+       writel((IC_CON_SD | IC_CON_SPD_FS | IC_CON_MM), &i2c_base->ic_con);
+       writel(IC_RX_TL, &i2c_base->ic_rx_tl);
+       writel(IC_TX_TL, &i2c_base->ic_tx_tl);
+       writel(IC_STOP_DET, &i2c_base->ic_intr_mask);
+#ifndef CONFIG_DM_I2C
+       __dw_i2c_set_bus_speed(i2c_base, NULL, speed);
+       writel(slaveaddr, &i2c_base->ic_sar);
+#endif
+
+       /* Enable i2c */
+       dw_i2c_enable(i2c_base, true);
 }
 
+#ifndef CONFIG_DM_I2C
 /*
- * i2c_probe - Probe the i2c chip
+ * The legacy I2C functions. These need to get removed once
+ * all users of this driver are converted to DM.
  */
+static struct i2c_regs *i2c_get_base(struct i2c_adapter *adap)
+{
+       switch (adap->hwadapnr) {
+#if CONFIG_SYS_I2C_BUS_MAX >= 4
+       case 3:
+               return (struct i2c_regs *)CONFIG_SYS_I2C_BASE3;
+#endif
+#if CONFIG_SYS_I2C_BUS_MAX >= 3
+       case 2:
+               return (struct i2c_regs *)CONFIG_SYS_I2C_BASE2;
+#endif
+#if CONFIG_SYS_I2C_BUS_MAX >= 2
+       case 1:
+               return (struct i2c_regs *)CONFIG_SYS_I2C_BASE1;
+#endif
+       case 0:
+               return (struct i2c_regs *)CONFIG_SYS_I2C_BASE;
+       default:
+               printf("Wrong I2C-adapter number %d\n", adap->hwadapnr);
+       }
+
+       return NULL;
+}
+
+static unsigned int dw_i2c_set_bus_speed(struct i2c_adapter *adap,
+                                        unsigned int speed)
+{
+       adap->speed = speed;
+       return __dw_i2c_set_bus_speed(i2c_get_base(adap), NULL, speed);
+}
+
+static void dw_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
+{
+       __dw_i2c_init(i2c_get_base(adap), speed, slaveaddr);
+}
+
+static int dw_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr,
+                      int alen, u8 *buffer, int len)
+{
+       return __dw_i2c_read(i2c_get_base(adap), dev, addr, alen, buffer, len);
+}
+
+static int dw_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr,
+                       int alen, u8 *buffer, int len)
+{
+       return __dw_i2c_write(i2c_get_base(adap), dev, addr, alen, buffer, len);
+}
+
+/* dw_i2c_probe - Probe the i2c chip */
 static int dw_i2c_probe(struct i2c_adapter *adap, u8 dev)
 {
+       struct i2c_regs *i2c_base = i2c_get_base(adap);
        u32 tmp;
        int ret;
 
        /*
         * Try to read the first location of the chip.
         */
-       ret = dw_i2c_read(adap, dev, 0, 1, (uchar *)&tmp, 1);
+       ret = __dw_i2c_read(i2c_base, dev, 0, 1, (uchar *)&tmp, 1);
        if (ret)
                dw_i2c_init(adap, adap->speed, adap->slaveaddr);
 
@@ -400,3 +458,139 @@ U_BOOT_I2C_ADAP_COMPLETE(dw_3, dw_i2c_init, dw_i2c_probe, dw_i2c_read,
                         dw_i2c_write, dw_i2c_set_bus_speed,
                         CONFIG_SYS_I2C_SPEED3, CONFIG_SYS_I2C_SLAVE3, 3)
 #endif
+
+#else /* CONFIG_DM_I2C */
+/* The DM I2C functions */
+
+static int designware_i2c_xfer(struct udevice *bus, struct i2c_msg *msg,
+                              int nmsgs)
+{
+       struct dw_i2c *i2c = dev_get_priv(bus);
+       int ret;
+
+       debug("i2c_xfer: %d messages\n", nmsgs);
+       for (; nmsgs > 0; nmsgs--, msg++) {
+               debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len);
+               if (msg->flags & I2C_M_RD) {
+                       ret = __dw_i2c_read(i2c->regs, msg->addr, 0, 0,
+                                           msg->buf, msg->len);
+               } else {
+                       ret = __dw_i2c_write(i2c->regs, msg->addr, 0, 0,
+                                            msg->buf, msg->len);
+               }
+               if (ret) {
+                       debug("i2c_write: error sending\n");
+                       return -EREMOTEIO;
+               }
+       }
+
+       return 0;
+}
+
+static int designware_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
+{
+       struct dw_i2c *i2c = dev_get_priv(bus);
+
+       return __dw_i2c_set_bus_speed(i2c->regs, i2c->scl_sda_cfg, speed);
+}
+
+static int designware_i2c_probe_chip(struct udevice *bus, uint chip_addr,
+                                    uint chip_flags)
+{
+       struct dw_i2c *i2c = dev_get_priv(bus);
+       struct i2c_regs *i2c_base = i2c->regs;
+       u32 tmp;
+       int ret;
+
+       /* Try to read the first location of the chip */
+       ret = __dw_i2c_read(i2c_base, chip_addr, 0, 1, (uchar *)&tmp, 1);
+       if (ret)
+               __dw_i2c_init(i2c_base, 0, 0);
+
+       return ret;
+}
+
+static int designware_i2c_probe(struct udevice *bus)
+{
+       struct dw_i2c *priv = dev_get_priv(bus);
+
+       if (device_is_on_pci_bus(bus)) {
+#ifdef CONFIG_DM_PCI
+               /* Save base address from PCI BAR */
+               priv->regs = (struct i2c_regs *)
+                       dm_pci_map_bar(bus, PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
+#ifdef CONFIG_X86
+               /* Use BayTrail specific timing values */
+               priv->scl_sda_cfg = &byt_config;
+#endif
+#endif
+       } else {
+               priv->regs = (struct i2c_regs *)dev_get_addr_ptr(bus);
+       }
+
+       __dw_i2c_init(priv->regs, 0, 0);
+
+       return 0;
+}
+
+static int designware_i2c_bind(struct udevice *dev)
+{
+       static int num_cards;
+       char name[20];
+
+       /* Create a unique device name for PCI type devices */
+       if (device_is_on_pci_bus(dev)) {
+               /*
+                * ToDo:
+                * Setting req_seq in the driver is probably not recommended.
+                * But without a DT alias the number is not configured. And
+                * using this driver is impossible for PCIe I2C devices.
+                * This can be removed, once a better (correct) way for this
+                * is found and implemented.
+                */
+               dev->req_seq = num_cards;
+               sprintf(name, "i2c_designware#%u", num_cards++);
+               device_set_name(dev, name);
+       }
+
+       return 0;
+}
+
+static const struct dm_i2c_ops designware_i2c_ops = {
+       .xfer           = designware_i2c_xfer,
+       .probe_chip     = designware_i2c_probe_chip,
+       .set_bus_speed  = designware_i2c_set_bus_speed,
+};
+
+static const struct udevice_id designware_i2c_ids[] = {
+       { .compatible = "snps,designware-i2c" },
+       { }
+};
+
+U_BOOT_DRIVER(i2c_designware) = {
+       .name   = "i2c_designware",
+       .id     = UCLASS_I2C,
+       .of_match = designware_i2c_ids,
+       .bind   = designware_i2c_bind,
+       .probe  = designware_i2c_probe,
+       .priv_auto_alloc_size = sizeof(struct dw_i2c),
+       .ops    = &designware_i2c_ops,
+};
+
+#ifdef CONFIG_X86
+static struct pci_device_id designware_pci_supported[] = {
+       /* Intel BayTrail has 7 I2C controller located on the PCI bus */
+       { PCI_VDEVICE(INTEL, 0x0f41) },
+       { PCI_VDEVICE(INTEL, 0x0f42) },
+       { PCI_VDEVICE(INTEL, 0x0f43) },
+       { PCI_VDEVICE(INTEL, 0x0f44) },
+       { PCI_VDEVICE(INTEL, 0x0f45) },
+       { PCI_VDEVICE(INTEL, 0x0f46) },
+       { PCI_VDEVICE(INTEL, 0x0f47) },
+       {},
+};
+
+U_BOOT_PCI_DEVICE(i2c_designware, designware_pci_supported);
+#endif
+
+#endif /* CONFIG_DM_I2C */
index 19b09dfa5a5b4c02d417051e6aed50f49054b4cb..270c29c59a4a1491b4fd32a76aa433dd237de4d9 100644 (file)
@@ -9,39 +9,41 @@
 #define __DW_I2C_H_
 
 struct i2c_regs {
-       u32 ic_con;
-       u32 ic_tar;
-       u32 ic_sar;
-       u32 ic_hs_maddr;
-       u32 ic_cmd_data;
-       u32 ic_ss_scl_hcnt;
-       u32 ic_ss_scl_lcnt;
-       u32 ic_fs_scl_hcnt;
-       u32 ic_fs_scl_lcnt;
-       u32 ic_hs_scl_hcnt;
-       u32 ic_hs_scl_lcnt;
-       u32 ic_intr_stat;
-       u32 ic_intr_mask;
-       u32 ic_raw_intr_stat;
-       u32 ic_rx_tl;
-       u32 ic_tx_tl;
-       u32 ic_clr_intr;
-       u32 ic_clr_rx_under;
-       u32 ic_clr_rx_over;
-       u32 ic_clr_tx_over;
-       u32 ic_clr_rd_req;
-       u32 ic_clr_tx_abrt;
-       u32 ic_clr_rx_done;
-       u32 ic_clr_activity;
-       u32 ic_clr_stop_det;
-       u32 ic_clr_start_det;
-       u32 ic_clr_gen_call;
-       u32 ic_enable;
-       u32 ic_status;
-       u32 ic_txflr;
-       u32 ix_rxflr;
-       u32 reserved_1;
-       u32 ic_tx_abrt_source;
+       u32 ic_con;             /* 0x00 */
+       u32 ic_tar;             /* 0x04 */
+       u32 ic_sar;             /* 0x08 */
+       u32 ic_hs_maddr;        /* 0x0c */
+       u32 ic_cmd_data;        /* 0x10 */
+       u32 ic_ss_scl_hcnt;     /* 0x14 */
+       u32 ic_ss_scl_lcnt;     /* 0x18 */
+       u32 ic_fs_scl_hcnt;     /* 0x1c */
+       u32 ic_fs_scl_lcnt;     /* 0x20 */
+       u32 ic_hs_scl_hcnt;     /* 0x24 */
+       u32 ic_hs_scl_lcnt;     /* 0x28 */
+       u32 ic_intr_stat;       /* 0x2c */
+       u32 ic_intr_mask;       /* 0x30 */
+       u32 ic_raw_intr_stat;   /* 0x34 */
+       u32 ic_rx_tl;           /* 0x38 */
+       u32 ic_tx_tl;           /* 0x3c */
+       u32 ic_clr_intr;        /* 0x40 */
+       u32 ic_clr_rx_under;    /* 0x44 */
+       u32 ic_clr_rx_over;     /* 0x48 */
+       u32 ic_clr_tx_over;     /* 0x4c */
+       u32 ic_clr_rd_req;      /* 0x50 */
+       u32 ic_clr_tx_abrt;     /* 0x54 */
+       u32 ic_clr_rx_done;     /* 0x58 */
+       u32 ic_clr_activity;    /* 0x5c */
+       u32 ic_clr_stop_det;    /* 0x60 */
+       u32 ic_clr_start_det;   /* 0x64 */
+       u32 ic_clr_gen_call;    /* 0x68 */
+       u32 ic_enable;          /* 0x6c */
+       u32 ic_status;          /* 0x70 */
+       u32 ic_txflr;           /* 0x74 */
+       u32 ic_rxflr;           /* 0x78 */
+       u32 ic_sda_hold;        /* 0x7c */
+       u32 ic_tx_abrt_source;  /* 0x80 */
+       u8 res1[0x18];          /* 0x84 */
+       u32 ic_enable_status;   /* 0x9c */
 };
 
 #if !defined(IC_CLK)
index 507b09172069f62ac621b0322c551ad3610f3081..e823ca56f23a723444c8af6dc494267a355cf418 100644 (file)
@@ -1528,6 +1528,7 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
                INIT_LIST_HEAD(&ubi->pq[i]);
        ubi->pq_head = 0;
 
+       ubi->free_count = 0;
        list_for_each_entry_safe(aeb, tmp, &ai->erase, u.list) {
                cond_resched();
 
@@ -1546,7 +1547,6 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
                found_pebs++;
        }
 
-       ubi->free_count = 0;
        list_for_each_entry(aeb, &ai->free, u.list) {
                cond_resched();
 
index bce9c30ef610a74c19ab9fb3f7065dba5b22de08..12f5c85c310e09cd3750f1bdd26f63c84270c66d 100644 (file)
@@ -229,13 +229,13 @@ static void complete_rx(struct dwc2_udc *dev, u8 ep_num)
                                ROUND(xfer_size, CONFIG_SYS_CACHELINE_SIZE));
 
        req->req.actual += min(xfer_size, req->req.length - req->req.actual);
-       is_short = (xfer_size < ep->ep.maxpacket);
+       is_short = !!(xfer_size % ep->ep.maxpacket);
 
        debug_cond(DEBUG_OUT_EP != 0,
                   "%s: RX DMA done : ep = %d, rx bytes = %d/%d, "
                   "is_short = %d, DOEPTSIZ = 0x%x, remained bytes = %d\n",
                   __func__, ep_num, req->req.actual, req->req.length,
-                  is_short, ep_tsr, xfer_size);
+                  is_short, ep_tsr, req->req.length - req->req.actual);
 
        if (is_short || req->req.actual == req->req.length) {
                if (ep_num == EP0_CON && dev->ep0state == DATA_STATE_RECV) {
@@ -292,7 +292,7 @@ static void complete_tx(struct dwc2_udc *dev, u8 ep_num)
                "%s: TX DMA done : ep = %d, tx bytes = %d/%d, "
                "is_short = %d, DIEPTSIZ = 0x%x, remained bytes = %d\n",
                __func__, ep_num, req->req.actual, req->req.length,
-               is_short, ep_tsr, xfer_size);
+               is_short, ep_tsr, req->req.length - req->req.actual);
 
        if (ep_num == 0) {
                if (dev->ep0state == DATA_STATE_XMIT) {
index 2e87feeece36a8a2e02ff441ab83d3da4b5b7442..28b244a8d002c1c6d15c8372477dd755e0e35abe 100644 (file)
 #define TX_ENDPOINT_MAXIMUM_PACKET_SIZE      (0x0040)
 
 #define EP_BUFFER_SIZE                 4096
+/*
+ * EP_BUFFER_SIZE must always be an integral multiple of maxpacket size
+ * (64 or 512 or 1024), else we break on certain controllers like DWC3
+ * that expect bulk OUT requests to be divisible by maxpacket size.
+ */
 
 struct f_fastboot {
        struct usb_function usb_function;
@@ -57,15 +62,13 @@ static struct f_fastboot *fastboot_func;
 static unsigned int fastboot_flash_session_id;
 static unsigned int download_size;
 static unsigned int download_bytes;
-static bool is_high_speed;
 
 static struct usb_endpoint_descriptor fs_ep_in = {
        .bLength            = USB_DT_ENDPOINT_SIZE,
        .bDescriptorType    = USB_DT_ENDPOINT,
        .bEndpointAddress   = USB_DIR_IN,
        .bmAttributes       = USB_ENDPOINT_XFER_BULK,
-       .wMaxPacketSize     = TX_ENDPOINT_MAXIMUM_PACKET_SIZE,
-       .bInterval          = 0x00,
+       .wMaxPacketSize     = cpu_to_le16(64),
 };
 
 static struct usb_endpoint_descriptor fs_ep_out = {
@@ -73,8 +76,15 @@ static struct usb_endpoint_descriptor fs_ep_out = {
        .bDescriptorType        = USB_DT_ENDPOINT,
        .bEndpointAddress       = USB_DIR_OUT,
        .bmAttributes           = USB_ENDPOINT_XFER_BULK,
-       .wMaxPacketSize         = RX_ENDPOINT_MAXIMUM_PACKET_SIZE_1_1,
-       .bInterval              = 0x00,
+       .wMaxPacketSize         = cpu_to_le16(64),
+};
+
+static struct usb_endpoint_descriptor hs_ep_in = {
+       .bLength                = USB_DT_ENDPOINT_SIZE,
+       .bDescriptorType        = USB_DT_ENDPOINT,
+       .bEndpointAddress       = USB_DIR_IN,
+       .bmAttributes           = USB_ENDPOINT_XFER_BULK,
+       .wMaxPacketSize         = cpu_to_le16(512),
 };
 
 static struct usb_endpoint_descriptor hs_ep_out = {
@@ -82,8 +92,7 @@ static struct usb_endpoint_descriptor hs_ep_out = {
        .bDescriptorType        = USB_DT_ENDPOINT,
        .bEndpointAddress       = USB_DIR_OUT,
        .bmAttributes           = USB_ENDPOINT_XFER_BULK,
-       .wMaxPacketSize         = RX_ENDPOINT_MAXIMUM_PACKET_SIZE_2_0,
-       .bInterval              = 0x00,
+       .wMaxPacketSize         = cpu_to_le16(512),
 };
 
 static struct usb_interface_descriptor interface_desc = {
@@ -97,13 +106,28 @@ static struct usb_interface_descriptor interface_desc = {
        .bInterfaceProtocol     = FASTBOOT_INTERFACE_PROTOCOL,
 };
 
-static struct usb_descriptor_header *fb_runtime_descs[] = {
+static struct usb_descriptor_header *fb_fs_function[] = {
        (struct usb_descriptor_header *)&interface_desc,
        (struct usb_descriptor_header *)&fs_ep_in,
+       (struct usb_descriptor_header *)&fs_ep_out,
+};
+
+static struct usb_descriptor_header *fb_hs_function[] = {
+       (struct usb_descriptor_header *)&interface_desc,
+       (struct usb_descriptor_header *)&hs_ep_in,
        (struct usb_descriptor_header *)&hs_ep_out,
        NULL,
 };
 
+static struct usb_endpoint_descriptor *
+fb_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs,
+           struct usb_endpoint_descriptor *hs)
+{
+       if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
+               return hs;
+       return fs;
+}
+
 /*
  * static strings, in UTF-8
  */
@@ -177,7 +201,15 @@ static int fastboot_bind(struct usb_configuration *c, struct usb_function *f)
                return -ENODEV;
        f_fb->out_ep->driver_data = c->cdev;
 
-       hs_ep_out.bEndpointAddress = fs_ep_out.bEndpointAddress;
+       f->descriptors = fb_fs_function;
+
+       if (gadget_is_dualspeed(gadget)) {
+               /* Assume endpoint addresses are the same for both speeds */
+               hs_ep_in.bEndpointAddress = fs_ep_in.bEndpointAddress;
+               hs_ep_out.bEndpointAddress = fs_ep_out.bEndpointAddress;
+               /* copy HS descriptors */
+               f->hs_descriptors = fb_hs_function;
+       }
 
        s = getenv("serial#");
        if (s)
@@ -236,18 +268,13 @@ static int fastboot_set_alt(struct usb_function *f,
        struct usb_composite_dev *cdev = f->config->cdev;
        struct usb_gadget *gadget = cdev->gadget;
        struct f_fastboot *f_fb = func_to_fastboot(f);
+       const struct usb_endpoint_descriptor *d;
 
        debug("%s: func: %s intf: %d alt: %d\n",
              __func__, f->name, interface, alt);
 
-       /* make sure we don't enable the ep twice */
-       if (gadget->speed == USB_SPEED_HIGH) {
-               ret = usb_ep_enable(f_fb->out_ep, &hs_ep_out);
-               is_high_speed = true;
-       } else {
-               ret = usb_ep_enable(f_fb->out_ep, &fs_ep_out);
-               is_high_speed = false;
-       }
+       d = fb_ep_desc(gadget, &fs_ep_out, &hs_ep_out);
+       ret = usb_ep_enable(f_fb->out_ep, d);
        if (ret) {
                puts("failed to enable out ep\n");
                return ret;
@@ -261,7 +288,8 @@ static int fastboot_set_alt(struct usb_function *f,
        }
        f_fb->out_req->complete = rx_handler_command;
 
-       ret = usb_ep_enable(f_fb->in_ep, &fs_ep_in);
+       d = fb_ep_desc(gadget, &fs_ep_in, &hs_ep_in);
+       ret = usb_ep_enable(f_fb->in_ep, d);
        if (ret) {
                puts("failed to enable in ep\n");
                goto err;
@@ -302,7 +330,6 @@ static int fastboot_add(struct usb_configuration *c)
        }
 
        f_fb->usb_function.name = "f_fastboot";
-       f_fb->usb_function.hs_descriptors = fb_runtime_descs;
        f_fb->usb_function.bind = fastboot_bind;
        f_fb->usb_function.unbind = fastboot_unbind;
        f_fb->usb_function.set_alt = fastboot_set_alt;
@@ -427,20 +454,27 @@ static void cb_getvar(struct usb_ep *ep, struct usb_request *req)
        fastboot_tx_write_str(response);
 }
 
-static unsigned int rx_bytes_expected(unsigned int maxpacket)
+static unsigned int rx_bytes_expected(struct usb_ep *ep)
 {
        int rx_remain = download_size - download_bytes;
-       int rem = 0;
-       if (rx_remain < 0)
+       unsigned int rem;
+       unsigned int maxpacket = ep->maxpacket;
+
+       if (rx_remain <= 0)
                return 0;
-       if (rx_remain > EP_BUFFER_SIZE)
+       else if (rx_remain > EP_BUFFER_SIZE)
                return EP_BUFFER_SIZE;
-       if (rx_remain < maxpacket) {
-               rx_remain = maxpacket;
-       } else if (rx_remain % maxpacket != 0) {
-               rem = rx_remain % maxpacket;
+
+       /*
+        * Some controllers e.g. DWC3 don't like OUT transfers to be
+        * not ending in maxpacket boundary. So just make them happy by
+        * always requesting for integral multiple of maxpackets.
+        * This shouldn't bother controllers that don't care about it.
+        */
+       rem = rx_remain % maxpacket;
+       if (rem > 0)
                rx_remain = rx_remain + (maxpacket - rem);
-       }
+
        return rx_remain;
 }
 
@@ -452,7 +486,6 @@ static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req)
        const unsigned char *buffer = req->buf;
        unsigned int buffer_size = req->actual;
        unsigned int pre_dot_num, now_dot_num;
-       unsigned int max;
 
        if (req->status != 0) {
                printf("Bad status: %d\n", req->status);
@@ -490,11 +523,7 @@ static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req)
 
                printf("\ndownloading of %d bytes finished\n", download_bytes);
        } else {
-               max = is_high_speed ? hs_ep_out.wMaxPacketSize :
-                               fs_ep_out.wMaxPacketSize;
-               req->length = rx_bytes_expected(max);
-               if (req->length < ep->maxpacket)
-                       req->length = ep->maxpacket;
+               req->length = rx_bytes_expected(ep);
        }
 
        req->actual = 0;
@@ -505,7 +534,6 @@ static void cb_download(struct usb_ep *ep, struct usb_request *req)
 {
        char *cmd = req->buf;
        char response[FASTBOOT_RESPONSE_LEN];
-       unsigned int max;
 
        strsep(&cmd, ":");
        download_size = simple_strtoul(cmd, NULL, 16);
@@ -521,11 +549,7 @@ static void cb_download(struct usb_ep *ep, struct usb_request *req)
        } else {
                sprintf(response, "DATA%08x", download_size);
                req->complete = rx_handler_dl_image;
-               max = is_high_speed ? hs_ep_out.wMaxPacketSize :
-                       fs_ep_out.wMaxPacketSize;
-               req->length = rx_bytes_expected(max);
-               if (req->length < ep->maxpacket)
-                       req->length = ep->maxpacket;
+               req->length = rx_bytes_expected(ep);
        }
        fastboot_tx_write_str(response);
 }
index dcf3a479479d6e786462ff9af60b807a5288117d..effa8d933fe9d0db7d7b91085e39e826f3b4f804 100644 (file)
@@ -48,7 +48,6 @@ struct vfsmount;
 #define INODE_LOCKED_MAX       64
 
 struct super_block *ubifs_sb;
-LIST_HEAD(super_blocks);
 
 static struct inode *inodes_locked_down[INODE_LOCKED_MAX];
 
@@ -2425,10 +2424,10 @@ retry:
        s->s_type = type;
 #ifndef __UBOOT__
        strlcpy(s->s_id, type->name, sizeof(s->s_id));
+       list_add_tail(&s->s_list, &super_blocks);
 #else
        strncpy(s->s_id, type->name, sizeof(s->s_id));
 #endif
-       list_add_tail(&s->s_list, &super_blocks);
        hlist_add_head(&s->s_instances, &type->fs_supers);
 #ifndef __UBOOT__
        spin_unlock(&sb_lock);
index 3a9739ee4b3f79f1c157f612feb85211dfc20622..fbdfdf0a26a6cbe9aabac2518811176ab3b8f886 100644 (file)
 #define CONFIG_IMX_HDMI
 #define CONFIG_IMX_VIDEO_SKIP
 
+#define CONFIG_PWM_IMX
+#define CONFIG_IMX6_PWM_PER_CLK        66000000
+
 #undef CONFIG_CMD_PCI
 #ifdef CONFIG_CMD_PCI
 #define CONFIG_PCI
diff --git a/include/configs/pico-imx6ul.h b/include/configs/pico-imx6ul.h
new file mode 100644 (file)
index 0000000..3e37815
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2015 Technexion Ltd.
+ *
+ * Configuration settings for the Technexion PICO-IMX6UL-EMMC board.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+#ifndef __PICO_IMX6UL_CONFIG_H
+#define __PICO_IMX6UL_CONFIG_H
+
+
+#include <asm/arch/imx-regs.h>
+#include <linux/sizes.h>
+#include "mx6_common.h"
+#include <asm/imx-common/gpio.h>
+
+#define CONFIG_DISPLAY_CPUINFO
+#define CONFIG_DISPLAY_BOARDINFO
+
+/* Size of malloc() pool */
+#define CONFIG_SYS_MALLOC_LEN          (16 * SZ_1M)
+
+#define CONFIG_BOARD_EARLY_INIT_F
+
+#define CONFIG_MXC_UART
+#define CONFIG_MXC_UART_BASE           UART6_BASE_ADDR
+
+/* MMC Configs */
+#define CONFIG_FSL_USDHC
+#define CONFIG_FSL_ESDHC
+#define CONFIG_SYS_FSL_ESDHC_ADDR      USDHC1_BASE_ADDR
+
+#define CONFIG_MMC
+#define CONFIG_CMD_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_CMD_FAT
+#define CONFIG_DOS_PARTITION
+#define CONFIG_SUPPORT_EMMC_BOOT
+
+/* USB Configs */
+#define CONFIG_CMD_USB
+#define CONFIG_USB_EHCI
+#define CONFIG_USB_EHCI_MX6
+#define CONFIG_USB_STORAGE
+#define CONFIG_EHCI_HCD_INIT_AFTER_RESET
+#define CONFIG_MXC_USB_PORTSC          (PORT_PTS_UTMI | PORT_PTS_PTW)
+#define CONFIG_MXC_USB_FLAGS           0
+#define CONFIG_USB_MAX_CONTROLLER_COUNT        1 /* Only OTG1 port enabled */
+
+#define CONFIG_CI_UDC
+#define CONFIG_USBD_HS
+#define CONFIG_USB_GADGET_DUALSPEED
+#define CONFIG_USB_GADGET
+
+#define CONFIG_CMD_USB_MASS_STORAGE
+#define CONFIG_USB_FUNCTION_MASS_STORAGE
+#define CONFIG_USB_GADGET_DOWNLOAD
+#define CONFIG_USB_GADGET_VBUS_DRAW    2
+
+#define CONFIG_G_DNL_VENDOR_NUM                0x0525
+#define CONFIG_G_DNL_PRODUCT_NUM       0xa4a5
+#define CONFIG_G_DNL_MANUFACTURER      "FSL"
+
+#define CONFIG_G_DNL_VENDOR_NUM                0x0525
+#define CONFIG_G_DNL_PRODUCT_NUM       0xa4a5
+#define CONFIG_G_DNL_MANUFACTURER      "FSL"
+
+#define CONFIG_DEFAULT_FDT_FILE                "imx6ul-pico-hobbit.dtb"
+
+#define CONFIG_SYS_MMC_IMG_LOAD_PART   1
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+       "image=zImage\0" \
+       "console=ttymxc5\0" \
+       "fdt_high=0xffffffff\0" \
+       "initrd_high=0xffffffff\0" \
+       "fdt_file=" CONFIG_DEFAULT_FDT_FILE "\0" \
+       "fdt_addr=0x83000000\0" \
+       "mmcdev="__stringify(CONFIG_SYS_MMC_ENV_DEV)"\0" \
+       "mmcpart=" __stringify(CONFIG_SYS_MMC_IMG_LOAD_PART) "\0" \
+       "mmcroot=" CONFIG_MMCROOT " rootwait rw\0" \
+       "mmcautodetect=yes\0" \
+       "mmcargs=setenv bootargs console=${console},${baudrate} " \
+               "root=${mmcroot}\0" \
+       "loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}\0" \
+       "loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}\0" \
+       "mmcboot=echo Booting from mmc ...; " \
+               "run mmcargs; " \
+               "if run loadfdt; then " \
+                       "bootz ${loadaddr} - ${fdt_addr}; " \
+               "else " \
+                       "echo WARN: Cannot load the DT; " \
+               "fi;\0"
+
+#define CONFIG_BOOTCOMMAND \
+          "if mmc rescan; then " \
+                  "if run loadimage; then " \
+                          "run mmcboot; " \
+                  "else run netboot; " \
+                  "fi; " \
+          "else run netboot; fi"
+
+#define CONFIG_CMD_MEMTEST
+#define CONFIG_SYS_MEMTEST_START       0x80000000
+#define CONFIG_SYS_MEMTEST_END         CONFIG_SYS_MEMTEST_START + SZ_128M
+
+#define CONFIG_SYS_LOAD_ADDR           CONFIG_LOADADDR
+#define CONFIG_SYS_HZ                  1000
+
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_STACKSIZE               SZ_128K
+
+/* Physical Memory Map */
+#define CONFIG_NR_DRAM_BANKS           1
+#define PHYS_SDRAM                     MMDC0_ARB_BASE_ADDR
+
+#define CONFIG_SYS_SDRAM_BASE          PHYS_SDRAM
+#define CONFIG_SYS_INIT_RAM_ADDR       IRAM_BASE_ADDR
+#define CONFIG_SYS_INIT_RAM_SIZE       IRAM_SIZE
+
+#define CONFIG_SYS_INIT_SP_OFFSET \
+       (CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
+#define CONFIG_SYS_INIT_SP_ADDR \
+       (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)
+
+/* FLASH and environment organization */
+#define CONFIG_SYS_NO_FLASH
+
+#define CONFIG_ENV_SIZE                        SZ_8K
+#define CONFIG_ENV_IS_IN_MMC
+#define CONFIG_ENV_OFFSET              (8 * SZ_64K)
+
+#define CONFIG_SYS_MMC_ENV_DEV         0
+#define CONFIG_SYS_MMC_ENV_PART                0
+#define CONFIG_MMCROOT                 "/dev/mmcblk0p2"
+
+#define CONFIG_CMD_BOOTZ
+#define CONFIG_CMD_CACHE
+
+#endif /* __PICO_IMX6UL_CONFIG_H */
index dad7591dfacb10c8231fa7867eaa9df6607ac388..8970fc015c7eb1158644110338d8e6f181181d1d 100644 (file)
@@ -453,6 +453,16 @@ int device_find_next_child(struct udevice **devp);
  */
 fdt_addr_t dev_get_addr(struct udevice *dev);
 
+/**
+ * dev_get_addr_ptr() - Return pointer to the address of the reg property
+ *                      of a device
+ *
+ * @dev: Pointer to a device
+ *
+ * @return Pointer to addr, or NULL if there is no such property
+ */
+void *dev_get_addr_ptr(struct udevice *dev);
+
 /**
  * dev_get_addr_index() - Get the indexed reg property of a device
  *
index 093e8d0678710304659a59663e07cfc32d46fe0e..8649d8731b73dd364384d04af82c58783424e47a 100644 (file)
@@ -30,6 +30,13 @@ env__usb_dev_ports = (
     },
 )
 
+# Optional entries (required only when "alt_id_test_file" and
+# "alt_id_dummy_file" are specified).
+test_file_name = "/dfu_test.bin"
+dummy_file_name = "/dfu_dummy.bin"
+# Above files are used to generate proper "alt_info" entry
+"alt_info": "/%s ext4 0 2;/%s ext4 0 2" % (test_file_name, dummy_file_name),
+
 env__dfu_configs = (
     # eMMC, partition 1
     {
@@ -44,6 +51,24 @@ env__dfu_configs = (
         # configurations, but don't want to test every single transfer size
         # on each, to avoid bloating the overall time taken by testing.
         "test_sizes": (63, 64, 65),
+        # This value is optional.
+        # The name of the environment variable that the the dfu command reads
+        # alt info from. If unspecified, this defaults to dfu_alt_info, which is
+        # valid for most systems. Some systems use a different variable name.
+        # One example is the Odroid XU3,  which automatically generates
+        # $dfu_alt_info, each time the dfu command is run, by concatenating
+        # $dfu_alt_boot and $dfu_alt_system.
+        "alt_info_env_name": "dfu_alt_system",
+        # This value is optional.
+        # For boards which require the "test file" alt setting number other than
+        # default (0) it is possible to specify exact file name to be used as
+        # this parameter.
+        "alt_id_test_file": test_file_name,
+        # This value is optional.
+        # For boards which require the "dummy file" alt setting number other
+        # than default (1) it is possible to specify exact file name to be used
+        # as this parameter.
+        "alt_id_dummy_file": dummy_file_name,
     },
 )
 
@@ -120,7 +145,11 @@ def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config):
         u_boot_console.log.action(
             'Starting long-running U-Boot dfu shell command')
 
-        cmd = 'setenv dfu_alt_info "%s"' % env__dfu_config['alt_info']
+        dfu_alt_info_env = env__dfu_config.get('alt_info_env_name', \
+                                                      'dfu_alt_info')
+
+        cmd = 'setenv "%s" "%s"' % (dfu_alt_info_env,
+                                    env__dfu_config['alt_info'])
         u_boot_console.run_command(cmd)
 
         cmd = 'dfu 0 ' + env__dfu_config['cmd_params']
@@ -172,7 +201,7 @@ def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config):
             Nothing.
         """
 
-        cmd = ['dfu-util', '-a', str(alt_setting), up_dn_load_arg, fn]
+        cmd = ['dfu-util', '-a', alt_setting, up_dn_load_arg, fn]
         if 'host_usb_port_path' in env__usb_dev_port:
             cmd += ['-p', env__usb_dev_port['host_usb_port_path']]
         u_boot_utils.run_and_log(u_boot_console, cmd)
@@ -229,15 +258,15 @@ def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config):
 
         u_boot_console.log.action('Writing test data to DFU primary ' +
             'altsetting')
-        dfu_write(0, test_f.abs_fn)
+        dfu_write(alt_setting_test_file, test_f.abs_fn)
 
         u_boot_console.log.action('Writing dummy data to DFU secondary ' +
             'altsetting to clear DFU buffers')
-        dfu_write(1, dummy_f.abs_fn)
+        dfu_write(alt_setting_dummy_file, dummy_f.abs_fn)
 
         u_boot_console.log.action('Reading DFU primary altsetting for ' +
             'comparison')
-        dfu_read(0, readback_fn)
+        dfu_read(alt_setting_test_file, readback_fn)
 
         u_boot_console.log.action('Comparing written and read data')
         written_hash = test_f.content_hash
@@ -260,13 +289,16 @@ def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config):
     dummy_f = u_boot_utils.PersistentRandomFile(u_boot_console,
         'dfu_dummy.bin', 1024)
 
+    alt_setting_test_file = env__dfu_config.get('alt_id_test_file', '0')
+    alt_setting_dummy_file = env__dfu_config.get('alt_id_dummy_file', '1')
+
     ignore_cleanup_errors = True
     try:
         start_dfu()
 
         u_boot_console.log.action(
             'Overwriting DFU primary altsetting with dummy data')
-        dfu_write(0, dummy_f.abs_fn)
+        dfu_write(alt_setting_test_file, dummy_f.abs_fn)
 
         for size in sizes:
             with u_boot_console.log.section('Data size %d' % size):