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, etc Version 2.2 : PSC9131, PSC9132, P3060, etc Signed-off-by: Ramneek Mehresh <ramneek.mehresh@xxxxxxxxxxxxx> --- Changes for v2: - Incorporated Greg's comment - moved fsl_usb.h from drivers/usb/misc to drivers/usb/host/fsl/ drivers/usb/gadget/fsl_udc_core.c | 25 ++++++++++++++- drivers/usb/gadget/fsl_usb2_udc.h | 13 ++++++++ drivers/usb/host/ehci-fsl.c | 35 +++++++++++++++++---- drivers/usb/host/ehci-fsl.h | 15 ++++++++- drivers/usb/host/fsl/fsl_usb.h | 61 +++++++++++++++++++++++++++++++++++++ 5 files changed, 141 insertions(+), 8 deletions(-) create mode 100644 drivers/usb/host/fsl/fsl_usb.h diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index d7ea6c0..3c28887 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007,2011 Freescale Semiconductor, Inc. + * Copyright (C) 2004-2007,2011-2012 Freescale Semiconductor, Inc. * All rights reserved. * * Author: Li Yang <leoli@xxxxxxxxxxxxx> @@ -48,6 +48,7 @@ #include <asm/dma.h> #include "fsl_usb2_udc.h" +#include "../host/fsl/fsl_usb.h" #define DRIVER_DESC "Freescale High-Speed USB SOC Device Controller driver" #define DRIVER_AUTHOR "Li Yang/Jiang Bo" @@ -245,23 +246,45 @@ static int dr_controller_setup(struct fsl_udc *udc) { unsigned int tmp, portctrl, ep_num; unsigned int max_no_of_ep; + int contr_ver = usb_get_ver_info(); #ifndef CONFIG_ARCH_MXC unsigned int ctrl; #endif unsigned long timeout; #define FSL_UDC_RESET_TIMEOUT 1000 + if (contr_ver < 0) { + printk(KERN_WARNING"fsl_usb: Could not get controller" + "version\n"); + return -ENODEV; + } + /* Config PHY interface */ portctrl = fsl_readl(&dr_regs->portsc1); portctrl &= ~(PORTSCX_PHY_TYPE_SEL | PORTSCX_PORT_WIDTH); switch (udc->phy_mode) { case FSL_USB2_PHY_ULPI: + if (contr_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 (contr_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: diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h index f781f5d..b4e5fd7 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.h +++ b/drivers/usb/gadget/fsl_usb2_udc.h @@ -1,4 +1,14 @@ /* + * 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 +358,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 diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 42414cd..3cb9ea2 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -1,6 +1,6 @@ /* * 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,17 +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; + u32 portsc, temp; + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + void __iomem *non_ehci = hcd->regs; + int contr_ver = usb_get_ver_info(); + + if (contr_ver < 0) { + printk(KERN_WARNING"fsl_usb: 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 (contr_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: @@ -231,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 (contr_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*/ + } portsc |= PORT_PTS_UTMI; break; case FSL_USB2_PHY_NONE: @@ -270,7 +293,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; @@ -284,9 +307,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) { diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h index 0855be8..cbc7e44 100644 --- a/drivers/usb/host/ehci-fsl.h +++ b/drivers/usb/host/ehci-fsl.h @@ -1,4 +1,4 @@ -/* 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 @@ -18,6 +18,8 @@ #ifndef _EHCI_FSL_H #define _EHCI_FSL_H +#include "fsl/fsl_usb.h" + /* offsets for the non-ehci registers in the FSL SOC USB controller */ #define FSL_SOC_USB_SBUSCFG 0x90 #define SBUSCFG_INCR8 0x02 /* INCR8, specified */ @@ -48,4 +50,15 @@ #define FSL_SOC_USB_SICTRL 0x410 /* NOTE: big-endian */ #define FSL_SOC_USB_CTRL 0x500 /* NOTE: big-endian */ #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 */ diff --git a/drivers/usb/host/fsl/fsl_usb.h b/drivers/usb/host/fsl/fsl_usb.h new file mode 100644 index 0000000..7ed8f9f --- /dev/null +++ b/drivers/usb/host/fsl/fsl_usb.h @@ -0,0 +1,61 @@ +/* + * Copyright 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 + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _FSL_USB_H +#define _FSL_USB_H + +#include <linux/of.h> + +#define FSL_UTMI_PHY_DLY 10 /*As per P1010RM, delay for UTMI + PHY CLK to become stable - 10ms*/ + +static inline int usb_get_ver_info(void) +{ + struct device_node *np; + int ver = -1; + + /* + * returns 1 for usb controller version 1.6 + * returns 2 for usb controller version 2.2 + * retruns 0 otherwise (for previous controller versions) + */ + for_each_compatible_node(np, NULL, "fsl-usb2-dr") { + if (of_device_is_compatible(np, "fsl-usb2-dr-v1.6")) + ver = 1; + else if (of_device_is_compatible(np, "fsl-usb2-dr-v2.2")) + ver = 2; + else + ver = 0; + } + + if (ver > -1) + return ver; + + for_each_compatible_node(np, NULL, "fsl-usb2-mph") { + if (of_device_is_compatible(np, "fsl-usb2-mph-v1.6")) + ver = 1; + else if (of_device_is_compatible(np, "fsl-usb2-mph-v2.2")) + ver = 2; + else + ver = 0; + } + + return ver; +} +#endif -- 1.7.1 -- 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