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

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
/* /*
* Copyright (C) 2004-2007,2011 Freescale Semiconductor, Inc. * Copyright (C) 2004-2007,2011-2012 Freescale Semiconductor, Inc.
* All rights reserved. * All rights reserved.
* *
* Author: Li Yang <leoli@freescale.com> * Author: Li Yang <leoli@freescale.com>
...@@ -58,9 +58,8 @@ static const char driver_name[] = "fsl-usb2-udc"; ...@@ -58,9 +58,8 @@ static const char driver_name[] = "fsl-usb2-udc";
static const char driver_desc[] = DRIVER_DESC; static const char driver_desc[] = DRIVER_DESC;
static struct usb_dr_device *dr_regs; static struct usb_dr_device *dr_regs;
#ifndef CONFIG_ARCH_MXC
static struct usb_sys_interface *usb_sys_regs; static struct usb_sys_interface *usb_sys_regs;
#endif
/* it is initialized in probe() */ /* it is initialized in probe() */
static struct fsl_udc *udc_controller = NULL; static struct fsl_udc *udc_controller = NULL;
...@@ -244,10 +243,9 @@ static int dr_controller_setup(struct fsl_udc *udc) ...@@ -244,10 +243,9 @@ static int dr_controller_setup(struct fsl_udc *udc)
{ {
unsigned int tmp, portctrl, ep_num; unsigned int tmp, portctrl, ep_num;
unsigned int max_no_of_ep; unsigned int max_no_of_ep;
#ifndef CONFIG_ARCH_MXC
unsigned int ctrl; unsigned int ctrl;
#endif
unsigned long timeout; unsigned long timeout;
#define FSL_UDC_RESET_TIMEOUT 1000 #define FSL_UDC_RESET_TIMEOUT 1000
/* Config PHY interface */ /* Config PHY interface */
...@@ -255,12 +253,32 @@ static int dr_controller_setup(struct fsl_udc *udc) ...@@ -255,12 +253,32 @@ static int dr_controller_setup(struct fsl_udc *udc)
portctrl &= ~(PORTSCX_PHY_TYPE_SEL | PORTSCX_PORT_WIDTH); portctrl &= ~(PORTSCX_PHY_TYPE_SEL | PORTSCX_PORT_WIDTH);
switch (udc->phy_mode) { switch (udc->phy_mode) {
case FSL_USB2_PHY_ULPI: 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; portctrl |= PORTSCX_PTS_ULPI;
break; break;
case FSL_USB2_PHY_UTMI_WIDE: case FSL_USB2_PHY_UTMI_WIDE:
portctrl |= PORTSCX_PTW_16BIT; portctrl |= PORTSCX_PTW_16BIT;
/* fall through */ /* fall through */
case FSL_USB2_PHY_UTMI: 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; portctrl |= PORTSCX_PTS_UTMI;
break; break;
case FSL_USB2_PHY_SERIAL: case FSL_USB2_PHY_SERIAL:
......
/* /*
* 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 * Freescale USB device/endpoint management registers
*/ */
#ifndef __FSL_USB2_UDC_H #ifndef __FSL_USB2_UDC_H
...@@ -348,6 +356,9 @@ struct usb_sys_interface { ...@@ -348,6 +356,9 @@ struct usb_sys_interface {
/* control Register Bit Masks */ /* control Register Bit Masks */
#define USB_CTRL_IOENB 0x00000004 #define USB_CTRL_IOENB 0x00000004
#define USB_CTRL_ULPI_INT0EN 0x00000001 #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 /* Endpoint Queue Head data struct
* Rem: all the variables of qh are LittleEndian Mode * Rem: all the variables of qh are LittleEndian Mode
......
/* /*
* Copyright 2005-2009 MontaVista Software, Inc. * 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 * 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 * 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, ...@@ -211,19 +211,32 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
usb_put_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, enum fsl_usb2_phy_modes phy_mode,
unsigned int port_offset) unsigned int port_offset)
{ {
u32 portsc; u32 portsc, temp;
struct usb_hcd *hcd = ehci_to_hcd(ehci); struct ehci_hcd *ehci = hcd_to_ehci(hcd);
void __iomem *non_ehci = hcd->regs; 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 = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);
portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW); portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);
switch (phy_mode) { switch (phy_mode) {
case FSL_USB2_PHY_ULPI: 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; portsc |= PORT_PTS_ULPI;
break; break;
case FSL_USB2_PHY_SERIAL: case FSL_USB2_PHY_SERIAL:
...@@ -233,6 +246,14 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci, ...@@ -233,6 +246,14 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
portsc |= PORT_PTS_PTW; portsc |= PORT_PTS_PTW;
/* fall through */ /* fall through */
case FSL_USB2_PHY_UTMI: 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 */ /* enable UTMI PHY */
setbits32(non_ehci + FSL_SOC_USB_CTRL, CTRL_UTMI_PHY_EN); setbits32(non_ehci + FSL_SOC_USB_CTRL, CTRL_UTMI_PHY_EN);
portsc |= PORT_PTS_UTMI; portsc |= PORT_PTS_UTMI;
...@@ -271,7 +292,7 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci) ...@@ -271,7 +292,7 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
if ((pdata->operating_mode == FSL_USB2_DR_HOST) || if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
(pdata->operating_mode == FSL_USB2_DR_OTG)) (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) { if (pdata->operating_mode == FSL_USB2_MPH_HOST) {
unsigned int chip, rev, svr; unsigned int chip, rev, svr;
...@@ -285,9 +306,9 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci) ...@@ -285,9 +306,9 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
ehci->has_fsl_port_bug = 1; ehci->has_fsl_port_bug = 1;
if (pdata->port_enables & FSL_USB2_PORT0_ENABLED) 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) 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) { if (pdata->have_sysif_regs) {
......
/* Copyright (C) 2005-2010 Freescale Semiconductor, Inc. /* Copyright (C) 2005-2010,2012 Freescale Semiconductor, Inc.
* Copyright (c) 2005 MontaVista Software * Copyright (c) 2005 MontaVista Software
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
...@@ -50,4 +50,15 @@ ...@@ -50,4 +50,15 @@
#define CTRL_UTMI_PHY_EN (1<<9) #define CTRL_UTMI_PHY_EN (1<<9)
#define CTRL_PHY_CLK_VALID (1 << 17) #define CTRL_PHY_CLK_VALID (1 << 17)
#define SNOOP_SIZE_2GB 0x1e #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 */ #endif /* _EHCI_FSL_H */
...@@ -119,6 +119,39 @@ struct platform_device * __devinit fsl_usb2_device_register( ...@@ -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 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) static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
{ {
struct device_node *np = ofdev->dev.of_node; 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) ...@@ -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); prop = of_get_property(np, "phy_type", NULL);
pdata->phy_mode = determine_usb_phy(prop); 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++) { for (i = 0; i < ARRAY_SIZE(dev_data->drivers); i++) {
if (!dev_data->drivers[i]) if (!dev_data->drivers[i])
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Maintainer: Kumar Gala <galak@kernel.crashing.org> * Maintainer: Kumar Gala <galak@kernel.crashing.org>
* *
* Copyright 2004 Freescale Semiconductor, Inc * Copyright 2004,2012 Freescale Semiconductor, Inc
* *
* This program is free software; you can redistribute it and/or modify it * 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 * under the terms of the GNU General Public License as published by the
...@@ -17,6 +17,12 @@ ...@@ -17,6 +17,12 @@
#ifndef _FSL_DEVICE_H_ #ifndef _FSL_DEVICE_H_
#define _FSL_DEVICE_H_ #define _FSL_DEVICE_H_
#define FSL_UTMI_PHY_DLY 10 /*As per P1010RM, delay for UTMI
PHY CLK to become stable - 10ms*/
#define FSL_USB_VER_OLD 0
#define FSL_USB_VER_1_6 1
#define FSL_USB_VER_2_2 2
#include <linux/types.h> #include <linux/types.h>
/* /*
...@@ -63,6 +69,7 @@ struct platform_device; ...@@ -63,6 +69,7 @@ struct platform_device;
struct fsl_usb2_platform_data { struct fsl_usb2_platform_data {
/* board specific information */ /* board specific information */
int controller_ver;
enum fsl_usb2_operating_modes operating_mode; enum fsl_usb2_operating_modes operating_mode;
enum fsl_usb2_phy_modes phy_mode; enum fsl_usb2_phy_modes phy_mode;
unsigned int port_enables; unsigned int port_enables;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment