[U-Boot] [PATCH v8 4/4] Add USB support for Efika

Wolfgang Grandegger wg at denx.de
Mon Nov 14 10:21:51 CET 2011


On 11/12/2011 06:45 PM, Jana Rapava wrote:
> This commit adds USB support for EfikaMX and EfikaSB.
> 
> Signed-off-by: Jana Rapava <fermata7 at gmail.com>
> Signed-off-by: Marek Vasut <marek.vasut at gmail.com>
> Cc: Remy Bohmer <linux at bohmer.net>
> Cc: Stefano Babic <sbabic at denx.de>
> Cc: Igor Grinberg <grinberg at compulab.co.il>
> Cc: Wolfgang Grandegger <wg at denx.de>
> 
> Acked-by: Marek Vasut <marek.vasut at gmail.com>
> ---
> Changes for v2:
>     - introduce temporary variable in ulpi_write
>     - whitespace changes
> Changes for v3:
>      - add protection against multiple inclusion of efika.h
> Changes for v4:
>       - rename multiple inclusion protection macro in efika.h
> Changes for v5:
>        - fix unterminated #ifndef in efika.h
> Changes for v6:
> 	- add Acked-by
> 	- no changes
> Changes for v7:
> 	- use ULPI-related definitions from ./include/usb/ulpi.h
> Changes for v8:
> 	- adjust to new and more generic ULPI implementation
> 
>  board/efikamx/Makefile      |    3 +
>  board/efikamx/efika.h       |   35 +++++
>  board/efikamx/efikamx-usb.c |  344 +++++++++++++++++++++++++++++++++++++++++++
>  board/efikamx/efikamx.c     |    3 +
>  include/configs/efikamx.h   |   18 +++
>  5 files changed, 403 insertions(+), 0 deletions(-)
>  create mode 100644 board/efikamx/efika.h
>  create mode 100644 board/efikamx/efikamx-usb.c
> 
...
> diff --git a/board/efikamx/efikamx-usb.c b/board/efikamx/efikamx-usb.c
> new file mode 100644
> index 0000000..cbcdb18
> --- /dev/null
> +++ b/board/efikamx/efikamx-usb.c
...
> +/*
> + * Configure control registers of the USB controller.
> + */
> +void control_regs_setup(struct mx5_usb_control_regs *control)
> +{
> +	clrsetbits_le32(&control->usbctrl,
> +		(MXC_OTG_WUE | MXC_OTG_PM | MX51_H1_ULPI_IE | MX51_H1_WUE),
> +		MX51_H1_PM);
> +
> +	clrsetbits_le32(&control->phyctrl0,
> +			MX51_OTG_OVERCURD,
> +			MX51_EHCI_POWERPINSE);
> +
> +	clrsetbits_le32(&control->phyctrl1,
> +			MX51_SYSCLOCK_MASK,
> +			MX51_SYSCLOCK_24_MHZ);
> +
> +	setbits_le32(&control->usbctrl1, MX51_H1_EXTCLKE);
> +
> +	clrsetbits_le32(&control->uh2ctrl,
> +			(MX51_H2_ULPI_IE | MX51_H2_WUE),
> +			MX51_H2_PM);
> +
> +	udelay(10000);
> +}
> +
> +void ulpi_set_flags(u32 ulpi_viewport, struct ulpi_regs *ulpi)
> +{
> +	ulpi_otg_ctrl_flags(ulpi_viewport, ulpi, ULPI_WRITE, ULPI_OTG_EXTVBUSIND |
> +		ULPI_OTG_DM_PULLDOWN | ULPI_OTG_DP_PULLDOWN);
> +	ulpi_function_ctrl_flags(ulpi_viewport, ulpi, ULPI_WRITE, ULPI_FC_XCVRSEL |
> +		ULPI_FC_OPMODE_NORMAL | ULPI_FC_SUSPENDM);
> +	ulpi_iface_ctrl_flags(ulpi_viewport, ulpi, ULPI_WRITE, 0);
> +
> +	/*
> +	 * NOTE: Setting ULPI_OTG_CHRGVBUS violates USB specification,
> +	 * but otherwise, USB on Efika doesn't charge VBUS
> +	 * and as a result, USB doesn't work.
> +	 */
> +	ulpi_otg_ctrl_flags(ulpi_viewport, ulpi, ULPI_SET, ULPI_OTG_DRVVBUS |
> +		ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_CHRGVBUS);
> +}
> +
> +/*
> + * 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 ulpi_regs *ulpi = (struct ulpi_regs *)0;
> +
> +	u32 tmp = ulpi_read((u32)&ehci->ulpi_viewport, (u32)&ulpi->otg_ctrl);
> +	tmp |= ULPI_OTG_CHRGVBUS;
> +	ulpi_write((u32)&ehci->ulpi_viewport, (u32)&ulpi->otg_ctrl, tmp);
> +
> +	/* USB 2.0 specification say 50 ms resets on root. */
> +	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 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((u32)&ehci->ulpi_viewport, ulpi);
> +	ulpi_set_flags((u32)&ehci->ulpi_viewport, ulpi);
> +}
> +
> +void ehci2_init(struct usb_ehci *ehci, struct 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((u32)&ehci->ulpi_viewport, ulpi);
> +	ulpi_set_flags((u32)&ehci->ulpi_viewport, ulpi);
> +}
> +
> +int ehci_hcd_init(void)
> +{
> +	struct usb_ehci *ehci;
> +	struct mx5_usb_control_regs *mx5_usb_control_regs;
> +	struct 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 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;
> +	};
> +
> +	/* EfikaMX USB has issues ... */
> +	udelay(10000);
> +
> +	return 0;
> +}
> +
> +int ehci_hcd_stop(void)
> +{
> +	return 0;
> +}

