Skip to content

Commit

Permalink
fsl/usb: Add controller version based ULPI and UTMI phy support
Browse files Browse the repository at this point in the history
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: Ramneek Mehresh <ramneek.mehresh@freescale.com>
Acked-by: Li Yang <leoli@freescale.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Ramneek Mehresh authored and Greg Kroah-Hartman committed Apr 18, 2012
1 parent 67c8838 commit 58c559e
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 14 deletions.
28 changes: 23 additions & 5 deletions drivers/usb/gadget/fsl_udc_core.c
Original file line number Diff line number Diff line change
@@ -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@freescale.com>
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -244,23 +243,42 @@ 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 */
portctrl = fsl_readl(&dr_regs->portsc1);
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:
Expand Down
11 changes: 11 additions & 0 deletions drivers/usb/gadget/fsl_usb2_udc.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
/*
* 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
Expand Down Expand Up @@ -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
Expand Down
35 changes: 28 additions & 7 deletions drivers/usb/host/ehci-fsl.c
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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:
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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) {
Expand Down
13 changes: 12 additions & 1 deletion drivers/usb/host/ehci-fsl.h
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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 changes: 41 additions & 0 deletions drivers/usb/host/fsl-mph-dr-of.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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])
Expand Down
9 changes: 8 additions & 1 deletion include/linux/fsl_devices.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*
* 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
* under the terms of the GNU General Public License as published by the
Expand All @@ -17,6 +17,12 @@
#ifndef _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>

/*
Expand Down Expand Up @@ -63,6 +69,7 @@ struct platform_device;

struct fsl_usb2_platform_data {
/* board specific information */
int controller_ver;
enum fsl_usb2_operating_modes operating_mode;
enum fsl_usb2_phy_modes phy_mode;
unsigned int port_enables;
Expand Down

0 comments on commit 58c559e

Please sign in to comment.