Re: [PATCH 3/5] pcm037: Add USB Host support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 21 Apr 2009, Sascha Hauer wrote:

> Signed-off-by: Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>
> ---
>  arch/arm/mach-mx3/Kconfig  |    1 +
>  arch/arm/mach-mx3/pcm037.c |  135 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 136 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/mach-mx3/Kconfig b/arch/arm/mach-mx3/Kconfig
> index 194b842..4bb7d69 100644
> --- a/arch/arm/mach-mx3/Kconfig
> +++ b/arch/arm/mach-mx3/Kconfig
> @@ -30,6 +30,7 @@ config MACH_MX31ADS_WM1133_EV1
>  config MACH_PCM037
>  	bool "Support Phytec pcm037 (i.MX31) platforms"
>  	select ARCH_MX31
> +	select MXC_ULPI
>  	help
>  	  Include support for Phytec pcm037 platform. This includes
>  	  specific configurations for the board and its peripherals.
> diff --git a/arch/arm/mach-mx3/pcm037.c b/arch/arm/mach-mx3/pcm037.c
> index b5227d8..dd16452 100644
> --- a/arch/arm/mach-mx3/pcm037.c
> +++ b/arch/arm/mach-mx3/pcm037.c
> @@ -28,6 +28,7 @@
>  #include <linux/interrupt.h>
>  #include <linux/i2c.h>
>  #include <linux/i2c/at24.h>
> +#include <linux/delay.h>
>  
>  #include <mach/hardware.h>
>  #include <asm/mach-types.h>
> @@ -43,6 +44,8 @@
>  #ifdef CONFIG_I2C_IMX
>  #include <mach/i2c.h>
>  #endif
> +#include <mach/mxc_ehci.h>
> +#include <mach/ulpi.h>
>  
>  #include "devices.h"
>  
> @@ -210,6 +213,136 @@ static int uart2_pins[] = {
>  	MX31_PIN_CSPI3_MISO__TXD3
>  };
>  
> +static int isp1504_set_vbus_power(void __iomem *view, int on)
> +{
> +	int vid, pid, ret = 0;
> +
> +	vid = (ulpi_read(ISP1504_VID_HIGH, view) << 8) |
> +		 ulpi_read(ISP1504_VID_LOW, view);
> +	pid = (ulpi_read(ISP1504_PID_HIGH, view) << 8) |
> +		 ulpi_read(ISP1504_PID_LOW, view);
> +
> +	pr_info("ULPI Vendor ID 0x%x    Product ID 0x%x\n", vid, pid);
> +	if (vid != 0x4cc || pid != 0x1504) {
> +		pr_err("No ISP1504 found\n");
> +		return -1;
> +	}
> +
> +	if (on) {
> +		ret = ulpi_set(DRV_VBUS_EXT |	/* enable external Vbus */
> +			    DRV_VBUS |		/* enable internal Vbus */
> +			    USE_EXT_VBUS_IND |	/* use external indicator */
> +			    CHRG_VBUS,		/* charge Vbus */
> +			    ISP1504_OTGCTL, view);
> +	} else {
> +		ret = ulpi_clear(DRV_VBUS_EXT |	/* disable external Vbus */
> +			      DRV_VBUS,		/* disable internal Vbus */
> +			      ISP1504_OTGCTL, view);
> +
> +		ret |= ulpi_set(USE_EXT_VBUS_IND | /* use external indicator */
> +			    DISCHRG_VBUS,	   /* discharge Vbus */
> +			    ISP1504_OTGCTL, view);
> +	}
> +
> +	return ret;
> +}
> +
> +static int pcm037_otg_init(struct platform_device *pdev)
> +{
> +	int ret;
> +	unsigned int tmp;
> +
> +	tmp = readl(IO_ADDRESS(OTG_BASE_ADDR) + 0x600);
> +	tmp &= ~((3 << 21) | 1);
> +	tmp |= (1 << 5) | (1 << 16) | (1 << 19) | (1 << 11) | (1 << 20);
> +	writel(tmp, IO_ADDRESS(OTG_BASE_ADDR) + 0x600);
> +
> +	tmp = readl(IO_ADDRESS(OTG_BASE_ADDR) + 0x184);
> +	tmp &= ~(3 << 30);
> +	tmp |= 2 << 30;
> +	writel(tmp, IO_ADDRESS(OTG_BASE_ADDR) + 0x184);

...some would say "no way! use macros!", I would be happy, if you 
commented these. Or do both to make us all happy:-)

Have you also tested this in pure device mode? CanI pull these from some 
tree or at least to which tree / branch can I apply this series?