We should share part of the code above, similar to
drivers/usb/ehci-mxc.c. The board specific code could then be put in
board_ehci_hcd_init().

> diff --git a/board/efikamx/efikamx.c b/board/efikamx/efikamx.c
> index 0c4e24b..8e9b42b 100644
> --- a/board/efikamx/efikamx.c
> +++ b/board/efikamx/efikamx.c
> @@ -37,6 +37,8 @@
>  #include <fsl_pmic.h>
>  #include <mc13892.h>
>  
> +#include "efika.h"
> +
>  DECLARE_GLOBAL_DATA_PTR;
>  
>  /*
> @@ -678,6 +680,7 @@ int board_late_init(void)
>  
>  	setup_iomux_led();
>  	setup_iomux_ata();
> +	setup_iomux_usb();
>  
>  	efikamx_toggle_led(EFIKAMX_LED_BLUE);
>  
> diff --git a/include/configs/efikamx.h b/include/configs/efikamx.h
> index 54f48e4..1c48376 100644
> --- a/include/configs/efikamx.h
> +++ b/include/configs/efikamx.h
> @@ -44,6 +44,10 @@
>  
>  #define CONFIG_SYS_TEXT_BASE		0x97800000
>  
> +#define	CONFIG_L2_OFF
> +#define	CONFIG_SYS_ICACHE_OFF
> +#define	CONFIG_SYS_DCACHE_OFF
> +
>  /*
>   * Bootloader Components Configuration
>   */
> @@ -172,6 +176,20 @@
>  #endif
>  
>  /*
> + * USB
> + */
> +#define CONFIG_CMD_USB
> +#ifdef CONFIG_CMD_USB
> +#define CONFIG_USB_EHCI			/* Enable EHCI USB support */
> +#define CONFIG_MXC_USB_PORT	1

The other related option should then be used as well.

> +#define CONFIG_EHCI_IS_TDI
> +#define CONFIG_USB_STORAGE
> +#define CONFIG_USB_KEYBOARD
> +#define CONFIG_USB_ULPI
> +#define CONFIG_USB_ULPI_VIEWPORT
> +#endif /* CONFIG_CMD_USB */
> +
> +/*
>   * Filesystems
>   */
>  #ifdef CONFIG_CMD_FAT


Wolfgang.


More information about the U-Boot mailing list