> This commit adds USB support for EfikaMX and EfikaSB. > > Signed-off-by: Jana Rapava <ferma...@gmail.com> > Signed-off-by: Marek Vasut <marek.va...@gmail.com> > Cc: Remy Bohmer <li...@bohmer.net> > Cc: Stefano Babic <sba...@denx.de> > --- > Changes for v2: > - changed to proper patch > Changes for v3: > - merged other USB patches from u-boot-pxa/efikasb > - offset-based access changed to struct-based access > - use {clrset,clr,set}bits_le32() calls > - CodingStyle and naming cleanup > Changes for v4: > - split into patchset > - CodingStyle and naming cleanup > - remove endless loops > - silence compiler warnings > Changes for v5: > - change order of arguments in ulpi* functions > - change type of reg argument > - rename offset macro > Changes for v6: > - rebase on top of u-boot-imx/next > - cleanup of CodingStyle and comments > - use macro machine_is_efikasb() > - introduce header file efika.h > Changes for v7: > - add proper header to efika.h > - include efika.h into efikamx.c > - check return values from ulpi_wait() > > board/efikamx/Makefile | 3 + > board/efikamx/efika.h | 30 ++++ > board/efikamx/efikamx-usb.c | 397 > +++++++++++++++++++++++++++++++++++++++++++ board/efikamx/efikamx.c > | 3 + include/configs/efikamx.h | 16 ++ > 5 files changed, 449 insertions(+), 0 deletions(-) > create mode 100644 board/efikamx/efika.h > create mode 100644 board/efikamx/efikamx-usb.c > Dear Jana Rapava,
[...] > +u32 ulpi_wait(struct usb_ehci *ehci, u32 ulpi_bit) > +{ > + int timeout = ULPI_TIMEOUT; > + u32 tmp; > + > + /* Wait for the ulpi_bit to become zero. */ > + while (--timeout) { > + tmp = readl(&ehci->ulpi_viewpoint); > + if (!(tmp & ulpi_bit)) > + break; > + WATCHDOG_RESET(); > + } > + > + if (!timeout) > + return 0; > + else > + return tmp; The logic here seems bogus, if the register is zero, this function returns zero either way. > +} > + > +void ulpi_write(struct usb_ehci *ehci, u32 reg, u32 value) > +{ > + if (!(readl(&ehci->ulpi_viewpoint) & ULPI_SS)) { > + writel(ULPI_WU, &ehci->ulpi_viewpoint); > + if (!ulpi_wait(ehci, ULPI_WU)) > + printf("ULPI wakeup timed out\n"); > + } > + > + writel(ULPI_RWRUN | ULPI_RWCTRL | > + reg << ULPI_ADDR_SHIFT | ulpi_write_mask(value), > + &ehci->ulpi_viewpoint); > + if (!ulpi_wait(ehci, ULPI_RWRUN)) > + printf("ULPI write timed out\n"); > +} > + > +u32 ulpi_read(struct usb_ehci *ehci, u32 reg) > +{ > + u32 tmp; > + if (!(readl(&ehci->ulpi_viewpoint) & ULPI_SS)) { > + writel(ULPI_WU, &ehci->ulpi_viewpoint); > + if (!ulpi_wait(ehci, ULPI_WU)) > + printf("ULPI wakeup timed out\n"); > + } > + > + writel(ULPI_RWRUN | reg << ULPI_ADDR_SHIFT, &ehci->ulpi_viewpoint); > + tmp = ulpi_wait(ehci, ULPI_RWRUN); > + if (!tmp) > + printf("ULPI read timed out\n"); > + return ulpi_read_mask(tmp); > +} > + > +void ulpi_init(struct usb_ehci *ehci, struct mxc_ulpi_regs *ulpi) > +{ > + u32 tmp = 0; > + int reg, i; > + > + /* get ID from ULPI immediate registers */ > + for (reg = ULPI_ID_REGS_COUNT - 1; reg >= 0; reg--) > + tmp |= ulpi_read(ehci, (u32)reg) << (reg * 8); Are you ignoring my comment and picking only some of them? Is the cast here necessary? > + /* split into vendor and product ID */ > + debug("Found ULPI TX, ID %04x:%04x\n", tmp >> 16, tmp & 0xffff); > + > + /* ULPI check integrity */ > + for (i = 0; i < 2; i++) { > + ulpi_write(ehci, (u32)&ulpi->scratch_write, > + ULPI_TEST_VALUE << i); > + tmp = ulpi_read(ehci, (u32)&ulpi->scratch_write); > + > + if (tmp != (ULPI_TEST_VALUE << i)) { > + printf("ULPI integrity check failed\n"); > + return; > + } > + } > + > + /* ULPI set flags */ > + ulpi_write(ehci, (u32)&ulpi->otg_ctrl_write, > + ULPI_OTG_EXT_VBUS_IND | > + ULPI_OTG_DM_PULLDOWN | ULPI_OTG_DP_PULLDOWN); > + ulpi_write(ehci, (u32)&ulpi->function_ctrl_write, > + ULPI_FC_XCVR_SELECT | ULPI_FC_OPMODE_NORMAL | > + ULPI_FC_SUSPENDM_PWRED); > + ulpi_write(ehci, (u32)&ulpi->iface_ctrl_write, 0); > + ulpi_write(ehci, (u32)&ulpi->otg_ctrl_set, > + ULPI_OTG_DRV_VBUS | ULPI_OTG_DRV_VBUS_EXT); > + > + /* > + * NOTE: This violates USB specification, but otherwise, USB on Efika > + * doesn't charge VBUS and as a result, USB doesn't work. > + */ > + ulpi_write(ehci, (u32)&ulpi->otg_ctrl_set, ULPI_OTG_CHRG_VBUS); > +} > + > +/* > + * Solve the VBUS reset problem on Efika > + * by setting the CHRG_VBUS bit in the reset. > + */ > +void ehci_fixup(uint32_t *status_reg, uint32_t *reg_ref) > +{ > + struct usb_ehci *ehci = (struct usb_ehci *)(OTG_BASE_ADDR + > + MX51_REGISTER_LAYOUT_LENGTH); > + struct mxc_ulpi_regs *ulpi = (struct mxc_ulpi_regs *)0; > + > + u32 tmp = ulpi_read(ehci, (u32)&ulpi->otg_ctrl_write); > + tmp |= ULPI_OTG_CHRG_VBUS; > + ulpi_write(ehci, (u32)&ulpi->otg_ctrl_write, tmp); > + > + /* USB 2.0 specification say 50 ms resets on root. */ Where can I read about this please? > + wait_ms(50); > + > + /* Now terminate the reset. */ > + *reg_ref = ehci_readl(status_reg); > + *reg_ref |= EHCI_PS_PE; > +} > + > +void ehci0_init(struct usb_ehci *ehci) > +{ > + writel(MX51_16BIT_UTMI, &ehci->portsc); > +} > + > +void ehci1_init(struct usb_ehci *ehci, struct mxc_ulpi_regs *ulpi) > +{ > + mxc_request_iomux(MX51_PIN_USBH1_STP, IOMUX_CONFIG_ALT2); > + mxc_iomux_set_pad(MX51_PIN_USBH1_STP, PAD_CTL_DRV_HIGH | > + PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); > + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_USBH1_STP), 0); > + udelay(1000); > + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_USBH1_STP), 1); > + udelay(1000); > + > + mxc_request_iomux(MX51_PIN_USBH1_STP, IOMUX_CONFIG_ALT0); > + mxc_iomux_set_pad(MX51_PIN_USBH1_STP, USB_PAD_CONFIG); > + udelay(10000); > + > + clrbits_le32(&ehci->usbcmd, MX51_ITC_IMMEDIATE_MASK); > + udelay(10000); > + > + writel(MX51_ULPI_MODE_MASK, &ehci->portsc); > + udelay(10000); > + > + ulpi_init(ehci, ulpi); > +} > + > + remove newline > +void ehci2_init(struct usb_ehci *ehci, struct mxc_ulpi_regs *ulpi) > +{ > + mxc_request_iomux(MX51_PIN_EIM_A26, IOMUX_CONFIG_ALT1); > + mxc_iomux_set_pad(MX51_PIN_EIM_A26, PAD_CTL_DRV_HIGH | > + PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); > + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_A26), 0); > + udelay(1000); > + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_A26), 1); > + udelay(1000); > + > + mxc_request_iomux(MX51_PIN_EIM_A26, IOMUX_CONFIG_ALT2); > + mxc_iomux_set_pad(MX51_PIN_EIM_A26, USB_PAD_CONFIG); > + > + writel(MX51_ULPI_MODE_MASK, &ehci->portsc); > + udelay(10000); > + > + ulpi_init(ehci, ulpi); > +} > + > +int ehci_hcd_init(void) > +{ > + struct usb_ehci *ehci; > + struct mx5_usb_control_regs *mx5_usb_control_regs; > + struct mxc_ulpi_regs *ulpi; > + > + mx5_usb_control_regs = (struct mx5_usb_control_regs *)(OTG_BASE_ADDR + > + MX5_CTRL_REGS_OFFSET); > + control_regs_setup(mx5_usb_control_regs); > + ulpi = (struct mxc_ulpi_regs *)0; > + > + /* Init EHCI core */ > + ehci = (struct usb_ehci *)(OTG_BASE_ADDR + > + (MX51_REGISTER_LAYOUT_LENGTH * CONFIG_MXC_USB_PORT)); > + hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); > + hcor = (struct ehci_hcor *)((uint32_t) hccr + > + HC_LENGTH(ehci_readl(&hccr->cr_capbase))); > + setbits_le32(&ehci->usbmode, CM_HOST); > + setbits_le32(&ehci->control, USB_EN); > + > + /* Init iMX51 EHCI */ > + efika_usb_phy_reset(); > + efika_usb_hub_reset(); > + efika_usb_enable_devices(); > + > + switch (CONFIG_MXC_USB_PORT) { > + case 0: > + ehci0_init(ehci); > + break; > + case 1: > + ehci1_init(ehci, ulpi); > + break; > + case 2: > + if (machine_is_efikasb()) { > + ehci2_init(ehci, ulpi); > + break; > + } the break should be past the if, also you can drop the braces then. > + }; > + > + /* EfikaMX USB has issues ... */ > + udelay(10000); > + > + return 0; > +} > + > +int ehci_hcd_stop(void) > +{ > + return 0; > +} _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot