diff options
| author | Greg Kroah-Hartman <gregkh@suse.de> | 2010-12-16 10:05:06 -0800 | 
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-12-16 10:05:06 -0800 | 
| commit | 36facadd9ea98f8415d0dbb63e0763b7ee9d3911 (patch) | |
| tree | 99dea00b332ed852f2b0a4923b581dd723f03634 /arch/arm/mach-omap2/omap_phy_internal.c | |
| parent | 2faa83e2a519abea1055d156ce1b42b8fa57e87b (diff) | |
| parent | 0b83ae960cd7d4a5ee02786ecf41ab45688999bf (diff) | |
| download | olio-linux-3.10-36facadd9ea98f8415d0dbb63e0763b7ee9d3911.tar.xz olio-linux-3.10-36facadd9ea98f8415d0dbb63e0763b7ee9d3911.zip  | |
Merge branch 'usb-next' into musb-merge
* usb-next: (132 commits)
  USB: uas: Use GFP_NOIO instead of GFP_KERNEL in I/O submission path
  USB: uas: Ensure we only bind to a UAS interface
  USB: uas: Rename sense pipe and sense urb to status pipe and status urb
  USB: uas: Use kzalloc instead of kmalloc
  USB: uas: Fix up the Sense IU
  usb: musb: core: kill unneeded #include's
  DA8xx: assign name to MUSB IRQ resource
  usb: gadget: g_ncm added
  usb: gadget: f_ncm.c added
  usb: gadget: u_ether: prepare for NCM
  usb: pch_udc: Fix setup transfers with data out
  usb: pch_udc: Fix compile error, warnings and checkpatch warnings
  usb: add ab8500 usb transceiver driver
  USB: gadget: Implement runtime PM for MSM bus glue driver
  USB: gadget: Implement runtime PM for ci13xxx gadget
  USB: gadget: Add USB controller driver for MSM SoC
  USB: gadget: Introduce ci13xxx_udc_driver struct
  USB: gadget: Initialize ci13xxx gadget device's coherent DMA mask
  USB: gadget: Fix "scheduling while atomic" bugs in ci13xxx_udc
  USB: gadget: Separate out PCI bus code from ci13xxx_udc
  ...
Diffstat (limited to 'arch/arm/mach-omap2/omap_phy_internal.c')
| -rw-r--r-- | arch/arm/mach-omap2/omap_phy_internal.c | 149 | 
1 files changed, 149 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/omap_phy_internal.c b/arch/arm/mach-omap2/omap_phy_internal.c new file mode 100644 index 00000000000..745252c60e3 --- /dev/null +++ b/arch/arm/mach-omap2/omap_phy_internal.c @@ -0,0 +1,149 @@ +/* +  * This file configures the internal USB PHY in OMAP4430. Used +  * with TWL6030 transceiver and MUSB on OMAP4430. +  * +  * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com +  * 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. +  * +  * Author: Hema HK <hemahk@ti.com> +  * +  * 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. +  * +  */ + +#include <linux/types.h> +#include <linux/delay.h> +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/err.h> +#include <linux/usb.h> + +#include <plat/usb.h> + +/* OMAP control module register for UTMI PHY */ +#define CONTROL_DEV_CONF		0x300 +#define PHY_PD				0x1 + +#define USBOTGHS_CONTROL		0x33c +#define	AVALID				BIT(0) +#define	BVALID				BIT(1) +#define	VBUSVALID			BIT(2) +#define	SESSEND				BIT(3) +#define	IDDIG				BIT(4) + +static struct clk *phyclk, *clk48m, *clk32k; +static void __iomem *ctrl_base; + +int omap4430_phy_init(struct device *dev) +{ +	ctrl_base = ioremap(OMAP443X_SCM_BASE, SZ_1K); +	if (!ctrl_base) { +		dev_err(dev, "control module ioremap failed\n"); +		return -ENOMEM; +	} +	/* Power down the phy */ +	__raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF); +	phyclk = clk_get(dev, "ocp2scp_usb_phy_ick"); + +	if (IS_ERR(phyclk)) { +		dev_err(dev, "cannot clk_get ocp2scp_usb_phy_ick\n"); +		iounmap(ctrl_base); +		return PTR_ERR(phyclk); +	} + +	clk48m = clk_get(dev, "ocp2scp_usb_phy_phy_48m"); +	if (IS_ERR(clk48m)) { +		dev_err(dev, "cannot clk_get ocp2scp_usb_phy_phy_48m\n"); +		clk_put(phyclk); +		iounmap(ctrl_base); +		return PTR_ERR(clk48m); +	} + +	clk32k = clk_get(dev, "usb_phy_cm_clk32k"); +	if (IS_ERR(clk32k)) { +		dev_err(dev, "cannot clk_get usb_phy_cm_clk32k\n"); +		clk_put(phyclk); +		clk_put(clk48m); +		iounmap(ctrl_base); +		return PTR_ERR(clk32k); +	} +	return 0; +} + +int omap4430_phy_set_clk(struct device *dev, int on) +{ +	static int state; + +	if (on && !state) { +		/* Enable the phy clocks */ +		clk_enable(phyclk); +		clk_enable(clk48m); +		clk_enable(clk32k); +		state = 1; +	} else if (state) { +		/* Disable the phy clocks */ +		clk_disable(phyclk); +		clk_disable(clk48m); +		clk_disable(clk32k); +		state = 0; +	} +	return 0; +} + +int omap4430_phy_power(struct device *dev, int ID, int on) +{ +	if (on) { +		/* enabled the clocks */ +		omap4430_phy_set_clk(dev, 1); +		/* power on the phy */ +		if (__raw_readl(ctrl_base + CONTROL_DEV_CONF) & PHY_PD) { +			__raw_writel(~PHY_PD, ctrl_base + CONTROL_DEV_CONF); +			mdelay(200); +		} +		if (ID) +			/* enable VBUS valid, IDDIG groung */ +			__raw_writel(AVALID | VBUSVALID, ctrl_base + +							USBOTGHS_CONTROL); +		else +			/* +			 * Enable VBUS Valid, AValid and IDDIG +			 * high impedence +			 */ +			__raw_writel(IDDIG | AVALID | VBUSVALID, +						ctrl_base + USBOTGHS_CONTROL); +	} else { +		/* Enable session END and IDIG to high impedence. */ +		__raw_writel(SESSEND | IDDIG, ctrl_base + +					USBOTGHS_CONTROL); +		/* Disable the clocks */ +		omap4430_phy_set_clk(dev, 0); +		/* Power down the phy */ +		__raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF); +	} + +	return 0; +} + +int omap4430_phy_exit(struct device *dev) +{ +	if (ctrl_base) +		iounmap(ctrl_base); +	if (phyclk) +		clk_put(phyclk); +	if (clk48m) +		clk_put(clk48m); +	if (clk32k) +		clk_put(clk32k); + +	return 0; +}  |