usb: musb: OMAP4430: Power down the PHY during board init
[deliverable/linux.git] / arch / arm / mach-omap2 / usb-musb.c
CommitLineData
18cb7aca
FB
1/*
2 * linux/arch/arm/mach-omap2/usb-musb.c
3 *
4 * This file will contain the board specific details for the
5 * MENTOR USB OTG controller on OMAP3430
6 *
7 * Copyright (C) 2007-2008 Texas Instruments
8 * Copyright (C) 2008 Nokia Corporation
9 * Author: Vikram Pandita
10 *
11 * Generalization by:
12 * Felipe Balbi <felipe.balbi@nokia.com>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
17 */
18
19#include <linux/types.h>
20#include <linux/errno.h>
21#include <linux/delay.h>
22#include <linux/platform_device.h>
23#include <linux/clk.h>
24#include <linux/dma-mapping.h>
25#include <linux/io.h>
26
27#include <linux/usb/musb.h>
28
29#include <mach/hardware.h>
30#include <mach/irqs.h>
3a0d30bc 31#include <mach/am35xx.h>
ce491cf8 32#include <plat/usb.h>
a9c03783 33#include "control.h"
18cb7aca 34
7c925546 35#if defined(CONFIG_USB_MUSB_OMAP2PLUS) || defined (CONFIG_USB_MUSB_AM35X)
94a3ef6f 36
a9c03783
AKG
37static void am35x_musb_reset(void)
38{
39 u32 regval;
40
41 /* Reset the musb interface */
42 regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
43
44 regval |= AM35XX_USBOTGSS_SW_RST;
45 omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
46
47 regval &= ~AM35XX_USBOTGSS_SW_RST;
48 omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
49
50 regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
51}
52
53static void am35x_musb_phy_power(u8 on)
54{
55 unsigned long timeout = jiffies + msecs_to_jiffies(100);
56 u32 devconf2;
57
58 if (on) {
59 /*
60 * Start the on-chip PHY and its PLL.
61 */
62 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
63
64 devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN);
65 devconf2 |= CONF2_PHY_PLLON;
66
67 omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
68
69 pr_info(KERN_INFO "Waiting for PHY clock good...\n");
70 while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2)
71 & CONF2_PHYCLKGD)) {
72 cpu_relax();
73
74 if (time_after(jiffies, timeout)) {
75 pr_err(KERN_ERR "musb PHY clock good timed out\n");
76 break;
77 }
78 }
79 } else {
80 /*
81 * Power down the on-chip PHY.
82 */
83 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
84
85 devconf2 &= ~CONF2_PHY_PLLON;
86 devconf2 |= CONF2_PHYPWRDN | CONF2_OTGPWRDN;
87 omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
88 }
89}
90
91static void am35x_musb_clear_irq(void)
92{
93 u32 regval;
94
95 regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
96 regval |= AM35XX_USBOTGSS_INT_CLR;
97 omap_ctrl_writel(regval, AM35XX_CONTROL_LVL_INTR_CLEAR);
98 regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
99}
100
101static void am35x_musb_set_mode(u8 musb_mode)
102{
103 u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
104
105 devconf2 &= ~CONF2_OTGMODE;
106 switch (musb_mode) {
107#ifdef CONFIG_USB_MUSB_HDRC_HCD
108 case MUSB_HOST: /* Force VBUS valid, ID = 0 */
109 devconf2 |= CONF2_FORCE_HOST;
110 break;
111#endif
112#ifdef CONFIG_USB_GADGET_MUSB_HDRC
113 case MUSB_PERIPHERAL: /* Force VBUS valid, ID = 1 */
114 devconf2 |= CONF2_FORCE_DEVICE;
115 break;
116#endif
117#ifdef CONFIG_USB_MUSB_OTG
118 case MUSB_OTG: /* Don't override the VBUS/ID comparators */
119 devconf2 |= CONF2_NO_OVERRIDE;
120 break;
121#endif
122 default:
123 pr_info(KERN_INFO "Unsupported mode %u\n", musb_mode);
124 }
125
126 omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
127}
128
18cb7aca
FB
129static struct resource musb_resources[] = {
130 [0] = { /* start and end set dynamically */
131 .flags = IORESOURCE_MEM,
132 },
133 [1] = { /* general IRQ */
134 .start = INT_243X_HS_USB_MC,
135 .flags = IORESOURCE_IRQ,
fcf173e4 136 .name = "mc",
18cb7aca
FB
137 },
138 [2] = { /* DMA IRQ */
139 .start = INT_243X_HS_USB_DMA,
140 .flags = IORESOURCE_IRQ,
fcf173e4 141 .name = "dma",
18cb7aca
FB
142 },
143};
144
18cb7aca
FB
145static struct musb_hdrc_config musb_config = {
146 .multipoint = 1,
147 .dyn_fifo = 1,
18cb7aca 148 .num_eps = 16,
18cb7aca 149 .ram_bits = 12,
18cb7aca
FB
150};
151
152static struct musb_hdrc_platform_data musb_plat = {
153#ifdef CONFIG_USB_MUSB_OTG
154 .mode = MUSB_OTG,
155#elif defined(CONFIG_USB_MUSB_HDRC_HCD)
156 .mode = MUSB_HOST,
157#elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
158 .mode = MUSB_PERIPHERAL,
159#endif
160 /* .clock is set dynamically */
18cb7aca
FB
161 .config = &musb_config,
162
163 /* REVISIT charge pump on TWL4030 can supply up to
164 * 100 mA ... but this value is board-specific, like
165 * "mode", and should be passed to usb_musb_init().
166 */
167 .power = 50, /* up to 100 mA */
168};
169
e930438c 170static u64 musb_dmamask = DMA_BIT_MASK(32);
18cb7aca
FB
171
172static struct platform_device musb_device = {
dc09886b 173 .name = "musb-omap2430",
18cb7aca
FB
174 .id = -1,
175 .dev = {
176 .dma_mask = &musb_dmamask,
e930438c 177 .coherent_dma_mask = DMA_BIT_MASK(32),
18cb7aca
FB
178 .platform_data = &musb_plat,
179 },
180 .num_resources = ARRAY_SIZE(musb_resources),
181 .resource = musb_resources,
182};
183
884b8369 184void __init usb_musb_init(struct omap_musb_board_data *board_data)
18cb7aca 185{
bce06683 186 if (cpu_is_omap243x()) {
18cb7aca 187 musb_resources[0].start = OMAP243X_HS_BASE;
3a0d30bc 188 } else if (cpu_is_omap3517() || cpu_is_omap3505()) {
ce40c576 189 musb_device.name = "musb-am35x";
3a0d30bc
AKG
190 musb_resources[0].start = AM35XX_IPSS_USBOTGSS_BASE;
191 musb_resources[1].start = INT_35XX_USBOTG_IRQ;
a9c03783
AKG
192 board_data->set_phy_power = am35x_musb_phy_power;
193 board_data->clear_irq = am35x_musb_clear_irq;
194 board_data->set_mode = am35x_musb_set_mode;
195 board_data->reset = am35x_musb_reset;
bce06683 196 } else if (cpu_is_omap34xx()) {
18cb7aca 197 musb_resources[0].start = OMAP34XX_HSUSB_OTG_BASE;
bce06683
MM
198 } else if (cpu_is_omap44xx()) {
199 musb_resources[0].start = OMAP44XX_HSUSB_OTG_BASE;
5772ca7d
SS
200 musb_resources[1].start = OMAP44XX_IRQ_HS_USB_MC_N;
201 musb_resources[2].start = OMAP44XX_IRQ_HS_USB_DMA_N;
bce06683 202 }
f9828552 203 musb_resources[0].end = musb_resources[0].start + SZ_4K - 1;
18cb7aca
FB
204
205 /*
206 * REVISIT: This line can be removed once all the platforms using
207 * musb_core.c have been converted to use use clkdev.
208 */
209 musb_plat.clock = "ick";
884b8369
MM
210 musb_plat.board_data = board_data;
211 musb_plat.power = board_data->power >> 1;
212 musb_plat.mode = board_data->mode;
58815fa3 213 musb_plat.extvbus = board_data->extvbus;
18cb7aca 214
bdfa3511 215 if (platform_device_register(&musb_device) < 0)
18cb7aca 216 printk(KERN_ERR "Unable to register HS-USB (MUSB) device\n");
fb91cde4
HH
217
218 if (cpu_is_omap44xx())
219 omap4430_phy_init(dev);
220
94a3ef6f
PDS
221}
222
223#else
884b8369 224void __init usb_musb_init(struct omap_musb_board_data *board_data)
94a3ef6f 225{
18cb7aca 226}
94a3ef6f 227#endif /* CONFIG_USB_MUSB_SOC */
This page took 0.140382 seconds and 5 git commands to generate.