blob: 5298949d4b110a9303826e7655ed3d13bbee4e97 [file] [log] [blame]
Felipe Balbi18cb7ac2009-03-23 18:34:06 -07001/*
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>
Ajay Kumar Gupta3a0d30b2010-10-19 10:08:11 +030031#include <mach/am35xx.h>
Tony Lindgrence491cf2009-10-20 09:40:47 -070032#include <plat/usb.h>
Ajay Kumar Guptaa9c03782010-12-07 18:57:45 +053033#include "control.h"
Felipe Balbi18cb7ac2009-03-23 18:34:06 -070034
Felipe Balbi7c925542010-12-01 14:23:48 +020035#if defined(CONFIG_USB_MUSB_OMAP2PLUS) || defined (CONFIG_USB_MUSB_AM35X)
Peter 'p2' De Schrijver94a3ef62009-01-19 19:09:22 +020036
Ajay Kumar Guptaa9c03782010-12-07 18:57:45 +053037static 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
Felipe Balbi18cb7ac2009-03-23 18:34:06 -0700129static 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,
Hema Kalliguddifcf173e2010-09-29 11:26:39 -0500136 .name = "mc",
Felipe Balbi18cb7ac2009-03-23 18:34:06 -0700137 },
138 [2] = { /* DMA IRQ */
139 .start = INT_243X_HS_USB_DMA,
140 .flags = IORESOURCE_IRQ,
Hema Kalliguddifcf173e2010-09-29 11:26:39 -0500141 .name = "dma",
Felipe Balbi18cb7ac2009-03-23 18:34:06 -0700142 },
143};
144
Felipe Balbi18cb7ac2009-03-23 18:34:06 -0700145static struct musb_hdrc_config musb_config = {
146 .multipoint = 1,
147 .dyn_fifo = 1,
Felipe Balbi18cb7ac2009-03-23 18:34:06 -0700148 .num_eps = 16,
Felipe Balbi18cb7ac2009-03-23 18:34:06 -0700149 .ram_bits = 12,
Felipe Balbi18cb7ac2009-03-23 18:34:06 -0700150};
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 */
Felipe Balbi18cb7ac2009-03-23 18:34:06 -0700161 .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
Yang Hongyange9304382009-04-13 14:40:14 -0700170static u64 musb_dmamask = DMA_BIT_MASK(32);
Felipe Balbi18cb7ac2009-03-23 18:34:06 -0700171
172static struct platform_device musb_device = {
Felipe Balbidc098862010-12-01 15:01:11 +0200173 .name = "musb-omap2430",
Felipe Balbi18cb7ac2009-03-23 18:34:06 -0700174 .id = -1,
175 .dev = {
176 .dma_mask = &musb_dmamask,
Yang Hongyange9304382009-04-13 14:40:14 -0700177 .coherent_dma_mask = DMA_BIT_MASK(32),
Felipe Balbi18cb7ac2009-03-23 18:34:06 -0700178 .platform_data = &musb_plat,
179 },
180 .num_resources = ARRAY_SIZE(musb_resources),
181 .resource = musb_resources,
182};
183
Maulik Mankad884b8362010-02-17 14:09:30 -0800184void __init usb_musb_init(struct omap_musb_board_data *board_data)
Felipe Balbi18cb7ac2009-03-23 18:34:06 -0700185{
Maulik Mankadbce06682010-02-17 14:09:32 -0800186 if (cpu_is_omap243x()) {
Felipe Balbi18cb7ac2009-03-23 18:34:06 -0700187 musb_resources[0].start = OMAP243X_HS_BASE;
Ajay Kumar Gupta3a0d30b2010-10-19 10:08:11 +0300188 } else if (cpu_is_omap3517() || cpu_is_omap3505()) {
Felipe Balbice40c572010-12-02 09:06:51 +0200189 musb_device.name = "musb-am35x";
Ajay Kumar Gupta3a0d30b2010-10-19 10:08:11 +0300190 musb_resources[0].start = AM35XX_IPSS_USBOTGSS_BASE;
191 musb_resources[1].start = INT_35XX_USBOTG_IRQ;
Ajay Kumar Guptaa9c03782010-12-07 18:57:45 +0530192 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;
Maulik Mankadbce06682010-02-17 14:09:32 -0800196 } else if (cpu_is_omap34xx()) {
Felipe Balbi18cb7ac2009-03-23 18:34:06 -0700197 musb_resources[0].start = OMAP34XX_HSUSB_OTG_BASE;
Maulik Mankadbce06682010-02-17 14:09:32 -0800198 } else if (cpu_is_omap44xx()) {
199 musb_resources[0].start = OMAP44XX_HSUSB_OTG_BASE;
Santosh Shilimkar5772ca72010-02-18 03:14:12 +0530200 musb_resources[1].start = OMAP44XX_IRQ_HS_USB_MC_N;
201 musb_resources[2].start = OMAP44XX_IRQ_HS_USB_DMA_N;
Maulik Mankadbce06682010-02-17 14:09:32 -0800202 }
Felipe Balbif9828552010-02-17 14:09:29 -0800203 musb_resources[0].end = musb_resources[0].start + SZ_4K - 1;
Felipe Balbi18cb7ac2009-03-23 18:34:06 -0700204
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";
Maulik Mankad884b8362010-02-17 14:09:30 -0800210 musb_plat.board_data = board_data;
211 musb_plat.power = board_data->power >> 1;
212 musb_plat.mode = board_data->mode;
Ajay Kumar Gupta58815fa2010-03-25 13:25:27 +0200213 musb_plat.extvbus = board_data->extvbus;
Felipe Balbi18cb7ac2009-03-23 18:34:06 -0700214
Felipe Balbibdfa3512010-02-17 14:09:31 -0800215 if (platform_device_register(&musb_device) < 0)
Felipe Balbi18cb7ac2009-03-23 18:34:06 -0700216 printk(KERN_ERR "Unable to register HS-USB (MUSB) device\n");
Felipe Balbi18cb7ac2009-03-23 18:34:06 -0700217}
Peter 'p2' De Schrijver94a3ef62009-01-19 19:09:22 +0200218
219#else
Maulik Mankad884b8362010-02-17 14:09:30 -0800220void __init usb_musb_init(struct omap_musb_board_data *board_data)
Peter 'p2' De Schrijver94a3ef62009-01-19 19:09:22 +0200221{
Peter 'p2' De Schrijver94a3ef62009-01-19 19:09:22 +0200222}
223#endif /* CONFIG_USB_MUSB_SOC */