Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 58c559e6 authored by Ramneek Mehresh's avatar Ramneek Mehresh Committed by Greg Kroah-Hartman
Browse files

fsl/usb: Add controller version based ULPI and UTMI phy support



Add support for ULPI and UTMI PHYs based on usb controller
version info read from device-tree

Example of USB Controller versioning info:
Version 1.2 and below : MPC8536, MPC8315, etc
Version 1.6 : P1020, P1010, P2020, P5020, etc
Version 2.2 : PSC9131, PSC9132, P3060, etc

No changes for non-DT users

Signed-off-by: default avatarRamneek Mehresh <ramneek.mehresh@freescale.com>
Acked-by: default avatarLi Yang <leoli@freescale.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 67c88382
Loading
Loading
Loading
Loading
+23 −5
Original line number Diff line number Diff line
/*
 * Copyright (C) 2004-2007,2011 Freescale Semiconductor, Inc.
 * Copyright (C) 2004-2007,2011-2012 Freescale Semiconductor, Inc.
 * All rights reserved.
 *
 * Author: Li Yang <leoli@freescale.com>
@@ -58,9 +58,8 @@ static const char driver_name[] = "fsl-usb2-udc";
static const char driver_desc[] = DRIVER_DESC;

static struct usb_dr_device *dr_regs;
#ifndef CONFIG_ARCH_MXC

static struct usb_sys_interface *usb_sys_regs;
#endif

/* it is initialized in probe()  */
static struct fsl_udc *udc_controller = NULL;
@@ -244,10 +243,9 @@ static int dr_controller_setup(struct fsl_udc *udc)
{
	unsigned int tmp, portctrl, ep_num;
	unsigned int max_no_of_ep;
#ifndef CONFIG_ARCH_MXC
	unsigned int ctrl;
#endif
	unsigned long timeout;

#define FSL_UDC_RESET_TIMEOUT 1000

	/* Config PHY interface */
@@ -255,12 +253,32 @@ static int dr_controller_setup(struct fsl_udc *udc)
	portctrl &= ~(PORTSCX_PHY_TYPE_SEL | PORTSCX_PORT_WIDTH);
	switch (udc->phy_mode) {
	case FSL_USB2_PHY_ULPI:
		if (udc->pdata->have_sysif_regs) {
			if (udc->pdata->controller_ver) {
				/* controller version 1.6 or above */
				ctrl = __raw_readl(&usb_sys_regs->control);
				ctrl &= ~USB_CTRL_UTMI_PHY_EN;
				ctrl |= USB_CTRL_USB_EN;
				__raw_writel(ctrl, &usb_sys_regs->control);
			}
		}
		portctrl |= PORTSCX_PTS_ULPI;
		break;
	case FSL_USB2_PHY_UTMI_WIDE:
		portctrl |= PORTSCX_PTW_16BIT;
		/* fall through */
	case FSL_USB2_PHY_UTMI:
		if (udc->pdata->have_sysif_regs) {
			if (udc->pdata->controller_ver) {
				/* controller version 1.6 or above */
				ctrl = __raw_readl(&usb_sys_regs->control);
				ctrl |= (USB_CTRL_UTMI_PHY_EN |
					USB_CTRL_USB_EN);
				__raw_writel(ctrl, &usb_sys_regs->control);
				mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI
					PHY CLK to become stable - 10ms*/
			}
		}
		portctrl |= PORTSCX_PTS_UTMI;
		break;
	case FSL_USB2_PHY_SERIAL:
+11 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2004,2012 Freescale Semiconductor, Inc
 * All rights reserved.
 *
 * This program is free software; you can redistribute  it and/or modify it
 * under  the terms of  the GNU General  Public License as published by the
 * Free Software Foundation;  either version 2 of the  License, or (at your
 * option) any later version.
 *
 * Freescale USB device/endpoint management registers
 */
#ifndef __FSL_USB2_UDC_H
@@ -348,6 +356,9 @@ struct usb_sys_interface {
/* control Register Bit Masks */
#define  USB_CTRL_IOENB                       0x00000004
#define  USB_CTRL_ULPI_INT0EN                 0x00000001
#define USB_CTRL_UTMI_PHY_EN		      0x00000200
#define USB_CTRL_USB_EN			      0x00000004
#define USB_CTRL_ULPI_PHY_CLK_SEL	      0x00000400

/* Endpoint Queue Head data struct
 * Rem: all the variables of qh are LittleEndian Mode
+28 −7
Original line number Diff line number Diff line
/*
 * Copyright 2005-2009 MontaVista Software, Inc.
 * Copyright 2008      Freescale Semiconductor, Inc.
 * Copyright 2008,2012      Freescale Semiconductor, Inc.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
@@ -211,19 +211,32 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
	usb_put_hcd(hcd);
}

static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
static void ehci_fsl_setup_phy(struct usb_hcd *hcd,
			       enum fsl_usb2_phy_modes phy_mode,
			       unsigned int port_offset)
{
	u32 portsc;
	struct usb_hcd *hcd = ehci_to_hcd(ehci);
	u32 portsc, temp;
	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
	void __iomem *non_ehci = hcd->regs;
	struct device *dev = hcd->self.controller;
	struct fsl_usb2_platform_data *pdata = dev->platform_data;

	if (pdata->controller_ver < 0) {
		dev_warn(hcd->self.controller, "Could not get controller version\n");
		return;
	}

	portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);
	portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);

	switch (phy_mode) {
	case FSL_USB2_PHY_ULPI:
		if (pdata->controller_ver) {
			/* controller version 1.6 or above */
			temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
			out_be32(non_ehci + FSL_SOC_USB_CTRL, temp |
				USB_CTRL_USB_EN | ULPI_PHY_CLK_SEL);
		}
		portsc |= PORT_PTS_ULPI;
		break;
	case FSL_USB2_PHY_SERIAL:
@@ -233,6 +246,14 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
		portsc |= PORT_PTS_PTW;
		/* fall through */
	case FSL_USB2_PHY_UTMI:
		if (pdata->controller_ver) {
			/* controller version 1.6 or above */
			temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
			out_be32(non_ehci + FSL_SOC_USB_CTRL, temp |
				UTMI_PHY_EN | USB_CTRL_USB_EN);
			mdelay(FSL_UTMI_PHY_DLY);  /* Delay for UTMI PHY CLK to
						become stable - 10ms*/
		}
		/* enable UTMI PHY */
		setbits32(non_ehci + FSL_SOC_USB_CTRL, CTRL_UTMI_PHY_EN);
		portsc |= PORT_PTS_UTMI;
@@ -271,7 +292,7 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)

	if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
			(pdata->operating_mode == FSL_USB2_DR_OTG))
		ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0);
		ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0);

	if (pdata->operating_mode == FSL_USB2_MPH_HOST) {
		unsigned int chip, rev, svr;
@@ -285,9 +306,9 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
			ehci->has_fsl_port_bug = 1;

		if (pdata->port_enables & FSL_USB2_PORT0_ENABLED)
			ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0);
			ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0);
		if (pdata->port_enables & FSL_USB2_PORT1_ENABLED)
			ehci_fsl_setup_phy(ehci, pdata->phy_mode, 1);
			ehci_fsl_setup_phy(hcd, pdata->phy_mode, 1);
	}

	if (pdata->have_sysif_regs) {
+12 −1
Original line number Diff line number Diff line
/* Copyright (C) 2005-2010 Freescale Semiconductor, Inc.
/* Copyright (C) 2005-2010,2012 Freescale Semiconductor, Inc.
 * Copyright (c) 2005 MontaVista Software
 *
 * This program is free software; you can redistribute  it and/or modify it
@@ -50,4 +50,15 @@
#define CTRL_UTMI_PHY_EN	(1<<9)
#define CTRL_PHY_CLK_VALID	(1 << 17)
#define SNOOP_SIZE_2GB		0x1e

/* control Register Bit Masks */
#define ULPI_INT_EN             (1<<0)
#define WU_INT_EN               (1<<1)
#define USB_CTRL_USB_EN         (1<<2)
#define LINE_STATE_FILTER__EN   (1<<3)
#define KEEP_OTG_ON             (1<<4)
#define OTG_PORT                (1<<5)
#define PLL_RESET               (1<<8)
#define UTMI_PHY_EN             (1<<9)
#define ULPI_PHY_CLK_SEL        (1<<10)
#endif				/* _EHCI_FSL_H */
+41 −0
Original line number Diff line number Diff line
@@ -119,6 +119,39 @@ struct platform_device * __devinit fsl_usb2_device_register(

static const struct of_device_id fsl_usb2_mph_dr_of_match[];

static int usb_get_ver_info(struct device_node *np)
{
	int ver = -1;

	/*
	 * returns 1 for usb controller version 1.6
	 * returns 2 for usb controller version 2.2
	 * returns 0 otherwise
	 */
	if (of_device_is_compatible(np, "fsl-usb2-dr")) {
		if (of_device_is_compatible(np, "fsl-usb2-dr-v1.6"))
			ver = FSL_USB_VER_1_6;
		else if (of_device_is_compatible(np, "fsl-usb2-dr-v2.2"))
			ver = FSL_USB_VER_2_2;
		else /* for previous controller versions */
			ver = FSL_USB_VER_OLD;

		if (ver > -1)
			return ver;
	}

	if (of_device_is_compatible(np, "fsl-usb2-mph")) {
		if (of_device_is_compatible(np, "fsl-usb2-mph-v1.6"))
			ver = FSL_USB_VER_1_6;
		else if (of_device_is_compatible(np, "fsl-usb2-mph-v2.2"))
			ver = FSL_USB_VER_2_2;
		else /* for previous controller versions */
			ver = FSL_USB_VER_OLD;
	}

	return ver;
}

static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
{
	struct device_node *np = ofdev->dev.of_node;
@@ -166,6 +199,14 @@ static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)

	prop = of_get_property(np, "phy_type", NULL);
	pdata->phy_mode = determine_usb_phy(prop);
	pdata->controller_ver = usb_get_ver_info(np);

	if (pdata->have_sysif_regs) {
		if (pdata->controller_ver < 0) {
			dev_warn(&ofdev->dev, "Could not get controller version\n");
			return -ENODEV;
		}
	}

	for (i = 0; i < ARRAY_SIZE(dev_data->drivers); i++) {
		if (!dev_data->drivers[i])
Loading