diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2010-12-15 12:29:38 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-12-15 12:29:38 -0500 |
commit | 5cdc5bd8b2b1190cb54548c03194b154b4892e2a (patch) | |
tree | 79e9f66825a1155605a30e063ba59297a4ad0618 /drivers/usb | |
parent | 6c34d2888221ca3df81e29f598873b4fb6cf838d (diff) | |
parent | e4a2b3565fc7ac2d70361a36337be57a59d783da (diff) |
Merge branch 'musb-hw' of git://gitorious.org/usb/usb into musb
* 'musb-hw' of git://gitorious.org/usb/usb: (43 commits)
usb: musb: core: kill unneeded #include's
DA8xx: assign name to MUSB IRQ resource
arm: OMAP4430: musb: Configure musb to OTG mode
usb: musb: Adding musb support for OMAP4430
usb: otg: TWL6030: Add twl6030_usb file for compilation
mfd: TWL6030: OMAP4: Registering the TWL6030-usb device
usb: musb: TWL6030: Selecting TWL6030_USB transceiver
usb: otg: Kconfig: Add Kconfig option for TWL6030 transceiver.
usb: otg: Adding twl6030-usb transceiver driver for OMAP4430
mfd: TWL6030: USBOTG VBUS event generation on
usb: musb: add support for ux500 platform
musb: am35x: fix compile error due to control apis
arm: omap4: enable usb on 4430sdp
usb: musb: drop board_set_vbus
usb: musb: drop musb_platform_suspend/resume
usb: musb: blackfin: usb dev_pm_ops structure
usb: musb: am35x: usb dev_pm_ops structure
usb: musb: omap2430: use dev_pm_ops structure
usb: musb: omap2430: drop the nops
usb: musb: mark musb_save/restore_context static
...
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/gadget/gadget_chips.h | 2 | ||||
-rw-r--r-- | drivers/usb/musb/Kconfig | 77 | ||||
-rw-r--r-- | drivers/usb/musb/Makefile | 21 | ||||
-rw-r--r-- | drivers/usb/musb/am35x.c | 410 | ||||
-rw-r--r-- | drivers/usb/musb/blackfin.c | 229 | ||||
-rw-r--r-- | drivers/usb/musb/da8xx.c | 170 | ||||
-rw-r--r-- | drivers/usb/musb/davinci.c | 174 | ||||
-rw-r--r-- | drivers/usb/musb/musb_core.c | 191 | ||||
-rw-r--r-- | drivers/usb/musb/musb_core.h | 190 | ||||
-rw-r--r-- | drivers/usb/musb/musb_io.h | 4 | ||||
-rw-r--r-- | drivers/usb/musb/musb_regs.h | 4 | ||||
-rw-r--r-- | drivers/usb/musb/musb_virthub.c | 2 | ||||
-rw-r--r-- | drivers/usb/musb/omap2430.c | 374 | ||||
-rw-r--r-- | drivers/usb/musb/tusb6010.c | 181 | ||||
-rw-r--r-- | drivers/usb/musb/ux500.c | 216 | ||||
-rw-r--r-- | drivers/usb/otg/Kconfig | 12 | ||||
-rw-r--r-- | drivers/usb/otg/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/otg/twl6030-usb.c | 493 |
18 files changed, 2166 insertions, 585 deletions
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index ad2114e87511..5c2720d64ffa 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h | |||
@@ -96,7 +96,7 @@ | |||
96 | 96 | ||
97 | /* Mentor high speed "dual role" controller, in peripheral role */ | 97 | /* Mentor high speed "dual role" controller, in peripheral role */ |
98 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC | 98 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC |
99 | #define gadget_is_musbhdrc(g) !strcmp("musb_hdrc", (g)->name) | 99 | #define gadget_is_musbhdrc(g) !strcmp("musb-hdrc", (g)->name) |
100 | #else | 100 | #else |
101 | #define gadget_is_musbhdrc(g) 0 | 101 | #define gadget_is_musbhdrc(g) 0 |
102 | #endif | 102 | #endif |
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 341a37a469bd..4cbb7e4b368d 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig | |||
@@ -12,6 +12,7 @@ config USB_MUSB_HDRC | |||
12 | depends on (ARM || (BF54x && !BF544) || (BF52x && !BF522 && !BF523)) | 12 | depends on (ARM || (BF54x && !BF544) || (BF52x && !BF522 && !BF523)) |
13 | select NOP_USB_XCEIV if (ARCH_DAVINCI || MACH_OMAP3EVM || BLACKFIN) | 13 | select NOP_USB_XCEIV if (ARCH_DAVINCI || MACH_OMAP3EVM || BLACKFIN) |
14 | select TWL4030_USB if MACH_OMAP_3430SDP | 14 | select TWL4030_USB if MACH_OMAP_3430SDP |
15 | select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA | ||
15 | select USB_OTG_UTILS | 16 | select USB_OTG_UTILS |
16 | tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)' | 17 | tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)' |
17 | help | 18 | help |
@@ -30,57 +31,41 @@ config USB_MUSB_HDRC | |||
30 | If you do not know what this is, please say N. | 31 | If you do not know what this is, please say N. |
31 | 32 | ||
32 | To compile this driver as a module, choose M here; the | 33 | To compile this driver as a module, choose M here; the |
33 | module will be called "musb_hdrc". | 34 | module will be called "musb-hdrc". |
34 | 35 | ||
35 | config USB_MUSB_SOC | 36 | choice |
36 | boolean | 37 | prompt "Platform Glue Layer" |
37 | depends on USB_MUSB_HDRC | 38 | depends on USB_MUSB_HDRC |
38 | default y if ARCH_DAVINCI | ||
39 | default y if ARCH_OMAP2430 | ||
40 | default y if ARCH_OMAP3 | ||
41 | default y if ARCH_OMAP4 | ||
42 | default y if (BF54x && !BF544) | ||
43 | default y if (BF52x && !BF522 && !BF523) | ||
44 | 39 | ||
45 | comment "DaVinci 35x and 644x USB support" | 40 | config USB_MUSB_DAVINCI |
46 | depends on USB_MUSB_HDRC && ARCH_DAVINCI_DMx | 41 | bool "DaVinci" |
42 | depends on ARCH_DAVINCI_DMx | ||
47 | 43 | ||
48 | comment "DA8xx/OMAP-L1x USB support" | 44 | config USB_MUSB_DA8XX |
49 | depends on USB_MUSB_HDRC && ARCH_DAVINCI_DA8XX | 45 | bool "DA8xx/OMAP-L1x" |
46 | depends on ARCH_DAVINCI_DA8XX | ||
50 | 47 | ||
51 | comment "OMAP 243x high speed USB support" | 48 | config USB_MUSB_TUSB6010 |
52 | depends on USB_MUSB_HDRC && ARCH_OMAP2430 | 49 | bool "TUSB6010" |
50 | depends on ARCH_OMAP | ||
53 | 51 | ||
54 | comment "OMAP 343x high speed USB support" | 52 | config USB_MUSB_OMAP2PLUS |
55 | depends on USB_MUSB_HDRC && ARCH_OMAP3 | 53 | bool "OMAP2430 and onwards" |
54 | depends on ARCH_OMAP2PLUS | ||
56 | 55 | ||
57 | comment "OMAP 44xx high speed USB support" | 56 | config USB_MUSB_AM35X |
58 | depends on USB_MUSB_HDRC && ARCH_OMAP4 | 57 | bool "AM35x" |
58 | depends on ARCH_OMAP | ||
59 | 59 | ||
60 | comment "Blackfin high speed USB Support" | 60 | config USB_MUSB_BLACKFIN |
61 | depends on USB_MUSB_HDRC && ((BF54x && !BF544) || (BF52x && !BF522 && !BF523)) | 61 | bool "Blackfin" |
62 | depends on (BF54x && !BF544) || (BF52x && ! BF522 && !BF523) | ||
62 | 63 | ||
63 | config USB_MUSB_AM35X | 64 | config USB_MUSB_UX500 |
64 | bool | 65 | bool "U8500 and U5500" |
65 | depends on USB_MUSB_HDRC && !ARCH_OMAP2430 && !ARCH_OMAP4 | 66 | depends on (ARCH_U8500 && AB8500_USB) || (ARCH_U5500) |
66 | select NOP_USB_XCEIV | 67 | |
67 | default MACH_OMAP3517EVM | 68 | endchoice |
68 | help | ||
69 | Select this option if your platform is based on AM35x. As | ||
70 | AM35x has an updated MUSB with CPPI4.1 DMA so this config | ||
71 | is introduced to differentiate musb ip between OMAP3x and | ||
72 | AM35x platforms. | ||
73 | |||
74 | config USB_TUSB6010 | ||
75 | boolean "TUSB 6010 support" | ||
76 | depends on USB_MUSB_HDRC && !USB_MUSB_SOC | ||
77 | select NOP_USB_XCEIV | ||
78 | default y | ||
79 | help | ||
80 | The TUSB 6010 chip, from Texas Instruments, connects a discrete | ||
81 | HDRC core using a 16-bit parallel bus (NOR flash style) or VLYNQ | ||
82 | (a high speed serial link). It can use system-specific external | ||
83 | DMA controllers. | ||
84 | 69 | ||
85 | choice | 70 | choice |
86 | prompt "Driver Mode" | 71 | prompt "Driver Mode" |
@@ -158,7 +143,7 @@ config USB_MUSB_HDRC_HCD | |||
158 | config MUSB_PIO_ONLY | 143 | config MUSB_PIO_ONLY |
159 | bool 'Disable DMA (always use PIO)' | 144 | bool 'Disable DMA (always use PIO)' |
160 | depends on USB_MUSB_HDRC | 145 | depends on USB_MUSB_HDRC |
161 | default USB_TUSB6010 || ARCH_DAVINCI_DA8XX || USB_MUSB_AM35X | 146 | default USB_MUSB_TUSB6010 || USB_MUSB_DA8XX || USB_MUSB_AM35X |
162 | help | 147 | help |
163 | All data is copied between memory and FIFO by the CPU. | 148 | All data is copied between memory and FIFO by the CPU. |
164 | DMA controllers are ignored. | 149 | DMA controllers are ignored. |
@@ -171,21 +156,21 @@ config MUSB_PIO_ONLY | |||
171 | config USB_INVENTRA_DMA | 156 | config USB_INVENTRA_DMA |
172 | bool | 157 | bool |
173 | depends on USB_MUSB_HDRC && !MUSB_PIO_ONLY | 158 | depends on USB_MUSB_HDRC && !MUSB_PIO_ONLY |
174 | default ARCH_OMAP2430 || ARCH_OMAP3 || BLACKFIN || ARCH_OMAP4 | 159 | default USB_MUSB_OMAP2PLUS || USB_MUSB_BLACKFIN |
175 | help | 160 | help |
176 | Enable DMA transfers using Mentor's engine. | 161 | Enable DMA transfers using Mentor's engine. |
177 | 162 | ||
178 | config USB_TI_CPPI_DMA | 163 | config USB_TI_CPPI_DMA |
179 | bool | 164 | bool |
180 | depends on USB_MUSB_HDRC && !MUSB_PIO_ONLY | 165 | depends on USB_MUSB_HDRC && !MUSB_PIO_ONLY |
181 | default ARCH_DAVINCI | 166 | default USB_MUSB_DAVINCI |
182 | help | 167 | help |
183 | Enable DMA transfers when TI CPPI DMA is available. | 168 | Enable DMA transfers when TI CPPI DMA is available. |
184 | 169 | ||
185 | config USB_TUSB_OMAP_DMA | 170 | config USB_TUSB_OMAP_DMA |
186 | bool | 171 | bool |
187 | depends on USB_MUSB_HDRC && !MUSB_PIO_ONLY | 172 | depends on USB_MUSB_HDRC && !MUSB_PIO_ONLY |
188 | depends on USB_TUSB6010 | 173 | depends on USB_MUSB_TUSB6010 |
189 | depends on ARCH_OMAP | 174 | depends on ARCH_OMAP |
190 | default y | 175 | default y |
191 | help | 176 | help |
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile index ce164e8998d8..74df5284894f 100644 --- a/drivers/usb/musb/Makefile +++ b/drivers/usb/musb/Makefile | |||
@@ -8,22 +8,19 @@ obj-$(CONFIG_USB_MUSB_HDRC) += musb_hdrc.o | |||
8 | 8 | ||
9 | musb_hdrc-y := musb_core.o | 9 | musb_hdrc-y := musb_core.o |
10 | 10 | ||
11 | musb_hdrc-$(CONFIG_ARCH_DAVINCI_DMx) += davinci.o | ||
12 | musb_hdrc-$(CONFIG_ARCH_DAVINCI_DA8XX) += da8xx.o | ||
13 | musb_hdrc-$(CONFIG_USB_TUSB6010) += tusb6010.o | ||
14 | musb_hdrc-$(CONFIG_ARCH_OMAP2430) += omap2430.o | ||
15 | ifeq ($(CONFIG_USB_MUSB_AM35X),y) | ||
16 | musb_hdrc-$(CONFIG_ARCH_OMAP3430) += am35x.o | ||
17 | else | ||
18 | musb_hdrc-$(CONFIG_ARCH_OMAP3430) += omap2430.o | ||
19 | endif | ||
20 | musb_hdrc-$(CONFIG_ARCH_OMAP4) += omap2430.o | ||
21 | musb_hdrc-$(CONFIG_BF54x) += blackfin.o | ||
22 | musb_hdrc-$(CONFIG_BF52x) += blackfin.o | ||
23 | musb_hdrc-$(CONFIG_USB_GADGET_MUSB_HDRC) += musb_gadget_ep0.o musb_gadget.o | 11 | musb_hdrc-$(CONFIG_USB_GADGET_MUSB_HDRC) += musb_gadget_ep0.o musb_gadget.o |
24 | musb_hdrc-$(CONFIG_USB_MUSB_HDRC_HCD) += musb_virthub.o musb_host.o | 12 | musb_hdrc-$(CONFIG_USB_MUSB_HDRC_HCD) += musb_virthub.o musb_host.o |
25 | musb_hdrc-$(CONFIG_DEBUG_FS) += musb_debugfs.o | 13 | musb_hdrc-$(CONFIG_DEBUG_FS) += musb_debugfs.o |
26 | 14 | ||
15 | # Hardware Glue Layer | ||
16 | obj-$(CONFIG_USB_MUSB_OMAP2PLUS) += omap2430.o | ||
17 | obj-$(CONFIG_USB_MUSB_AM35X) += am35x.o | ||
18 | obj-$(CONFIG_USB_MUSB_TUSB6010) += tusb6010.o | ||
19 | obj-$(CONFIG_USB_MUSB_DAVINCI) += davinci.o | ||
20 | obj-$(CONFIG_USB_MUSB_DA8XX) += da8xx.o | ||
21 | obj-$(CONFIG_USB_MUSB_BLACKFIN) += blackfin.o | ||
22 | obj-$(CONFIG_USB_MUSB_UX500) += ux500.o | ||
23 | |||
27 | # the kconfig must guarantee that only one of the | 24 | # the kconfig must guarantee that only one of the |
28 | # possible I/O schemes will be enabled at a time ... | 25 | # possible I/O schemes will be enabled at a time ... |
29 | # PIO only, or DMA (several potential schemes). | 26 | # PIO only, or DMA (several potential schemes). |
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c index b0aabf3a606f..d5a3da37c90c 100644 --- a/drivers/usb/musb/am35x.c +++ b/drivers/usb/musb/am35x.c | |||
@@ -29,8 +29,9 @@ | |||
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
31 | #include <linux/io.h> | 31 | #include <linux/io.h> |
32 | #include <linux/platform_device.h> | ||
33 | #include <linux/dma-mapping.h> | ||
32 | 34 | ||
33 | #include <plat/control.h> | ||
34 | #include <plat/usb.h> | 35 | #include <plat/usb.h> |
35 | 36 | ||
36 | #include "musb_core.h" | 37 | #include "musb_core.h" |
@@ -80,51 +81,18 @@ | |||
80 | 81 | ||
81 | #define USB_MENTOR_CORE_OFFSET 0x400 | 82 | #define USB_MENTOR_CORE_OFFSET 0x400 |
82 | 83 | ||
83 | static inline void phy_on(void) | 84 | struct am35x_glue { |
84 | { | 85 | struct device *dev; |
85 | unsigned long timeout = jiffies + msecs_to_jiffies(100); | 86 | struct platform_device *musb; |
86 | u32 devconf2; | 87 | struct clk *phy_clk; |
87 | 88 | struct clk *clk; | |
88 | /* | 89 | }; |
89 | * Start the on-chip PHY and its PLL. | 90 | #define glue_to_musb(g) platform_get_drvdata(g->musb) |
90 | */ | ||
91 | devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); | ||
92 | |||
93 | devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN); | ||
94 | devconf2 |= CONF2_PHY_PLLON; | ||
95 | |||
96 | omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); | ||
97 | |||
98 | DBG(1, "Waiting for PHY clock good...\n"); | ||
99 | while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2) | ||
100 | & CONF2_PHYCLKGD)) { | ||
101 | cpu_relax(); | ||
102 | |||
103 | if (time_after(jiffies, timeout)) { | ||
104 | DBG(1, "musb PHY clock good timed out\n"); | ||
105 | break; | ||
106 | } | ||
107 | } | ||
108 | } | ||
109 | |||
110 | static inline void phy_off(void) | ||
111 | { | ||
112 | u32 devconf2; | ||
113 | |||
114 | /* | ||
115 | * Power down the on-chip PHY. | ||
116 | */ | ||
117 | devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); | ||
118 | |||
119 | devconf2 &= ~CONF2_PHY_PLLON; | ||
120 | devconf2 |= CONF2_PHYPWRDN | CONF2_OTGPWRDN; | ||
121 | omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); | ||
122 | } | ||
123 | 91 | ||
124 | /* | 92 | /* |
125 | * musb_platform_enable - enable interrupts | 93 | * am35x_musb_enable - enable interrupts |
126 | */ | 94 | */ |
127 | void musb_platform_enable(struct musb *musb) | 95 | static void am35x_musb_enable(struct musb *musb) |
128 | { | 96 | { |
129 | void __iomem *reg_base = musb->ctrl_base; | 97 | void __iomem *reg_base = musb->ctrl_base; |
130 | u32 epmask; | 98 | u32 epmask; |
@@ -143,9 +111,9 @@ void musb_platform_enable(struct musb *musb) | |||
143 | } | 111 | } |
144 | 112 | ||
145 | /* | 113 | /* |
146 | * musb_platform_disable - disable HDRC and flush interrupts | 114 | * am35x_musb_disable - disable HDRC and flush interrupts |
147 | */ | 115 | */ |
148 | void musb_platform_disable(struct musb *musb) | 116 | static void am35x_musb_disable(struct musb *musb) |
149 | { | 117 | { |
150 | void __iomem *reg_base = musb->ctrl_base; | 118 | void __iomem *reg_base = musb->ctrl_base; |
151 | 119 | ||
@@ -162,7 +130,7 @@ void musb_platform_disable(struct musb *musb) | |||
162 | #define portstate(stmt) | 130 | #define portstate(stmt) |
163 | #endif | 131 | #endif |
164 | 132 | ||
165 | static void am35x_set_vbus(struct musb *musb, int is_on) | 133 | static void am35x_musb_set_vbus(struct musb *musb, int is_on) |
166 | { | 134 | { |
167 | WARN_ON(is_on && is_peripheral_active(musb)); | 135 | WARN_ON(is_on && is_peripheral_active(musb)); |
168 | } | 136 | } |
@@ -221,7 +189,7 @@ static void otg_timer(unsigned long _musb) | |||
221 | spin_unlock_irqrestore(&musb->lock, flags); | 189 | spin_unlock_irqrestore(&musb->lock, flags); |
222 | } | 190 | } |
223 | 191 | ||
224 | void musb_platform_try_idle(struct musb *musb, unsigned long timeout) | 192 | static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout) |
225 | { | 193 | { |
226 | static unsigned long last_timer; | 194 | static unsigned long last_timer; |
227 | 195 | ||
@@ -251,13 +219,16 @@ void musb_platform_try_idle(struct musb *musb, unsigned long timeout) | |||
251 | mod_timer(&otg_workaround, timeout); | 219 | mod_timer(&otg_workaround, timeout); |
252 | } | 220 | } |
253 | 221 | ||
254 | static irqreturn_t am35x_interrupt(int irq, void *hci) | 222 | static irqreturn_t am35x_musb_interrupt(int irq, void *hci) |
255 | { | 223 | { |
256 | struct musb *musb = hci; | 224 | struct musb *musb = hci; |
257 | void __iomem *reg_base = musb->ctrl_base; | 225 | void __iomem *reg_base = musb->ctrl_base; |
226 | struct device *dev = musb->controller; | ||
227 | struct musb_hdrc_platform_data *plat = dev->platform_data; | ||
228 | struct omap_musb_board_data *data = plat->board_data; | ||
258 | unsigned long flags; | 229 | unsigned long flags; |
259 | irqreturn_t ret = IRQ_NONE; | 230 | irqreturn_t ret = IRQ_NONE; |
260 | u32 epintr, usbintr, lvl_intr; | 231 | u32 epintr, usbintr; |
261 | 232 | ||
262 | spin_lock_irqsave(&musb->lock, flags); | 233 | spin_lock_irqsave(&musb->lock, flags); |
263 | 234 | ||
@@ -346,9 +317,8 @@ eoi: | |||
346 | /* EOI needs to be written for the IRQ to be re-asserted. */ | 317 | /* EOI needs to be written for the IRQ to be re-asserted. */ |
347 | if (ret == IRQ_HANDLED || epintr || usbintr) { | 318 | if (ret == IRQ_HANDLED || epintr || usbintr) { |
348 | /* clear level interrupt */ | 319 | /* clear level interrupt */ |
349 | lvl_intr = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); | 320 | if (data->clear_irq) |
350 | lvl_intr |= AM35XX_USBOTGSS_INT_CLR; | 321 | data->clear_irq(); |
351 | omap_ctrl_writel(lvl_intr, AM35XX_CONTROL_LVL_INTR_CLEAR); | ||
352 | /* write EOI */ | 322 | /* write EOI */ |
353 | musb_writel(reg_base, USB_END_OF_INTR_REG, 0); | 323 | musb_writel(reg_base, USB_END_OF_INTR_REG, 0); |
354 | } | 324 | } |
@@ -362,137 +332,85 @@ eoi: | |||
362 | return ret; | 332 | return ret; |
363 | } | 333 | } |
364 | 334 | ||
365 | int musb_platform_set_mode(struct musb *musb, u8 musb_mode) | 335 | static int am35x_musb_set_mode(struct musb *musb, u8 musb_mode) |
366 | { | 336 | { |
367 | u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); | 337 | struct device *dev = musb->controller; |
338 | struct musb_hdrc_platform_data *plat = dev->platform_data; | ||
339 | struct omap_musb_board_data *data = plat->board_data; | ||
340 | int retval = 0; | ||
368 | 341 | ||
369 | devconf2 &= ~CONF2_OTGMODE; | 342 | if (data->set_mode) |
370 | switch (musb_mode) { | 343 | data->set_mode(musb_mode); |
371 | #ifdef CONFIG_USB_MUSB_HDRC_HCD | 344 | else |
372 | case MUSB_HOST: /* Force VBUS valid, ID = 0 */ | 345 | retval = -EIO; |
373 | devconf2 |= CONF2_FORCE_HOST; | ||
374 | break; | ||
375 | #endif | ||
376 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC | ||
377 | case MUSB_PERIPHERAL: /* Force VBUS valid, ID = 1 */ | ||
378 | devconf2 |= CONF2_FORCE_DEVICE; | ||
379 | break; | ||
380 | #endif | ||
381 | #ifdef CONFIG_USB_MUSB_OTG | ||
382 | case MUSB_OTG: /* Don't override the VBUS/ID comparators */ | ||
383 | devconf2 |= CONF2_NO_OVERRIDE; | ||
384 | break; | ||
385 | #endif | ||
386 | default: | ||
387 | DBG(2, "Trying to set unsupported mode %u\n", musb_mode); | ||
388 | } | ||
389 | 346 | ||
390 | omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); | 347 | return retval; |
391 | return 0; | ||
392 | } | 348 | } |
393 | 349 | ||
394 | int __init musb_platform_init(struct musb *musb, void *board_data) | 350 | static int am35x_musb_init(struct musb *musb) |
395 | { | 351 | { |
352 | struct device *dev = musb->controller; | ||
353 | struct musb_hdrc_platform_data *plat = dev->platform_data; | ||
354 | struct omap_musb_board_data *data = plat->board_data; | ||
396 | void __iomem *reg_base = musb->ctrl_base; | 355 | void __iomem *reg_base = musb->ctrl_base; |
397 | u32 rev, lvl_intr, sw_reset; | 356 | u32 rev; |
398 | int status; | ||
399 | 357 | ||
400 | musb->mregs += USB_MENTOR_CORE_OFFSET; | 358 | musb->mregs += USB_MENTOR_CORE_OFFSET; |
401 | 359 | ||
402 | clk_enable(musb->clock); | ||
403 | DBG(2, "musb->clock=%lud\n", clk_get_rate(musb->clock)); | ||
404 | |||
405 | musb->phy_clock = clk_get(musb->controller, "fck"); | ||
406 | if (IS_ERR(musb->phy_clock)) { | ||
407 | status = PTR_ERR(musb->phy_clock); | ||
408 | goto exit0; | ||
409 | } | ||
410 | clk_enable(musb->phy_clock); | ||
411 | DBG(2, "musb->phy_clock=%lud\n", clk_get_rate(musb->phy_clock)); | ||
412 | |||
413 | /* Returns zero if e.g. not clocked */ | 360 | /* Returns zero if e.g. not clocked */ |
414 | rev = musb_readl(reg_base, USB_REVISION_REG); | 361 | rev = musb_readl(reg_base, USB_REVISION_REG); |
415 | if (!rev) { | 362 | if (!rev) |
416 | status = -ENODEV; | 363 | return -ENODEV; |
417 | goto exit1; | ||
418 | } | ||
419 | 364 | ||
420 | usb_nop_xceiv_register(); | 365 | usb_nop_xceiv_register(); |
421 | musb->xceiv = otg_get_transceiver(); | 366 | musb->xceiv = otg_get_transceiver(); |
422 | if (!musb->xceiv) { | 367 | if (!musb->xceiv) |
423 | status = -ENODEV; | 368 | return -ENODEV; |
424 | goto exit1; | ||
425 | } | ||
426 | 369 | ||
427 | if (is_host_enabled(musb)) | 370 | if (is_host_enabled(musb)) |
428 | setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); | 371 | setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); |
429 | 372 | ||
430 | musb->board_set_vbus = am35x_set_vbus; | 373 | /* Reset the musb */ |
431 | 374 | if (data->reset) | |
432 | /* Global reset */ | 375 | data->reset(); |
433 | sw_reset = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); | ||
434 | |||
435 | sw_reset |= AM35XX_USBOTGSS_SW_RST; | ||
436 | omap_ctrl_writel(sw_reset, AM35XX_CONTROL_IP_SW_RESET); | ||
437 | |||
438 | sw_reset &= ~AM35XX_USBOTGSS_SW_RST; | ||
439 | omap_ctrl_writel(sw_reset, AM35XX_CONTROL_IP_SW_RESET); | ||
440 | 376 | ||
441 | /* Reset the controller */ | 377 | /* Reset the controller */ |
442 | musb_writel(reg_base, USB_CTRL_REG, AM35X_SOFT_RESET_MASK); | 378 | musb_writel(reg_base, USB_CTRL_REG, AM35X_SOFT_RESET_MASK); |
443 | 379 | ||
444 | /* Start the on-chip PHY and its PLL. */ | 380 | /* Start the on-chip PHY and its PLL. */ |
445 | phy_on(); | 381 | if (data->set_phy_power) |
382 | data->set_phy_power(1); | ||
446 | 383 | ||
447 | msleep(5); | 384 | msleep(5); |
448 | 385 | ||
449 | musb->isr = am35x_interrupt; | 386 | musb->isr = am35x_musb_interrupt; |
450 | 387 | ||
451 | /* clear level interrupt */ | 388 | /* clear level interrupt */ |
452 | lvl_intr = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); | 389 | if (data->clear_irq) |
453 | lvl_intr |= AM35XX_USBOTGSS_INT_CLR; | 390 | data->clear_irq(); |
454 | omap_ctrl_writel(lvl_intr, AM35XX_CONTROL_LVL_INTR_CLEAR); | 391 | |
455 | return 0; | 392 | return 0; |
456 | exit1: | ||
457 | clk_disable(musb->phy_clock); | ||
458 | clk_put(musb->phy_clock); | ||
459 | exit0: | ||
460 | clk_disable(musb->clock); | ||
461 | return status; | ||
462 | } | 393 | } |
463 | 394 | ||
464 | int musb_platform_exit(struct musb *musb) | 395 | static int am35x_musb_exit(struct musb *musb) |
465 | { | 396 | { |
397 | struct device *dev = musb->controller; | ||
398 | struct musb_hdrc_platform_data *plat = dev->platform_data; | ||
399 | struct omap_musb_board_data *data = plat->board_data; | ||
400 | |||
466 | if (is_host_enabled(musb)) | 401 | if (is_host_enabled(musb)) |
467 | del_timer_sync(&otg_workaround); | 402 | del_timer_sync(&otg_workaround); |
468 | 403 | ||
469 | phy_off(); | 404 | /* Shutdown the on-chip PHY and its PLL. */ |
405 | if (data->set_phy_power) | ||
406 | data->set_phy_power(0); | ||
470 | 407 | ||
471 | otg_put_transceiver(musb->xceiv); | 408 | otg_put_transceiver(musb->xceiv); |
472 | usb_nop_xceiv_unregister(); | 409 | usb_nop_xceiv_unregister(); |
473 | 410 | ||
474 | clk_disable(musb->clock); | ||
475 | |||
476 | clk_disable(musb->phy_clock); | ||
477 | clk_put(musb->phy_clock); | ||
478 | |||
479 | return 0; | 411 | return 0; |
480 | } | 412 | } |
481 | 413 | ||
482 | #ifdef CONFIG_PM | ||
483 | void musb_platform_save_context(struct musb *musb, | ||
484 | struct musb_context_registers *musb_context) | ||
485 | { | ||
486 | phy_off(); | ||
487 | } | ||
488 | |||
489 | void musb_platform_restore_context(struct musb *musb, | ||
490 | struct musb_context_registers *musb_context) | ||
491 | { | ||
492 | phy_on(); | ||
493 | } | ||
494 | #endif | ||
495 | |||
496 | /* AM35x supports only 32bit read operation */ | 414 | /* AM35x supports only 32bit read operation */ |
497 | void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) | 415 | void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) |
498 | { | 416 | { |
@@ -522,3 +440,215 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) | |||
522 | memcpy(dst, &val, len); | 440 | memcpy(dst, &val, len); |
523 | } | 441 | } |
524 | } | 442 | } |
443 | |||
444 | static const struct musb_platform_ops am35x_ops = { | ||
445 | .init = am35x_musb_init, | ||
446 | .exit = am35x_musb_exit, | ||
447 | |||
448 | .enable = am35x_musb_enable, | ||
449 | .disable = am35x_musb_disable, | ||
450 | |||
451 | .set_mode = am35x_musb_set_mode, | ||
452 | .try_idle = am35x_musb_try_idle, | ||
453 | |||
454 | .set_vbus = am35x_musb_set_vbus, | ||
455 | }; | ||
456 | |||
457 | static u64 am35x_dmamask = DMA_BIT_MASK(32); | ||
458 | |||
459 | static int __init am35x_probe(struct platform_device *pdev) | ||
460 | { | ||
461 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; | ||
462 | struct platform_device *musb; | ||
463 | struct am35x_glue *glue; | ||
464 | |||
465 | struct clk *phy_clk; | ||
466 | struct clk *clk; | ||
467 | |||
468 | int ret = -ENOMEM; | ||
469 | |||
470 | glue = kzalloc(sizeof(*glue), GFP_KERNEL); | ||
471 | if (!glue) { | ||
472 | dev_err(&pdev->dev, "failed to allocate glue context\n"); | ||
473 | goto err0; | ||
474 | } | ||
475 | |||
476 | musb = platform_device_alloc("musb-hdrc", -1); | ||
477 | if (!musb) { | ||
478 | dev_err(&pdev->dev, "failed to allocate musb device\n"); | ||
479 | goto err1; | ||
480 | } | ||
481 | |||
482 | phy_clk = clk_get(&pdev->dev, "fck"); | ||
483 | if (IS_ERR(phy_clk)) { | ||
484 | dev_err(&pdev->dev, "failed to get PHY clock\n"); | ||
485 | ret = PTR_ERR(phy_clk); | ||
486 | goto err2; | ||
487 | } | ||
488 | |||
489 | clk = clk_get(&pdev->dev, "ick"); | ||
490 | if (IS_ERR(clk)) { | ||
491 | dev_err(&pdev->dev, "failed to get clock\n"); | ||
492 | ret = PTR_ERR(clk); | ||
493 | goto err3; | ||
494 | } | ||
495 | |||
496 | ret = clk_enable(phy_clk); | ||
497 | if (ret) { | ||
498 | dev_err(&pdev->dev, "failed to enable PHY clock\n"); | ||
499 | goto err4; | ||
500 | } | ||
501 | |||
502 | ret = clk_enable(clk); | ||
503 | if (ret) { | ||
504 | dev_err(&pdev->dev, "failed to enable clock\n"); | ||
505 | goto err5; | ||
506 | } | ||
507 | |||
508 | musb->dev.parent = &pdev->dev; | ||
509 | musb->dev.dma_mask = &am35x_dmamask; | ||
510 | musb->dev.coherent_dma_mask = am35x_dmamask; | ||
511 | |||
512 | glue->dev = &pdev->dev; | ||
513 | glue->musb = musb; | ||
514 | glue->phy_clk = phy_clk; | ||
515 | glue->clk = clk; | ||
516 | |||
517 | pdata->platform_ops = &am35x_ops; | ||
518 | |||
519 | platform_set_drvdata(pdev, glue); | ||
520 | |||
521 | ret = platform_device_add_resources(musb, pdev->resource, | ||
522 | pdev->num_resources); | ||
523 | if (ret) { | ||
524 | dev_err(&pdev->dev, "failed to add resources\n"); | ||
525 | goto err6; | ||
526 | } | ||
527 | |||
528 | ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); | ||
529 | if (ret) { | ||
530 | dev_err(&pdev->dev, "failed to add platform_data\n"); | ||
531 | goto err6; | ||
532 | } | ||
533 | |||
534 | ret = platform_device_add(musb); | ||
535 | if (ret) { | ||
536 | dev_err(&pdev->dev, "failed to register musb device\n"); | ||
537 | goto err6; | ||
538 | } | ||
539 | |||
540 | return 0; | ||
541 | |||
542 | err6: | ||
543 | clk_disable(clk); | ||
544 | |||
545 | err5: | ||
546 | clk_disable(phy_clk); | ||
547 | |||
548 | err4: | ||
549 | clk_put(clk); | ||
550 | |||
551 | err3: | ||
552 | clk_put(phy_clk); | ||
553 | |||
554 | err2: | ||
555 | platform_device_put(musb); | ||
556 | |||
557 | err1: | ||
558 | kfree(glue); | ||
559 | |||
560 | err0: | ||
561 | return ret; | ||
562 | } | ||
563 | |||
564 | static int __exit am35x_remove(struct platform_device *pdev) | ||
565 | { | ||
566 | struct am35x_glue *glue = platform_get_drvdata(pdev); | ||
567 | |||
568 | platform_device_del(glue->musb); | ||
569 | platform_device_put(glue->musb); | ||
570 | clk_disable(glue->clk); | ||
571 | clk_disable(glue->phy_clk); | ||
572 | clk_put(glue->clk); | ||
573 | clk_put(glue->phy_clk); | ||
574 | kfree(glue); | ||
575 | |||
576 | return 0; | ||
577 | } | ||
578 | |||
579 | #ifdef CONFIG_PM | ||
580 | static int am35x_suspend(struct device *dev) | ||
581 | { | ||
582 | struct am35x_glue *glue = dev_get_drvdata(dev); | ||
583 | struct musb_hdrc_platform_data *plat = dev->platform_data; | ||
584 | struct omap_musb_board_data *data = plat->board_data; | ||
585 | |||
586 | /* Shutdown the on-chip PHY and its PLL. */ | ||
587 | if (data->set_phy_power) | ||
588 | data->set_phy_power(0); | ||
589 | |||
590 | clk_disable(glue->phy_clk); | ||
591 | clk_disable(glue->clk); | ||
592 | |||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | static int am35x_resume(struct device *dev) | ||
597 | { | ||
598 | struct am35x_glue *glue = dev_get_drvdata(dev); | ||
599 | struct musb_hdrc_platform_data *plat = dev->platform_data; | ||
600 | struct omap_musb_board_data *data = plat->board_data; | ||
601 | int ret; | ||
602 | |||
603 | /* Start the on-chip PHY and its PLL. */ | ||
604 | if (data->set_phy_power) | ||
605 | data->set_phy_power(1); | ||
606 | |||
607 | ret = clk_enable(glue->phy_clk); | ||
608 | if (ret) { | ||
609 | dev_err(dev, "failed to enable PHY clock\n"); | ||
610 | return ret; | ||
611 | } | ||
612 | |||
613 | ret = clk_enable(glue->clk); | ||
614 | if (ret) { | ||
615 | dev_err(dev, "failed to enable clock\n"); | ||
616 | return ret; | ||
617 | } | ||
618 | |||
619 | return 0; | ||
620 | } | ||
621 | |||
622 | static struct dev_pm_ops am35x_pm_ops = { | ||
623 | .suspend = am35x_suspend, | ||
624 | .resume = am35x_resume, | ||
625 | }; | ||
626 | |||
627 | #define DEV_PM_OPS &am35x_pm_ops | ||
628 | #else | ||
629 | #define DEV_PM_OPS NULL | ||
630 | #endif | ||
631 | |||
632 | static struct platform_driver am35x_driver = { | ||
633 | .remove = __exit_p(am35x_remove), | ||
634 | .driver = { | ||
635 | .name = "musb-am35x", | ||
636 | .pm = DEV_PM_OPS, | ||
637 | }, | ||
638 | }; | ||
639 | |||
640 | MODULE_DESCRIPTION("AM35x MUSB Glue Layer"); | ||
641 | MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>"); | ||
642 | MODULE_LICENSE("GPL v2"); | ||
643 | |||
644 | static int __init am35x_init(void) | ||
645 | { | ||
646 | return platform_driver_probe(&am35x_driver, am35x_probe); | ||
647 | } | ||
648 | subsys_initcall(am35x_init); | ||
649 | |||
650 | static void __exit am35x_exit(void) | ||
651 | { | ||
652 | platform_driver_unregister(&am35x_driver); | ||
653 | } | ||
654 | module_exit(am35x_exit); | ||
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index e8cbcc59c419..e72f762d214d 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c | |||
@@ -15,12 +15,20 @@ | |||
15 | #include <linux/list.h> | 15 | #include <linux/list.h> |
16 | #include <linux/gpio.h> | 16 | #include <linux/gpio.h> |
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/dma-mapping.h> | ||
18 | 20 | ||
19 | #include <asm/cacheflush.h> | 21 | #include <asm/cacheflush.h> |
20 | 22 | ||
21 | #include "musb_core.h" | 23 | #include "musb_core.h" |
22 | #include "blackfin.h" | 24 | #include "blackfin.h" |
23 | 25 | ||
26 | struct bfin_glue { | ||
27 | struct device *dev; | ||
28 | struct platform_device *musb; | ||
29 | }; | ||
30 | #define glue_to_musb(g) platform_get_drvdata(g->musb) | ||
31 | |||
24 | /* | 32 | /* |
25 | * Load an endpoint's FIFO | 33 | * Load an endpoint's FIFO |
26 | */ | 34 | */ |
@@ -277,7 +285,7 @@ static void musb_conn_timer_handler(unsigned long _musb) | |||
277 | DBG(4, "state is %s\n", otg_state_string(musb)); | 285 | DBG(4, "state is %s\n", otg_state_string(musb)); |
278 | } | 286 | } |
279 | 287 | ||
280 | void musb_platform_enable(struct musb *musb) | 288 | static void bfin_musb_enable(struct musb *musb) |
281 | { | 289 | { |
282 | if (!is_otg_enabled(musb) && is_host_enabled(musb)) { | 290 | if (!is_otg_enabled(musb) && is_host_enabled(musb)) { |
283 | mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY); | 291 | mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY); |
@@ -285,11 +293,11 @@ void musb_platform_enable(struct musb *musb) | |||
285 | } | 293 | } |
286 | } | 294 | } |
287 | 295 | ||
288 | void musb_platform_disable(struct musb *musb) | 296 | static void bfin_musb_disable(struct musb *musb) |
289 | { | 297 | { |
290 | } | 298 | } |
291 | 299 | ||
292 | static void bfin_set_vbus(struct musb *musb, int is_on) | 300 | static void bfin_musb_set_vbus(struct musb *musb, int is_on) |
293 | { | 301 | { |
294 | int value = musb->config->gpio_vrsel_active; | 302 | int value = musb->config->gpio_vrsel_active; |
295 | if (!is_on) | 303 | if (!is_on) |
@@ -302,51 +310,29 @@ static void bfin_set_vbus(struct musb *musb, int is_on) | |||
302 | musb_readb(musb->mregs, MUSB_DEVCTL)); | 310 | musb_readb(musb->mregs, MUSB_DEVCTL)); |
303 | } | 311 | } |
304 | 312 | ||
305 | static int bfin_set_power(struct otg_transceiver *x, unsigned mA) | 313 | static int bfin_musb_set_power(struct otg_transceiver *x, unsigned mA) |
306 | { | 314 | { |
307 | return 0; | 315 | return 0; |
308 | } | 316 | } |
309 | 317 | ||
310 | void musb_platform_try_idle(struct musb *musb, unsigned long timeout) | 318 | static void bfin_musb_try_idle(struct musb *musb, unsigned long timeout) |
311 | { | 319 | { |
312 | if (!is_otg_enabled(musb) && is_host_enabled(musb)) | 320 | if (!is_otg_enabled(musb) && is_host_enabled(musb)) |
313 | mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY); | 321 | mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY); |
314 | } | 322 | } |
315 | 323 | ||
316 | int musb_platform_get_vbus_status(struct musb *musb) | 324 | static int bfin_musb_get_vbus_status(struct musb *musb) |
317 | { | 325 | { |
318 | return 0; | 326 | return 0; |
319 | } | 327 | } |
320 | 328 | ||
321 | int musb_platform_set_mode(struct musb *musb, u8 musb_mode) | 329 | static int bfin_musb_set_mode(struct musb *musb, u8 musb_mode) |
322 | { | 330 | { |
323 | return -EIO; | 331 | return -EIO; |
324 | } | 332 | } |
325 | 333 | ||
326 | int __init musb_platform_init(struct musb *musb) | 334 | static void bfin_musb_reg_init(struct musb *musb) |
327 | { | 335 | { |
328 | |||
329 | /* | ||
330 | * Rev 1.0 BF549 EZ-KITs require PE7 to be high for both DEVICE | ||
331 | * and OTG HOST modes, while rev 1.1 and greater require PE7 to | ||
332 | * be low for DEVICE mode and high for HOST mode. We set it high | ||
333 | * here because we are in host mode | ||
334 | */ | ||
335 | |||
336 | if (gpio_request(musb->config->gpio_vrsel, "USB_VRSEL")) { | ||
337 | printk(KERN_ERR "Failed ro request USB_VRSEL GPIO_%d \n", | ||
338 | musb->config->gpio_vrsel); | ||
339 | return -ENODEV; | ||
340 | } | ||
341 | gpio_direction_output(musb->config->gpio_vrsel, 0); | ||
342 | |||
343 | usb_nop_xceiv_register(); | ||
344 | musb->xceiv = otg_get_transceiver(); | ||
345 | if (!musb->xceiv) { | ||
346 | gpio_free(musb->config->gpio_vrsel); | ||
347 | return -ENODEV; | ||
348 | } | ||
349 | |||
350 | if (ANOMALY_05000346) { | 336 | if (ANOMALY_05000346) { |
351 | bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value); | 337 | bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value); |
352 | SSYNC(); | 338 | SSYNC(); |
@@ -380,21 +366,47 @@ int __init musb_platform_init(struct musb *musb) | |||
380 | EP2_RX_ENA | EP3_RX_ENA | EP4_RX_ENA | | 366 | EP2_RX_ENA | EP3_RX_ENA | EP4_RX_ENA | |
381 | EP5_RX_ENA | EP6_RX_ENA | EP7_RX_ENA); | 367 | EP5_RX_ENA | EP6_RX_ENA | EP7_RX_ENA); |
382 | SSYNC(); | 368 | SSYNC(); |
369 | } | ||
370 | |||
371 | static int bfin_musb_init(struct musb *musb) | ||
372 | { | ||
373 | |||
374 | /* | ||
375 | * Rev 1.0 BF549 EZ-KITs require PE7 to be high for both DEVICE | ||
376 | * and OTG HOST modes, while rev 1.1 and greater require PE7 to | ||
377 | * be low for DEVICE mode and high for HOST mode. We set it high | ||
378 | * here because we are in host mode | ||
379 | */ | ||
380 | |||
381 | if (gpio_request(musb->config->gpio_vrsel, "USB_VRSEL")) { | ||
382 | printk(KERN_ERR "Failed ro request USB_VRSEL GPIO_%d\n", | ||
383 | musb->config->gpio_vrsel); | ||
384 | return -ENODEV; | ||
385 | } | ||
386 | gpio_direction_output(musb->config->gpio_vrsel, 0); | ||
387 | |||
388 | usb_nop_xceiv_register(); | ||
389 | musb->xceiv = otg_get_transceiver(); | ||
390 | if (!musb->xceiv) { | ||
391 | gpio_free(musb->config->gpio_vrsel); | ||
392 | return -ENODEV; | ||
393 | } | ||
394 | |||
395 | bfin_musb_reg_init(musb); | ||
383 | 396 | ||
384 | if (is_host_enabled(musb)) { | 397 | if (is_host_enabled(musb)) { |
385 | musb->board_set_vbus = bfin_set_vbus; | ||
386 | setup_timer(&musb_conn_timer, | 398 | setup_timer(&musb_conn_timer, |
387 | musb_conn_timer_handler, (unsigned long) musb); | 399 | musb_conn_timer_handler, (unsigned long) musb); |
388 | } | 400 | } |
389 | if (is_peripheral_enabled(musb)) | 401 | if (is_peripheral_enabled(musb)) |
390 | musb->xceiv->set_power = bfin_set_power; | 402 | musb->xceiv->set_power = bfin_musb_set_power; |
391 | 403 | ||
392 | musb->isr = blackfin_interrupt; | 404 | musb->isr = blackfin_interrupt; |
393 | 405 | ||
394 | return 0; | 406 | return 0; |
395 | } | 407 | } |
396 | 408 | ||
397 | int musb_platform_exit(struct musb *musb) | 409 | static int bfin_musb_exit(struct musb *musb) |
398 | { | 410 | { |
399 | gpio_free(musb->config->gpio_vrsel); | 411 | gpio_free(musb->config->gpio_vrsel); |
400 | 412 | ||
@@ -402,3 +414,154 @@ int musb_platform_exit(struct musb *musb) | |||
402 | usb_nop_xceiv_unregister(); | 414 | usb_nop_xceiv_unregister(); |
403 | return 0; | 415 | return 0; |
404 | } | 416 | } |
417 | |||
418 | static const struct musb_platform_ops bfin_ops = { | ||
419 | .init = bfin_musb_init, | ||
420 | .exit = bfin_musb_exit, | ||
421 | |||
422 | .enable = bfin_musb_enable, | ||
423 | .disable = bfin_musb_disable, | ||
424 | |||
425 | .set_mode = bfin_musb_set_mode, | ||
426 | .try_idle = bfin_musb_try_idle, | ||
427 | |||
428 | .vbus_status = bfin_musb_vbus_status, | ||
429 | .set_vbus = bfin_musb_set_vbus, | ||
430 | }; | ||
431 | |||
432 | static u64 bfin_dmamask = DMA_BIT_MASK(32); | ||
433 | |||
434 | static int __init bfin_probe(struct platform_device *pdev) | ||
435 | { | ||
436 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; | ||
437 | struct platform_device *musb; | ||
438 | struct bfin_glue *glue; | ||
439 | |||
440 | int ret = -ENOMEM; | ||
441 | |||
442 | glue = kzalloc(sizeof(*glue), GFP_KERNEL); | ||
443 | if (!glue) { | ||
444 | dev_err(&pdev->dev, "failed to allocate glue context\n"); | ||
445 | goto err0; | ||
446 | } | ||
447 | |||
448 | musb = platform_device_alloc("musb-hdrc", -1); | ||
449 | if (!musb) { | ||
450 | dev_err(&pdev->dev, "failed to allocate musb device\n"); | ||
451 | goto err1; | ||
452 | } | ||
453 | |||
454 | musb->dev.parent = &pdev->dev; | ||
455 | musb->dev.dma_mask = &bfin_dmamask; | ||
456 | musb->dev.coherent_dma_mask = bfin_dmamask; | ||
457 | |||
458 | glue->dev = &pdev->dev; | ||
459 | glue->musb = musb; | ||
460 | |||
461 | pdata->platform_ops = &bfin_ops; | ||
462 | |||
463 | platform_set_drvdata(pdev, glue); | ||
464 | |||
465 | ret = platform_device_add_resources(musb, pdev->resource, | ||
466 | pdev->num_resources); | ||
467 | if (ret) { | ||
468 | dev_err(&pdev->dev, "failed to add resources\n"); | ||
469 | goto err2; | ||
470 | } | ||
471 | |||
472 | ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); | ||
473 | if (ret) { | ||
474 | dev_err(&pdev->dev, "failed to add platform_data\n"); | ||
475 | goto err2; | ||
476 | } | ||
477 | |||
478 | ret = platform_device_add(musb); | ||
479 | if (ret) { | ||
480 | dev_err(&pdev->dev, "failed to register musb device\n"); | ||
481 | goto err2; | ||
482 | } | ||
483 | |||
484 | return 0; | ||
485 | |||
486 | err2: | ||
487 | platform_device_put(musb); | ||
488 | |||
489 | err1: | ||
490 | kfree(glue); | ||
491 | |||
492 | err0: | ||
493 | return ret; | ||
494 | } | ||
495 | |||
496 | static int __exit bfin_remove(struct platform_device *pdev) | ||
497 | { | ||
498 | struct bfin_glue *glue = platform_get_drvdata(pdev); | ||
499 | |||
500 | platform_device_del(glue->musb); | ||
501 | platform_device_put(glue->musb); | ||
502 | kfree(glue); | ||
503 | |||
504 | return 0; | ||
505 | } | ||
506 | |||
507 | #ifdef CONFIG_PM | ||
508 | static int bfin_suspend(struct device *dev) | ||
509 | { | ||
510 | struct bfin_glue *glue = dev_get_drvdata(dev); | ||
511 | struct musb *musb = glue_to_musb(glue); | ||
512 | |||
513 | if (is_host_active(musb)) | ||
514 | /* | ||
515 | * During hibernate gpio_vrsel will change from high to low | ||
516 | * low which will generate wakeup event resume the system | ||
517 | * immediately. Set it to 0 before hibernate to avoid this | ||
518 | * wakeup event. | ||
519 | */ | ||
520 | gpio_set_value(musb->config->gpio_vrsel, 0); | ||
521 | |||
522 | return 0; | ||
523 | } | ||
524 | |||
525 | static int bfin_resume(struct device *dev) | ||
526 | { | ||
527 | struct bfin_glue *glue = dev_get_drvdata(dev); | ||
528 | struct musb *musb = glue_to_musb(glue); | ||
529 | |||
530 | bfin_musb_reg_init(musb); | ||
531 | |||
532 | return 0; | ||
533 | } | ||
534 | |||
535 | static struct dev_pm_ops bfin_pm_ops = { | ||
536 | .suspend = bfin_suspend, | ||
537 | .resume = bfin_resume, | ||
538 | }; | ||
539 | |||
540 | #define DEV_PM_OPS &bfin_pm_op, | ||
541 | #else | ||
542 | #define DEV_PM_OPS NULL | ||
543 | #endif | ||
544 | |||
545 | static struct platform_driver bfin_driver = { | ||
546 | .remove = __exit_p(bfin_remove), | ||
547 | .driver = { | ||
548 | .name = "musb-bfin", | ||
549 | .pm = DEV_PM_OPS, | ||
550 | }, | ||
551 | }; | ||
552 | |||
553 | MODULE_DESCRIPTION("Blackfin MUSB Glue Layer"); | ||
554 | MODULE_AUTHOR("Bryan Wy <cooloney@kernel.org>"); | ||
555 | MODULE_LICENSE("GPL v2"); | ||
556 | |||
557 | static int __init bfin_init(void) | ||
558 | { | ||
559 | return platform_driver_probe(&bfin_driver, bfin_probe); | ||
560 | } | ||
561 | subsys_initcall(bfin_init); | ||
562 | |||
563 | static void __exit bfin_exit(void) | ||
564 | { | ||
565 | platform_driver_unregister(&bfin_driver); | ||
566 | } | ||
567 | module_exit(bfin_exit); | ||
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c index 84427bebbf62..69a0da3c8f09 100644 --- a/drivers/usb/musb/da8xx.c +++ b/drivers/usb/musb/da8xx.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
31 | #include <linux/io.h> | 31 | #include <linux/io.h> |
32 | #include <linux/platform_device.h> | ||
33 | #include <linux/dma-mapping.h> | ||
32 | 34 | ||
33 | #include <mach/da8xx.h> | 35 | #include <mach/da8xx.h> |
34 | #include <mach/usb.h> | 36 | #include <mach/usb.h> |
@@ -78,6 +80,12 @@ | |||
78 | 80 | ||
79 | #define CFGCHIP2 IO_ADDRESS(DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP2_REG) | 81 | #define CFGCHIP2 IO_ADDRESS(DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP2_REG) |
80 | 82 | ||
83 | struct da8xx_glue { | ||
84 | struct device *dev; | ||
85 | struct platform_device *musb; | ||
86 | struct clk *clk; | ||
87 | }; | ||
88 | |||
81 | /* | 89 | /* |
82 | * REVISIT (PM): we should be able to keep the PHY in low power mode most | 90 | * REVISIT (PM): we should be able to keep the PHY in low power mode most |
83 | * of the time (24 MHz oscillator and PLL off, etc.) by setting POWER.D0 | 91 | * of the time (24 MHz oscillator and PLL off, etc.) by setting POWER.D0 |
@@ -131,9 +139,9 @@ static inline void phy_off(void) | |||
131 | */ | 139 | */ |
132 | 140 | ||
133 | /** | 141 | /** |
134 | * musb_platform_enable - enable interrupts | 142 | * da8xx_musb_enable - enable interrupts |
135 | */ | 143 | */ |
136 | void musb_platform_enable(struct musb *musb) | 144 | static void da8xx_musb_enable(struct musb *musb) |
137 | { | 145 | { |
138 | void __iomem *reg_base = musb->ctrl_base; | 146 | void __iomem *reg_base = musb->ctrl_base; |
139 | u32 mask; | 147 | u32 mask; |
@@ -151,9 +159,9 @@ void musb_platform_enable(struct musb *musb) | |||
151 | } | 159 | } |
152 | 160 | ||
153 | /** | 161 | /** |
154 | * musb_platform_disable - disable HDRC and flush interrupts | 162 | * da8xx_musb_disable - disable HDRC and flush interrupts |
155 | */ | 163 | */ |
156 | void musb_platform_disable(struct musb *musb) | 164 | static void da8xx_musb_disable(struct musb *musb) |
157 | { | 165 | { |
158 | void __iomem *reg_base = musb->ctrl_base; | 166 | void __iomem *reg_base = musb->ctrl_base; |
159 | 167 | ||
@@ -170,7 +178,7 @@ void musb_platform_disable(struct musb *musb) | |||
170 | #define portstate(stmt) | 178 | #define portstate(stmt) |
171 | #endif | 179 | #endif |
172 | 180 | ||
173 | static void da8xx_set_vbus(struct musb *musb, int is_on) | 181 | static void da8xx_musb_set_vbus(struct musb *musb, int is_on) |
174 | { | 182 | { |
175 | WARN_ON(is_on && is_peripheral_active(musb)); | 183 | WARN_ON(is_on && is_peripheral_active(musb)); |
176 | } | 184 | } |
@@ -252,7 +260,7 @@ static void otg_timer(unsigned long _musb) | |||
252 | spin_unlock_irqrestore(&musb->lock, flags); | 260 | spin_unlock_irqrestore(&musb->lock, flags); |
253 | } | 261 | } |
254 | 262 | ||
255 | void musb_platform_try_idle(struct musb *musb, unsigned long timeout) | 263 | static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout) |
256 | { | 264 | { |
257 | static unsigned long last_timer; | 265 | static unsigned long last_timer; |
258 | 266 | ||
@@ -282,7 +290,7 @@ void musb_platform_try_idle(struct musb *musb, unsigned long timeout) | |||
282 | mod_timer(&otg_workaround, timeout); | 290 | mod_timer(&otg_workaround, timeout); |
283 | } | 291 | } |
284 | 292 | ||
285 | static irqreturn_t da8xx_interrupt(int irq, void *hci) | 293 | static irqreturn_t da8xx_musb_interrupt(int irq, void *hci) |
286 | { | 294 | { |
287 | struct musb *musb = hci; | 295 | struct musb *musb = hci; |
288 | void __iomem *reg_base = musb->ctrl_base; | 296 | void __iomem *reg_base = musb->ctrl_base; |
@@ -380,7 +388,7 @@ static irqreturn_t da8xx_interrupt(int irq, void *hci) | |||
380 | return ret; | 388 | return ret; |
381 | } | 389 | } |
382 | 390 | ||
383 | int musb_platform_set_mode(struct musb *musb, u8 musb_mode) | 391 | static int da8xx_musb_set_mode(struct musb *musb, u8 musb_mode) |
384 | { | 392 | { |
385 | u32 cfgchip2 = __raw_readl(CFGCHIP2); | 393 | u32 cfgchip2 = __raw_readl(CFGCHIP2); |
386 | 394 | ||
@@ -409,15 +417,13 @@ int musb_platform_set_mode(struct musb *musb, u8 musb_mode) | |||
409 | return 0; | 417 | return 0; |
410 | } | 418 | } |
411 | 419 | ||
412 | int __init musb_platform_init(struct musb *musb, void *board_data) | 420 | static int da8xx_musb_init(struct musb *musb) |
413 | { | 421 | { |
414 | void __iomem *reg_base = musb->ctrl_base; | 422 | void __iomem *reg_base = musb->ctrl_base; |
415 | u32 rev; | 423 | u32 rev; |
416 | 424 | ||
417 | musb->mregs += DA8XX_MENTOR_CORE_OFFSET; | 425 | musb->mregs += DA8XX_MENTOR_CORE_OFFSET; |
418 | 426 | ||
419 | clk_enable(musb->clock); | ||
420 | |||
421 | /* Returns zero if e.g. not clocked */ | 427 | /* Returns zero if e.g. not clocked */ |
422 | rev = musb_readl(reg_base, DA8XX_USB_REVISION_REG); | 428 | rev = musb_readl(reg_base, DA8XX_USB_REVISION_REG); |
423 | if (!rev) | 429 | if (!rev) |
@@ -431,8 +437,6 @@ int __init musb_platform_init(struct musb *musb, void *board_data) | |||
431 | if (is_host_enabled(musb)) | 437 | if (is_host_enabled(musb)) |
432 | setup_timer(&otg_workaround, otg_timer, (unsigned long)musb); | 438 | setup_timer(&otg_workaround, otg_timer, (unsigned long)musb); |
433 | 439 | ||
434 | musb->board_set_vbus = da8xx_set_vbus; | ||
435 | |||
436 | /* Reset the controller */ | 440 | /* Reset the controller */ |
437 | musb_writel(reg_base, DA8XX_USB_CTRL_REG, DA8XX_SOFT_RESET_MASK); | 441 | musb_writel(reg_base, DA8XX_USB_CTRL_REG, DA8XX_SOFT_RESET_MASK); |
438 | 442 | ||
@@ -446,14 +450,13 @@ int __init musb_platform_init(struct musb *musb, void *board_data) | |||
446 | rev, __raw_readl(CFGCHIP2), | 450 | rev, __raw_readl(CFGCHIP2), |
447 | musb_readb(reg_base, DA8XX_USB_CTRL_REG)); | 451 | musb_readb(reg_base, DA8XX_USB_CTRL_REG)); |
448 | 452 | ||
449 | musb->isr = da8xx_interrupt; | 453 | musb->isr = da8xx_musb_interrupt; |
450 | return 0; | 454 | return 0; |
451 | fail: | 455 | fail: |
452 | clk_disable(musb->clock); | ||
453 | return -ENODEV; | 456 | return -ENODEV; |
454 | } | 457 | } |
455 | 458 | ||
456 | int musb_platform_exit(struct musb *musb) | 459 | static int da8xx_musb_exit(struct musb *musb) |
457 | { | 460 | { |
458 | if (is_host_enabled(musb)) | 461 | if (is_host_enabled(musb)) |
459 | del_timer_sync(&otg_workaround); | 462 | del_timer_sync(&otg_workaround); |
@@ -463,7 +466,140 @@ int musb_platform_exit(struct musb *musb) | |||
463 | otg_put_transceiver(musb->xceiv); | 466 | otg_put_transceiver(musb->xceiv); |
464 | usb_nop_xceiv_unregister(); | 467 | usb_nop_xceiv_unregister(); |
465 | 468 | ||
466 | clk_disable(musb->clock); | 469 | return 0; |
470 | } | ||
471 | |||
472 | static const struct musb_platform_ops da8xx_ops = { | ||
473 | .init = da8xx_musb_init, | ||
474 | .exit = da8xx_musb_exit, | ||
475 | |||
476 | .enable = da8xx_musb_enable, | ||
477 | .disable = da8xx_musb_disable, | ||
478 | |||
479 | .set_mode = da8xx_musb_set_mode, | ||
480 | .try_idle = da8xx_musb_try_idle, | ||
481 | |||
482 | .set_vbus = da8xx_musb_set_vbus, | ||
483 | }; | ||
484 | |||
485 | static u64 da8xx_dmamask = DMA_BIT_MASK(32); | ||
486 | |||
487 | static int __init da8xx_probe(struct platform_device *pdev) | ||
488 | { | ||
489 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; | ||
490 | struct platform_device *musb; | ||
491 | struct da8xx_glue *glue; | ||
492 | |||
493 | struct clk *clk; | ||
494 | |||
495 | int ret = -ENOMEM; | ||
496 | |||
497 | glue = kzalloc(sizeof(*glue), GFP_KERNEL); | ||
498 | if (!glue) { | ||
499 | dev_err(&pdev->dev, "failed to allocate glue context\n"); | ||
500 | goto err0; | ||
501 | } | ||
502 | |||
503 | musb = platform_device_alloc("musb-hdrc", -1); | ||
504 | if (!musb) { | ||
505 | dev_err(&pdev->dev, "failed to allocate musb device\n"); | ||
506 | goto err1; | ||
507 | } | ||
508 | |||
509 | clk = clk_get(&pdev->dev, "usb20"); | ||
510 | if (IS_ERR(clk)) { | ||
511 | dev_err(&pdev->dev, "failed to get clock\n"); | ||
512 | ret = PTR_ERR(clk); | ||
513 | goto err2; | ||
514 | } | ||
515 | |||
516 | ret = clk_enable(clk); | ||
517 | if (ret) { | ||
518 | dev_err(&pdev->dev, "failed to enable clock\n"); | ||
519 | goto err3; | ||
520 | } | ||
521 | |||
522 | musb->dev.parent = &pdev->dev; | ||
523 | musb->dev.dma_mask = &da8xx_dmamask; | ||
524 | musb->dev.coherent_dma_mask = da8xx_dmamask; | ||
525 | |||
526 | glue->dev = &pdev->dev; | ||
527 | glue->musb = musb; | ||
528 | glue->clk = clk; | ||
529 | |||
530 | pdata->platform_ops = &da8xx_ops; | ||
531 | |||
532 | platform_set_drvdata(pdev, glue); | ||
533 | |||
534 | ret = platform_device_add_resources(musb, pdev->resource, | ||
535 | pdev->num_resources); | ||
536 | if (ret) { | ||
537 | dev_err(&pdev->dev, "failed to add resources\n"); | ||
538 | goto err4; | ||
539 | } | ||
540 | |||
541 | ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); | ||
542 | if (ret) { | ||
543 | dev_err(&pdev->dev, "failed to add platform_data\n"); | ||
544 | goto err4; | ||
545 | } | ||
546 | |||
547 | ret = platform_device_add(musb); | ||
548 | if (ret) { | ||
549 | dev_err(&pdev->dev, "failed to register musb device\n"); | ||
550 | goto err4; | ||
551 | } | ||
552 | |||
553 | return 0; | ||
554 | |||
555 | err4: | ||
556 | clk_disable(clk); | ||
557 | |||
558 | err3: | ||
559 | clk_put(clk); | ||
560 | |||
561 | err2: | ||
562 | platform_device_put(musb); | ||
563 | |||
564 | err1: | ||
565 | kfree(glue); | ||
566 | |||
567 | err0: | ||
568 | return ret; | ||
569 | } | ||
570 | |||
571 | static int __exit da8xx_remove(struct platform_device *pdev) | ||
572 | { | ||
573 | struct da8xx_glue *glue = platform_get_drvdata(pdev); | ||
574 | |||
575 | platform_device_del(glue->musb); | ||
576 | platform_device_put(glue->musb); | ||
577 | clk_disable(glue->clk); | ||
578 | clk_put(glue->clk); | ||
579 | kfree(glue); | ||
467 | 580 | ||
468 | return 0; | 581 | return 0; |
469 | } | 582 | } |
583 | |||
584 | static struct platform_driver da8xx_driver = { | ||
585 | .remove = __exit_p(da8xx_remove), | ||
586 | .driver = { | ||
587 | .name = "musb-da8xx", | ||
588 | }, | ||
589 | }; | ||
590 | |||
591 | MODULE_DESCRIPTION("DA8xx/OMAP-L1x MUSB Glue Layer"); | ||
592 | MODULE_AUTHOR("Sergei Shtylyov <sshtylyov@ru.mvista.com>"); | ||
593 | MODULE_LICENSE("GPL v2"); | ||
594 | |||
595 | static int __init da8xx_init(void) | ||
596 | { | ||
597 | return platform_driver_probe(&da8xx_driver, da8xx_probe); | ||
598 | } | ||
599 | subsys_initcall(da8xx_init); | ||
600 | |||
601 | static void __exit da8xx_exit(void) | ||
602 | { | ||
603 | platform_driver_unregister(&da8xx_driver); | ||
604 | } | ||
605 | module_exit(da8xx_exit); | ||
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 051e2bf1897a..e6de097fb7e8 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
31 | #include <linux/io.h> | 31 | #include <linux/io.h> |
32 | #include <linux/gpio.h> | 32 | #include <linux/gpio.h> |
33 | #include <linux/platform_device.h> | ||
34 | #include <linux/dma-mapping.h> | ||
33 | 35 | ||
34 | #include <mach/hardware.h> | 36 | #include <mach/hardware.h> |
35 | #include <mach/memory.h> | 37 | #include <mach/memory.h> |
@@ -51,6 +53,12 @@ | |||
51 | #define USB_PHY_CTRL IO_ADDRESS(USBPHY_CTL_PADDR) | 53 | #define USB_PHY_CTRL IO_ADDRESS(USBPHY_CTL_PADDR) |
52 | #define DM355_DEEPSLEEP IO_ADDRESS(DM355_DEEPSLEEP_PADDR) | 54 | #define DM355_DEEPSLEEP IO_ADDRESS(DM355_DEEPSLEEP_PADDR) |
53 | 55 | ||
56 | struct davinci_glue { | ||
57 | struct device *dev; | ||
58 | struct platform_device *musb; | ||
59 | struct clk *clk; | ||
60 | }; | ||
61 | |||
54 | /* REVISIT (PM) we should be able to keep the PHY in low power mode most | 62 | /* REVISIT (PM) we should be able to keep the PHY in low power mode most |
55 | * of the time (24 MHZ oscillator and PLL off, etc) by setting POWER.D0 | 63 | * of the time (24 MHZ oscillator and PLL off, etc) by setting POWER.D0 |
56 | * and, when in host mode, autosuspending idle root ports... PHYPLLON | 64 | * and, when in host mode, autosuspending idle root ports... PHYPLLON |
@@ -83,7 +91,7 @@ static inline void phy_off(void) | |||
83 | 91 | ||
84 | static int dma_off = 1; | 92 | static int dma_off = 1; |
85 | 93 | ||
86 | void musb_platform_enable(struct musb *musb) | 94 | static void davinci_musb_enable(struct musb *musb) |
87 | { | 95 | { |
88 | u32 tmp, old, val; | 96 | u32 tmp, old, val; |
89 | 97 | ||
@@ -116,7 +124,7 @@ void musb_platform_enable(struct musb *musb) | |||
116 | /* | 124 | /* |
117 | * Disable the HDRC and flush interrupts | 125 | * Disable the HDRC and flush interrupts |
118 | */ | 126 | */ |
119 | void musb_platform_disable(struct musb *musb) | 127 | static void davinci_musb_disable(struct musb *musb) |
120 | { | 128 | { |
121 | /* because we don't set CTRLR.UINT, "important" to: | 129 | /* because we don't set CTRLR.UINT, "important" to: |
122 | * - not read/write INTRUSB/INTRUSBE | 130 | * - not read/write INTRUSB/INTRUSBE |
@@ -167,7 +175,7 @@ static void evm_deferred_drvvbus(struct work_struct *ignored) | |||
167 | 175 | ||
168 | #endif /* EVM */ | 176 | #endif /* EVM */ |
169 | 177 | ||
170 | static void davinci_source_power(struct musb *musb, int is_on, int immediate) | 178 | static void davinci_musb_source_power(struct musb *musb, int is_on, int immediate) |
171 | { | 179 | { |
172 | #ifdef CONFIG_MACH_DAVINCI_EVM | 180 | #ifdef CONFIG_MACH_DAVINCI_EVM |
173 | if (is_on) | 181 | if (is_on) |
@@ -190,10 +198,10 @@ static void davinci_source_power(struct musb *musb, int is_on, int immediate) | |||
190 | #endif | 198 | #endif |
191 | } | 199 | } |
192 | 200 | ||
193 | static void davinci_set_vbus(struct musb *musb, int is_on) | 201 | static void davinci_musb_set_vbus(struct musb *musb, int is_on) |
194 | { | 202 | { |
195 | WARN_ON(is_on && is_peripheral_active(musb)); | 203 | WARN_ON(is_on && is_peripheral_active(musb)); |
196 | davinci_source_power(musb, is_on, 0); | 204 | davinci_musb_source_power(musb, is_on, 0); |
197 | } | 205 | } |
198 | 206 | ||
199 | 207 | ||
@@ -259,7 +267,7 @@ static void otg_timer(unsigned long _musb) | |||
259 | spin_unlock_irqrestore(&musb->lock, flags); | 267 | spin_unlock_irqrestore(&musb->lock, flags); |
260 | } | 268 | } |
261 | 269 | ||
262 | static irqreturn_t davinci_interrupt(int irq, void *__hci) | 270 | static irqreturn_t davinci_musb_interrupt(int irq, void *__hci) |
263 | { | 271 | { |
264 | unsigned long flags; | 272 | unsigned long flags; |
265 | irqreturn_t retval = IRQ_NONE; | 273 | irqreturn_t retval = IRQ_NONE; |
@@ -345,7 +353,7 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) | |||
345 | /* NOTE: this must complete poweron within 100 msec | 353 | /* NOTE: this must complete poweron within 100 msec |
346 | * (OTG_TIME_A_WAIT_VRISE) but we don't check for that. | 354 | * (OTG_TIME_A_WAIT_VRISE) but we don't check for that. |
347 | */ | 355 | */ |
348 | davinci_source_power(musb, drvvbus, 0); | 356 | davinci_musb_source_power(musb, drvvbus, 0); |
349 | DBG(2, "VBUS %s (%s)%s, devctl %02x\n", | 357 | DBG(2, "VBUS %s (%s)%s, devctl %02x\n", |
350 | drvvbus ? "on" : "off", | 358 | drvvbus ? "on" : "off", |
351 | otg_state_string(musb), | 359 | otg_state_string(musb), |
@@ -370,13 +378,13 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) | |||
370 | return retval; | 378 | return retval; |
371 | } | 379 | } |
372 | 380 | ||
373 | int musb_platform_set_mode(struct musb *musb, u8 mode) | 381 | static int davinci_musb_set_mode(struct musb *musb, u8 mode) |
374 | { | 382 | { |
375 | /* EVM can't do this (right?) */ | 383 | /* EVM can't do this (right?) */ |
376 | return -EIO; | 384 | return -EIO; |
377 | } | 385 | } |
378 | 386 | ||
379 | int __init musb_platform_init(struct musb *musb) | 387 | static int davinci_musb_init(struct musb *musb) |
380 | { | 388 | { |
381 | void __iomem *tibase = musb->ctrl_base; | 389 | void __iomem *tibase = musb->ctrl_base; |
382 | u32 revision; | 390 | u32 revision; |
@@ -388,8 +396,6 @@ int __init musb_platform_init(struct musb *musb) | |||
388 | 396 | ||
389 | musb->mregs += DAVINCI_BASE_OFFSET; | 397 | musb->mregs += DAVINCI_BASE_OFFSET; |
390 | 398 | ||
391 | clk_enable(musb->clock); | ||
392 | |||
393 | /* returns zero if e.g. not clocked */ | 399 | /* returns zero if e.g. not clocked */ |
394 | revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG); | 400 | revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG); |
395 | if (revision == 0) | 401 | if (revision == 0) |
@@ -398,8 +404,7 @@ int __init musb_platform_init(struct musb *musb) | |||
398 | if (is_host_enabled(musb)) | 404 | if (is_host_enabled(musb)) |
399 | setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); | 405 | setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); |
400 | 406 | ||
401 | musb->board_set_vbus = davinci_set_vbus; | 407 | davinci_musb_source_power(musb, 0, 1); |
402 | davinci_source_power(musb, 0, 1); | ||
403 | 408 | ||
404 | /* dm355 EVM swaps D+/D- for signal integrity, and | 409 | /* dm355 EVM swaps D+/D- for signal integrity, and |
405 | * is clocked from the main 24 MHz crystal. | 410 | * is clocked from the main 24 MHz crystal. |
@@ -440,18 +445,16 @@ int __init musb_platform_init(struct musb *musb) | |||
440 | revision, __raw_readl(USB_PHY_CTRL), | 445 | revision, __raw_readl(USB_PHY_CTRL), |
441 | musb_readb(tibase, DAVINCI_USB_CTRL_REG)); | 446 | musb_readb(tibase, DAVINCI_USB_CTRL_REG)); |
442 | 447 | ||
443 | musb->isr = davinci_interrupt; | 448 | musb->isr = davinci_musb_interrupt; |
444 | return 0; | 449 | return 0; |
445 | 450 | ||
446 | fail: | 451 | fail: |
447 | clk_disable(musb->clock); | ||
448 | |||
449 | otg_put_transceiver(musb->xceiv); | 452 | otg_put_transceiver(musb->xceiv); |
450 | usb_nop_xceiv_unregister(); | 453 | usb_nop_xceiv_unregister(); |
451 | return -ENODEV; | 454 | return -ENODEV; |
452 | } | 455 | } |
453 | 456 | ||
454 | int musb_platform_exit(struct musb *musb) | 457 | static int davinci_musb_exit(struct musb *musb) |
455 | { | 458 | { |
456 | if (is_host_enabled(musb)) | 459 | if (is_host_enabled(musb)) |
457 | del_timer_sync(&otg_workaround); | 460 | del_timer_sync(&otg_workaround); |
@@ -465,7 +468,7 @@ int musb_platform_exit(struct musb *musb) | |||
465 | __raw_writel(deepsleep, DM355_DEEPSLEEP); | 468 | __raw_writel(deepsleep, DM355_DEEPSLEEP); |
466 | } | 469 | } |
467 | 470 | ||
468 | davinci_source_power(musb, 0 /*off*/, 1); | 471 | davinci_musb_source_power(musb, 0 /*off*/, 1); |
469 | 472 | ||
470 | /* delay, to avoid problems with module reload */ | 473 | /* delay, to avoid problems with module reload */ |
471 | if (is_host_enabled(musb) && musb->xceiv->default_a) { | 474 | if (is_host_enabled(musb) && musb->xceiv->default_a) { |
@@ -495,10 +498,141 @@ int musb_platform_exit(struct musb *musb) | |||
495 | 498 | ||
496 | phy_off(); | 499 | phy_off(); |
497 | 500 | ||
498 | clk_disable(musb->clock); | ||
499 | |||
500 | otg_put_transceiver(musb->xceiv); | 501 | otg_put_transceiver(musb->xceiv); |
501 | usb_nop_xceiv_unregister(); | 502 | usb_nop_xceiv_unregister(); |
502 | 503 | ||
503 | return 0; | 504 | return 0; |
504 | } | 505 | } |
506 | |||
507 | static const struct musb_platform_ops davinci_ops = { | ||
508 | .init = davinci_musb_init, | ||
509 | .exit = davinci_musb_exit, | ||
510 | |||
511 | .enable = davinci_musb_enable, | ||
512 | .disable = davinci_musb_disable, | ||
513 | |||
514 | .set_mode = davinci_musb_set_mode, | ||
515 | |||
516 | .set_vbus = davinci_musb_set_vbus, | ||
517 | }; | ||
518 | |||
519 | static u64 davinci_dmamask = DMA_BIT_MASK(32); | ||
520 | |||
521 | static int __init davinci_probe(struct platform_device *pdev) | ||
522 | { | ||
523 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; | ||
524 | struct platform_device *musb; | ||
525 | struct davinci_glue *glue; | ||
526 | struct clk *clk; | ||
527 | |||
528 | int ret = -ENOMEM; | ||
529 | |||
530 | glue = kzalloc(sizeof(*glue), GFP_KERNEL); | ||
531 | if (!glue) { | ||
532 | dev_err(&pdev->dev, "failed to allocate glue context\n"); | ||
533 | goto err0; | ||
534 | } | ||
535 | |||
536 | musb = platform_device_alloc("musb-hdrc", -1); | ||
537 | if (!musb) { | ||
538 | dev_err(&pdev->dev, "failed to allocate musb device\n"); | ||
539 | goto err1; | ||
540 | } | ||
541 | |||
542 | clk = clk_get(&pdev->dev, "usb"); | ||
543 | if (IS_ERR(clk)) { | ||
544 | dev_err(&pdev->dev, "failed to get clock\n"); | ||
545 | ret = PTR_ERR(clk); | ||
546 | goto err2; | ||
547 | } | ||
548 | |||
549 | ret = clk_enable(clk); | ||
550 | if (ret) { | ||
551 | dev_err(&pdev->dev, "failed to enable clock\n"); | ||
552 | goto err3; | ||
553 | } | ||
554 | |||
555 | musb->dev.parent = &pdev->dev; | ||
556 | musb->dev.dma_mask = &davinci_dmamask; | ||
557 | musb->dev.coherent_dma_mask = davinci_dmamask; | ||
558 | |||
559 | glue->dev = &pdev->dev; | ||
560 | glue->musb = musb; | ||
561 | glue->clk = clk; | ||
562 | |||
563 | pdata->platform_ops = &davinci_ops; | ||
564 | |||
565 | platform_set_drvdata(pdev, glue); | ||
566 | |||
567 | ret = platform_device_add_resources(musb, pdev->resource, | ||
568 | pdev->num_resources); | ||
569 | if (ret) { | ||
570 | dev_err(&pdev->dev, "failed to add resources\n"); | ||
571 | goto err4; | ||
572 | } | ||
573 | |||
574 | ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); | ||
575 | if (ret) { | ||
576 | dev_err(&pdev->dev, "failed to add platform_data\n"); | ||
577 | goto err4; | ||
578 | } | ||
579 | |||
580 | ret = platform_device_add(musb); | ||
581 | if (ret) { | ||
582 | dev_err(&pdev->dev, "failed to register musb device\n"); | ||
583 | goto err4; | ||
584 | } | ||
585 | |||
586 | return 0; | ||
587 | |||
588 | err4: | ||
589 | clk_disable(clk); | ||
590 | |||
591 | err3: | ||
592 | clk_put(clk); | ||
593 | |||
594 | err2: | ||
595 | platform_device_put(musb); | ||
596 | |||
597 | err1: | ||
598 | kfree(glue); | ||
599 | |||
600 | err0: | ||
601 | return ret; | ||
602 | } | ||
603 | |||
604 | static int __exit davinci_remove(struct platform_device *pdev) | ||
605 | { | ||
606 | struct davinci_glue *glue = platform_get_drvdata(pdev); | ||
607 | |||
608 | platform_device_del(glue->musb); | ||
609 | platform_device_put(glue->musb); | ||
610 | clk_disable(glue->clk); | ||
611 | clk_put(glue->clk); | ||
612 | kfree(glue); | ||
613 | |||
614 | return 0; | ||
615 | } | ||
616 | |||
617 | static struct platform_driver davinci_driver = { | ||
618 | .remove = __exit_p(davinci_remove), | ||
619 | .driver = { | ||
620 | .name = "musb-davinci", | ||
621 | }, | ||
622 | }; | ||
623 | |||
624 | MODULE_DESCRIPTION("DaVinci MUSB Glue Layer"); | ||
625 | MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); | ||
626 | MODULE_LICENSE("GPL v2"); | ||
627 | |||
628 | static int __init davinci_init(void) | ||
629 | { | ||
630 | return platform_driver_probe(&davinci_driver, davinci_probe); | ||
631 | } | ||
632 | subsys_initcall(davinci_init); | ||
633 | |||
634 | static void __exit davinci_exit(void) | ||
635 | { | ||
636 | platform_driver_unregister(&davinci_driver); | ||
637 | } | ||
638 | module_exit(davinci_exit); | ||
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index a5ceddfe57d6..7816c0180430 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c | |||
@@ -99,19 +99,8 @@ | |||
99 | #include <linux/platform_device.h> | 99 | #include <linux/platform_device.h> |
100 | #include <linux/io.h> | 100 | #include <linux/io.h> |
101 | 101 | ||
102 | #ifdef CONFIG_ARM | ||
103 | #include <mach/hardware.h> | ||
104 | #include <mach/memory.h> | ||
105 | #include <asm/mach-types.h> | ||
106 | #endif | ||
107 | |||
108 | #include "musb_core.h" | 102 | #include "musb_core.h" |
109 | 103 | ||
110 | |||
111 | #ifdef CONFIG_ARCH_DAVINCI | ||
112 | #include "davinci.h" | ||
113 | #endif | ||
114 | |||
115 | #define TA_WAIT_BCON(m) max_t(int, (m)->a_wait_bcon, OTG_TIME_A_WAIT_BCON) | 104 | #define TA_WAIT_BCON(m) max_t(int, (m)->a_wait_bcon, OTG_TIME_A_WAIT_BCON) |
116 | 105 | ||
117 | 106 | ||
@@ -126,7 +115,7 @@ MODULE_PARM_DESC(debug, "Debug message level. Default = 0"); | |||
126 | 115 | ||
127 | #define DRIVER_INFO DRIVER_DESC ", v" MUSB_VERSION | 116 | #define DRIVER_INFO DRIVER_DESC ", v" MUSB_VERSION |
128 | 117 | ||
129 | #define MUSB_DRIVER_NAME "musb_hdrc" | 118 | #define MUSB_DRIVER_NAME "musb-hdrc" |
130 | const char musb_driver_name[] = MUSB_DRIVER_NAME; | 119 | const char musb_driver_name[] = MUSB_DRIVER_NAME; |
131 | 120 | ||
132 | MODULE_DESCRIPTION(DRIVER_INFO); | 121 | MODULE_DESCRIPTION(DRIVER_INFO); |
@@ -230,7 +219,7 @@ static struct otg_io_access_ops musb_ulpi_access = { | |||
230 | 219 | ||
231 | /*-------------------------------------------------------------------------*/ | 220 | /*-------------------------------------------------------------------------*/ |
232 | 221 | ||
233 | #if !defined(CONFIG_USB_TUSB6010) && !defined(CONFIG_BLACKFIN) | 222 | #if !defined(CONFIG_USB_MUSB_TUSB6010) && !defined(CONFIG_USB_MUSB_BLACKFIN) |
234 | 223 | ||
235 | /* | 224 | /* |
236 | * Load an endpoint's FIFO | 225 | * Load an endpoint's FIFO |
@@ -390,7 +379,7 @@ void musb_otg_timer_func(unsigned long data) | |||
390 | case OTG_STATE_A_SUSPEND: | 379 | case OTG_STATE_A_SUSPEND: |
391 | case OTG_STATE_A_WAIT_BCON: | 380 | case OTG_STATE_A_WAIT_BCON: |
392 | DBG(1, "HNP: %s timeout\n", otg_state_string(musb)); | 381 | DBG(1, "HNP: %s timeout\n", otg_state_string(musb)); |
393 | musb_set_vbus(musb, 0); | 382 | musb_platform_set_vbus(musb, 0); |
394 | musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; | 383 | musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; |
395 | break; | 384 | break; |
396 | default: | 385 | default: |
@@ -570,7 +559,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | |||
570 | musb->ep0_stage = MUSB_EP0_START; | 559 | musb->ep0_stage = MUSB_EP0_START; |
571 | musb->xceiv->state = OTG_STATE_A_IDLE; | 560 | musb->xceiv->state = OTG_STATE_A_IDLE; |
572 | MUSB_HST_MODE(musb); | 561 | MUSB_HST_MODE(musb); |
573 | musb_set_vbus(musb, 1); | 562 | musb_platform_set_vbus(musb, 1); |
574 | 563 | ||
575 | handled = IRQ_HANDLED; | 564 | handled = IRQ_HANDLED; |
576 | } | 565 | } |
@@ -641,7 +630,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | |||
641 | 630 | ||
642 | /* go through A_WAIT_VFALL then start a new session */ | 631 | /* go through A_WAIT_VFALL then start a new session */ |
643 | if (!ignore) | 632 | if (!ignore) |
644 | musb_set_vbus(musb, 0); | 633 | musb_platform_set_vbus(musb, 0); |
645 | handled = IRQ_HANDLED; | 634 | handled = IRQ_HANDLED; |
646 | } | 635 | } |
647 | 636 | ||
@@ -1048,8 +1037,6 @@ static void musb_shutdown(struct platform_device *pdev) | |||
1048 | spin_lock_irqsave(&musb->lock, flags); | 1037 | spin_lock_irqsave(&musb->lock, flags); |
1049 | musb_platform_disable(musb); | 1038 | musb_platform_disable(musb); |
1050 | musb_generic_disable(musb); | 1039 | musb_generic_disable(musb); |
1051 | if (musb->clock) | ||
1052 | clk_put(musb->clock); | ||
1053 | spin_unlock_irqrestore(&musb->lock, flags); | 1040 | spin_unlock_irqrestore(&musb->lock, flags); |
1054 | 1041 | ||
1055 | /* FIXME power down */ | 1042 | /* FIXME power down */ |
@@ -1068,10 +1055,11 @@ static void musb_shutdown(struct platform_device *pdev) | |||
1068 | * We don't currently use dynamic fifo setup capability to do anything | 1055 | * We don't currently use dynamic fifo setup capability to do anything |
1069 | * more than selecting one of a bunch of predefined configurations. | 1056 | * more than selecting one of a bunch of predefined configurations. |
1070 | */ | 1057 | */ |
1071 | #if defined(CONFIG_USB_TUSB6010) || \ | 1058 | #if defined(CONFIG_USB_MUSB_TUSB6010) || defined(CONFIG_USB_MUSB_OMAP2PLUS) \ |
1072 | defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) \ | 1059 | || defined(CONFIG_USB_MUSB_AM35X) |
1073 | || defined(CONFIG_ARCH_OMAP4) | ||
1074 | static ushort __initdata fifo_mode = 4; | 1060 | static ushort __initdata fifo_mode = 4; |
1061 | #elif defined(CONFIG_USB_MUSB_UX500) | ||
1062 | static ushort __initdata fifo_mode = 5; | ||
1075 | #else | 1063 | #else |
1076 | static ushort __initdata fifo_mode = 2; | 1064 | static ushort __initdata fifo_mode = 2; |
1077 | #endif | 1065 | #endif |
@@ -1495,7 +1483,7 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb) | |||
1495 | struct musb_hw_ep *hw_ep = musb->endpoints + i; | 1483 | struct musb_hw_ep *hw_ep = musb->endpoints + i; |
1496 | 1484 | ||
1497 | hw_ep->fifo = MUSB_FIFO_OFFSET(i) + mbase; | 1485 | hw_ep->fifo = MUSB_FIFO_OFFSET(i) + mbase; |
1498 | #ifdef CONFIG_USB_TUSB6010 | 1486 | #ifdef CONFIG_USB_MUSB_TUSB6010 |
1499 | hw_ep->fifo_async = musb->async + 0x400 + MUSB_FIFO_OFFSET(i); | 1487 | hw_ep->fifo_async = musb->async + 0x400 + MUSB_FIFO_OFFSET(i); |
1500 | hw_ep->fifo_sync = musb->sync + 0x400 + MUSB_FIFO_OFFSET(i); | 1488 | hw_ep->fifo_sync = musb->sync + 0x400 + MUSB_FIFO_OFFSET(i); |
1501 | hw_ep->fifo_sync_va = | 1489 | hw_ep->fifo_sync_va = |
@@ -1542,7 +1530,8 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb) | |||
1542 | /*-------------------------------------------------------------------------*/ | 1530 | /*-------------------------------------------------------------------------*/ |
1543 | 1531 | ||
1544 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430) || \ | 1532 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430) || \ |
1545 | defined(CONFIG_ARCH_OMAP4) | 1533 | defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500) || \ |
1534 | defined(CONFIG_ARCH_U5500) | ||
1546 | 1535 | ||
1547 | static irqreturn_t generic_interrupt(int irq, void *__hci) | 1536 | static irqreturn_t generic_interrupt(int irq, void *__hci) |
1548 | { | 1537 | { |
@@ -1898,6 +1887,7 @@ allocate_instance(struct device *dev, | |||
1898 | } | 1887 | } |
1899 | 1888 | ||
1900 | musb->controller = dev; | 1889 | musb->controller = dev; |
1890 | |||
1901 | return musb; | 1891 | return musb; |
1902 | } | 1892 | } |
1903 | 1893 | ||
@@ -1994,30 +1984,14 @@ bad_config: | |||
1994 | spin_lock_init(&musb->lock); | 1984 | spin_lock_init(&musb->lock); |
1995 | musb->board_mode = plat->mode; | 1985 | musb->board_mode = plat->mode; |
1996 | musb->board_set_power = plat->set_power; | 1986 | musb->board_set_power = plat->set_power; |
1997 | musb->set_clock = plat->set_clock; | ||
1998 | musb->min_power = plat->min_power; | 1987 | musb->min_power = plat->min_power; |
1999 | 1988 | musb->ops = plat->platform_ops; | |
2000 | /* Clock usage is chip-specific ... functional clock (DaVinci, | ||
2001 | * OMAP2430), or PHY ref (some TUSB6010 boards). All this core | ||
2002 | * code does is make sure a clock handle is available; platform | ||
2003 | * code manages it during start/stop and suspend/resume. | ||
2004 | */ | ||
2005 | if (plat->clock) { | ||
2006 | musb->clock = clk_get(dev, plat->clock); | ||
2007 | if (IS_ERR(musb->clock)) { | ||
2008 | status = PTR_ERR(musb->clock); | ||
2009 | musb->clock = NULL; | ||
2010 | goto fail1; | ||
2011 | } | ||
2012 | } | ||
2013 | 1989 | ||
2014 | /* The musb_platform_init() call: | 1990 | /* The musb_platform_init() call: |
2015 | * - adjusts musb->mregs and musb->isr if needed, | 1991 | * - adjusts musb->mregs and musb->isr if needed, |
2016 | * - may initialize an integrated tranceiver | 1992 | * - may initialize an integrated tranceiver |
2017 | * - initializes musb->xceiv, usually by otg_get_transceiver() | 1993 | * - initializes musb->xceiv, usually by otg_get_transceiver() |
2018 | * - activates clocks. | ||
2019 | * - stops powering VBUS | 1994 | * - stops powering VBUS |
2020 | * - assigns musb->board_set_vbus if host mode is enabled | ||
2021 | * | 1995 | * |
2022 | * There are various transciever configurations. Blackfin, | 1996 | * There are various transciever configurations. Blackfin, |
2023 | * DaVinci, TUSB60x0, and others integrate them. OMAP3 uses | 1997 | * DaVinci, TUSB60x0, and others integrate them. OMAP3 uses |
@@ -2027,7 +2001,7 @@ bad_config: | |||
2027 | musb->isr = generic_interrupt; | 2001 | musb->isr = generic_interrupt; |
2028 | status = musb_platform_init(musb); | 2002 | status = musb_platform_init(musb); |
2029 | if (status < 0) | 2003 | if (status < 0) |
2030 | goto fail2; | 2004 | goto fail1; |
2031 | 2005 | ||
2032 | if (!musb->isr) { | 2006 | if (!musb->isr) { |
2033 | status = -ENODEV; | 2007 | status = -ENODEV; |
@@ -2177,10 +2151,6 @@ fail3: | |||
2177 | device_init_wakeup(dev, 0); | 2151 | device_init_wakeup(dev, 0); |
2178 | musb_platform_exit(musb); | 2152 | musb_platform_exit(musb); |
2179 | 2153 | ||
2180 | fail2: | ||
2181 | if (musb->clock) | ||
2182 | clk_put(musb->clock); | ||
2183 | |||
2184 | fail1: | 2154 | fail1: |
2185 | dev_err(musb->controller, | 2155 | dev_err(musb->controller, |
2186 | "musb_init_controller failed with status %d\n", status); | 2156 | "musb_init_controller failed with status %d\n", status); |
@@ -2263,144 +2233,138 @@ static int __exit musb_remove(struct platform_device *pdev) | |||
2263 | 2233 | ||
2264 | #ifdef CONFIG_PM | 2234 | #ifdef CONFIG_PM |
2265 | 2235 | ||
2266 | static struct musb_context_registers musb_context; | 2236 | static void musb_save_context(struct musb *musb) |
2267 | |||
2268 | void musb_save_context(struct musb *musb) | ||
2269 | { | 2237 | { |
2270 | int i; | 2238 | int i; |
2271 | void __iomem *musb_base = musb->mregs; | 2239 | void __iomem *musb_base = musb->mregs; |
2272 | void __iomem *epio; | 2240 | void __iomem *epio; |
2273 | 2241 | ||
2274 | if (is_host_enabled(musb)) { | 2242 | if (is_host_enabled(musb)) { |
2275 | musb_context.frame = musb_readw(musb_base, MUSB_FRAME); | 2243 | musb->context.frame = musb_readw(musb_base, MUSB_FRAME); |
2276 | musb_context.testmode = musb_readb(musb_base, MUSB_TESTMODE); | 2244 | musb->context.testmode = musb_readb(musb_base, MUSB_TESTMODE); |
2277 | musb_context.busctl = musb_read_ulpi_buscontrol(musb->mregs); | 2245 | musb->context.busctl = musb_read_ulpi_buscontrol(musb->mregs); |
2278 | } | 2246 | } |
2279 | musb_context.power = musb_readb(musb_base, MUSB_POWER); | 2247 | musb->context.power = musb_readb(musb_base, MUSB_POWER); |
2280 | musb_context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE); | 2248 | musb->context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE); |
2281 | musb_context.intrrxe = musb_readw(musb_base, MUSB_INTRRXE); | 2249 | musb->context.intrrxe = musb_readw(musb_base, MUSB_INTRRXE); |
2282 | musb_context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE); | 2250 | musb->context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE); |
2283 | musb_context.index = musb_readb(musb_base, MUSB_INDEX); | 2251 | musb->context.index = musb_readb(musb_base, MUSB_INDEX); |
2284 | musb_context.devctl = musb_readb(musb_base, MUSB_DEVCTL); | 2252 | musb->context.devctl = musb_readb(musb_base, MUSB_DEVCTL); |
2285 | 2253 | ||
2286 | for (i = 0; i < musb->config->num_eps; ++i) { | 2254 | for (i = 0; i < musb->config->num_eps; ++i) { |
2287 | epio = musb->endpoints[i].regs; | 2255 | epio = musb->endpoints[i].regs; |
2288 | musb_context.index_regs[i].txmaxp = | 2256 | musb->context.index_regs[i].txmaxp = |
2289 | musb_readw(epio, MUSB_TXMAXP); | 2257 | musb_readw(epio, MUSB_TXMAXP); |
2290 | musb_context.index_regs[i].txcsr = | 2258 | musb->context.index_regs[i].txcsr = |
2291 | musb_readw(epio, MUSB_TXCSR); | 2259 | musb_readw(epio, MUSB_TXCSR); |
2292 | musb_context.index_regs[i].rxmaxp = | 2260 | musb->context.index_regs[i].rxmaxp = |
2293 | musb_readw(epio, MUSB_RXMAXP); | 2261 | musb_readw(epio, MUSB_RXMAXP); |
2294 | musb_context.index_regs[i].rxcsr = | 2262 | musb->context.index_regs[i].rxcsr = |
2295 | musb_readw(epio, MUSB_RXCSR); | 2263 | musb_readw(epio, MUSB_RXCSR); |
2296 | 2264 | ||
2297 | if (musb->dyn_fifo) { | 2265 | if (musb->dyn_fifo) { |
2298 | musb_context.index_regs[i].txfifoadd = | 2266 | musb->context.index_regs[i].txfifoadd = |
2299 | musb_read_txfifoadd(musb_base); | 2267 | musb_read_txfifoadd(musb_base); |
2300 | musb_context.index_regs[i].rxfifoadd = | 2268 | musb->context.index_regs[i].rxfifoadd = |
2301 | musb_read_rxfifoadd(musb_base); | 2269 | musb_read_rxfifoadd(musb_base); |
2302 | musb_context.index_regs[i].txfifosz = | 2270 | musb->context.index_regs[i].txfifosz = |
2303 | musb_read_txfifosz(musb_base); | 2271 | musb_read_txfifosz(musb_base); |
2304 | musb_context.index_regs[i].rxfifosz = | 2272 | musb->context.index_regs[i].rxfifosz = |
2305 | musb_read_rxfifosz(musb_base); | 2273 | musb_read_rxfifosz(musb_base); |
2306 | } | 2274 | } |
2307 | if (is_host_enabled(musb)) { | 2275 | if (is_host_enabled(musb)) { |
2308 | musb_context.index_regs[i].txtype = | 2276 | musb->context.index_regs[i].txtype = |
2309 | musb_readb(epio, MUSB_TXTYPE); | 2277 | musb_readb(epio, MUSB_TXTYPE); |
2310 | musb_context.index_regs[i].txinterval = | 2278 | musb->context.index_regs[i].txinterval = |
2311 | musb_readb(epio, MUSB_TXINTERVAL); | 2279 | musb_readb(epio, MUSB_TXINTERVAL); |
2312 | musb_context.index_regs[i].rxtype = | 2280 | musb->context.index_regs[i].rxtype = |
2313 | musb_readb(epio, MUSB_RXTYPE); | 2281 | musb_readb(epio, MUSB_RXTYPE); |
2314 | musb_context.index_regs[i].rxinterval = | 2282 | musb->context.index_regs[i].rxinterval = |
2315 | musb_readb(epio, MUSB_RXINTERVAL); | 2283 | musb_readb(epio, MUSB_RXINTERVAL); |
2316 | 2284 | ||
2317 | musb_context.index_regs[i].txfunaddr = | 2285 | musb->context.index_regs[i].txfunaddr = |
2318 | musb_read_txfunaddr(musb_base, i); | 2286 | musb_read_txfunaddr(musb_base, i); |
2319 | musb_context.index_regs[i].txhubaddr = | 2287 | musb->context.index_regs[i].txhubaddr = |
2320 | musb_read_txhubaddr(musb_base, i); | 2288 | musb_read_txhubaddr(musb_base, i); |
2321 | musb_context.index_regs[i].txhubport = | 2289 | musb->context.index_regs[i].txhubport = |
2322 | musb_read_txhubport(musb_base, i); | 2290 | musb_read_txhubport(musb_base, i); |
2323 | 2291 | ||
2324 | musb_context.index_regs[i].rxfunaddr = | 2292 | musb->context.index_regs[i].rxfunaddr = |
2325 | musb_read_rxfunaddr(musb_base, i); | 2293 | musb_read_rxfunaddr(musb_base, i); |
2326 | musb_context.index_regs[i].rxhubaddr = | 2294 | musb->context.index_regs[i].rxhubaddr = |
2327 | musb_read_rxhubaddr(musb_base, i); | 2295 | musb_read_rxhubaddr(musb_base, i); |
2328 | musb_context.index_regs[i].rxhubport = | 2296 | musb->context.index_regs[i].rxhubport = |
2329 | musb_read_rxhubport(musb_base, i); | 2297 | musb_read_rxhubport(musb_base, i); |
2330 | } | 2298 | } |
2331 | } | 2299 | } |
2332 | |||
2333 | musb_platform_save_context(musb, &musb_context); | ||
2334 | } | 2300 | } |
2335 | 2301 | ||
2336 | void musb_restore_context(struct musb *musb) | 2302 | static void musb_restore_context(struct musb *musb) |
2337 | { | 2303 | { |
2338 | int i; | 2304 | int i; |
2339 | void __iomem *musb_base = musb->mregs; | 2305 | void __iomem *musb_base = musb->mregs; |
2340 | void __iomem *ep_target_regs; | 2306 | void __iomem *ep_target_regs; |
2341 | void __iomem *epio; | 2307 | void __iomem *epio; |
2342 | 2308 | ||
2343 | musb_platform_restore_context(musb, &musb_context); | ||
2344 | |||
2345 | if (is_host_enabled(musb)) { | 2309 | if (is_host_enabled(musb)) { |
2346 | musb_writew(musb_base, MUSB_FRAME, musb_context.frame); | 2310 | musb_writew(musb_base, MUSB_FRAME, musb->context.frame); |
2347 | musb_writeb(musb_base, MUSB_TESTMODE, musb_context.testmode); | 2311 | musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode); |
2348 | musb_write_ulpi_buscontrol(musb->mregs, musb_context.busctl); | 2312 | musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl); |
2349 | } | 2313 | } |
2350 | musb_writeb(musb_base, MUSB_POWER, musb_context.power); | 2314 | musb_writeb(musb_base, MUSB_POWER, musb->context.power); |
2351 | musb_writew(musb_base, MUSB_INTRTXE, musb_context.intrtxe); | 2315 | musb_writew(musb_base, MUSB_INTRTXE, musb->context.intrtxe); |
2352 | musb_writew(musb_base, MUSB_INTRRXE, musb_context.intrrxe); | 2316 | musb_writew(musb_base, MUSB_INTRRXE, musb->context.intrrxe); |
2353 | musb_writeb(musb_base, MUSB_INTRUSBE, musb_context.intrusbe); | 2317 | musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe); |
2354 | musb_writeb(musb_base, MUSB_DEVCTL, musb_context.devctl); | 2318 | musb_writeb(musb_base, MUSB_DEVCTL, musb->context.devctl); |
2355 | 2319 | ||
2356 | for (i = 0; i < musb->config->num_eps; ++i) { | 2320 | for (i = 0; i < musb->config->num_eps; ++i) { |
2357 | epio = musb->endpoints[i].regs; | 2321 | epio = musb->endpoints[i].regs; |
2358 | musb_writew(epio, MUSB_TXMAXP, | 2322 | musb_writew(epio, MUSB_TXMAXP, |
2359 | musb_context.index_regs[i].txmaxp); | 2323 | musb->context.index_regs[i].txmaxp); |
2360 | musb_writew(epio, MUSB_TXCSR, | 2324 | musb_writew(epio, MUSB_TXCSR, |
2361 | musb_context.index_regs[i].txcsr); | 2325 | musb->context.index_regs[i].txcsr); |
2362 | musb_writew(epio, MUSB_RXMAXP, | 2326 | musb_writew(epio, MUSB_RXMAXP, |
2363 | musb_context.index_regs[i].rxmaxp); | 2327 | musb->context.index_regs[i].rxmaxp); |
2364 | musb_writew(epio, MUSB_RXCSR, | 2328 | musb_writew(epio, MUSB_RXCSR, |
2365 | musb_context.index_regs[i].rxcsr); | 2329 | musb->context.index_regs[i].rxcsr); |
2366 | 2330 | ||
2367 | if (musb->dyn_fifo) { | 2331 | if (musb->dyn_fifo) { |
2368 | musb_write_txfifosz(musb_base, | 2332 | musb_write_txfifosz(musb_base, |
2369 | musb_context.index_regs[i].txfifosz); | 2333 | musb->context.index_regs[i].txfifosz); |
2370 | musb_write_rxfifosz(musb_base, | 2334 | musb_write_rxfifosz(musb_base, |
2371 | musb_context.index_regs[i].rxfifosz); | 2335 | musb->context.index_regs[i].rxfifosz); |
2372 | musb_write_txfifoadd(musb_base, | 2336 | musb_write_txfifoadd(musb_base, |
2373 | musb_context.index_regs[i].txfifoadd); | 2337 | musb->context.index_regs[i].txfifoadd); |
2374 | musb_write_rxfifoadd(musb_base, | 2338 | musb_write_rxfifoadd(musb_base, |
2375 | musb_context.index_regs[i].rxfifoadd); | 2339 | musb->context.index_regs[i].rxfifoadd); |
2376 | } | 2340 | } |
2377 | 2341 | ||
2378 | if (is_host_enabled(musb)) { | 2342 | if (is_host_enabled(musb)) { |
2379 | musb_writeb(epio, MUSB_TXTYPE, | 2343 | musb_writeb(epio, MUSB_TXTYPE, |
2380 | musb_context.index_regs[i].txtype); | 2344 | musb->context.index_regs[i].txtype); |
2381 | musb_writeb(epio, MUSB_TXINTERVAL, | 2345 | musb_writeb(epio, MUSB_TXINTERVAL, |
2382 | musb_context.index_regs[i].txinterval); | 2346 | musb->context.index_regs[i].txinterval); |
2383 | musb_writeb(epio, MUSB_RXTYPE, | 2347 | musb_writeb(epio, MUSB_RXTYPE, |
2384 | musb_context.index_regs[i].rxtype); | 2348 | musb->context.index_regs[i].rxtype); |
2385 | musb_writeb(epio, MUSB_RXINTERVAL, | 2349 | musb_writeb(epio, MUSB_RXINTERVAL, |
2386 | 2350 | ||
2387 | musb_context.index_regs[i].rxinterval); | 2351 | musb->context.index_regs[i].rxinterval); |
2388 | musb_write_txfunaddr(musb_base, i, | 2352 | musb_write_txfunaddr(musb_base, i, |
2389 | musb_context.index_regs[i].txfunaddr); | 2353 | musb->context.index_regs[i].txfunaddr); |
2390 | musb_write_txhubaddr(musb_base, i, | 2354 | musb_write_txhubaddr(musb_base, i, |
2391 | musb_context.index_regs[i].txhubaddr); | 2355 | musb->context.index_regs[i].txhubaddr); |
2392 | musb_write_txhubport(musb_base, i, | 2356 | musb_write_txhubport(musb_base, i, |
2393 | musb_context.index_regs[i].txhubport); | 2357 | musb->context.index_regs[i].txhubport); |
2394 | 2358 | ||
2395 | ep_target_regs = | 2359 | ep_target_regs = |
2396 | musb_read_target_reg_base(i, musb_base); | 2360 | musb_read_target_reg_base(i, musb_base); |
2397 | 2361 | ||
2398 | musb_write_rxfunaddr(ep_target_regs, | 2362 | musb_write_rxfunaddr(ep_target_regs, |
2399 | musb_context.index_regs[i].rxfunaddr); | 2363 | musb->context.index_regs[i].rxfunaddr); |
2400 | musb_write_rxhubaddr(ep_target_regs, | 2364 | musb_write_rxhubaddr(ep_target_regs, |
2401 | musb_context.index_regs[i].rxhubaddr); | 2365 | musb->context.index_regs[i].rxhubaddr); |
2402 | musb_write_rxhubport(ep_target_regs, | 2366 | musb_write_rxhubport(ep_target_regs, |
2403 | musb_context.index_regs[i].rxhubport); | 2367 | musb->context.index_regs[i].rxhubport); |
2404 | } | 2368 | } |
2405 | } | 2369 | } |
2406 | } | 2370 | } |
@@ -2411,9 +2375,6 @@ static int musb_suspend(struct device *dev) | |||
2411 | unsigned long flags; | 2375 | unsigned long flags; |
2412 | struct musb *musb = dev_to_musb(&pdev->dev); | 2376 | struct musb *musb = dev_to_musb(&pdev->dev); |
2413 | 2377 | ||
2414 | if (!musb->clock) | ||
2415 | return 0; | ||
2416 | |||
2417 | spin_lock_irqsave(&musb->lock, flags); | 2378 | spin_lock_irqsave(&musb->lock, flags); |
2418 | 2379 | ||
2419 | if (is_peripheral_active(musb)) { | 2380 | if (is_peripheral_active(musb)) { |
@@ -2428,10 +2389,6 @@ static int musb_suspend(struct device *dev) | |||
2428 | 2389 | ||
2429 | musb_save_context(musb); | 2390 | musb_save_context(musb); |
2430 | 2391 | ||
2431 | if (musb->set_clock) | ||
2432 | musb->set_clock(musb->clock, 0); | ||
2433 | else | ||
2434 | clk_disable(musb->clock); | ||
2435 | spin_unlock_irqrestore(&musb->lock, flags); | 2392 | spin_unlock_irqrestore(&musb->lock, flags); |
2436 | return 0; | 2393 | return 0; |
2437 | } | 2394 | } |
@@ -2441,14 +2398,6 @@ static int musb_resume_noirq(struct device *dev) | |||
2441 | struct platform_device *pdev = to_platform_device(dev); | 2398 | struct platform_device *pdev = to_platform_device(dev); |
2442 | struct musb *musb = dev_to_musb(&pdev->dev); | 2399 | struct musb *musb = dev_to_musb(&pdev->dev); |
2443 | 2400 | ||
2444 | if (!musb->clock) | ||
2445 | return 0; | ||
2446 | |||
2447 | if (musb->set_clock) | ||
2448 | musb->set_clock(musb->clock, 1); | ||
2449 | else | ||
2450 | clk_enable(musb->clock); | ||
2451 | |||
2452 | musb_restore_context(musb); | 2401 | musb_restore_context(musb); |
2453 | 2402 | ||
2454 | /* for static cmos like DaVinci, register values were preserved | 2403 | /* for static cmos like DaVinci, register values were preserved |
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 6ad72f395e28..d0c236f8e191 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h | |||
@@ -222,7 +222,7 @@ enum musb_g_ep0_state { | |||
222 | #endif | 222 | #endif |
223 | 223 | ||
224 | /* TUSB mapping: "flat" plus ep0 special cases */ | 224 | /* TUSB mapping: "flat" plus ep0 special cases */ |
225 | #if defined(CONFIG_USB_TUSB6010) | 225 | #if defined(CONFIG_USB_MUSB_TUSB6010) |
226 | #define musb_ep_select(_mbase, _epnum) \ | 226 | #define musb_ep_select(_mbase, _epnum) \ |
227 | musb_writeb((_mbase), MUSB_INDEX, (_epnum)) | 227 | musb_writeb((_mbase), MUSB_INDEX, (_epnum)) |
228 | #define MUSB_EP_OFFSET MUSB_TUSB_OFFSET | 228 | #define MUSB_EP_OFFSET MUSB_TUSB_OFFSET |
@@ -253,6 +253,29 @@ enum musb_g_ep0_state { | |||
253 | 253 | ||
254 | /******************************** TYPES *************************************/ | 254 | /******************************** TYPES *************************************/ |
255 | 255 | ||
256 | /** | ||
257 | * struct musb_platform_ops - Operations passed to musb_core by HW glue layer | ||
258 | * @init: turns on clocks, sets up platform-specific registers, etc | ||
259 | * @exit: undoes @init | ||
260 | * @set_mode: forcefully changes operating mode | ||
261 | * @try_ilde: tries to idle the IP | ||
262 | * @vbus_status: returns vbus status if possible | ||
263 | * @set_vbus: forces vbus status | ||
264 | */ | ||
265 | struct musb_platform_ops { | ||
266 | int (*init)(struct musb *musb); | ||
267 | int (*exit)(struct musb *musb); | ||
268 | |||
269 | void (*enable)(struct musb *musb); | ||
270 | void (*disable)(struct musb *musb); | ||
271 | |||
272 | int (*set_mode)(struct musb *musb, u8 mode); | ||
273 | void (*try_idle)(struct musb *musb, unsigned long timeout); | ||
274 | |||
275 | int (*vbus_status)(struct musb *musb); | ||
276 | void (*set_vbus)(struct musb *musb, int on); | ||
277 | }; | ||
278 | |||
256 | /* | 279 | /* |
257 | * struct musb_hw_ep - endpoint hardware (bidirectional) | 280 | * struct musb_hw_ep - endpoint hardware (bidirectional) |
258 | * | 281 | * |
@@ -263,7 +286,7 @@ struct musb_hw_ep { | |||
263 | void __iomem *fifo; | 286 | void __iomem *fifo; |
264 | void __iomem *regs; | 287 | void __iomem *regs; |
265 | 288 | ||
266 | #ifdef CONFIG_USB_TUSB6010 | 289 | #ifdef CONFIG_USB_MUSB_TUSB6010 |
267 | void __iomem *conf; | 290 | void __iomem *conf; |
268 | #endif | 291 | #endif |
269 | 292 | ||
@@ -280,7 +303,7 @@ struct musb_hw_ep { | |||
280 | struct dma_channel *tx_channel; | 303 | struct dma_channel *tx_channel; |
281 | struct dma_channel *rx_channel; | 304 | struct dma_channel *rx_channel; |
282 | 305 | ||
283 | #ifdef CONFIG_USB_TUSB6010 | 306 | #ifdef CONFIG_USB_MUSB_TUSB6010 |
284 | /* TUSB has "asynchronous" and "synchronous" dma modes */ | 307 | /* TUSB has "asynchronous" and "synchronous" dma modes */ |
285 | dma_addr_t fifo_async; | 308 | dma_addr_t fifo_async; |
286 | dma_addr_t fifo_sync; | 309 | dma_addr_t fifo_sync; |
@@ -323,14 +346,43 @@ static inline struct usb_request *next_out_request(struct musb_hw_ep *hw_ep) | |||
323 | #endif | 346 | #endif |
324 | } | 347 | } |
325 | 348 | ||
349 | struct musb_csr_regs { | ||
350 | /* FIFO registers */ | ||
351 | u16 txmaxp, txcsr, rxmaxp, rxcsr; | ||
352 | u16 rxfifoadd, txfifoadd; | ||
353 | u8 txtype, txinterval, rxtype, rxinterval; | ||
354 | u8 rxfifosz, txfifosz; | ||
355 | u8 txfunaddr, txhubaddr, txhubport; | ||
356 | u8 rxfunaddr, rxhubaddr, rxhubport; | ||
357 | }; | ||
358 | |||
359 | struct musb_context_registers { | ||
360 | |||
361 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \ | ||
362 | defined(CONFIG_ARCH_OMAP4) | ||
363 | u32 otg_sysconfig, otg_forcestandby; | ||
364 | #endif | ||
365 | u8 power; | ||
366 | u16 intrtxe, intrrxe; | ||
367 | u8 intrusbe; | ||
368 | u16 frame; | ||
369 | u8 index, testmode; | ||
370 | |||
371 | u8 devctl, busctl, misc; | ||
372 | |||
373 | struct musb_csr_regs index_regs[MUSB_C_NUM_EPS]; | ||
374 | }; | ||
375 | |||
326 | /* | 376 | /* |
327 | * struct musb - Driver instance data. | 377 | * struct musb - Driver instance data. |
328 | */ | 378 | */ |
329 | struct musb { | 379 | struct musb { |
330 | /* device lock */ | 380 | /* device lock */ |
331 | spinlock_t lock; | 381 | spinlock_t lock; |
332 | struct clk *clock; | 382 | |
333 | struct clk *phy_clock; | 383 | const struct musb_platform_ops *ops; |
384 | struct musb_context_registers context; | ||
385 | |||
334 | irqreturn_t (*isr)(int, void *); | 386 | irqreturn_t (*isr)(int, void *); |
335 | struct work_struct irq_work; | 387 | struct work_struct irq_work; |
336 | u16 hwvers; | 388 | u16 hwvers; |
@@ -359,11 +411,7 @@ struct musb { | |||
359 | 411 | ||
360 | struct timer_list otg_timer; | 412 | struct timer_list otg_timer; |
361 | #endif | 413 | #endif |
362 | 414 | struct notifier_block nb; | |
363 | /* called with IRQs blocked; ON/nonzero implies starting a session, | ||
364 | * and waiting at least a_wait_vrise_tmout. | ||
365 | */ | ||
366 | void (*board_set_vbus)(struct musb *, int is_on); | ||
367 | 415 | ||
368 | struct dma_controller *dma_controller; | 416 | struct dma_controller *dma_controller; |
369 | 417 | ||
@@ -371,7 +419,7 @@ struct musb { | |||
371 | void __iomem *ctrl_base; | 419 | void __iomem *ctrl_base; |
372 | void __iomem *mregs; | 420 | void __iomem *mregs; |
373 | 421 | ||
374 | #ifdef CONFIG_USB_TUSB6010 | 422 | #ifdef CONFIG_USB_MUSB_TUSB6010 |
375 | dma_addr_t async; | 423 | dma_addr_t async; |
376 | dma_addr_t sync; | 424 | dma_addr_t sync; |
377 | void __iomem *sync_va; | 425 | void __iomem *sync_va; |
@@ -398,8 +446,6 @@ struct musb { | |||
398 | u8 board_mode; /* enum musb_mode */ | 446 | u8 board_mode; /* enum musb_mode */ |
399 | int (*board_set_power)(int state); | 447 | int (*board_set_power)(int state); |
400 | 448 | ||
401 | int (*set_clock)(struct clk *clk, int is_active); | ||
402 | |||
403 | u8 min_power; /* vbus for periph, in mA/2 */ | 449 | u8 min_power; /* vbus for periph, in mA/2 */ |
404 | 450 | ||
405 | bool is_host; | 451 | bool is_host; |
@@ -458,52 +504,6 @@ struct musb { | |||
458 | #endif | 504 | #endif |
459 | }; | 505 | }; |
460 | 506 | ||
461 | #ifdef CONFIG_PM | ||
462 | struct musb_csr_regs { | ||
463 | /* FIFO registers */ | ||
464 | u16 txmaxp, txcsr, rxmaxp, rxcsr; | ||
465 | u16 rxfifoadd, txfifoadd; | ||
466 | u8 txtype, txinterval, rxtype, rxinterval; | ||
467 | u8 rxfifosz, txfifosz; | ||
468 | u8 txfunaddr, txhubaddr, txhubport; | ||
469 | u8 rxfunaddr, rxhubaddr, rxhubport; | ||
470 | }; | ||
471 | |||
472 | struct musb_context_registers { | ||
473 | |||
474 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \ | ||
475 | defined(CONFIG_ARCH_OMAP4) | ||
476 | u32 otg_sysconfig, otg_forcestandby; | ||
477 | #endif | ||
478 | u8 power; | ||
479 | u16 intrtxe, intrrxe; | ||
480 | u8 intrusbe; | ||
481 | u16 frame; | ||
482 | u8 index, testmode; | ||
483 | |||
484 | u8 devctl, busctl, misc; | ||
485 | |||
486 | struct musb_csr_regs index_regs[MUSB_C_NUM_EPS]; | ||
487 | }; | ||
488 | |||
489 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \ | ||
490 | defined(CONFIG_ARCH_OMAP4) | ||
491 | extern void musb_platform_save_context(struct musb *musb, | ||
492 | struct musb_context_registers *musb_context); | ||
493 | extern void musb_platform_restore_context(struct musb *musb, | ||
494 | struct musb_context_registers *musb_context); | ||
495 | #else | ||
496 | #define musb_platform_save_context(m, x) do {} while (0) | ||
497 | #define musb_platform_restore_context(m, x) do {} while (0) | ||
498 | #endif | ||
499 | |||
500 | #endif | ||
501 | |||
502 | static inline void musb_set_vbus(struct musb *musb, int is_on) | ||
503 | { | ||
504 | musb->board_set_vbus(musb, is_on); | ||
505 | } | ||
506 | |||
507 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC | 507 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC |
508 | static inline struct musb *gadget_to_musb(struct usb_gadget *g) | 508 | static inline struct musb *gadget_to_musb(struct usb_gadget *g) |
509 | { | 509 | { |
@@ -592,29 +592,63 @@ extern void musb_load_testpacket(struct musb *); | |||
592 | 592 | ||
593 | extern irqreturn_t musb_interrupt(struct musb *); | 593 | extern irqreturn_t musb_interrupt(struct musb *); |
594 | 594 | ||
595 | extern void musb_platform_enable(struct musb *musb); | ||
596 | extern void musb_platform_disable(struct musb *musb); | ||
597 | |||
598 | extern void musb_hnp_stop(struct musb *musb); | 595 | extern void musb_hnp_stop(struct musb *musb); |
599 | 596 | ||
600 | extern int musb_platform_set_mode(struct musb *musb, u8 musb_mode); | 597 | static inline void musb_platform_set_vbus(struct musb *musb, int is_on) |
598 | { | ||
599 | if (musb->ops->set_vbus) | ||
600 | musb->ops->set_vbus(musb, is_on); | ||
601 | } | ||
601 | 602 | ||
602 | #if defined(CONFIG_USB_TUSB6010) || defined(CONFIG_BLACKFIN) || \ | 603 | static inline void musb_platform_enable(struct musb *musb) |
603 | defined(CONFIG_ARCH_DAVINCI_DA8XX) || \ | 604 | { |
604 | defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \ | 605 | if (musb->ops->enable) |
605 | defined(CONFIG_ARCH_OMAP4) | 606 | musb->ops->enable(musb); |
606 | extern void musb_platform_try_idle(struct musb *musb, unsigned long timeout); | 607 | } |
607 | #else | ||
608 | #define musb_platform_try_idle(x, y) do {} while (0) | ||
609 | #endif | ||
610 | 608 | ||
611 | #if defined(CONFIG_USB_TUSB6010) || defined(CONFIG_BLACKFIN) | 609 | static inline void musb_platform_disable(struct musb *musb) |
612 | extern int musb_platform_get_vbus_status(struct musb *musb); | 610 | { |
613 | #else | 611 | if (musb->ops->disable) |
614 | #define musb_platform_get_vbus_status(x) 0 | 612 | musb->ops->disable(musb); |
615 | #endif | 613 | } |
614 | |||
615 | static inline int musb_platform_set_mode(struct musb *musb, u8 mode) | ||
616 | { | ||
617 | if (!musb->ops->set_mode) | ||
618 | return 0; | ||
619 | |||
620 | return musb->ops->set_mode(musb, mode); | ||
621 | } | ||
622 | |||
623 | static inline void musb_platform_try_idle(struct musb *musb, | ||
624 | unsigned long timeout) | ||
625 | { | ||
626 | if (musb->ops->try_idle) | ||
627 | musb->ops->try_idle(musb, timeout); | ||
628 | } | ||
629 | |||
630 | static inline int musb_platform_get_vbus_status(struct musb *musb) | ||
631 | { | ||
632 | if (!musb->ops->vbus_status) | ||
633 | return 0; | ||
616 | 634 | ||
617 | extern int __init musb_platform_init(struct musb *musb); | 635 | return musb->ops->vbus_status(musb); |
618 | extern int musb_platform_exit(struct musb *musb); | 636 | } |
637 | |||
638 | static inline int musb_platform_init(struct musb *musb) | ||
639 | { | ||
640 | if (!musb->ops->init) | ||
641 | return -EINVAL; | ||
642 | |||
643 | return musb->ops->init(musb); | ||
644 | } | ||
645 | |||
646 | static inline int musb_platform_exit(struct musb *musb) | ||
647 | { | ||
648 | if (!musb->ops->exit) | ||
649 | return -EINVAL; | ||
650 | |||
651 | return musb->ops->exit(musb); | ||
652 | } | ||
619 | 653 | ||
620 | #endif /* __MUSB_CORE_H__ */ | 654 | #endif /* __MUSB_CORE_H__ */ |
diff --git a/drivers/usb/musb/musb_io.h b/drivers/usb/musb/musb_io.h index b06e9ef00cfc..03c6ccdbb3be 100644 --- a/drivers/usb/musb/musb_io.h +++ b/drivers/usb/musb/musb_io.h | |||
@@ -74,7 +74,7 @@ static inline void musb_writel(void __iomem *addr, unsigned offset, u32 data) | |||
74 | { __raw_writel(data, addr + offset); } | 74 | { __raw_writel(data, addr + offset); } |
75 | 75 | ||
76 | 76 | ||
77 | #ifdef CONFIG_USB_TUSB6010 | 77 | #ifdef CONFIG_USB_MUSB_TUSB6010 |
78 | 78 | ||
79 | /* | 79 | /* |
80 | * TUSB6010 doesn't allow 8-bit access; 16-bit access is the minimum. | 80 | * TUSB6010 doesn't allow 8-bit access; 16-bit access is the minimum. |
@@ -114,7 +114,7 @@ static inline u8 musb_readb(const void __iomem *addr, unsigned offset) | |||
114 | static inline void musb_writeb(void __iomem *addr, unsigned offset, u8 data) | 114 | static inline void musb_writeb(void __iomem *addr, unsigned offset, u8 data) |
115 | { __raw_writeb(data, addr + offset); } | 115 | { __raw_writeb(data, addr + offset); } |
116 | 116 | ||
117 | #endif /* CONFIG_USB_TUSB6010 */ | 117 | #endif /* CONFIG_USB_MUSB_TUSB6010 */ |
118 | 118 | ||
119 | #else | 119 | #else |
120 | 120 | ||
diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h index 244267527a60..9cb5fe044438 100644 --- a/drivers/usb/musb/musb_regs.h +++ b/drivers/usb/musb/musb_regs.h | |||
@@ -234,7 +234,7 @@ | |||
234 | #define MUSB_TESTMODE 0x0F /* 8 bit */ | 234 | #define MUSB_TESTMODE 0x0F /* 8 bit */ |
235 | 235 | ||
236 | /* Get offset for a given FIFO from musb->mregs */ | 236 | /* Get offset for a given FIFO from musb->mregs */ |
237 | #ifdef CONFIG_USB_TUSB6010 | 237 | #ifdef CONFIG_USB_MUSB_TUSB6010 |
238 | #define MUSB_FIFO_OFFSET(epnum) (0x200 + ((epnum) * 0x20)) | 238 | #define MUSB_FIFO_OFFSET(epnum) (0x200 + ((epnum) * 0x20)) |
239 | #else | 239 | #else |
240 | #define MUSB_FIFO_OFFSET(epnum) (0x20 + ((epnum) * 4)) | 240 | #define MUSB_FIFO_OFFSET(epnum) (0x20 + ((epnum) * 4)) |
@@ -295,7 +295,7 @@ | |||
295 | #define MUSB_FLAT_OFFSET(_epnum, _offset) \ | 295 | #define MUSB_FLAT_OFFSET(_epnum, _offset) \ |
296 | (0x100 + (0x10*(_epnum)) + (_offset)) | 296 | (0x100 + (0x10*(_epnum)) + (_offset)) |
297 | 297 | ||
298 | #ifdef CONFIG_USB_TUSB6010 | 298 | #ifdef CONFIG_USB_MUSB_TUSB6010 |
299 | /* TUSB6010 EP0 configuration register is special */ | 299 | /* TUSB6010 EP0 configuration register is special */ |
300 | #define MUSB_TUSB_OFFSET(_epnum, _offset) \ | 300 | #define MUSB_TUSB_OFFSET(_epnum, _offset) \ |
301 | (0x10 + _offset) | 301 | (0x10 + _offset) |
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index 43233c397b6e..b46d1877e28e 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c | |||
@@ -276,7 +276,7 @@ int musb_hub_control( | |||
276 | break; | 276 | break; |
277 | case USB_PORT_FEAT_POWER: | 277 | case USB_PORT_FEAT_POWER: |
278 | if (!(is_otg_enabled(musb) && hcd->self.is_b_host)) | 278 | if (!(is_otg_enabled(musb) && hcd->self.is_b_host)) |
279 | musb_set_vbus(musb, 0); | 279 | musb_platform_set_vbus(musb, 0); |
280 | break; | 280 | break; |
281 | case USB_PORT_FEAT_C_CONNECTION: | 281 | case USB_PORT_FEAT_C_CONNECTION: |
282 | case USB_PORT_FEAT_C_ENABLE: | 282 | case USB_PORT_FEAT_C_ENABLE: |
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 27dabcf0a868..a3f12333fc41 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c | |||
@@ -31,10 +31,18 @@ | |||
31 | #include <linux/list.h> | 31 | #include <linux/list.h> |
32 | #include <linux/clk.h> | 32 | #include <linux/clk.h> |
33 | #include <linux/io.h> | 33 | #include <linux/io.h> |
34 | #include <linux/platform_device.h> | ||
35 | #include <linux/dma-mapping.h> | ||
34 | 36 | ||
35 | #include "musb_core.h" | 37 | #include "musb_core.h" |
36 | #include "omap2430.h" | 38 | #include "omap2430.h" |
37 | 39 | ||
40 | struct omap2430_glue { | ||
41 | struct device *dev; | ||
42 | struct platform_device *musb; | ||
43 | struct clk *clk; | ||
44 | }; | ||
45 | #define glue_to_musb(g) platform_get_drvdata(g->musb) | ||
38 | 46 | ||
39 | static struct timer_list musb_idle_timer; | 47 | static struct timer_list musb_idle_timer; |
40 | 48 | ||
@@ -49,12 +57,8 @@ static void musb_do_idle(unsigned long _musb) | |||
49 | 57 | ||
50 | spin_lock_irqsave(&musb->lock, flags); | 58 | spin_lock_irqsave(&musb->lock, flags); |
51 | 59 | ||
52 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); | ||
53 | |||
54 | switch (musb->xceiv->state) { | 60 | switch (musb->xceiv->state) { |
55 | case OTG_STATE_A_WAIT_BCON: | 61 | case OTG_STATE_A_WAIT_BCON: |
56 | devctl &= ~MUSB_DEVCTL_SESSION; | ||
57 | musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); | ||
58 | 62 | ||
59 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); | 63 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); |
60 | if (devctl & MUSB_DEVCTL_BDEVICE) { | 64 | if (devctl & MUSB_DEVCTL_BDEVICE) { |
@@ -98,7 +102,7 @@ static void musb_do_idle(unsigned long _musb) | |||
98 | } | 102 | } |
99 | 103 | ||
100 | 104 | ||
101 | void musb_platform_try_idle(struct musb *musb, unsigned long timeout) | 105 | static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout) |
102 | { | 106 | { |
103 | unsigned long default_timeout = jiffies + msecs_to_jiffies(3); | 107 | unsigned long default_timeout = jiffies + msecs_to_jiffies(3); |
104 | static unsigned long last_timer; | 108 | static unsigned long last_timer; |
@@ -131,15 +135,11 @@ void musb_platform_try_idle(struct musb *musb, unsigned long timeout) | |||
131 | mod_timer(&musb_idle_timer, timeout); | 135 | mod_timer(&musb_idle_timer, timeout); |
132 | } | 136 | } |
133 | 137 | ||
134 | void musb_platform_enable(struct musb *musb) | 138 | static void omap2430_musb_set_vbus(struct musb *musb, int is_on) |
135 | { | ||
136 | } | ||
137 | void musb_platform_disable(struct musb *musb) | ||
138 | { | ||
139 | } | ||
140 | static void omap_set_vbus(struct musb *musb, int is_on) | ||
141 | { | 139 | { |
142 | u8 devctl; | 140 | u8 devctl; |
141 | unsigned long timeout = jiffies + msecs_to_jiffies(1000); | ||
142 | int ret = 1; | ||
143 | /* HDRC controls CPEN, but beware current surges during device | 143 | /* HDRC controls CPEN, but beware current surges during device |
144 | * connect. They can trigger transient overcurrent conditions | 144 | * connect. They can trigger transient overcurrent conditions |
145 | * that must be ignored. | 145 | * that must be ignored. |
@@ -148,12 +148,35 @@ static void omap_set_vbus(struct musb *musb, int is_on) | |||
148 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); | 148 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); |
149 | 149 | ||
150 | if (is_on) { | 150 | if (is_on) { |
151 | musb->is_active = 1; | 151 | if (musb->xceiv->state == OTG_STATE_A_IDLE) { |
152 | musb->xceiv->default_a = 1; | 152 | /* start the session */ |
153 | musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; | 153 | devctl |= MUSB_DEVCTL_SESSION; |
154 | devctl |= MUSB_DEVCTL_SESSION; | 154 | musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); |
155 | 155 | /* | |
156 | MUSB_HST_MODE(musb); | 156 | * Wait for the musb to set as A device to enable the |
157 | * VBUS | ||
158 | */ | ||
159 | while (musb_readb(musb->mregs, MUSB_DEVCTL) & 0x80) { | ||
160 | |||
161 | cpu_relax(); | ||
162 | |||
163 | if (time_after(jiffies, timeout)) { | ||
164 | dev_err(musb->controller, | ||
165 | "configured as A device timeout"); | ||
166 | ret = -EINVAL; | ||
167 | break; | ||
168 | } | ||
169 | } | ||
170 | |||
171 | if (ret && musb->xceiv->set_vbus) | ||
172 | otg_set_vbus(musb->xceiv, 1); | ||
173 | } else { | ||
174 | musb->is_active = 1; | ||
175 | musb->xceiv->default_a = 1; | ||
176 | musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; | ||
177 | devctl |= MUSB_DEVCTL_SESSION; | ||
178 | MUSB_HST_MODE(musb); | ||
179 | } | ||
157 | } else { | 180 | } else { |
158 | musb->is_active = 0; | 181 | musb->is_active = 0; |
159 | 182 | ||
@@ -175,9 +198,7 @@ static void omap_set_vbus(struct musb *musb, int is_on) | |||
175 | musb_readb(musb->mregs, MUSB_DEVCTL)); | 198 | musb_readb(musb->mregs, MUSB_DEVCTL)); |
176 | } | 199 | } |
177 | 200 | ||
178 | static int musb_platform_resume(struct musb *musb); | 201 | static int omap2430_musb_set_mode(struct musb *musb, u8 musb_mode) |
179 | |||
180 | int musb_platform_set_mode(struct musb *musb, u8 musb_mode) | ||
181 | { | 202 | { |
182 | u8 devctl = musb_readb(musb->mregs, MUSB_DEVCTL); | 203 | u8 devctl = musb_readb(musb->mregs, MUSB_DEVCTL); |
183 | 204 | ||
@@ -187,9 +208,91 @@ int musb_platform_set_mode(struct musb *musb, u8 musb_mode) | |||
187 | return 0; | 208 | return 0; |
188 | } | 209 | } |
189 | 210 | ||
190 | int __init musb_platform_init(struct musb *musb) | 211 | static inline void omap2430_low_level_exit(struct musb *musb) |
212 | { | ||
213 | u32 l; | ||
214 | |||
215 | /* in any role */ | ||
216 | l = musb_readl(musb->mregs, OTG_FORCESTDBY); | ||
217 | l |= ENABLEFORCE; /* enable MSTANDBY */ | ||
218 | musb_writel(musb->mregs, OTG_FORCESTDBY, l); | ||
219 | |||
220 | l = musb_readl(musb->mregs, OTG_SYSCONFIG); | ||
221 | l |= ENABLEWAKEUP; /* enable wakeup */ | ||
222 | musb_writel(musb->mregs, OTG_SYSCONFIG, l); | ||
223 | } | ||
224 | |||
225 | static inline void omap2430_low_level_init(struct musb *musb) | ||
191 | { | 226 | { |
192 | u32 l; | 227 | u32 l; |
228 | |||
229 | l = musb_readl(musb->mregs, OTG_SYSCONFIG); | ||
230 | l &= ~ENABLEWAKEUP; /* disable wakeup */ | ||
231 | musb_writel(musb->mregs, OTG_SYSCONFIG, l); | ||
232 | |||
233 | l = musb_readl(musb->mregs, OTG_FORCESTDBY); | ||
234 | l &= ~ENABLEFORCE; /* disable MSTANDBY */ | ||
235 | musb_writel(musb->mregs, OTG_FORCESTDBY, l); | ||
236 | } | ||
237 | |||
238 | /* blocking notifier support */ | ||
239 | static int musb_otg_notifications(struct notifier_block *nb, | ||
240 | unsigned long event, void *unused) | ||
241 | { | ||
242 | struct musb *musb = container_of(nb, struct musb, nb); | ||
243 | struct device *dev = musb->controller; | ||
244 | struct musb_hdrc_platform_data *pdata = dev->platform_data; | ||
245 | struct omap_musb_board_data *data = pdata->board_data; | ||
246 | |||
247 | switch (event) { | ||
248 | case USB_EVENT_ID: | ||
249 | DBG(4, "ID GND\n"); | ||
250 | |||
251 | if (is_otg_enabled(musb)) { | ||
252 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC | ||
253 | if (musb->gadget_driver) { | ||
254 | otg_init(musb->xceiv); | ||
255 | |||
256 | if (data->interface_type == | ||
257 | MUSB_INTERFACE_UTMI) | ||
258 | omap2430_musb_set_vbus(musb, 1); | ||
259 | |||
260 | } | ||
261 | #endif | ||
262 | } else { | ||
263 | otg_init(musb->xceiv); | ||
264 | if (data->interface_type == | ||
265 | MUSB_INTERFACE_UTMI) | ||
266 | omap2430_musb_set_vbus(musb, 1); | ||
267 | } | ||
268 | break; | ||
269 | |||
270 | case USB_EVENT_VBUS: | ||
271 | DBG(4, "VBUS Connect\n"); | ||
272 | |||
273 | otg_init(musb->xceiv); | ||
274 | break; | ||
275 | |||
276 | case USB_EVENT_NONE: | ||
277 | DBG(4, "VBUS Disconnect\n"); | ||
278 | |||
279 | if (data->interface_type == MUSB_INTERFACE_UTMI) { | ||
280 | if (musb->xceiv->set_vbus) | ||
281 | otg_set_vbus(musb->xceiv, 0); | ||
282 | } | ||
283 | otg_shutdown(musb->xceiv); | ||
284 | break; | ||
285 | default: | ||
286 | DBG(4, "ID float\n"); | ||
287 | return NOTIFY_DONE; | ||
288 | } | ||
289 | |||
290 | return NOTIFY_OK; | ||
291 | } | ||
292 | |||
293 | static int omap2430_musb_init(struct musb *musb) | ||
294 | { | ||
295 | u32 l, status = 0; | ||
193 | struct device *dev = musb->controller; | 296 | struct device *dev = musb->controller; |
194 | struct musb_hdrc_platform_data *plat = dev->platform_data; | 297 | struct musb_hdrc_platform_data *plat = dev->platform_data; |
195 | struct omap_musb_board_data *data = plat->board_data; | 298 | struct omap_musb_board_data *data = plat->board_data; |
@@ -204,7 +307,7 @@ int __init musb_platform_init(struct musb *musb) | |||
204 | return -ENODEV; | 307 | return -ENODEV; |
205 | } | 308 | } |
206 | 309 | ||
207 | musb_platform_resume(musb); | 310 | omap2430_low_level_init(musb); |
208 | 311 | ||
209 | l = musb_readl(musb->mregs, OTG_SYSCONFIG); | 312 | l = musb_readl(musb->mregs, OTG_SYSCONFIG); |
210 | l &= ~ENABLEWAKEUP; /* disable wakeup */ | 313 | l &= ~ENABLEWAKEUP; /* disable wakeup */ |
@@ -241,87 +344,214 @@ int __init musb_platform_init(struct musb *musb) | |||
241 | musb_readl(musb->mregs, OTG_INTERFSEL), | 344 | musb_readl(musb->mregs, OTG_INTERFSEL), |
242 | musb_readl(musb->mregs, OTG_SIMENABLE)); | 345 | musb_readl(musb->mregs, OTG_SIMENABLE)); |
243 | 346 | ||
244 | if (is_host_enabled(musb)) | 347 | musb->nb.notifier_call = musb_otg_notifications; |
245 | musb->board_set_vbus = omap_set_vbus; | 348 | status = otg_register_notifier(musb->xceiv, &musb->nb); |
349 | |||
350 | if (status) | ||
351 | DBG(1, "notification register failed\n"); | ||
352 | |||
353 | /* check whether cable is already connected */ | ||
354 | if (musb->xceiv->state ==OTG_STATE_B_IDLE) | ||
355 | musb_otg_notifications(&musb->nb, 1, | ||
356 | musb->xceiv->gadget); | ||
246 | 357 | ||
247 | setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); | 358 | setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); |
248 | 359 | ||
249 | return 0; | 360 | return 0; |
250 | } | 361 | } |
251 | 362 | ||
252 | #ifdef CONFIG_PM | 363 | static int omap2430_musb_exit(struct musb *musb) |
253 | void musb_platform_save_context(struct musb *musb, | ||
254 | struct musb_context_registers *musb_context) | ||
255 | { | 364 | { |
256 | musb_context->otg_sysconfig = musb_readl(musb->mregs, OTG_SYSCONFIG); | ||
257 | musb_context->otg_forcestandby = musb_readl(musb->mregs, OTG_FORCESTDBY); | ||
258 | } | ||
259 | 365 | ||
260 | void musb_platform_restore_context(struct musb *musb, | 366 | omap2430_low_level_exit(musb); |
261 | struct musb_context_registers *musb_context) | 367 | otg_put_transceiver(musb->xceiv); |
262 | { | 368 | |
263 | musb_writel(musb->mregs, OTG_SYSCONFIG, musb_context->otg_sysconfig); | 369 | return 0; |
264 | musb_writel(musb->mregs, OTG_FORCESTDBY, musb_context->otg_forcestandby); | ||
265 | } | 370 | } |
266 | #endif | ||
267 | 371 | ||
268 | static int musb_platform_suspend(struct musb *musb) | 372 | static const struct musb_platform_ops omap2430_ops = { |
373 | .init = omap2430_musb_init, | ||
374 | .exit = omap2430_musb_exit, | ||
375 | |||
376 | .set_mode = omap2430_musb_set_mode, | ||
377 | .try_idle = omap2430_musb_try_idle, | ||
378 | |||
379 | .set_vbus = omap2430_musb_set_vbus, | ||
380 | }; | ||
381 | |||
382 | static u64 omap2430_dmamask = DMA_BIT_MASK(32); | ||
383 | |||
384 | static int __init omap2430_probe(struct platform_device *pdev) | ||
269 | { | 385 | { |
270 | u32 l; | 386 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; |
387 | struct platform_device *musb; | ||
388 | struct omap2430_glue *glue; | ||
389 | struct clk *clk; | ||
271 | 390 | ||
272 | if (!musb->clock) | 391 | int ret = -ENOMEM; |
273 | return 0; | ||
274 | 392 | ||
275 | /* in any role */ | 393 | glue = kzalloc(sizeof(*glue), GFP_KERNEL); |
276 | l = musb_readl(musb->mregs, OTG_FORCESTDBY); | 394 | if (!glue) { |
277 | l |= ENABLEFORCE; /* enable MSTANDBY */ | 395 | dev_err(&pdev->dev, "failed to allocate glue context\n"); |
278 | musb_writel(musb->mregs, OTG_FORCESTDBY, l); | 396 | goto err0; |
397 | } | ||
279 | 398 | ||
280 | l = musb_readl(musb->mregs, OTG_SYSCONFIG); | 399 | musb = platform_device_alloc("musb-hdrc", -1); |
281 | l |= ENABLEWAKEUP; /* enable wakeup */ | 400 | if (!musb) { |
282 | musb_writel(musb->mregs, OTG_SYSCONFIG, l); | 401 | dev_err(&pdev->dev, "failed to allocate musb device\n"); |
402 | goto err1; | ||
403 | } | ||
283 | 404 | ||
284 | otg_set_suspend(musb->xceiv, 1); | 405 | clk = clk_get(&pdev->dev, "ick"); |
406 | if (IS_ERR(clk)) { | ||
407 | dev_err(&pdev->dev, "failed to get clock\n"); | ||
408 | ret = PTR_ERR(clk); | ||
409 | goto err2; | ||
410 | } | ||
285 | 411 | ||
286 | if (musb->set_clock) | 412 | ret = clk_enable(clk); |
287 | musb->set_clock(musb->clock, 0); | 413 | if (ret) { |
288 | else | 414 | dev_err(&pdev->dev, "failed to enable clock\n"); |
289 | clk_disable(musb->clock); | 415 | goto err3; |
416 | } | ||
417 | |||
418 | musb->dev.parent = &pdev->dev; | ||
419 | musb->dev.dma_mask = &omap2430_dmamask; | ||
420 | musb->dev.coherent_dma_mask = omap2430_dmamask; | ||
421 | |||
422 | glue->dev = &pdev->dev; | ||
423 | glue->musb = musb; | ||
424 | glue->clk = clk; | ||
425 | |||
426 | pdata->platform_ops = &omap2430_ops; | ||
427 | |||
428 | platform_set_drvdata(pdev, glue); | ||
429 | |||
430 | ret = platform_device_add_resources(musb, pdev->resource, | ||
431 | pdev->num_resources); | ||
432 | if (ret) { | ||
433 | dev_err(&pdev->dev, "failed to add resources\n"); | ||
434 | goto err4; | ||
435 | } | ||
436 | |||
437 | ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); | ||
438 | if (ret) { | ||
439 | dev_err(&pdev->dev, "failed to add platform_data\n"); | ||
440 | goto err4; | ||
441 | } | ||
442 | |||
443 | ret = platform_device_add(musb); | ||
444 | if (ret) { | ||
445 | dev_err(&pdev->dev, "failed to register musb device\n"); | ||
446 | goto err4; | ||
447 | } | ||
290 | 448 | ||
291 | return 0; | 449 | return 0; |
450 | |||
451 | err4: | ||
452 | clk_disable(clk); | ||
453 | |||
454 | err3: | ||
455 | clk_put(clk); | ||
456 | |||
457 | err2: | ||
458 | platform_device_put(musb); | ||
459 | |||
460 | err1: | ||
461 | kfree(glue); | ||
462 | |||
463 | err0: | ||
464 | return ret; | ||
292 | } | 465 | } |
293 | 466 | ||
294 | static int musb_platform_resume(struct musb *musb) | 467 | static int __exit omap2430_remove(struct platform_device *pdev) |
295 | { | 468 | { |
296 | u32 l; | 469 | struct omap2430_glue *glue = platform_get_drvdata(pdev); |
297 | 470 | ||
298 | if (!musb->clock) | 471 | platform_device_del(glue->musb); |
299 | return 0; | 472 | platform_device_put(glue->musb); |
473 | clk_disable(glue->clk); | ||
474 | clk_put(glue->clk); | ||
475 | kfree(glue); | ||
300 | 476 | ||
301 | otg_set_suspend(musb->xceiv, 0); | 477 | return 0; |
478 | } | ||
302 | 479 | ||
303 | if (musb->set_clock) | 480 | #ifdef CONFIG_PM |
304 | musb->set_clock(musb->clock, 1); | 481 | static void omap2430_save_context(struct musb *musb) |
305 | else | 482 | { |
306 | clk_enable(musb->clock); | 483 | musb->context.otg_sysconfig = musb_readl(musb->mregs, OTG_SYSCONFIG); |
484 | musb->context.otg_forcestandby = musb_readl(musb->mregs, OTG_FORCESTDBY); | ||
485 | } | ||
307 | 486 | ||
308 | l = musb_readl(musb->mregs, OTG_SYSCONFIG); | 487 | static void omap2430_restore_context(struct musb *musb) |
309 | l &= ~ENABLEWAKEUP; /* disable wakeup */ | 488 | { |
310 | musb_writel(musb->mregs, OTG_SYSCONFIG, l); | 489 | musb_writel(musb->mregs, OTG_SYSCONFIG, musb->context.otg_sysconfig); |
490 | musb_writel(musb->mregs, OTG_FORCESTDBY, musb->context.otg_forcestandby); | ||
491 | } | ||
311 | 492 | ||
312 | l = musb_readl(musb->mregs, OTG_FORCESTDBY); | 493 | static int omap2430_suspend(struct device *dev) |
313 | l &= ~ENABLEFORCE; /* disable MSTANDBY */ | 494 | { |
314 | musb_writel(musb->mregs, OTG_FORCESTDBY, l); | 495 | struct omap2430_glue *glue = dev_get_drvdata(dev); |
496 | struct musb *musb = glue_to_musb(glue); | ||
497 | |||
498 | omap2430_low_level_exit(musb); | ||
499 | otg_set_suspend(musb->xceiv, 1); | ||
500 | omap2430_save_context(musb); | ||
501 | clk_disable(glue->clk); | ||
315 | 502 | ||
316 | return 0; | 503 | return 0; |
317 | } | 504 | } |
318 | 505 | ||
319 | 506 | static int omap2430_resume(struct device *dev) | |
320 | int musb_platform_exit(struct musb *musb) | ||
321 | { | 507 | { |
508 | struct omap2430_glue *glue = dev_get_drvdata(dev); | ||
509 | struct musb *musb = glue_to_musb(glue); | ||
510 | int ret; | ||
511 | |||
512 | ret = clk_enable(glue->clk); | ||
513 | if (ret) { | ||
514 | dev_err(dev, "faled to enable clock\n"); | ||
515 | return ret; | ||
516 | } | ||
322 | 517 | ||
323 | musb_platform_suspend(musb); | 518 | omap2430_low_level_init(musb); |
519 | omap2430_restore_context(musb); | ||
520 | otg_set_suspend(musb->xceiv, 0); | ||
324 | 521 | ||
325 | otg_put_transceiver(musb->xceiv); | ||
326 | return 0; | 522 | return 0; |
327 | } | 523 | } |
524 | |||
525 | static struct dev_pm_ops omap2430_pm_ops = { | ||
526 | .suspend = omap2430_suspend, | ||
527 | .resume = omap2430_resume, | ||
528 | }; | ||
529 | |||
530 | #define DEV_PM_OPS (&omap2430_pm_ops) | ||
531 | #else | ||
532 | #define DEV_PM_OPS NULL | ||
533 | #endif | ||
534 | |||
535 | static struct platform_driver omap2430_driver = { | ||
536 | .remove = __exit_p(omap2430_remove), | ||
537 | .driver = { | ||
538 | .name = "musb-omap2430", | ||
539 | .pm = DEV_PM_OPS, | ||
540 | }, | ||
541 | }; | ||
542 | |||
543 | MODULE_DESCRIPTION("OMAP2PLUS MUSB Glue Layer"); | ||
544 | MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); | ||
545 | MODULE_LICENSE("GPL v2"); | ||
546 | |||
547 | static int __init omap2430_init(void) | ||
548 | { | ||
549 | return platform_driver_probe(&omap2430_driver, omap2430_probe); | ||
550 | } | ||
551 | subsys_initcall(omap2430_init); | ||
552 | |||
553 | static void __exit omap2430_exit(void) | ||
554 | { | ||
555 | platform_driver_unregister(&omap2430_driver); | ||
556 | } | ||
557 | module_exit(omap2430_exit); | ||
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 41b04b906ce1..2ba3b070ed0b 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c | |||
@@ -21,10 +21,16 @@ | |||
21 | #include <linux/usb.h> | 21 | #include <linux/usb.h> |
22 | #include <linux/irq.h> | 22 | #include <linux/irq.h> |
23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | #include <linux/dma-mapping.h> | ||
24 | 25 | ||
25 | #include "musb_core.h" | 26 | #include "musb_core.h" |
26 | 27 | ||
27 | static void tusb_source_power(struct musb *musb, int is_on); | 28 | struct tusb6010_glue { |
29 | struct device *dev; | ||
30 | struct platform_device *musb; | ||
31 | }; | ||
32 | |||
33 | static void tusb_musb_set_vbus(struct musb *musb, int is_on); | ||
28 | 34 | ||
29 | #define TUSB_REV_MAJOR(reg_val) ((reg_val >> 4) & 0xf) | 35 | #define TUSB_REV_MAJOR(reg_val) ((reg_val >> 4) & 0xf) |
30 | #define TUSB_REV_MINOR(reg_val) (reg_val & 0xf) | 36 | #define TUSB_REV_MINOR(reg_val) (reg_val & 0xf) |
@@ -50,7 +56,7 @@ u8 tusb_get_revision(struct musb *musb) | |||
50 | return rev; | 56 | return rev; |
51 | } | 57 | } |
52 | 58 | ||
53 | static int __init tusb_print_revision(struct musb *musb) | 59 | static int tusb_print_revision(struct musb *musb) |
54 | { | 60 | { |
55 | void __iomem *tbase = musb->ctrl_base; | 61 | void __iomem *tbase = musb->ctrl_base; |
56 | u8 rev; | 62 | u8 rev; |
@@ -275,17 +281,6 @@ static int tusb_draw_power(struct otg_transceiver *x, unsigned mA) | |||
275 | void __iomem *tbase = musb->ctrl_base; | 281 | void __iomem *tbase = musb->ctrl_base; |
276 | u32 reg; | 282 | u32 reg; |
277 | 283 | ||
278 | /* | ||
279 | * Keep clock active when enabled. Note that this is not tied to | ||
280 | * drawing VBUS, as with OTG mA can be less than musb->min_power. | ||
281 | */ | ||
282 | if (musb->set_clock) { | ||
283 | if (mA) | ||
284 | musb->set_clock(musb->clock, 1); | ||
285 | else | ||
286 | musb->set_clock(musb->clock, 0); | ||
287 | } | ||
288 | |||
289 | /* tps65030 seems to consume max 100mA, with maybe 60mA available | 284 | /* tps65030 seems to consume max 100mA, with maybe 60mA available |
290 | * (measured on one board) for things other than tps and tusb. | 285 | * (measured on one board) for things other than tps and tusb. |
291 | * | 286 | * |
@@ -348,7 +343,7 @@ static void tusb_set_clock_source(struct musb *musb, unsigned mode) | |||
348 | * USB link is not suspended ... and tells us the relevant wakeup | 343 | * USB link is not suspended ... and tells us the relevant wakeup |
349 | * events. SW_EN for voltage is handled separately. | 344 | * events. SW_EN for voltage is handled separately. |
350 | */ | 345 | */ |
351 | void tusb_allow_idle(struct musb *musb, u32 wakeup_enables) | 346 | static void tusb_allow_idle(struct musb *musb, u32 wakeup_enables) |
352 | { | 347 | { |
353 | void __iomem *tbase = musb->ctrl_base; | 348 | void __iomem *tbase = musb->ctrl_base; |
354 | u32 reg; | 349 | u32 reg; |
@@ -385,7 +380,7 @@ void tusb_allow_idle(struct musb *musb, u32 wakeup_enables) | |||
385 | /* | 380 | /* |
386 | * Updates cable VBUS status. Caller must take care of locking. | 381 | * Updates cable VBUS status. Caller must take care of locking. |
387 | */ | 382 | */ |
388 | int musb_platform_get_vbus_status(struct musb *musb) | 383 | static int tusb_musb_vbus_status(struct musb *musb) |
389 | { | 384 | { |
390 | void __iomem *tbase = musb->ctrl_base; | 385 | void __iomem *tbase = musb->ctrl_base; |
391 | u32 otg_stat, prcm_mngmt; | 386 | u32 otg_stat, prcm_mngmt; |
@@ -431,7 +426,7 @@ static void musb_do_idle(unsigned long _musb) | |||
431 | } | 426 | } |
432 | /* FALLTHROUGH */ | 427 | /* FALLTHROUGH */ |
433 | case OTG_STATE_A_IDLE: | 428 | case OTG_STATE_A_IDLE: |
434 | tusb_source_power(musb, 0); | 429 | tusb_musb_set_vbus(musb, 0); |
435 | default: | 430 | default: |
436 | break; | 431 | break; |
437 | } | 432 | } |
@@ -475,7 +470,7 @@ done: | |||
475 | * we don't want to treat that full speed J as a wakeup event. | 470 | * we don't want to treat that full speed J as a wakeup event. |
476 | * ... peripherals must draw only suspend current after 10 msec. | 471 | * ... peripherals must draw only suspend current after 10 msec. |
477 | */ | 472 | */ |
478 | void musb_platform_try_idle(struct musb *musb, unsigned long timeout) | 473 | static void tusb_musb_try_idle(struct musb *musb, unsigned long timeout) |
479 | { | 474 | { |
480 | unsigned long default_timeout = jiffies + msecs_to_jiffies(3); | 475 | unsigned long default_timeout = jiffies + msecs_to_jiffies(3); |
481 | static unsigned long last_timer; | 476 | static unsigned long last_timer; |
@@ -515,7 +510,7 @@ void musb_platform_try_idle(struct musb *musb, unsigned long timeout) | |||
515 | | TUSB_DEV_OTG_TIMER_ENABLE) \ | 510 | | TUSB_DEV_OTG_TIMER_ENABLE) \ |
516 | : 0) | 511 | : 0) |
517 | 512 | ||
518 | static void tusb_source_power(struct musb *musb, int is_on) | 513 | static void tusb_musb_set_vbus(struct musb *musb, int is_on) |
519 | { | 514 | { |
520 | void __iomem *tbase = musb->ctrl_base; | 515 | void __iomem *tbase = musb->ctrl_base; |
521 | u32 conf, prcm, timer; | 516 | u32 conf, prcm, timer; |
@@ -531,8 +526,6 @@ static void tusb_source_power(struct musb *musb, int is_on) | |||
531 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); | 526 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); |
532 | 527 | ||
533 | if (is_on) { | 528 | if (is_on) { |
534 | if (musb->set_clock) | ||
535 | musb->set_clock(musb->clock, 1); | ||
536 | timer = OTG_TIMER_MS(OTG_TIME_A_WAIT_VRISE); | 529 | timer = OTG_TIMER_MS(OTG_TIME_A_WAIT_VRISE); |
537 | musb->xceiv->default_a = 1; | 530 | musb->xceiv->default_a = 1; |
538 | musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; | 531 | musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; |
@@ -571,8 +564,6 @@ static void tusb_source_power(struct musb *musb, int is_on) | |||
571 | 564 | ||
572 | devctl &= ~MUSB_DEVCTL_SESSION; | 565 | devctl &= ~MUSB_DEVCTL_SESSION; |
573 | conf &= ~TUSB_DEV_CONF_USB_HOST_MODE; | 566 | conf &= ~TUSB_DEV_CONF_USB_HOST_MODE; |
574 | if (musb->set_clock) | ||
575 | musb->set_clock(musb->clock, 0); | ||
576 | } | 567 | } |
577 | prcm &= ~(TUSB_PRCM_MNGMT_15_SW_EN | TUSB_PRCM_MNGMT_33_SW_EN); | 568 | prcm &= ~(TUSB_PRCM_MNGMT_15_SW_EN | TUSB_PRCM_MNGMT_33_SW_EN); |
578 | 569 | ||
@@ -599,7 +590,7 @@ static void tusb_source_power(struct musb *musb, int is_on) | |||
599 | * and peripheral modes in non-OTG configurations by reconfiguring hardware | 590 | * and peripheral modes in non-OTG configurations by reconfiguring hardware |
600 | * and then setting musb->board_mode. For now, only support OTG mode. | 591 | * and then setting musb->board_mode. For now, only support OTG mode. |
601 | */ | 592 | */ |
602 | int musb_platform_set_mode(struct musb *musb, u8 musb_mode) | 593 | static int tusb_musb_set_mode(struct musb *musb, u8 musb_mode) |
603 | { | 594 | { |
604 | void __iomem *tbase = musb->ctrl_base; | 595 | void __iomem *tbase = musb->ctrl_base; |
605 | u32 otg_stat, phy_otg_ctrl, phy_otg_ena, dev_conf; | 596 | u32 otg_stat, phy_otg_ctrl, phy_otg_ena, dev_conf; |
@@ -677,7 +668,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) | |||
677 | default_a = is_host_enabled(musb); | 668 | default_a = is_host_enabled(musb); |
678 | DBG(2, "Default-%c\n", default_a ? 'A' : 'B'); | 669 | DBG(2, "Default-%c\n", default_a ? 'A' : 'B'); |
679 | musb->xceiv->default_a = default_a; | 670 | musb->xceiv->default_a = default_a; |
680 | tusb_source_power(musb, default_a); | 671 | tusb_musb_set_vbus(musb, default_a); |
681 | 672 | ||
682 | /* Don't allow idling immediately */ | 673 | /* Don't allow idling immediately */ |
683 | if (default_a) | 674 | if (default_a) |
@@ -722,7 +713,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) | |||
722 | switch (musb->xceiv->state) { | 713 | switch (musb->xceiv->state) { |
723 | case OTG_STATE_A_IDLE: | 714 | case OTG_STATE_A_IDLE: |
724 | DBG(2, "Got SRP, turning on VBUS\n"); | 715 | DBG(2, "Got SRP, turning on VBUS\n"); |
725 | musb_set_vbus(musb, 1); | 716 | musb_platform_set_vbus(musb, 1); |
726 | 717 | ||
727 | /* CONNECT can wake if a_wait_bcon is set */ | 718 | /* CONNECT can wake if a_wait_bcon is set */ |
728 | if (musb->a_wait_bcon != 0) | 719 | if (musb->a_wait_bcon != 0) |
@@ -748,11 +739,11 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) | |||
748 | */ | 739 | */ |
749 | if (musb->vbuserr_retry) { | 740 | if (musb->vbuserr_retry) { |
750 | musb->vbuserr_retry--; | 741 | musb->vbuserr_retry--; |
751 | tusb_source_power(musb, 1); | 742 | tusb_musb_set_vbus(musb, 1); |
752 | } else { | 743 | } else { |
753 | musb->vbuserr_retry | 744 | musb->vbuserr_retry |
754 | = VBUSERR_RETRY_COUNT; | 745 | = VBUSERR_RETRY_COUNT; |
755 | tusb_source_power(musb, 0); | 746 | tusb_musb_set_vbus(musb, 0); |
756 | } | 747 | } |
757 | break; | 748 | break; |
758 | default: | 749 | default: |
@@ -786,7 +777,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) | |||
786 | } else { | 777 | } else { |
787 | /* REVISIT report overcurrent to hub? */ | 778 | /* REVISIT report overcurrent to hub? */ |
788 | ERR("vbus too slow, devctl %02x\n", devctl); | 779 | ERR("vbus too slow, devctl %02x\n", devctl); |
789 | tusb_source_power(musb, 0); | 780 | tusb_musb_set_vbus(musb, 0); |
790 | } | 781 | } |
791 | break; | 782 | break; |
792 | case OTG_STATE_A_WAIT_BCON: | 783 | case OTG_STATE_A_WAIT_BCON: |
@@ -807,7 +798,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) | |||
807 | return idle_timeout; | 798 | return idle_timeout; |
808 | } | 799 | } |
809 | 800 | ||
810 | static irqreturn_t tusb_interrupt(int irq, void *__hci) | 801 | static irqreturn_t tusb_musb_interrupt(int irq, void *__hci) |
811 | { | 802 | { |
812 | struct musb *musb = __hci; | 803 | struct musb *musb = __hci; |
813 | void __iomem *tbase = musb->ctrl_base; | 804 | void __iomem *tbase = musb->ctrl_base; |
@@ -911,7 +902,7 @@ static irqreturn_t tusb_interrupt(int irq, void *__hci) | |||
911 | musb_writel(tbase, TUSB_INT_SRC_CLEAR, | 902 | musb_writel(tbase, TUSB_INT_SRC_CLEAR, |
912 | int_src & ~TUSB_INT_MASK_RESERVED_BITS); | 903 | int_src & ~TUSB_INT_MASK_RESERVED_BITS); |
913 | 904 | ||
914 | musb_platform_try_idle(musb, idle_timeout); | 905 | tusb_musb_try_idle(musb, idle_timeout); |
915 | 906 | ||
916 | musb_writel(tbase, TUSB_INT_MASK, int_mask); | 907 | musb_writel(tbase, TUSB_INT_MASK, int_mask); |
917 | spin_unlock_irqrestore(&musb->lock, flags); | 908 | spin_unlock_irqrestore(&musb->lock, flags); |
@@ -926,7 +917,7 @@ static int dma_off; | |||
926 | * REVISIT: | 917 | * REVISIT: |
927 | * - Check what is unnecessary in MGC_HdrcStart() | 918 | * - Check what is unnecessary in MGC_HdrcStart() |
928 | */ | 919 | */ |
929 | void musb_platform_enable(struct musb *musb) | 920 | static void tusb_musb_enable(struct musb *musb) |
930 | { | 921 | { |
931 | void __iomem *tbase = musb->ctrl_base; | 922 | void __iomem *tbase = musb->ctrl_base; |
932 | 923 | ||
@@ -970,7 +961,7 @@ void musb_platform_enable(struct musb *musb) | |||
970 | /* | 961 | /* |
971 | * Disables TUSB6010. Caller must take care of locking. | 962 | * Disables TUSB6010. Caller must take care of locking. |
972 | */ | 963 | */ |
973 | void musb_platform_disable(struct musb *musb) | 964 | static void tusb_musb_disable(struct musb *musb) |
974 | { | 965 | { |
975 | void __iomem *tbase = musb->ctrl_base; | 966 | void __iomem *tbase = musb->ctrl_base; |
976 | 967 | ||
@@ -995,7 +986,7 @@ void musb_platform_disable(struct musb *musb) | |||
995 | * Sets up TUSB6010 CPU interface specific signals and registers | 986 | * Sets up TUSB6010 CPU interface specific signals and registers |
996 | * Note: Settings optimized for OMAP24xx | 987 | * Note: Settings optimized for OMAP24xx |
997 | */ | 988 | */ |
998 | static void __init tusb_setup_cpu_interface(struct musb *musb) | 989 | static void tusb_setup_cpu_interface(struct musb *musb) |
999 | { | 990 | { |
1000 | void __iomem *tbase = musb->ctrl_base; | 991 | void __iomem *tbase = musb->ctrl_base; |
1001 | 992 | ||
@@ -1022,7 +1013,7 @@ static void __init tusb_setup_cpu_interface(struct musb *musb) | |||
1022 | musb_writel(tbase, TUSB_WAIT_COUNT, 1); | 1013 | musb_writel(tbase, TUSB_WAIT_COUNT, 1); |
1023 | } | 1014 | } |
1024 | 1015 | ||
1025 | static int __init tusb_start(struct musb *musb) | 1016 | static int tusb_musb_start(struct musb *musb) |
1026 | { | 1017 | { |
1027 | void __iomem *tbase = musb->ctrl_base; | 1018 | void __iomem *tbase = musb->ctrl_base; |
1028 | int ret = 0; | 1019 | int ret = 0; |
@@ -1091,7 +1082,7 @@ err: | |||
1091 | return -ENODEV; | 1082 | return -ENODEV; |
1092 | } | 1083 | } |
1093 | 1084 | ||
1094 | int __init musb_platform_init(struct musb *musb) | 1085 | static int tusb_musb_init(struct musb *musb) |
1095 | { | 1086 | { |
1096 | struct platform_device *pdev; | 1087 | struct platform_device *pdev; |
1097 | struct resource *mem; | 1088 | struct resource *mem; |
@@ -1131,16 +1122,14 @@ int __init musb_platform_init(struct musb *musb) | |||
1131 | */ | 1122 | */ |
1132 | musb->mregs += TUSB_BASE_OFFSET; | 1123 | musb->mregs += TUSB_BASE_OFFSET; |
1133 | 1124 | ||
1134 | ret = tusb_start(musb); | 1125 | ret = tusb_musb_start(musb); |
1135 | if (ret) { | 1126 | if (ret) { |
1136 | printk(KERN_ERR "Could not start tusb6010 (%d)\n", | 1127 | printk(KERN_ERR "Could not start tusb6010 (%d)\n", |
1137 | ret); | 1128 | ret); |
1138 | goto done; | 1129 | goto done; |
1139 | } | 1130 | } |
1140 | musb->isr = tusb_interrupt; | 1131 | musb->isr = tusb_musb_interrupt; |
1141 | 1132 | ||
1142 | if (is_host_enabled(musb)) | ||
1143 | musb->board_set_vbus = tusb_source_power; | ||
1144 | if (is_peripheral_enabled(musb)) { | 1133 | if (is_peripheral_enabled(musb)) { |
1145 | musb->xceiv->set_power = tusb_draw_power; | 1134 | musb->xceiv->set_power = tusb_draw_power; |
1146 | the_musb = musb; | 1135 | the_musb = musb; |
@@ -1159,7 +1148,7 @@ done: | |||
1159 | return ret; | 1148 | return ret; |
1160 | } | 1149 | } |
1161 | 1150 | ||
1162 | int musb_platform_exit(struct musb *musb) | 1151 | static int tusb_musb_exit(struct musb *musb) |
1163 | { | 1152 | { |
1164 | del_timer_sync(&musb_idle_timer); | 1153 | del_timer_sync(&musb_idle_timer); |
1165 | the_musb = NULL; | 1154 | the_musb = NULL; |
@@ -1173,3 +1162,115 @@ int musb_platform_exit(struct musb *musb) | |||
1173 | usb_nop_xceiv_unregister(); | 1162 | usb_nop_xceiv_unregister(); |
1174 | return 0; | 1163 | return 0; |
1175 | } | 1164 | } |
1165 | |||
1166 | static const struct musb_platform_ops tusb_ops = { | ||
1167 | .init = tusb_musb_init, | ||
1168 | .exit = tusb_musb_exit, | ||
1169 | |||
1170 | .enable = tusb_musb_enable, | ||
1171 | .disable = tusb_musb_disable, | ||
1172 | |||
1173 | .set_mode = tusb_musb_set_mode, | ||
1174 | .try_idle = tusb_musb_try_idle, | ||
1175 | |||
1176 | .vbus_status = tusb_musb_vbus_status, | ||
1177 | .set_vbus = tusb_musb_set_vbus, | ||
1178 | }; | ||
1179 | |||
1180 | static u64 tusb_dmamask = DMA_BIT_MASK(32); | ||
1181 | |||
1182 | static int __init tusb_probe(struct platform_device *pdev) | ||
1183 | { | ||
1184 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; | ||
1185 | struct platform_device *musb; | ||
1186 | struct tusb6010_glue *glue; | ||
1187 | |||
1188 | int ret = -ENOMEM; | ||
1189 | |||
1190 | glue = kzalloc(sizeof(*glue), GFP_KERNEL); | ||
1191 | if (!glue) { | ||
1192 | dev_err(&pdev->dev, "failed to allocate glue context\n"); | ||
1193 | goto err0; | ||
1194 | } | ||
1195 | |||
1196 | musb = platform_device_alloc("musb-hdrc", -1); | ||
1197 | if (!musb) { | ||
1198 | dev_err(&pdev->dev, "failed to allocate musb device\n"); | ||
1199 | goto err1; | ||
1200 | } | ||
1201 | |||
1202 | musb->dev.parent = &pdev->dev; | ||
1203 | musb->dev.dma_mask = &tusb_dmamask; | ||
1204 | musb->dev.coherent_dma_mask = tusb_dmamask; | ||
1205 | |||
1206 | glue->dev = &pdev->dev; | ||
1207 | glue->musb = musb; | ||
1208 | |||
1209 | pdata->platform_ops = &tusb_ops; | ||
1210 | |||
1211 | platform_set_drvdata(pdev, glue); | ||
1212 | |||
1213 | ret = platform_device_add_resources(musb, pdev->resource, | ||
1214 | pdev->num_resources); | ||
1215 | if (ret) { | ||
1216 | dev_err(&pdev->dev, "failed to add resources\n"); | ||
1217 | goto err2; | ||
1218 | } | ||
1219 | |||
1220 | ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); | ||
1221 | if (ret) { | ||
1222 | dev_err(&pdev->dev, "failed to add platform_data\n"); | ||
1223 | goto err2; | ||
1224 | } | ||
1225 | |||
1226 | ret = platform_device_add(musb); | ||
1227 | if (ret) { | ||
1228 | dev_err(&pdev->dev, "failed to register musb device\n"); | ||
1229 | goto err1; | ||
1230 | } | ||
1231 | |||
1232 | return 0; | ||
1233 | |||
1234 | err2: | ||
1235 | platform_device_put(musb); | ||
1236 | |||
1237 | err1: | ||
1238 | kfree(glue); | ||
1239 | |||
1240 | err0: | ||
1241 | return ret; | ||
1242 | } | ||
1243 | |||
1244 | static int __exit tusb_remove(struct platform_device *pdev) | ||
1245 | { | ||
1246 | struct tusb6010_glue *glue = platform_get_drvdata(pdev); | ||
1247 | |||
1248 | platform_device_del(glue->musb); | ||
1249 | platform_device_put(glue->musb); | ||
1250 | kfree(glue); | ||
1251 | |||
1252 | return 0; | ||
1253 | } | ||
1254 | |||
1255 | static struct platform_driver tusb_driver = { | ||
1256 | .remove = __exit_p(tusb_remove), | ||
1257 | .driver = { | ||
1258 | .name = "musb-tusb", | ||
1259 | }, | ||
1260 | }; | ||
1261 | |||
1262 | MODULE_DESCRIPTION("TUSB6010 MUSB Glue Layer"); | ||
1263 | MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); | ||
1264 | MODULE_LICENSE("GPL v2"); | ||
1265 | |||
1266 | static int __init tusb_init(void) | ||
1267 | { | ||
1268 | return platform_driver_probe(&tusb_driver, tusb_probe); | ||
1269 | } | ||
1270 | subsys_initcall(tusb_init); | ||
1271 | |||
1272 | static void __exit tusb_exit(void) | ||
1273 | { | ||
1274 | platform_driver_unregister(&tusb_driver); | ||
1275 | } | ||
1276 | module_exit(tusb_exit); | ||
diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c new file mode 100644 index 000000000000..d6384e4aeef9 --- /dev/null +++ b/drivers/usb/musb/ux500.c | |||
@@ -0,0 +1,216 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 ST-Ericsson AB | ||
3 | * Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> | ||
4 | * | ||
5 | * Based on omap2430.c | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/clk.h> | ||
26 | #include <linux/io.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | |||
29 | #include "musb_core.h" | ||
30 | |||
31 | struct ux500_glue { | ||
32 | struct device *dev; | ||
33 | struct platform_device *musb; | ||
34 | struct clk *clk; | ||
35 | }; | ||
36 | #define glue_to_musb(g) platform_get_drvdata(g->musb) | ||
37 | |||
38 | static int ux500_musb_init(struct musb *musb) | ||
39 | { | ||
40 | musb->xceiv = otg_get_transceiver(); | ||
41 | if (!musb->xceiv) { | ||
42 | pr_err("HS USB OTG: no transceiver configured\n"); | ||
43 | return -ENODEV; | ||
44 | } | ||
45 | |||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | static int ux500_musb_exit(struct musb *musb) | ||
50 | { | ||
51 | otg_put_transceiver(musb->xceiv); | ||
52 | |||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | static const struct musb_platform_ops ux500_ops = { | ||
57 | .init = ux500_musb_init, | ||
58 | .exit = ux500_musb_exit, | ||
59 | }; | ||
60 | |||
61 | static int __init ux500_probe(struct platform_device *pdev) | ||
62 | { | ||
63 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; | ||
64 | struct platform_device *musb; | ||
65 | struct ux500_glue *glue; | ||
66 | struct clk *clk; | ||
67 | |||
68 | int ret = -ENOMEM; | ||
69 | |||
70 | glue = kzalloc(sizeof(*glue), GFP_KERNEL); | ||
71 | if (!glue) { | ||
72 | dev_err(&pdev->dev, "failed to allocate glue context\n"); | ||
73 | goto err0; | ||
74 | } | ||
75 | |||
76 | musb = platform_device_alloc("musb-hdrc", -1); | ||
77 | if (!musb) { | ||
78 | dev_err(&pdev->dev, "failed to allocate musb device\n"); | ||
79 | goto err1; | ||
80 | } | ||
81 | |||
82 | clk = clk_get(&pdev->dev, "usb"); | ||
83 | if (IS_ERR(clk)) { | ||
84 | dev_err(&pdev->dev, "failed to get clock\n"); | ||
85 | ret = PTR_ERR(clk); | ||
86 | goto err2; | ||
87 | } | ||
88 | |||
89 | ret = clk_enable(clk); | ||
90 | if (ret) { | ||
91 | dev_err(&pdev->dev, "failed to enable clock\n"); | ||
92 | goto err3; | ||
93 | } | ||
94 | |||
95 | musb->dev.parent = &pdev->dev; | ||
96 | |||
97 | glue->dev = &pdev->dev; | ||
98 | glue->musb = musb; | ||
99 | glue->clk = clk; | ||
100 | |||
101 | pdata->platform_ops = &ux500_ops; | ||
102 | |||
103 | platform_set_drvdata(pdev, glue); | ||
104 | |||
105 | ret = platform_device_add_resources(musb, pdev->resource, | ||
106 | pdev->num_resources); | ||
107 | if (ret) { | ||
108 | dev_err(&pdev->dev, "failed to add resources\n"); | ||
109 | goto err4; | ||
110 | } | ||
111 | |||
112 | ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); | ||
113 | if (ret) { | ||
114 | dev_err(&pdev->dev, "failed to add platform_data\n"); | ||
115 | goto err4; | ||
116 | } | ||
117 | |||
118 | ret = platform_device_add(musb); | ||
119 | if (ret) { | ||
120 | dev_err(&pdev->dev, "failed to register musb device\n"); | ||
121 | goto err4; | ||
122 | } | ||
123 | |||
124 | return 0; | ||
125 | |||
126 | err4: | ||
127 | clk_disable(clk); | ||
128 | |||
129 | err3: | ||
130 | clk_put(clk); | ||
131 | |||
132 | err2: | ||
133 | platform_device_put(musb); | ||
134 | |||
135 | err1: | ||
136 | kfree(glue); | ||
137 | |||
138 | err0: | ||
139 | return ret; | ||
140 | } | ||
141 | |||
142 | static int __exit ux500_remove(struct platform_device *pdev) | ||
143 | { | ||
144 | struct ux500_glue *glue = platform_get_drvdata(pdev); | ||
145 | |||
146 | platform_device_del(glue->musb); | ||
147 | platform_device_put(glue->musb); | ||
148 | clk_disable(glue->clk); | ||
149 | clk_put(glue->clk); | ||
150 | kfree(glue); | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | #ifdef CONFIG_PM | ||
156 | static int ux500_suspend(struct device *dev) | ||
157 | { | ||
158 | struct ux500_glue *glue = dev_get_drvdata(dev); | ||
159 | struct musb *musb = glue_to_musb(glue); | ||
160 | |||
161 | otg_set_suspend(musb->xceiv, 1); | ||
162 | clk_disable(glue->clk); | ||
163 | |||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | static int ux500_resume(struct device *dev) | ||
168 | { | ||
169 | struct ux500_glue *glue = dev_get_drvdata(dev); | ||
170 | struct musb *musb = glue_to_musb(glue); | ||
171 | int ret; | ||
172 | |||
173 | ret = clk_enable(glue->clk); | ||
174 | if (ret) { | ||
175 | dev_err(dev, "failed to enable clock\n"); | ||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | otg_set_suspend(musb->xceiv, 0); | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static const struct dev_pm_ops ux500_pm_ops = { | ||
185 | .suspend = ux500_suspend, | ||
186 | .resume = ux500_resume, | ||
187 | }; | ||
188 | |||
189 | #define DEV_PM_OPS (&ux500_pm_ops) | ||
190 | #else | ||
191 | #define DEV_PM_OPS NULL | ||
192 | #endif | ||
193 | |||
194 | static struct platform_driver ux500_driver = { | ||
195 | .remove = __exit_p(ux500_remove), | ||
196 | .driver = { | ||
197 | .name = "musb-ux500", | ||
198 | .pm = DEV_PM_OPS, | ||
199 | }, | ||
200 | }; | ||
201 | |||
202 | MODULE_DESCRIPTION("UX500 MUSB Glue Layer"); | ||
203 | MODULE_AUTHOR("Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>"); | ||
204 | MODULE_LICENSE("GPL v2"); | ||
205 | |||
206 | static int __init ux500_init(void) | ||
207 | { | ||
208 | return platform_driver_probe(&ux500_driver, ux500_probe); | ||
209 | } | ||
210 | subsys_initcall(ux500_init); | ||
211 | |||
212 | static void __exit ux500_exit(void) | ||
213 | { | ||
214 | platform_driver_unregister(&ux500_driver); | ||
215 | } | ||
216 | module_exit(ux500_exit); | ||
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 6491717a636a..9fb875d5f09c 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig | |||
@@ -59,6 +59,18 @@ config TWL4030_USB | |||
59 | This transceiver supports high and full speed devices plus, | 59 | This transceiver supports high and full speed devices plus, |
60 | in host mode, low speed. | 60 | in host mode, low speed. |
61 | 61 | ||
62 | config TWL6030_USB | ||
63 | tristate "TWL6030 USB Transceiver Driver" | ||
64 | depends on TWL4030_CORE | ||
65 | select USB_OTG_UTILS | ||
66 | help | ||
67 | Enable this to support the USB OTG transceiver on TWL6030 | ||
68 | family chips. This TWL6030 transceiver has the VBUS and ID GND | ||
69 | and OTG SRP events capabilities. For all other transceiver functionality | ||
70 | UTMI PHY is embedded in OMAP4430. The internal PHY configurations APIs | ||
71 | are hooked to this driver through platform_data structure. | ||
72 | The definition of internal PHY APIs are in the mach-omap2 layer. | ||
73 | |||
62 | config NOP_USB_XCEIV | 74 | config NOP_USB_XCEIV |
63 | tristate "NOP USB Transceiver Driver" | 75 | tristate "NOP USB Transceiver Driver" |
64 | select USB_OTG_UTILS | 76 | select USB_OTG_UTILS |
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index 30a23f3b7a1f..a520e715cfd6 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile | |||
@@ -12,6 +12,7 @@ obj-$(CONFIG_USB_OTG_UTILS) += otg.o | |||
12 | obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o | 12 | obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o |
13 | obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o | 13 | obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o |
14 | obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o | 14 | obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o |
15 | obj-$(CONFIG_TWL6030_USB) += twl6030-usb.o | ||
15 | obj-$(CONFIG_USB_LANGWELL_OTG) += langwell_otg.o | 16 | obj-$(CONFIG_USB_LANGWELL_OTG) += langwell_otg.o |
16 | obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o | 17 | obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o |
17 | obj-$(CONFIG_USB_ULPI) += ulpi.o | 18 | obj-$(CONFIG_USB_ULPI) += ulpi.o |
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c new file mode 100644 index 000000000000..28f770103640 --- /dev/null +++ b/drivers/usb/otg/twl6030-usb.c | |||
@@ -0,0 +1,493 @@ | |||
1 | /* | ||
2 | * twl6030_usb - TWL6030 USB transceiver, talking to OMAP OTG driver. | ||
3 | * | ||
4 | * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * Author: Hema HK <hemahk@ti.com> | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/io.h> | ||
28 | #include <linux/usb/otg.h> | ||
29 | #include <linux/i2c/twl.h> | ||
30 | #include <linux/regulator/consumer.h> | ||
31 | #include <linux/err.h> | ||
32 | #include <linux/notifier.h> | ||
33 | #include <linux/slab.h> | ||
34 | |||
35 | /* usb register definitions */ | ||
36 | #define USB_VENDOR_ID_LSB 0x00 | ||
37 | #define USB_VENDOR_ID_MSB 0x01 | ||
38 | #define USB_PRODUCT_ID_LSB 0x02 | ||
39 | #define USB_PRODUCT_ID_MSB 0x03 | ||
40 | #define USB_VBUS_CTRL_SET 0x04 | ||
41 | #define USB_VBUS_CTRL_CLR 0x05 | ||
42 | #define USB_ID_CTRL_SET 0x06 | ||
43 | #define USB_ID_CTRL_CLR 0x07 | ||
44 | #define USB_VBUS_INT_SRC 0x08 | ||
45 | #define USB_VBUS_INT_LATCH_SET 0x09 | ||
46 | #define USB_VBUS_INT_LATCH_CLR 0x0A | ||
47 | #define USB_VBUS_INT_EN_LO_SET 0x0B | ||
48 | #define USB_VBUS_INT_EN_LO_CLR 0x0C | ||
49 | #define USB_VBUS_INT_EN_HI_SET 0x0D | ||
50 | #define USB_VBUS_INT_EN_HI_CLR 0x0E | ||
51 | #define USB_ID_INT_SRC 0x0F | ||
52 | #define USB_ID_INT_LATCH_SET 0x10 | ||
53 | #define USB_ID_INT_LATCH_CLR 0x11 | ||
54 | |||
55 | #define USB_ID_INT_EN_LO_SET 0x12 | ||
56 | #define USB_ID_INT_EN_LO_CLR 0x13 | ||
57 | #define USB_ID_INT_EN_HI_SET 0x14 | ||
58 | #define USB_ID_INT_EN_HI_CLR 0x15 | ||
59 | #define USB_OTG_ADP_CTRL 0x16 | ||
60 | #define USB_OTG_ADP_HIGH 0x17 | ||
61 | #define USB_OTG_ADP_LOW 0x18 | ||
62 | #define USB_OTG_ADP_RISE 0x19 | ||
63 | #define USB_OTG_REVISION 0x1A | ||
64 | |||
65 | /* to be moved to LDO */ | ||
66 | #define TWL6030_MISC2 0xE5 | ||
67 | #define TWL6030_CFG_LDO_PD2 0xF5 | ||
68 | #define TWL6030_BACKUP_REG 0xFA | ||
69 | |||
70 | #define STS_HW_CONDITIONS 0x21 | ||
71 | |||
72 | /* In module TWL6030_MODULE_PM_MASTER */ | ||
73 | #define STS_HW_CONDITIONS 0x21 | ||
74 | #define STS_USB_ID BIT(2) | ||
75 | |||
76 | /* In module TWL6030_MODULE_PM_RECEIVER */ | ||
77 | #define VUSB_CFG_TRANS 0x71 | ||
78 | #define VUSB_CFG_STATE 0x72 | ||
79 | #define VUSB_CFG_VOLTAGE 0x73 | ||
80 | |||
81 | /* in module TWL6030_MODULE_MAIN_CHARGE */ | ||
82 | |||
83 | #define CHARGERUSB_CTRL1 0x8 | ||
84 | |||
85 | #define CONTROLLER_STAT1 0x03 | ||
86 | #define VBUS_DET BIT(2) | ||
87 | |||
88 | struct twl6030_usb { | ||
89 | struct otg_transceiver otg; | ||
90 | struct device *dev; | ||
91 | |||
92 | /* for vbus reporting with irqs disabled */ | ||
93 | spinlock_t lock; | ||
94 | |||
95 | struct regulator *usb3v3; | ||
96 | |||
97 | int irq1; | ||
98 | int irq2; | ||
99 | u8 linkstat; | ||
100 | u8 asleep; | ||
101 | bool irq_enabled; | ||
102 | }; | ||
103 | |||
104 | #define xceiv_to_twl(x) container_of((x), struct twl6030_usb, otg); | ||
105 | |||
106 | /*-------------------------------------------------------------------------*/ | ||
107 | |||
108 | static inline int twl6030_writeb(struct twl6030_usb *twl, u8 module, | ||
109 | u8 data, u8 address) | ||
110 | { | ||
111 | int ret = 0; | ||
112 | |||
113 | ret = twl_i2c_write_u8(module, data, address); | ||
114 | if (ret < 0) | ||
115 | dev_err(twl->dev, | ||
116 | "Write[0x%x] Error %d\n", address, ret); | ||
117 | return ret; | ||
118 | } | ||
119 | |||
120 | static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address) | ||
121 | { | ||
122 | u8 data, ret = 0; | ||
123 | |||
124 | ret = twl_i2c_read_u8(module, &data, address); | ||
125 | if (ret >= 0) | ||
126 | ret = data; | ||
127 | else | ||
128 | dev_err(twl->dev, | ||
129 | "readb[0x%x,0x%x] Error %d\n", | ||
130 | module, address, ret); | ||
131 | return ret; | ||
132 | } | ||
133 | |||
134 | /*-------------------------------------------------------------------------*/ | ||
135 | static int twl6030_set_phy_clk(struct otg_transceiver *x, int on) | ||
136 | { | ||
137 | struct twl6030_usb *twl; | ||
138 | struct device *dev; | ||
139 | struct twl4030_usb_data *pdata; | ||
140 | |||
141 | twl = xceiv_to_twl(x); | ||
142 | dev = twl->dev; | ||
143 | pdata = dev->platform_data; | ||
144 | |||
145 | pdata->phy_set_clock(twl->dev, on); | ||
146 | |||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | static int twl6030_phy_init(struct otg_transceiver *x) | ||
151 | { | ||
152 | u8 hw_state; | ||
153 | struct twl6030_usb *twl; | ||
154 | struct device *dev; | ||
155 | struct twl4030_usb_data *pdata; | ||
156 | |||
157 | twl = xceiv_to_twl(x); | ||
158 | dev = twl->dev; | ||
159 | pdata = dev->platform_data; | ||
160 | |||
161 | regulator_enable(twl->usb3v3); | ||
162 | |||
163 | hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); | ||
164 | |||
165 | if (hw_state & STS_USB_ID) | ||
166 | pdata->phy_power(twl->dev, 1, 1); | ||
167 | else | ||
168 | pdata->phy_power(twl->dev, 0, 1); | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | static void twl6030_phy_shutdown(struct otg_transceiver *x) | ||
174 | { | ||
175 | struct twl6030_usb *twl; | ||
176 | struct device *dev; | ||
177 | struct twl4030_usb_data *pdata; | ||
178 | |||
179 | twl = xceiv_to_twl(x); | ||
180 | dev = twl->dev; | ||
181 | pdata = dev->platform_data; | ||
182 | pdata->phy_power(twl->dev, 0, 0); | ||
183 | regulator_disable(twl->usb3v3); | ||
184 | } | ||
185 | |||
186 | static int twl6030_usb_ldo_init(struct twl6030_usb *twl) | ||
187 | { | ||
188 | |||
189 | /* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */ | ||
190 | twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG); | ||
191 | |||
192 | /* Program CFG_LDO_PD2 register and set VUSB bit */ | ||
193 | twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_CFG_LDO_PD2); | ||
194 | |||
195 | /* Program MISC2 register and set bit VUSB_IN_VBAT */ | ||
196 | twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2); | ||
197 | |||
198 | twl->usb3v3 = regulator_get(twl->dev, "vusb"); | ||
199 | if (IS_ERR(twl->usb3v3)) | ||
200 | return -ENODEV; | ||
201 | |||
202 | regulator_enable(twl->usb3v3); | ||
203 | |||
204 | /* Program the VUSB_CFG_TRANS for ACTIVE state. */ | ||
205 | twl6030_writeb(twl, TWL_MODULE_PM_RECEIVER, 0x3F, | ||
206 | VUSB_CFG_TRANS); | ||
207 | |||
208 | /* Program the VUSB_CFG_STATE register to ON on all groups. */ | ||
209 | twl6030_writeb(twl, TWL_MODULE_PM_RECEIVER, 0xE1, | ||
210 | VUSB_CFG_STATE); | ||
211 | |||
212 | /* Program the USB_VBUS_CTRL_SET and set VBUS_ACT_COMP bit */ | ||
213 | twl6030_writeb(twl, TWL_MODULE_USB, 0x4, USB_VBUS_CTRL_SET); | ||
214 | |||
215 | /* | ||
216 | * Program the USB_ID_CTRL_SET register to enable GND drive | ||
217 | * and the ID comparators | ||
218 | */ | ||
219 | twl6030_writeb(twl, TWL_MODULE_USB, 0x14, USB_ID_CTRL_SET); | ||
220 | |||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | static ssize_t twl6030_usb_vbus_show(struct device *dev, | ||
225 | struct device_attribute *attr, char *buf) | ||
226 | { | ||
227 | struct twl6030_usb *twl = dev_get_drvdata(dev); | ||
228 | unsigned long flags; | ||
229 | int ret = -EINVAL; | ||
230 | |||
231 | spin_lock_irqsave(&twl->lock, flags); | ||
232 | |||
233 | switch (twl->linkstat) { | ||
234 | case USB_EVENT_VBUS: | ||
235 | ret = snprintf(buf, PAGE_SIZE, "vbus\n"); | ||
236 | break; | ||
237 | case USB_EVENT_ID: | ||
238 | ret = snprintf(buf, PAGE_SIZE, "id\n"); | ||
239 | break; | ||
240 | case USB_EVENT_NONE: | ||
241 | ret = snprintf(buf, PAGE_SIZE, "none\n"); | ||
242 | break; | ||
243 | default: | ||
244 | ret = snprintf(buf, PAGE_SIZE, "UNKNOWN\n"); | ||
245 | } | ||
246 | spin_unlock_irqrestore(&twl->lock, flags); | ||
247 | |||
248 | return ret; | ||
249 | } | ||
250 | static DEVICE_ATTR(vbus, 0444, twl6030_usb_vbus_show, NULL); | ||
251 | |||
252 | static irqreturn_t twl6030_usb_irq(int irq, void *_twl) | ||
253 | { | ||
254 | struct twl6030_usb *twl = _twl; | ||
255 | int status; | ||
256 | u8 vbus_state, hw_state; | ||
257 | |||
258 | hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); | ||
259 | |||
260 | vbus_state = twl6030_readb(twl, TWL_MODULE_MAIN_CHARGE, | ||
261 | CONTROLLER_STAT1); | ||
262 | if (!(hw_state & STS_USB_ID)) { | ||
263 | if (vbus_state & VBUS_DET) { | ||
264 | status = USB_EVENT_VBUS; | ||
265 | twl->otg.default_a = false; | ||
266 | twl->otg.state = OTG_STATE_B_IDLE; | ||
267 | } else { | ||
268 | status = USB_EVENT_NONE; | ||
269 | } | ||
270 | if (status >= 0) { | ||
271 | twl->linkstat = status; | ||
272 | blocking_notifier_call_chain(&twl->otg.notifier, | ||
273 | status, twl->otg.gadget); | ||
274 | } | ||
275 | } | ||
276 | sysfs_notify(&twl->dev->kobj, NULL, "vbus"); | ||
277 | |||
278 | return IRQ_HANDLED; | ||
279 | } | ||
280 | |||
281 | static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) | ||
282 | { | ||
283 | struct twl6030_usb *twl = _twl; | ||
284 | int status = USB_EVENT_NONE; | ||
285 | u8 hw_state; | ||
286 | |||
287 | hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); | ||
288 | |||
289 | if (hw_state & STS_USB_ID) { | ||
290 | |||
291 | twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, 0x1); | ||
292 | twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, | ||
293 | 0x10); | ||
294 | status = USB_EVENT_ID; | ||
295 | twl->otg.default_a = true; | ||
296 | twl->otg.state = OTG_STATE_A_IDLE; | ||
297 | blocking_notifier_call_chain(&twl->otg.notifier, status, | ||
298 | twl->otg.gadget); | ||
299 | } else { | ||
300 | twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, | ||
301 | 0x10); | ||
302 | twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, | ||
303 | 0x1); | ||
304 | } | ||
305 | twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_LATCH_CLR, status); | ||
306 | twl->linkstat = status; | ||
307 | |||
308 | return IRQ_HANDLED; | ||
309 | } | ||
310 | |||
311 | static int twl6030_set_peripheral(struct otg_transceiver *x, | ||
312 | struct usb_gadget *gadget) | ||
313 | { | ||
314 | struct twl6030_usb *twl; | ||
315 | |||
316 | if (!x) | ||
317 | return -ENODEV; | ||
318 | |||
319 | twl = xceiv_to_twl(x); | ||
320 | twl->otg.gadget = gadget; | ||
321 | if (!gadget) | ||
322 | twl->otg.state = OTG_STATE_UNDEFINED; | ||
323 | |||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | static int twl6030_enable_irq(struct otg_transceiver *x) | ||
328 | { | ||
329 | struct twl6030_usb *twl = xceiv_to_twl(x); | ||
330 | |||
331 | twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, 0x1); | ||
332 | twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C); | ||
333 | twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C); | ||
334 | |||
335 | twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK, | ||
336 | REG_INT_MSK_LINE_C); | ||
337 | twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK, | ||
338 | REG_INT_MSK_STS_C); | ||
339 | twl6030_usb_irq(twl->irq2, twl); | ||
340 | twl6030_usbotg_irq(twl->irq1, twl); | ||
341 | |||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static int twl6030_set_vbus(struct otg_transceiver *x, bool enabled) | ||
346 | { | ||
347 | struct twl6030_usb *twl = xceiv_to_twl(x); | ||
348 | |||
349 | /* | ||
350 | * Start driving VBUS. Set OPA_MODE bit in CHARGERUSB_CTRL1 | ||
351 | * register. This enables boost mode. | ||
352 | */ | ||
353 | if (enabled) | ||
354 | twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x40, | ||
355 | CHARGERUSB_CTRL1); | ||
356 | else | ||
357 | twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x00, | ||
358 | CHARGERUSB_CTRL1); | ||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | static int twl6030_set_host(struct otg_transceiver *x, struct usb_bus *host) | ||
363 | { | ||
364 | struct twl6030_usb *twl; | ||
365 | |||
366 | if (!x) | ||
367 | return -ENODEV; | ||
368 | |||
369 | twl = xceiv_to_twl(x); | ||
370 | twl->otg.host = host; | ||
371 | if (!host) | ||
372 | twl->otg.state = OTG_STATE_UNDEFINED; | ||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | static int __devinit twl6030_usb_probe(struct platform_device *pdev) | ||
377 | { | ||
378 | struct twl6030_usb *twl; | ||
379 | int status, err; | ||
380 | struct twl4030_usb_data *pdata; | ||
381 | struct device *dev = &pdev->dev; | ||
382 | pdata = dev->platform_data; | ||
383 | |||
384 | twl = kzalloc(sizeof *twl, GFP_KERNEL); | ||
385 | if (!twl) | ||
386 | return -ENOMEM; | ||
387 | |||
388 | twl->dev = &pdev->dev; | ||
389 | twl->irq1 = platform_get_irq(pdev, 0); | ||
390 | twl->irq2 = platform_get_irq(pdev, 1); | ||
391 | twl->otg.dev = twl->dev; | ||
392 | twl->otg.label = "twl6030"; | ||
393 | twl->otg.set_host = twl6030_set_host; | ||
394 | twl->otg.set_peripheral = twl6030_set_peripheral; | ||
395 | twl->otg.set_vbus = twl6030_set_vbus; | ||
396 | twl->otg.init = twl6030_phy_init; | ||
397 | twl->otg.shutdown = twl6030_phy_shutdown; | ||
398 | |||
399 | /* init spinlock for workqueue */ | ||
400 | spin_lock_init(&twl->lock); | ||
401 | |||
402 | err = twl6030_usb_ldo_init(twl); | ||
403 | if (err) { | ||
404 | dev_err(&pdev->dev, "ldo init failed\n"); | ||
405 | kfree(twl); | ||
406 | return err; | ||
407 | } | ||
408 | otg_set_transceiver(&twl->otg); | ||
409 | |||
410 | platform_set_drvdata(pdev, twl); | ||
411 | if (device_create_file(&pdev->dev, &dev_attr_vbus)) | ||
412 | dev_warn(&pdev->dev, "could not create sysfs file\n"); | ||
413 | |||
414 | BLOCKING_INIT_NOTIFIER_HEAD(&twl->otg.notifier); | ||
415 | |||
416 | twl->irq_enabled = true; | ||
417 | status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq, | ||
418 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | ||
419 | "twl6030_usb", twl); | ||
420 | if (status < 0) { | ||
421 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", | ||
422 | twl->irq1, status); | ||
423 | device_remove_file(twl->dev, &dev_attr_vbus); | ||
424 | kfree(twl); | ||
425 | return status; | ||
426 | } | ||
427 | |||
428 | status = request_threaded_irq(twl->irq2, NULL, twl6030_usb_irq, | ||
429 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | ||
430 | "twl6030_usb", twl); | ||
431 | if (status < 0) { | ||
432 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", | ||
433 | twl->irq2, status); | ||
434 | free_irq(twl->irq1, twl); | ||
435 | device_remove_file(twl->dev, &dev_attr_vbus); | ||
436 | kfree(twl); | ||
437 | return status; | ||
438 | } | ||
439 | |||
440 | pdata->phy_init(dev); | ||
441 | twl6030_enable_irq(&twl->otg); | ||
442 | dev_info(&pdev->dev, "Initialized TWL6030 USB module\n"); | ||
443 | |||
444 | return 0; | ||
445 | } | ||
446 | |||
447 | static int __exit twl6030_usb_remove(struct platform_device *pdev) | ||
448 | { | ||
449 | struct twl6030_usb *twl = platform_get_drvdata(pdev); | ||
450 | |||
451 | struct twl4030_usb_data *pdata; | ||
452 | struct device *dev = &pdev->dev; | ||
453 | pdata = dev->platform_data; | ||
454 | |||
455 | twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, | ||
456 | REG_INT_MSK_LINE_C); | ||
457 | twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, | ||
458 | REG_INT_MSK_STS_C); | ||
459 | free_irq(twl->irq1, twl); | ||
460 | free_irq(twl->irq2, twl); | ||
461 | regulator_put(twl->usb3v3); | ||
462 | pdata->phy_exit(twl->dev); | ||
463 | device_remove_file(twl->dev, &dev_attr_vbus); | ||
464 | kfree(twl); | ||
465 | |||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | static struct platform_driver twl6030_usb_driver = { | ||
470 | .probe = twl6030_usb_probe, | ||
471 | .remove = __exit_p(twl6030_usb_remove), | ||
472 | .driver = { | ||
473 | .name = "twl6030_usb", | ||
474 | .owner = THIS_MODULE, | ||
475 | }, | ||
476 | }; | ||
477 | |||
478 | static int __init twl6030_usb_init(void) | ||
479 | { | ||
480 | return platform_driver_register(&twl6030_usb_driver); | ||
481 | } | ||
482 | subsys_initcall(twl6030_usb_init); | ||
483 | |||
484 | static void __exit twl6030_usb_exit(void) | ||
485 | { | ||
486 | platform_driver_unregister(&twl6030_usb_driver); | ||
487 | } | ||
488 | module_exit(twl6030_usb_exit); | ||
489 | |||
490 | MODULE_ALIAS("platform:twl6030_usb"); | ||
491 | MODULE_AUTHOR("Hema HK <hemahk@ti.com>"); | ||
492 | MODULE_DESCRIPTION("TWL6030 USB transceiver driver"); | ||
493 | MODULE_LICENSE("GPL"); | ||