Linux Audio

Check our new training course

Loading...
v3.5.6
 
  1/*
  2  * This file configures the internal USB PHY in OMAP4430. Used
  3  * with TWL6030 transceiver and MUSB on OMAP4430.
  4  *
  5  * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
  6  * This program is free software; you can redistribute it and/or modify
  7  * it under the terms of the GNU General Public License as published by
  8  * the Free Software Foundation; either version 2 of the License, or
  9  * (at your option) any later version.
 10  *
 11  * Author: Hema HK <hemahk@ti.com>
 12  *
 13  * This program is distributed in the hope that it will be useful,
 14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16  * GNU General Public License for more details.
 17  *
 18  * You should have received a copy of the GNU General Public License
 19  * along with this program; if not, write to the Free Software
 20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 21  *
 22  */
 23
 
 
 24#include <linux/types.h>
 25#include <linux/delay.h>
 26#include <linux/clk.h>
 27#include <linux/io.h>
 28#include <linux/err.h>
 29#include <linux/usb.h>
 
 30
 31#include <plat/usb.h>
 32#include "control.h"
 
 33
 34/* OMAP control module register for UTMI PHY */
 35#define CONTROL_DEV_CONF		0x300
 36#define PHY_PD				0x1
 37
 38#define USBOTGHS_CONTROL		0x33c
 39#define	AVALID				BIT(0)
 40#define	BVALID				BIT(1)
 41#define	VBUSVALID			BIT(2)
 42#define	SESSEND				BIT(3)
 43#define	IDDIG				BIT(4)
 44
 45static struct clk *phyclk, *clk48m, *clk32k;
 46static void __iomem *ctrl_base;
 47static int usbotghs_control;
 48
 49int omap4430_phy_init(struct device *dev)
 50{
 
 
 
 
 
 51	ctrl_base = ioremap(OMAP443X_SCM_BASE, SZ_1K);
 52	if (!ctrl_base) {
 53		pr_err("control module ioremap failed\n");
 54		return -ENOMEM;
 55	}
 56	/* Power down the phy */
 57	__raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
 58
 59	if (!dev) {
 60		iounmap(ctrl_base);
 61		return 0;
 62	}
 63
 64	phyclk = clk_get(dev, "ocp2scp_usb_phy_ick");
 65	if (IS_ERR(phyclk)) {
 66		dev_err(dev, "cannot clk_get ocp2scp_usb_phy_ick\n");
 67		iounmap(ctrl_base);
 68		return PTR_ERR(phyclk);
 69	}
 70
 71	clk48m = clk_get(dev, "ocp2scp_usb_phy_phy_48m");
 72	if (IS_ERR(clk48m)) {
 73		dev_err(dev, "cannot clk_get ocp2scp_usb_phy_phy_48m\n");
 74		clk_put(phyclk);
 75		iounmap(ctrl_base);
 76		return PTR_ERR(clk48m);
 77	}
 78
 79	clk32k = clk_get(dev, "usb_phy_cm_clk32k");
 80	if (IS_ERR(clk32k)) {
 81		dev_err(dev, "cannot clk_get usb_phy_cm_clk32k\n");
 82		clk_put(phyclk);
 83		clk_put(clk48m);
 84		iounmap(ctrl_base);
 85		return PTR_ERR(clk32k);
 86	}
 87	return 0;
 88}
 89
 90int omap4430_phy_set_clk(struct device *dev, int on)
 91{
 92	static int state;
 93
 94	if (on && !state) {
 95		/* Enable the phy clocks */
 96		clk_enable(phyclk);
 97		clk_enable(clk48m);
 98		clk_enable(clk32k);
 99		state = 1;
100	} else if (state) {
101		/* Disable the phy clocks */
102		clk_disable(phyclk);
103		clk_disable(clk48m);
104		clk_disable(clk32k);
105		state = 0;
106	}
107	return 0;
108}
109
110int omap4430_phy_power(struct device *dev, int ID, int on)
111{
112	if (on) {
113		if (ID)
114			/* enable VBUS valid, IDDIG groung */
115			__raw_writel(AVALID | VBUSVALID, ctrl_base +
116							USBOTGHS_CONTROL);
117		else
118			/*
119			 * Enable VBUS Valid, AValid and IDDIG
120			 * high impedance
121			 */
122			__raw_writel(IDDIG | AVALID | VBUSVALID,
123						ctrl_base + USBOTGHS_CONTROL);
124	} else {
125		/* Enable session END and IDIG to high impedance. */
126		__raw_writel(SESSEND | IDDIG, ctrl_base +
127					USBOTGHS_CONTROL);
128	}
129	return 0;
130}
131
132int omap4430_phy_suspend(struct device *dev, int suspend)
133{
134	if (suspend) {
135		/* Disable the clocks */
136		omap4430_phy_set_clk(dev, 0);
137		/* Power down the phy */
138		__raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
139
140		/* save the context */
141		usbotghs_control = __raw_readl(ctrl_base + USBOTGHS_CONTROL);
142	} else {
143		/* Enable the internel phy clcoks */
144		omap4430_phy_set_clk(dev, 1);
145		/* power on the phy */
146		if (__raw_readl(ctrl_base + CONTROL_DEV_CONF) & PHY_PD) {
147			__raw_writel(~PHY_PD, ctrl_base + CONTROL_DEV_CONF);
148			mdelay(200);
149		}
150
151		/* restore the context */
152		__raw_writel(usbotghs_control, ctrl_base + USBOTGHS_CONTROL);
153	}
154
155	return 0;
156}
157
158int omap4430_phy_exit(struct device *dev)
159{
160	if (ctrl_base)
161		iounmap(ctrl_base);
162	if (phyclk)
163		clk_put(phyclk);
164	if (clk48m)
165		clk_put(clk48m);
166	if (clk32k)
167		clk_put(clk32k);
168
169	return 0;
170}
 
171
172void am35x_musb_reset(void)
173{
174	u32	regval;
175
176	/* Reset the musb interface */
177	regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
178
179	regval |= AM35XX_USBOTGSS_SW_RST;
180	omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
181
182	regval &= ~AM35XX_USBOTGSS_SW_RST;
183	omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
184
185	regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
186}
187
188void am35x_musb_phy_power(u8 on)
189{
190	unsigned long timeout = jiffies + msecs_to_jiffies(100);
191	u32 devconf2;
192
193	if (on) {
194		/*
195		 * Start the on-chip PHY and its PLL.
196		 */
197		devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
198
199		devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN);
200		devconf2 |= CONF2_PHY_PLLON;
201
202		omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
203
204		pr_info(KERN_INFO "Waiting for PHY clock good...\n");
205		while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2)
206				& CONF2_PHYCLKGD)) {
207			cpu_relax();
208
209			if (time_after(jiffies, timeout)) {
210				pr_err(KERN_ERR "musb PHY clock good timed out\n");
211				break;
212			}
213		}
214	} else {
215		/*
216		 * Power down the on-chip PHY.
217		 */
218		devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
219
220		devconf2 &= ~CONF2_PHY_PLLON;
221		devconf2 |=  CONF2_PHYPWRDN | CONF2_OTGPWRDN;
222		omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
223	}
224}
225
226void am35x_musb_clear_irq(void)
227{
228	u32 regval;
229
230	regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
231	regval |= AM35XX_USBOTGSS_INT_CLR;
232	omap_ctrl_writel(regval, AM35XX_CONTROL_LVL_INTR_CLEAR);
233	regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
234}
235
236void am35x_set_mode(u8 musb_mode)
237{
238	u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
239
240	devconf2 &= ~CONF2_OTGMODE;
241	switch (musb_mode) {
242	case MUSB_HOST:		/* Force VBUS valid, ID = 0 */
243		devconf2 |= CONF2_FORCE_HOST;
244		break;
245	case MUSB_PERIPHERAL:	/* Force VBUS valid, ID = 1 */
246		devconf2 |= CONF2_FORCE_DEVICE;
247		break;
248	case MUSB_OTG:		/* Don't override the VBUS/ID comparators */
249		devconf2 |= CONF2_NO_OVERRIDE;
250		break;
251	default:
252		pr_info(KERN_INFO "Unsupported mode %u\n", musb_mode);
253	}
254
255	omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
256}
257
258void ti81xx_musb_phy_power(u8 on)
259{
260	void __iomem *scm_base = NULL;
261	u32 usbphycfg;
262
263	scm_base = ioremap(TI81XX_SCM_BASE, SZ_2K);
264	if (!scm_base) {
265		pr_err("system control module ioremap failed\n");
266		return;
267	}
268
269	usbphycfg = __raw_readl(scm_base + USBCTRL0);
270
271	if (on) {
272		if (cpu_is_ti816x()) {
273			usbphycfg |= TI816X_USBPHY0_NORMAL_MODE;
274			usbphycfg &= ~TI816X_USBPHY_REFCLK_OSC;
275		} else if (cpu_is_ti814x()) {
276			usbphycfg &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN
277				| USBPHY_DPINPUT | USBPHY_DMINPUT);
278			usbphycfg |= (USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN
279				| USBPHY_DPOPBUFCTL | USBPHY_DMOPBUFCTL);
280		}
281	} else {
282		if (cpu_is_ti816x())
283			usbphycfg &= ~TI816X_USBPHY0_NORMAL_MODE;
284		else if (cpu_is_ti814x())
285			usbphycfg |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN;
286
287	}
288	__raw_writel(usbphycfg, scm_base + USBCTRL0);
289
290	iounmap(scm_base);
291}
v6.2
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3  * This file configures the internal USB PHY in OMAP4430. Used
  4  * with TWL6030 transceiver and MUSB on OMAP4430.
  5  *
  6  * Copyright (C) 2010 Texas Instruments Incorporated - https://www.ti.com
 
 
 
 
 
  7  * Author: Hema HK <hemahk@ti.com>
 
 
 
 
 
 
 
 
 
 
  8  */
  9
 10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 11
 12#include <linux/types.h>
 13#include <linux/delay.h>
 14#include <linux/clk.h>
 15#include <linux/io.h>
 16#include <linux/err.h>
 17#include <linux/usb.h>
 18#include <linux/usb/musb.h>
 19
 20#include "soc.h"
 21#include "control.h"
 22#include "usb.h"
 23
 
 24#define CONTROL_DEV_CONF		0x300
 25#define PHY_PD				0x1
 26
 27/**
 28 * omap4430_phy_power_down: disable MUSB PHY during early init
 29 *
 30 * OMAP4 MUSB PHY module is enabled by default on reset, but this will
 31 * prevent core retention if not disabled by SW. USB driver will
 32 * later on enable this, once and if the driver needs it.
 33 */
 34static int __init omap4430_phy_power_down(void)
 
 
 
 
 35{
 36	void __iomem *ctrl_base;
 37
 38	if (!cpu_is_omap44xx())
 39		return 0;
 40
 41	ctrl_base = ioremap(OMAP443X_SCM_BASE, SZ_1K);
 42	if (!ctrl_base) {
 43		pr_err("control module ioremap failed\n");
 44		return -ENOMEM;
 45	}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 46
 47	/* Power down the phy */
 48	writel_relaxed(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
 
 
 
 
 
 
 
 
 49
 50	iounmap(ctrl_base);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 51
 52	return 0;
 53}
 54omap_early_initcall(omap4430_phy_power_down);
 55
 56void am35x_musb_reset(void)
 57{
 58	u32	regval;
 59
 60	/* Reset the musb interface */
 61	regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
 62
 63	regval |= AM35XX_USBOTGSS_SW_RST;
 64	omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
 65
 66	regval &= ~AM35XX_USBOTGSS_SW_RST;
 67	omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
 68
 69	regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
 70}
 71
 72void am35x_musb_phy_power(u8 on)
 73{
 74	unsigned long timeout = jiffies + msecs_to_jiffies(100);
 75	u32 devconf2;
 76
 77	if (on) {
 78		/*
 79		 * Start the on-chip PHY and its PLL.
 80		 */
 81		devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
 82
 83		devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN);
 84		devconf2 |= CONF2_PHY_PLLON;
 85
 86		omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
 87
 88		pr_info("Waiting for PHY clock good...\n");
 89		while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2)
 90				& CONF2_PHYCLKGD)) {
 91			cpu_relax();
 92
 93			if (time_after(jiffies, timeout)) {
 94				pr_err("musb PHY clock good timed out\n");
 95				break;
 96			}
 97		}
 98	} else {
 99		/*
100		 * Power down the on-chip PHY.
101		 */
102		devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
103
104		devconf2 &= ~CONF2_PHY_PLLON;
105		devconf2 |=  CONF2_PHYPWRDN | CONF2_OTGPWRDN;
106		omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
107	}
108}
109
110void am35x_musb_clear_irq(void)
111{
112	u32 regval;
113
114	regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
115	regval |= AM35XX_USBOTGSS_INT_CLR;
116	omap_ctrl_writel(regval, AM35XX_CONTROL_LVL_INTR_CLEAR);
117	regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
118}
119
120void am35x_set_mode(u8 musb_mode)
121{
122	u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
123
124	devconf2 &= ~CONF2_OTGMODE;
125	switch (musb_mode) {
126	case MUSB_HOST:		/* Force VBUS valid, ID = 0 */
127		devconf2 |= CONF2_FORCE_HOST;
128		break;
129	case MUSB_PERIPHERAL:	/* Force VBUS valid, ID = 1 */
130		devconf2 |= CONF2_FORCE_DEVICE;
131		break;
132	case MUSB_OTG:		/* Don't override the VBUS/ID comparators */
133		devconf2 |= CONF2_NO_OVERRIDE;
134		break;
135	default:
136		pr_info("Unsupported mode %u\n", musb_mode);
137	}
138
139	omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140}