diff options
-rw-r--r-- | arch/arm/cpu/arm926ejs/mxs/spl_power_init.c | 34 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/mx6/clock.c | 2 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/mx6/ddr.c | 1 | ||||
-rw-r--r-- | arch/arm/imx-common/spl.c | 8 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-mx6/imx-regs.h | 8 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-mxs/sys_proto.h | 2 | ||||
-rw-r--r-- | board/congatec/cgtqmx6eval/MAINTAINERS | 2 | ||||
-rw-r--r-- | board/congatec/cgtqmx6eval/cgtqmx6eval.c | 2 | ||||
-rw-r--r-- | board/freescale/mx6qsabreauto/mx6qsabreauto.c | 87 | ||||
-rw-r--r-- | board/freescale/mx6sxsabresd/mx6sxsabresd.c | 10 | ||||
-rw-r--r-- | common/usb.c | 98 | ||||
-rw-r--r-- | doc/README.imx6 | 51 | ||||
-rw-r--r-- | drivers/i2c/mxc_i2c.c | 12 | ||||
-rw-r--r-- | drivers/mmc/fsl_esdhc.c | 15 | ||||
-rw-r--r-- | drivers/net/fec_mxc.c | 20 | ||||
-rw-r--r-- | drivers/serial/serial_mxc.c | 9 | ||||
-rw-r--r-- | drivers/usb/host/dwc2.c | 7 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 50 | ||||
-rw-r--r-- | drivers/usb/musb-new/musb_host.c | 10 | ||||
-rw-r--r-- | drivers/usb/musb-new/usb-compat.h | 53 | ||||
-rw-r--r-- | include/configs/mx7_common.h | 2 | ||||
-rw-r--r-- | include/configs/novena.h | 23 | ||||
-rw-r--r-- | include/fsl_esdhc.h | 2 | ||||
-rw-r--r-- | include/usb.h | 17 |
24 files changed, 383 insertions, 142 deletions
diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c b/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c index 1972de8..1ec8e2b 100644 --- a/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c +++ b/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c @@ -248,6 +248,39 @@ static void mxs_power_setup_5v_detect(void) } /** + * mxs_power_switch_dcdc_clocksource() - Switch PLL clock for DC-DC converters + * @freqsel: One of the POWER_MISC_FREQSEL_xxx defines to select the clock + * + * This function configures and then enables an alternative PLL clock source + * for the DC-DC converters. + */ +void mxs_power_switch_dcdc_clocksource(uint32_t freqsel) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + /* Select clocksource for DC-DC converters */ + clrsetbits_le32(&power_regs->hw_power_misc, + POWER_MISC_FREQSEL_MASK, + freqsel); + setbits_le32(&power_regs->hw_power_misc, + POWER_MISC_SEL_PLLCLK); +} + +/** + * mxs_power_setup_dcdc_clocksource() - Setup PLL clock source for DC-DC converters + * + * Normally, there is no need to switch DC-DC clocksource. This is the reason, + * why this function is a stub and does nothing. However, boards can implement + * this function when required and call mxs_power_switch_dcdc_clocksource() to + * switch to an alternative clock source. + */ +__weak void mxs_power_setup_dcdc_clocksource(void) +{ + debug("SPL: Using default DC-DC clocksource\n"); +} + +/** * mxs_src_power_init() - Preconfigure the power block * * This function configures reasonable values for the DC-DC control loop @@ -872,6 +905,7 @@ static void mxs_power_configure_power_source(void) debug("SPL: Configuring power source\n"); + mxs_power_setup_dcdc_clocksource(); mxs_src_power_init(); if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) { diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c index d325191..64514b1 100644 --- a/arch/arm/cpu/armv7/mx6/clock.c +++ b/arch/arm/cpu/armv7/mx6/clock.c @@ -727,6 +727,8 @@ int enable_lcdif_clock(u32 base_addr) reg = readl(&imx_ccm->CCGR2); reg |= MXC_CCM_CCGR2_LCD_MASK; writel(reg, &imx_ccm->CCGR2); + + return 0; } #endif diff --git a/arch/arm/cpu/armv7/mx6/ddr.c b/arch/arm/cpu/armv7/mx6/ddr.c index 6b039e4..567ddc4 100644 --- a/arch/arm/cpu/armv7/mx6/ddr.c +++ b/arch/arm/cpu/armv7/mx6/ddr.c @@ -796,7 +796,6 @@ void mx6_ddr3_cfg(const struct mx6_ddr_sysinfo *sysinfo, debug("Rtt_wr=%d\n", sysinfo->rtt_wr); debug("Rtt_nom=%d\n", sysinfo->rtt_nom); debug("SRT=%d\n", ddr3_cfg->SRT); - debug("tcl=%d\n", tcl); debug("twr=%d\n", twr); /* diff --git a/arch/arm/imx-common/spl.c b/arch/arm/imx-common/spl.c index ac6e40e..caa45cf 100644 --- a/arch/arm/imx-common/spl.c +++ b/arch/arm/imx-common/spl.c @@ -20,7 +20,15 @@ u32 spl_boot_device(void) struct src *psrc = (struct src *)SRC_BASE_ADDR; unsigned int gpr10_boot = readl(&psrc->gpr10) & (1 << 28); unsigned reg = gpr10_boot ? readl(&psrc->gpr9) : readl(&psrc->sbmr1); + unsigned int bmode = readl(&psrc->sbmr2); + /* + * Check for BMODE if serial downloader is enabled + * BOOT_MODE - see IMX6DQRM Table 8-1 + */ + if ((((bmode >> 24) & 0x03) == 0x01) || /* Serial Downloader */ + (gpr10_boot && (reg == 1))) + return BOOT_DEVICE_UART; /* BOOT_CFG1[7:4] - see IMX6DQRM Table 8-8 */ switch ((reg & 0x000000FF) >> 4) { /* EIM: See 8.5.1, Table 8-9 */ diff --git a/arch/arm/include/asm/arch-mx6/imx-regs.h b/arch/arm/include/asm/arch-mx6/imx-regs.h index 2f068e5..f24525e 100644 --- a/arch/arm/include/asm/arch-mx6/imx-regs.h +++ b/arch/arm/include/asm/arch-mx6/imx-regs.h @@ -335,10 +335,10 @@ #include <asm/types.h> /* only for i.MX6SX/UL */ -#define WDOG3_BASE_ADDR (is_cpu_type(MXC_CPU_MX6UL) ? \ - MX6UL_WDOG3_BASE_ADDR : MX6SX_WDOG3_BASE_ADDR) -#define LCDIF1_BASE_ADDR (is_cpu_type(MXC_CPU_MX6UL)) ? \ - MX6UL_LCDIF1_BASE_ADDR : MX6SX_LCDIF1_BASE_ADDR +#define WDOG3_BASE_ADDR ((is_cpu_type(MXC_CPU_MX6UL) ? \ + MX6UL_WDOG3_BASE_ADDR : MX6SX_WDOG3_BASE_ADDR)) +#define LCDIF1_BASE_ADDR ((is_cpu_type(MXC_CPU_MX6UL)) ? \ + MX6UL_LCDIF1_BASE_ADDR : MX6SX_LCDIF1_BASE_ADDR) extern void imx_get_mac_from_fuse(int dev_id, unsigned char *mac); diff --git a/arch/arm/include/asm/arch-mxs/sys_proto.h b/arch/arm/include/asm/arch-mxs/sys_proto.h index 20ff101..f2b075e 100644 --- a/arch/arm/include/asm/arch-mxs/sys_proto.h +++ b/arch/arm/include/asm/arch-mxs/sys_proto.h @@ -25,6 +25,8 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int)); void mxs_common_spl_init(const uint32_t arg, const uint32_t *resptr, const iomux_cfg_t *iomux_setup, const unsigned int iomux_size); + +void mxs_power_switch_dcdc_clocksource(uint32_t freqsel); #endif struct mxs_pair { diff --git a/board/congatec/cgtqmx6eval/MAINTAINERS b/board/congatec/cgtqmx6eval/MAINTAINERS index c41ebf5..48c0889 100644 --- a/board/congatec/cgtqmx6eval/MAINTAINERS +++ b/board/congatec/cgtqmx6eval/MAINTAINERS @@ -3,4 +3,4 @@ M: Otavio Salvador <otavio@ossystems.com.br> S: Maintained F: board/congatec/cgtqmx6eval/ F: include/configs/cgtqmx6eval.h -F: configs/cgtqmx6qeval_defconfig +F: configs/cgtqmx6eval_defconfig diff --git a/board/congatec/cgtqmx6eval/cgtqmx6eval.c b/board/congatec/cgtqmx6eval/cgtqmx6eval.c index 5fd526d..225de7c 100644 --- a/board/congatec/cgtqmx6eval/cgtqmx6eval.c +++ b/board/congatec/cgtqmx6eval/cgtqmx6eval.c @@ -404,7 +404,7 @@ static void setup_iomux_uart(void) #ifdef CONFIG_MXC_SPI static void setup_spi(void) { - imx_iomux_v3_setup_multiple_pads(ecspi1_pads, ARRAY_SIZE(ecspi1_pads)); + SETUP_IOMUX_PADS(ecspi1_pads); gpio_direction_output(IMX_GPIO_NR(3, 19), 0); } #endif diff --git a/board/freescale/mx6qsabreauto/mx6qsabreauto.c b/board/freescale/mx6qsabreauto/mx6qsabreauto.c index 7c0e90a..c2e9c57 100644 --- a/board/freescale/mx6qsabreauto/mx6qsabreauto.c +++ b/board/freescale/mx6qsabreauto/mx6qsabreauto.c @@ -412,14 +412,44 @@ u32 get_board_rev(void) } #if defined(CONFIG_VIDEO_IPUV3) +static void disable_lvds(struct display_info_t const *dev) +{ + struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; + + clrbits_le32(&iomux->gpr[2], + IOMUXC_GPR2_LVDS_CH0_MODE_MASK | + IOMUXC_GPR2_LVDS_CH1_MODE_MASK); +} + static void do_enable_hdmi(struct display_info_t const *dev) { + disable_lvds(dev); imx_enable_hdmi_phy(); } struct display_info_t const displays[] = {{ .bus = -1, .addr = 0, + .pixfmt = IPU_PIX_FMT_RGB666, + .detect = NULL, + .enable = NULL, + .mode = { + .name = "Hannstar-XGA", + .refresh = 60, + .xres = 1024, + .yres = 768, + .pixclock = 15385, + .left_margin = 220, + .right_margin = 40, + .upper_margin = 21, + .lower_margin = 7, + .hsync_len = 60, + .vsync_len = 10, + .sync = FB_SYNC_EXT, + .vmode = FB_VMODE_NONINTERLACED +} }, { + .bus = -1, + .addr = 0, .pixfmt = IPU_PIX_FMT_RGB24, .detect = detect_hdmi, .enable = do_enable_hdmi, @@ -440,18 +470,69 @@ struct display_info_t const displays[] = {{ } } }; size_t display_count = ARRAY_SIZE(displays); +iomux_v3_cfg_t const backlight_pads[] = { + MX6_PAD_SD4_DAT1__GPIO2_IO09 | MUX_PAD_CTRL(ENET_PAD_CTRL), +}; + +static void setup_iomux_backlight(void) +{ + gpio_direction_output(IMX_GPIO_NR(2, 9), 1); + imx_iomux_v3_setup_multiple_pads(backlight_pads, + ARRAY_SIZE(backlight_pads)); +} + static void setup_display(void) { struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; + struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; int reg; + setup_iomux_backlight(); enable_ipu_clock(); imx_setup_hdmi(); + /* Turn on LDB_DI0 and LDB_DI1 clocks */ + reg = readl(&mxc_ccm->CCGR3); + reg |= MXC_CCM_CCGR3_LDB_DI0_MASK | MXC_CCM_CCGR3_LDB_DI1_MASK; + writel(reg, &mxc_ccm->CCGR3); + + /* Set LDB_DI0 and LDB_DI1 clk select to 3b'011 */ + 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 | MXC_CCM_CSCMR2_LDB_DI1_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); + reg |= (CHSCCDR_CLK_SEL_LDB_DI0 << + MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_OFFSET); writel(reg, &mxc_ccm->chsccdr); + + reg = 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_18BIT | + IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG | + IOMUXC_GPR2_DATA_WIDTH_CH0_18BIT | + IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0 | + IOMUXC_GPR2_LVDS_CH1_MODE_DISABLED; + writel(reg, &iomux->gpr[2]); + + reg = readl(&iomux->gpr[3]); + reg &= ~(IOMUXC_GPR3_LVDS0_MUX_CTL_MASK | + IOMUXC_GPR3_HDMI_MUX_CTL_MASK); + reg |= (IOMUXC_GPR3_MUX_SRC_IPU1_DI0 << + IOMUXC_GPR3_LVDS0_MUX_CTL_OFFSET) | + (IOMUXC_GPR3_MUX_SRC_IPU1_DI0 << + IOMUXC_GPR3_HDMI_MUX_CTL_OFFSET); + writel(reg, &iomux->gpr[3]); } #endif /* CONFIG_VIDEO_IPUV3 */ @@ -467,9 +548,6 @@ int overwrite_console(void) int board_early_init_f(void) { setup_iomux_uart(); -#ifdef CONFIG_VIDEO_IPUV3 - setup_display(); -#endif #ifdef CONFIG_NAND_MXS setup_gpmi_nand(); @@ -494,6 +572,9 @@ int board_init(void) gpio_direction_output(IMX_GPIO_NR(1, 15), 1); imx_iomux_v3_setup_multiple_pads(port_exp, ARRAY_SIZE(port_exp)); +#ifdef CONFIG_VIDEO_IPUV3 + setup_display(); +#endif setup_iomux_eimnor(); return 0; } diff --git a/board/freescale/mx6sxsabresd/mx6sxsabresd.c b/board/freescale/mx6sxsabresd/mx6sxsabresd.c index 3ee4662..56dc020 100644 --- a/board/freescale/mx6sxsabresd/mx6sxsabresd.c +++ b/board/freescale/mx6sxsabresd/mx6sxsabresd.c @@ -150,11 +150,15 @@ static int setup_fec(void) { struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; - int reg; + int reg, ret; /* Use 125MHz anatop loopback REF_CLK1 for ENET1 */ clrsetbits_le32(&iomuxc_regs->gpr[1], IOMUX_GPR1_FEC1_MASK, 0); + ret = enable_fec_anatop_clock(0, ENET_125MHZ); + if (ret) + return ret; + imx_iomux_v3_setup_multiple_pads(phy_control_pads, ARRAY_SIZE(phy_control_pads)); @@ -163,14 +167,14 @@ static int setup_fec(void) /* Reset AR8031 PHY */ gpio_direction_output(IMX_GPIO_NR(2, 7) , 0); - udelay(500); + mdelay(10); gpio_set_value(IMX_GPIO_NR(2, 7), 1); reg = readl(&anatop->pll_enet); reg |= BM_ANADIG_PLL_ENET_REF_25M_ENABLE; writel(reg, &anatop->pll_enet); - return enable_fec_anatop_clock(0, ENET_125MHZ); + return 0; } int board_eth_init(bd_t *bis) diff --git a/common/usb.c b/common/usb.c index 700bfc3..9f67cc1 100644 --- a/common/usb.c +++ b/common/usb.c @@ -566,13 +566,12 @@ static int usb_get_descriptor(struct usb_device *dev, unsigned char type, } /********************************************************************** - * gets configuration cfgno and store it in the buffer + * gets len of configuration cfgno */ -int usb_get_configuration_no(struct usb_device *dev, - unsigned char *buffer, int cfgno) +int usb_get_configuration_len(struct usb_device *dev, int cfgno) { int result; - unsigned int length; + ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, 9); struct usb_config_descriptor *config; config = (struct usb_config_descriptor *)&buffer[0]; @@ -586,17 +585,23 @@ int usb_get_configuration_no(struct usb_device *dev, "(expected %i, got %i)\n", 9, result); return -EIO; } - length = le16_to_cpu(config->wTotalLength); + return le16_to_cpu(config->wTotalLength); +} - if (length > USB_BUFSIZ) { - printf("%s: failed to get descriptor - too long: %d\n", - __func__, length); - return -EIO; - } +/********************************************************************** + * gets configuration cfgno and store it in the buffer + */ +int usb_get_configuration_no(struct usb_device *dev, int cfgno, + unsigned char *buffer, int length) +{ + int result; + struct usb_config_descriptor *config; + config = (struct usb_config_descriptor *)&buffer[0]; result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, length); - debug("get_conf_no %d Result %d, wLength %d\n", cfgno, result, length); - config->wTotalLength = length; /* validated, with CPU byte order */ + debug("get_conf_no %d Result %d, wLength %d\n", cfgno, result, + le16_to_cpu(config->wTotalLength)); + config->wTotalLength = result; /* validated, with CPU byte order */ return result; } @@ -1070,7 +1075,7 @@ static int usb_prepare_device(struct usb_device *dev, int addr, bool do_read, int usb_select_config(struct usb_device *dev) { - ALLOC_CACHE_ALIGN_BUFFER(unsigned char, tmpbuf, USB_BUFSIZ); + unsigned char *tmpbuf = 0; int err; err = get_descriptor_len(dev, USB_DT_DEVICE_SIZE, USB_DT_DEVICE_SIZE); @@ -1084,14 +1089,23 @@ int usb_select_config(struct usb_device *dev) le16_to_cpus(&dev->descriptor.bcdDevice); /* only support for one config for now */ - err = usb_get_configuration_no(dev, tmpbuf, 0); + err = usb_get_configuration_len(dev, 0); + if (err >= 0) { + tmpbuf = (unsigned char *)malloc_cache_aligned(err); + if (!tmpbuf) + err = -ENOMEM; + else + err = usb_get_configuration_no(dev, 0, tmpbuf, err); + } if (err < 0) { printf("usb_new_device: Cannot read configuration, " \ "skipping device %04x:%04x\n", dev->descriptor.idVendor, dev->descriptor.idProduct); + free(tmpbuf); return err; } usb_parse_config(dev, tmpbuf, 0); + free(tmpbuf); usb_set_maxpacket(dev); /* * we set the default configuration here @@ -1200,4 +1214,60 @@ bool usb_device_has_child_on_port(struct usb_device *parent, int port) #endif } +#ifdef CONFIG_DM_USB +void usb_find_usb2_hub_address_port(struct usb_device *udev, + uint8_t *hub_address, uint8_t *hub_port) +{ + struct udevice *parent; + struct usb_device *uparent, *ttdev; + + /* + * When called from usb-uclass.c: usb_scan_device() udev->dev points + * to the parent udevice, not the actual udevice belonging to the + * udev as the device is not instantiated yet. So when searching + * for the first usb-2 parent start with udev->dev not + * udev->dev->parent . + */ + ttdev = udev; + parent = udev->dev; + uparent = dev_get_parent_priv(parent); + + while (uparent->speed != USB_SPEED_HIGH) { + struct udevice *dev = parent; + + if (device_get_uclass_id(dev->parent) != UCLASS_USB_HUB) { + printf("Error: Cannot find high speed parent of usb-1 device\n"); + *hub_address = 0; + *hub_port = 0; + return; + } + + ttdev = dev_get_parent_priv(dev); + parent = dev->parent; + uparent = dev_get_parent_priv(parent); + } + *hub_address = uparent->devnum; + *hub_port = ttdev->portnr; +} +#else +void usb_find_usb2_hub_address_port(struct usb_device *udev, + uint8_t *hub_address, uint8_t *hub_port) +{ + /* Find out the nearest parent which is high speed */ + while (udev->parent->parent != NULL) + if (udev->parent->speed != USB_SPEED_HIGH) { + udev = udev->parent; + } else { + *hub_address = udev->parent->devnum; + *hub_port = udev->portnr; + return; + } + + printf("Error: Cannot find high speed parent of usb-1 device\n"); + *hub_address = 0; + *hub_port = 0; +} +#endif + + /* EOF */ diff --git a/doc/README.imx6 b/doc/README.imx6 index 437af2f..e26ab71 100644 --- a/doc/README.imx6 +++ b/doc/README.imx6 @@ -84,3 +84,54 @@ Address: Reading bank 4: Word 0x00000002: 9f027772 00000004 + +2. Using imx_usb_loader for first install with SPL +-------------------------------------------------- + +imx_usb_loader is a very nice tool by BoundaryDevice that +allow to install U-Boot without a JTAG debugger, using +the USB boot mode as described in the manual. It is +a replacement for Freescale's MFGTOOLS. + +The sources can be found here: + + https://github.com/boundarydevices/imx_usb_loader.git + +Booting in USB mode, the i.MX6 announces itself to the Linux Host as: + +Bus 001 Device 111: ID 15a2:0061 Freescale Semiconductor, Inc. + +imx_usb_loader is able to download a single file (u-boot.imx) +to the board. For boards without SPL support, it is enough to +issue the command: + + sudo ../imx_usb_loader/imx_usb -v u-boot.imx + +Getting U-Boot when SPL support is active, it requires +two downloads. imx_usb_loader downloads the SPL into +OCRAM and starts it. SPL will check for a valid u-boot.img, and +because it is not found, it will wait for it using the y-modem +protocol via the console. + +A first install is then possible by combining imx_usb_loader with +another tool such as kermit. + +sudo ../imx_usb_loader/imx_usb -v SPL +kermit kermit_uboot + +and kermit_uboot contains something like this (set line should be adjusted): + +set line /dev/ttyUSB1 +set speed 115200 +SET CARRIER-WATCH OFF +set flow-control none +set handshake none +set prefixing all +set file type bin +set protocol ymodem +send u-boot.img +c + +The last "c" command tells kermit (from ckermit package in most distros) +to switch from command line mode to communication mode, and when the +script is finished, the U-Boot prompt is shown in the same shell. diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c index fa4c82f..b2d15c9 100644 --- a/drivers/i2c/mxc_i2c.c +++ b/drivers/i2c/mxc_i2c.c @@ -581,8 +581,16 @@ void bus_i2c_init(int index, int speed, int unused, return; } - mxc_i2c_buses[index].idle_bus_fn = idle_bus_fn; - mxc_i2c_buses[index].idle_bus_data = idle_bus_data; + /* + * Warning: Be careful to allow the assignment to a static + * variable here. This function could be called while U-Boot is + * still running in flash memory. So such assignment is equal + * to write data to flash without erasing. + */ + if (idle_bus_fn) + mxc_i2c_buses[index].idle_bus_fn = idle_bus_fn; + if (idle_bus_data) + mxc_i2c_buses[index].idle_bus_data = idle_bus_data; ret = enable_i2c_clk(1, index); if (ret < 0) { diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index c5054d6..1ccc576 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -502,15 +502,22 @@ static void set_sysctl(struct mmc *mmc, uint clock) clk = (pre_div << 8) | (div << 4); +#ifdef CONFIG_FSL_USDHC + esdhc_setbits32(®s->sysctl, SYSCTL_RSTA); +#else esdhc_clrbits32(®s->sysctl, SYSCTL_CKEN); +#endif esdhc_clrsetbits32(®s->sysctl, SYSCTL_CLOCK_MASK, clk); udelay(10000); - clk = SYSCTL_PEREN | SYSCTL_CKEN; +#ifdef CONFIG_FSL_USDHC + esdhc_clrbits32(®s->sysctl, SYSCTL_RSTA); +#else + esdhc_setbits32(®s->sysctl, SYSCTL_PEREN | SYSCTL_CKEN); +#endif - esdhc_setbits32(®s->sysctl, clk); } #ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK @@ -585,7 +592,9 @@ static int esdhc_init(struct mmc *mmc) esdhc_write32(®s->scr, 0x00000040); #endif +#ifndef CONFIG_FSL_USDHC esdhc_setbits32(®s->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN); +#endif /* Set the initial clock speed */ mmc_set_clock(mmc, 400000); @@ -657,8 +666,10 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) /* First reset the eSDHC controller */ esdhc_reset(regs); +#ifndef CONFIG_FSL_USDHC esdhc_setbits32(®s->sysctl, SYSCTL_PEREN | SYSCTL_HCKEN | SYSCTL_IPGEN | SYSCTL_CKEN); +#endif writel(SDHCI_IRQ_EN_BITS, ®s->irqstaten); memset(&cfg->cfg, 0, sizeof(cfg->cfg)); diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index 79f6737..3340dd2 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -131,13 +131,25 @@ static void fec_mii_setspeed(struct ethernet_regs *eth) /* * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock * and do not drop the Preamble. + * + * The i.MX28 and i.MX6 types have another field in the MSCR (aka + * MII_SPEED) register that defines the MDIO output hold time. Earlier + * versions are RAZ there, so just ignore the difference and write the + * register always. + * The minimal hold time according to IEE802.3 (clause 22) is 10 ns. + * HOLDTIME + 1 is the number of clk cycles the fec is holding the + * output. + * The HOLDTIME bitfield takes values between 0 and 7 (inclusive). + * Given that ceil(clkrate / 5000000) <= 64, the calculation for + * holdtime cannot result in a value greater than 3. */ - register u32 speed = DIV_ROUND_UP(imx_get_fecclk(), 5000000); + u32 pclk = imx_get_fecclk(); + u32 speed = DIV_ROUND_UP(pclk, 5000000); + u32 hold = DIV_ROUND_UP(pclk, 100000000) - 1; #ifdef FEC_QUIRK_ENET_MAC speed--; #endif - speed <<= 1; - writel(speed, ð->mii_speed); + writel(speed << 1 | hold << 8, ð->mii_speed); debug("%s: mii_speed %08x\n", __func__, readl(ð->mii_speed)); } @@ -1097,6 +1109,7 @@ int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr) #ifdef CONFIG_PHYLIB phydev = phy_find_by_mask(bus, 1 << phy_id, PHY_INTERFACE_MODE_RGMII); if (!phydev) { + mdio_unregister(bus); free(bus); return -ENOMEM; } @@ -1108,6 +1121,7 @@ int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr) #ifdef CONFIG_PHYLIB free(phydev); #endif + mdio_unregister(bus); free(bus); } return ret; diff --git a/drivers/serial/serial_mxc.c b/drivers/serial/serial_mxc.c index d6cf1d8..51485c0 100644 --- a/drivers/serial/serial_mxc.c +++ b/drivers/serial/serial_mxc.c @@ -75,6 +75,7 @@ #define UCR4_DREN (1<<0) /* Recv data ready interrupt enable */ #define UFCR_RXTL_SHF 0 /* Receiver trigger level shift */ #define UFCR_RFDIV (7<<7) /* Reference freq divider mask */ +#define UFCR_RFDIV_SHF 7 /* Reference freq divider shift */ #define UFCR_TXTL_SHF 10 /* Transmitter trigger level shift */ #define USR1_PARITYERR (1<<15) /* Parity error interrupt flag */ #define USR1_RTSS (1<<14) /* RTS pin status */ @@ -135,6 +136,10 @@ DECLARE_GLOBAL_DATA_PTR; +#define TXTL 2 /* reset default */ +#define RXTL 1 /* reset default */ +#define RFDIV 4 /* divide input clock by 2 */ + static void mxc_serial_setbrg(void) { u32 clk = imx_get_uartclk(); @@ -142,7 +147,9 @@ static void mxc_serial_setbrg(void) if (!gd->baudrate) gd->baudrate = CONFIG_BAUDRATE; - __REG(UART_PHYS + UFCR) = 4 << 7; /* divide input clock by 2 */ + __REG(UART_PHYS + UFCR) = (RFDIV << UFCR_RFDIV_SHF) + | (TXTL << UFCR_TXTL_SHF) + | (RXTL << UFCR_RXTL_SHF); __REG(UART_PHYS + UBIR) = 0xf; __REG(UART_PHYS + UBMR) = clk / (2 * gd->baudrate); diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c index 541c0f9..5ef6deb 100644 --- a/drivers/usb/host/dwc2.c +++ b/drivers/usb/host/dwc2.c @@ -823,12 +823,13 @@ int chunk_msg(struct dwc2_priv *priv, struct usb_device *dev, (*pid << DWC2_HCTSIZ_PID_OFFSET), &hc_regs->hctsiz); - if (!in) { - memcpy(priv->aligned_buffer, (char *)buffer + done, len); + if (!in && xfer_len) { + memcpy(priv->aligned_buffer, (char *)buffer + done, + xfer_len); flush_dcache_range((unsigned long)priv->aligned_buffer, (unsigned long)((void *)priv->aligned_buffer + - roundup(len, ARCH_DMA_MINALIGN))); + roundup(xfer_len, ARCH_DMA_MINALIGN))); } writel(phys_to_bus((unsigned long)priv->aligned_buffer), diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index c85dbce..c664b16 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -279,56 +279,16 @@ static inline u8 ehci_encode_speed(enum usb_device_speed speed) static void ehci_update_endpt2_dev_n_port(struct usb_device *udev, struct QH *qh) { - struct usb_device *ttdev; - int parent_devnum; + uint8_t portnr = 0; + uint8_t hubaddr = 0; if (udev->speed != USB_SPEED_LOW && udev->speed != USB_SPEED_FULL) return; - /* - * For full / low speed devices we need to get the devnum and portnr of - * the tt, so of the first upstream usb-2 hub, there may be usb-1 hubs - * in the tree before that one! - */ -#ifdef CONFIG_DM_USB - /* - * When called from usb-uclass.c: usb_scan_device() udev->dev points - * to the parent udevice, not the actual udevice belonging to the - * udev as the device is not instantiated yet. So when searching - * for the first usb-2 parent start with udev->dev not - * udev->dev->parent . - */ - struct udevice *parent; - struct usb_device *uparent; - - ttdev = udev; - parent = udev->dev; - uparent = dev_get_parent_priv(parent); - - while (uparent->speed != USB_SPEED_HIGH) { - struct udevice *dev = parent; - - if (device_get_uclass_id(dev->parent) != UCLASS_USB_HUB) { - printf("ehci: Error cannot find high-speed parent of usb-1 device\n"); - return; - } - - ttdev = dev_get_parent_priv(dev); - parent = dev->parent; - uparent = dev_get_parent_priv(parent); - } - parent_devnum = uparent->devnum; -#else - ttdev = udev; - while (ttdev->parent && ttdev->parent->speed != USB_SPEED_HIGH) - ttdev = ttdev->parent; - if (!ttdev->parent) - return; - parent_devnum = ttdev->parent->devnum; -#endif + usb_find_usb2_hub_address_port(udev, &hubaddr, &portnr); - qh->qh_endpt2 |= cpu_to_hc32(QH_ENDPT2_PORTNUM(ttdev->portnr) | - QH_ENDPT2_HUBADDR(parent_devnum)); + qh->qh_endpt2 |= cpu_to_hc32(QH_ENDPT2_PORTNUM(portnr) | + QH_ENDPT2_HUBADDR(hubaddr)); } static int diff --git a/drivers/usb/musb-new/musb_host.c b/drivers/usb/musb-new/musb_host.c index 40b9c66..2515447 100644 --- a/drivers/usb/musb-new/musb_host.c +++ b/drivers/usb/musb-new/musb_host.c @@ -2092,9 +2092,13 @@ int musb_urb_enqueue( } #else if (tt_needed(musb, urb->dev)) { - u16 hub_port = find_tt(urb->dev); - qh->h_addr_reg = (u8) (hub_port >> 8); - qh->h_port_reg = (u8) (hub_port & 0xff); + uint8_t portnr = 0; + uint8_t hubaddr = 0; + usb_find_usb2_hub_address_port(urb->dev, + &hubaddr, + &portnr); + qh->h_addr_reg = hubaddr; + qh->h_port_reg = portnr; } #endif } diff --git a/drivers/usb/musb-new/usb-compat.h b/drivers/usb/musb-new/usb-compat.h index 1c41e2a..760bd78 100644 --- a/drivers/usb/musb-new/usb-compat.h +++ b/drivers/usb/musb-new/usb-compat.h @@ -68,38 +68,6 @@ static inline int usb_hcd_unmap_urb_for_dma(struct usb_hcd *hcd, } #ifdef CONFIG_DM_USB -static inline u16 find_tt(struct usb_device *udev) -{ - struct udevice *parent; - struct usb_device *uparent, *ttdev; - - /* - * When called from usb-uclass.c: usb_scan_device() udev->dev points - * to the parent udevice, not the actual udevice belonging to the - * udev as the device is not instantiated yet. So when searching - * for the first usb-2 parent start with udev->dev not - * udev->dev->parent . - */ - ttdev = udev; - parent = udev->dev; - uparent = dev_get_parent_priv(parent); - - while (uparent->speed != USB_SPEED_HIGH) { - struct udevice *dev = parent; - - if (device_get_uclass_id(dev->parent) != UCLASS_USB_HUB) { - printf("musb: Error cannot find high speed parent of usb-1 device\n"); - return 0; - } - - ttdev = dev_get_parent_priv(dev); - parent = dev->parent; - uparent = dev_get_parent_priv(parent); - } - - return (uparent->devnum << 8) | (ttdev->portnr - 1); -} - static inline struct usb_device *usb_dev_get_parent(struct usb_device *udev) { struct udevice *parent = udev->dev->parent; @@ -129,27 +97,6 @@ static inline struct usb_device *usb_dev_get_parent(struct usb_device *udev) return NULL; } #else -static inline u16 find_tt(struct usb_device *dev) -{ - u8 chid; - u8 hub; - - /* Find out the nearest parent which is high speed */ - while (dev->parent->parent != NULL) - if (dev->parent->speed != USB_SPEED_HIGH) - dev = dev->parent; - else - break; - - /* determine the port address at that hub */ - hub = dev->parent->devnum; - for (chid = 0; chid < USB_MAXCHILDREN; chid++) - if (dev->parent->children[chid] == dev) - break; - - return (hub << 8) | chid; -} - static inline struct usb_device *usb_dev_get_parent(struct usb_device *dev) { return dev->parent; diff --git a/include/configs/mx7_common.h b/include/configs/mx7_common.h index 870e12e..d507fb4 100644 --- a/include/configs/mx7_common.h +++ b/include/configs/mx7_common.h @@ -36,6 +36,8 @@ #define CONFIG_DISPLAY_CPUINFO #define CONFIG_DISPLAY_BOARDINFO +#define CONFIG_FSL_CLK + #define CONFIG_LOADADDR 0x80800000 #define CONFIG_SYS_TEXT_BASE 0x87800000 diff --git a/include/configs/novena.h b/include/configs/novena.h index 4b4f2d7..5f0a230 100644 --- a/include/configs/novena.h +++ b/include/configs/novena.h @@ -16,6 +16,7 @@ #define CONFIG_FIT #define CONFIG_KEYBOARD +#include <config_distro_defaults.h> #include "mx6_common.h" /* U-Boot Commands */ @@ -58,7 +59,7 @@ /* Booting Linux */ #define CONFIG_BOOTFILE "fitImage" #define CONFIG_BOOTARGS "console=ttymxc1,115200 " -#define CONFIG_BOOTCOMMAND "run net_nfs" +#define CONFIG_BOOTCOMMAND "run distro_bootcmd ; run net_nfs" #define CONFIG_HOSTNAME novena /* Physical Memory Map */ @@ -190,6 +191,7 @@ #endif /* Extra U-Boot environment. */ +#ifndef CONFIG_SPL_BUILD #define CONFIG_EXTRA_ENV_SETTINGS \ "fdt_high=0xffffffff\0" \ "initrd_high=0xffffffff\0" \ @@ -199,6 +201,11 @@ "rootdev=/dev/mmcblk0p2\0" \ "netdev=eth0\0" \ "kernel_addr_r="__stringify(CONFIG_LOADADDR)"\0" \ + "pxefile_addr_r="__stringify(CONFIG_LOADADDR)"\0" \ + "scriptaddr="__stringify(CONFIG_LOADADDR)"\0" \ + "ramdisk_addr_r=0x28000000\0" \ + "fdt_addr_r=0x18000000\0" \ + "fdtfile=imx6q-novena.dtb\0" \ "addcons=" \ "setenv bootargs ${bootargs} " \ "console=${consdev},${baudrate}\0" \ @@ -242,5 +249,19 @@ "fatwrite mmc 0:1 ${loadaddr} u-boot.img ${filesize} ; "\ "fi ; " \ "fi\0" \ + BOOTENV + +#define BOOT_TARGET_DEVICES(func) \ + func(MMC, mmc, 0) \ + func(USB, usb, 0) \ + func(SATA, sata, 0) \ + func(PXE, pxe, na) \ + func(DHCP, dhcp, na) + +#include <config_distro_bootcmd.h> + +#else +#define CONFIG_EXTRA_ENV_SETTINGS +#endif /* CONFIG_SPL_BUILD */ #endif /* __CONFIG_H */ diff --git a/include/fsl_esdhc.h b/include/fsl_esdhc.h index aa1b4cf..073048f 100644 --- a/include/fsl_esdhc.h +++ b/include/fsl_esdhc.h @@ -25,10 +25,12 @@ #define SYSCTL_INITA 0x08000000 #define SYSCTL_TIMEOUT_MASK 0x000f0000 #define SYSCTL_CLOCK_MASK 0x0000fff0 +#if !defined(CONFIG_FSL_USDHC) #define SYSCTL_CKEN 0x00000008 #define SYSCTL_PEREN 0x00000004 #define SYSCTL_HCKEN 0x00000002 #define SYSCTL_IPGEN 0x00000001 +#endif #define SYSCTL_RSTA 0x01000000 #define SYSCTL_RSTC 0x02000000 #define SYSCTL_RSTD 0x04000000 diff --git a/include/usb.h b/include/usb.h index 55b9268..2539364 100644 --- a/include/usb.h +++ b/include/usb.h @@ -266,8 +266,9 @@ int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len, int interval); int usb_disable_asynch(int disable); int usb_maxpacket(struct usb_device *dev, unsigned long pipe); -int usb_get_configuration_no(struct usb_device *dev, unsigned char *buffer, - int cfgno); +int usb_get_configuration_no(struct usb_device *dev, int cfgno, + unsigned char *buffer, int length); +int usb_get_configuration_len(struct usb_device *dev, int cfgno); int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type, unsigned char id, void *buf, int size); int usb_get_class_descriptor(struct usb_device *dev, int ifnum, @@ -874,6 +875,18 @@ int legacy_hub_port_reset(struct usb_device *dev, int port, int hub_port_reset(struct udevice *dev, int port, unsigned short *portstat); +/* + * usb_find_usb2_hub_address_port() - Get hub address and port for TT setting + * + * Searches for the first HS hub above the given device. If a + * HS hub is found, the hub address and the port the device is + * connected to is return, as required for SPLIT transactions + * + * @param: udev full speed or low speed device + */ +void usb_find_usb2_hub_address_port(struct usb_device *udev, + uint8_t *hub_address, uint8_t *hub_port); + /** * usb_alloc_new_device() - Allocate a new device * |