> +
> +	mxc_iomux_mode(MX31_PIN_USBOTG_DATA0__USBOTG_DATA0);
> +	mxc_iomux_mode(MX31_PIN_USBOTG_DATA1__USBOTG_DATA1);
> +	mxc_iomux_mode(MX31_PIN_USBOTG_DATA2__USBOTG_DATA2);
> +	mxc_iomux_mode(MX31_PIN_USBOTG_DATA3__USBOTG_DATA3);
> +	mxc_iomux_mode(MX31_PIN_USBOTG_DATA4__USBOTG_DATA4);
> +	mxc_iomux_mode(MX31_PIN_USBOTG_DATA5__USBOTG_DATA5);
> +	mxc_iomux_mode(MX31_PIN_USBOTG_DATA6__USBOTG_DATA6);
> +	mxc_iomux_mode(MX31_PIN_USBOTG_DATA7__USBOTG_DATA7);
> +	mxc_iomux_mode(MX31_PIN_USBOTG_CLK__USBOTG_CLK);
> +	mxc_iomux_mode(MX31_PIN_USBOTG_DIR__USBOTG_DIR);
> +	mxc_iomux_mode(MX31_PIN_USBOTG_NXT__USBOTG_NXT);
> +	mxc_iomux_mode(MX31_PIN_USBOTG_STP__USBOTG_STP);
> +
> +	mdelay(10);
> +
> +	ret = isp1504_set_vbus_power(IO_ADDRESS(OTG_BASE_ADDR + 0x170), 1);
> +
> +	return 0;
> +}
> +
> +struct mxc_usbh_platform_data otg_pdata = {
> +	.init = pcm037_otg_init,
> +};
> +
> +static int pcm037_usbh2_init(struct platform_device *pdev)
> +{
> +	int ret;
> +	unsigned int tmp;
> +
> +	tmp = readl(IO_ADDRESS(IOMUXC_BASE_ADDR + 0x8));
> +	tmp |= 1 << 11;
> +	writel(tmp, IO_ADDRESS(IOMUXC_BASE_ADDR + 0x8));

Hm, isn't this what the mxc_iomux_set_gpr() function is for?

> +
> +	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_USBH2_CLK, IOMUX_CONFIG_FUNC));
> +	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_USBH2_DIR, IOMUX_CONFIG_FUNC));
> +	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_USBH2_NXT, IOMUX_CONFIG_FUNC));
> +	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_USBH2_STP, IOMUX_CONFIG_FUNC));
> +	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_USBH2_DATA0, IOMUX_CONFIG_FUNC));
> +	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_USBH2_DATA1, IOMUX_CONFIG_FUNC));
> +	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_STXD3, IOMUX_CONFIG_FUNC));
> +	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_SRXD3, IOMUX_CONFIG_FUNC));
> +	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_SCK3, IOMUX_CONFIG_FUNC));
> +	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_SFS3, IOMUX_CONFIG_FUNC));
> +	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_STXD6, IOMUX_CONFIG_FUNC));
> +	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_SRXD6, IOMUX_CONFIG_FUNC));
> +
> +#define H2_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST | PAD_CTL_HYS_CMOS | PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU)
> +	mxc_iomux_set_pad(MX31_PIN_USBH2_CLK, H2_PAD_CFG);
> +	mxc_iomux_set_pad(MX31_PIN_USBH2_DIR, H2_PAD_CFG);
> +	mxc_iomux_set_pad(MX31_PIN_USBH2_NXT, H2_PAD_CFG);
> +	mxc_iomux_set_pad(MX31_PIN_USBH2_STP, H2_PAD_CFG);
> +	mxc_iomux_set_pad(MX31_PIN_USBH2_DATA0, H2_PAD_CFG); /* USBH2_DATA0 */
> +	mxc_iomux_set_pad(MX31_PIN_USBH2_DATA1, H2_PAD_CFG); /* USBH2_DATA1 */
> +	mxc_iomux_set_pad(MX31_PIN_SRXD6, H2_PAD_CFG);	/* USBH2_DATA2 */
> +	mxc_iomux_set_pad(MX31_PIN_STXD6, H2_PAD_CFG);	/* USBH2_DATA3 */
> +	mxc_iomux_set_pad(MX31_PIN_SFS3, H2_PAD_CFG);	/* USBH2_DATA4 */
> +	mxc_iomux_set_pad(MX31_PIN_SCK3, H2_PAD_CFG);	/* USBH2_DATA5 */
> +	mxc_iomux_set_pad(MX31_PIN_SRXD3, H2_PAD_CFG);	/* USBH2_DATA6 */
> +	mxc_iomux_set_pad(MX31_PIN_STXD3, H2_PAD_CFG);	/* USBH2_DATA7 */
> +
> +	tmp = readl(IO_ADDRESS(OTG_BASE_ADDR) + 0x600);
> +	tmp &= ~((3 << 21) | 1);
> +	tmp |= (1 << 5) | (1 << 16) | (1 << 19) | (1 << 20);
> +	writel(tmp, IO_ADDRESS(OTG_BASE_ADDR) + 0x600);
> +
> +	tmp = readl(IO_ADDRESS(OTG_BASE_ADDR) + 0x584);
> +	tmp &= ~(3 << 30);
> +	tmp |= 2 << 30;
> +	writel(tmp, IO_ADDRESS(OTG_BASE_ADDR) + 0x584);

Comments here too please.

Thanks
Guennadi
> +
> +	mdelay(10);
> +
> +	ret = isp1504_set_vbus_power(IO_ADDRESS(OTG_BASE_ADDR + 0x570), 1);
> +
> +	return 0;
> +}
> +
> +struct mxc_usbh_platform_data usbh2_pdata = {
> +	.init = pcm037_usbh2_init,
> +};
> +
>  /*
>   * Board specific initialization.
>   */
> @@ -239,6 +372,8 @@ static void __init mxc_board_init(void)
>  #endif
>  	mxc_register_device(&mxc_nand_device, &pcm037_nand_board_info);
>  	mxc_register_device(&mxcsdhc_device0, &sdhc_pdata);
> +	mxc_register_device(&mxc_otg, &otg_pdata);
> +	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
>  }
>  
>  static void __init pcm037_timer_init(void)
> -- 
> 1.6.2.1
> 

---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux