1/* 2 * Platform level USB initialization for FS USB OTG controller on omap1 and 24xx 3 * 4 * Copyright (C) 2004 Texas Instruments, Inc. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21#include <linux/module.h> 22#include <linux/kernel.h> 23#include <linux/types.h> 24#include <linux/errno.h> 25#include <linux/init.h> 26#include <linux/platform_device.h> 27#include <linux/clk.h> 28#include <linux/err.h> 29 30#include <asm/irq.h> 31 32#include <plat/control.h> 33#include <plat/usb.h> 34#include <plat/board.h> 35 36#define INT_USB_IRQ_GEN INT_24XX_USB_IRQ_GEN 37#define INT_USB_IRQ_NISO INT_24XX_USB_IRQ_NISO 38#define INT_USB_IRQ_ISO INT_24XX_USB_IRQ_ISO 39#define INT_USB_IRQ_HGEN INT_24XX_USB_IRQ_HGEN 40#define INT_USB_IRQ_OTG INT_24XX_USB_IRQ_OTG 41 42#include "mux.h" 43 44#if defined(CONFIG_ARCH_OMAP2) 45 46#ifdef CONFIG_USB_GADGET_OMAP 47 48static struct resource udc_resources[] = { 49 /* order is significant! */ 50 { /* registers */ 51 .start = UDC_BASE, 52 .end = UDC_BASE + 0xff, 53 .flags = IORESOURCE_MEM, 54 }, { /* general IRQ */ 55 .start = INT_USB_IRQ_GEN, 56 .flags = IORESOURCE_IRQ, 57 }, { /* PIO IRQ */ 58 .start = INT_USB_IRQ_NISO, 59 .flags = IORESOURCE_IRQ, 60 }, { /* SOF IRQ */ 61 .start = INT_USB_IRQ_ISO, 62 .flags = IORESOURCE_IRQ, 63 }, 64}; 65 66static u64 udc_dmamask = ~(u32)0; 67 68static struct platform_device udc_device = { 69 .name = "omap_udc", 70 .id = -1, 71 .dev = { 72 .dma_mask = &udc_dmamask, 73 .coherent_dma_mask = 0xffffffff, 74 }, 75 .num_resources = ARRAY_SIZE(udc_resources), 76 .resource = udc_resources, 77}; 78 79static inline void udc_device_init(struct omap_usb_config *pdata) 80{ 81 pdata->udc_device = &udc_device; 82} 83 84#else 85 86static inline void udc_device_init(struct omap_usb_config *pdata) 87{ 88} 89 90#endif 91 92#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) 93 94/* The dmamask must be set for OHCI to work */ 95static u64 ohci_dmamask = ~(u32)0; 96 97static struct resource ohci_resources[] = { 98 { 99 .start = OMAP_OHCI_BASE, 100 .end = OMAP_OHCI_BASE + 0xff, 101 .flags = IORESOURCE_MEM, 102 }, 103 { 104 .start = INT_USB_IRQ_HGEN, 105 .flags = IORESOURCE_IRQ, 106 }, 107}; 108 109static struct platform_device ohci_device = { 110 .name = "ohci", 111 .id = -1, 112 .dev = { 113 .dma_mask = &ohci_dmamask, 114 .coherent_dma_mask = 0xffffffff, 115 }, 116 .num_resources = ARRAY_SIZE(ohci_resources), 117 .resource = ohci_resources, 118}; 119 120static inline void ohci_device_init(struct omap_usb_config *pdata) 121{ 122 pdata->ohci_device = &ohci_device; 123} 124 125#else 126 127static inline void ohci_device_init(struct omap_usb_config *pdata) 128{ 129} 130 131#endif 132 133#if defined(CONFIG_USB_OTG) && defined(CONFIG_ARCH_OMAP_OTG) 134 135static struct resource otg_resources[] = { 136 /* order is significant! */ 137 { 138 .start = OTG_BASE, 139 .end = OTG_BASE + 0xff, 140 .flags = IORESOURCE_MEM, 141 }, { 142 .start = INT_USB_IRQ_OTG, 143 .flags = IORESOURCE_IRQ, 144 }, 145}; 146 147static struct platform_device otg_device = { 148 .name = "omap_otg", 149 .id = -1, 150 .num_resources = ARRAY_SIZE(otg_resources), 151 .resource = otg_resources, 152}; 153 154static inline void otg_device_init(struct omap_usb_config *pdata) 155{ 156 pdata->otg_device = &otg_device; 157} 158 159#else 160 161static inline void otg_device_init(struct omap_usb_config *pdata) 162{ 163} 164 165#endif 166 167static void omap2_usb_devconf_clear(u8 port, u32 mask) 168{ 169 u32 r; 170 171 r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); 172 r &= ~USBTXWRMODEI(port, mask); 173 omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0); 174} 175 176static void omap2_usb_devconf_set(u8 port, u32 mask) 177{ 178 u32 r; 179 180 r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); 181 r |= USBTXWRMODEI(port, mask); 182 omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0); 183} 184 185static void omap2_usb2_disable_5pinbitll(void) 186{ 187 u32 r; 188 189 r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); 190 r &= ~(USBTXWRMODEI(2, USB_BIDIR_TLL) | USBT2TLL5PI); 191 omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0); 192} 193 194static void omap2_usb2_enable_5pinunitll(void) 195{ 196 u32 r; 197 198 r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); 199 r |= USBTXWRMODEI(2, USB_UNIDIR_TLL) | USBT2TLL5PI; 200 omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0); 201} 202 203static u32 __init omap2_usb0_init(unsigned nwires, unsigned is_device) 204{ 205 u32 syscon1 = 0; 206 207 omap2_usb_devconf_clear(0, USB_BIDIR_TLL); 208 209 if (nwires == 0) 210 return 0; 211 212 if (is_device) 213 omap_mux_init_signal("usb0_puen", 0); 214 215 omap_mux_init_signal("usb0_dat", 0); 216 omap_mux_init_signal("usb0_txen", 0); 217 omap_mux_init_signal("usb0_se0", 0); 218 if (nwires != 3) 219 omap_mux_init_signal("usb0_rcv", 0); 220 221 switch (nwires) { 222 case 3: 223 syscon1 = 2; 224 omap2_usb_devconf_set(0, USB_BIDIR); 225 break; 226 case 4: 227 syscon1 = 1; 228 omap2_usb_devconf_set(0, USB_BIDIR); 229 break; 230 case 6: 231 syscon1 = 3; 232 omap_mux_init_signal("usb0_vp", 0); 233 omap_mux_init_signal("usb0_vm", 0); 234 omap2_usb_devconf_set(0, USB_UNIDIR); 235 break; 236 default: 237 printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", 238 0, nwires); 239 } 240 241 return syscon1 << 16; 242} 243 244static u32 __init omap2_usb1_init(unsigned nwires) 245{ 246 u32 syscon1 = 0; 247 248 omap2_usb_devconf_clear(1, USB_BIDIR_TLL); 249 250 if (nwires == 0) 251 return 0; 252 253 /* NOTE: board-specific code must set up pin muxing for usb1, 254 * since each signal could come out on either of two balls. 255 */ 256 257 switch (nwires) { 258 case 2: 259 /* NOTE: board-specific code must override this setting if 260 * this TLL link is not using DP/DM 261 */ 262 syscon1 = 1; 263 omap2_usb_devconf_set(1, USB_BIDIR_TLL); 264 break; 265 case 3: 266 syscon1 = 2; 267 omap2_usb_devconf_set(1, USB_BIDIR); 268 break; 269 case 4: 270 syscon1 = 1; 271 omap2_usb_devconf_set(1, USB_BIDIR); 272 break; 273 case 6: 274 default: 275 printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", 276 1, nwires); 277 } 278 279 return syscon1 << 20; 280} 281 282static u32 __init omap2_usb2_init(unsigned nwires, unsigned alt_pingroup) 283{ 284 u32 syscon1 = 0; 285 286 omap2_usb2_disable_5pinbitll(); 287 alt_pingroup = 0; 288 289 /* NOTE omap1 erratum: must leave USB2_UNI_R set if usb0 in use */ 290 if (alt_pingroup || nwires == 0) 291 return 0; 292 293 omap_mux_init_signal("usb2_dat", 0); 294 omap_mux_init_signal("usb2_se0", 0); 295 if (nwires > 2) 296 omap_mux_init_signal("usb2_txen", 0); 297 if (nwires > 3) 298 omap_mux_init_signal("usb2_rcv", 0); 299 300 switch (nwires) { 301 case 2: 302 /* NOTE: board-specific code must override this setting if 303 * this TLL link is not using DP/DM 304 */ 305 syscon1 = 1; 306 omap2_usb_devconf_set(2, USB_BIDIR_TLL); 307 break; 308 case 3: 309 syscon1 = 2; 310 omap2_usb_devconf_set(2, USB_BIDIR); 311 break; 312 case 4: 313 syscon1 = 1; 314 omap2_usb_devconf_set(2, USB_BIDIR); 315 break; 316 case 5: 317 /* NOTE: board-specific code must mux this setting depending 318 * on TLL link using DP/DM. Something must also 319 * set up OTG_SYSCON2.HMC_TLL{ATTACH,SPEED} 320 * 2420: hdq_sio.usb2_tllse0 or vlynq_rx0.usb2_tllse0 321 * 2430: hdq_sio.usb2_tllse0 or sdmmc2_dat0.usb2_tllse0 322 */ 323 324 syscon1 = 3; 325 omap2_usb2_enable_5pinunitll(); 326 break; 327 case 6: 328 default: 329 printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", 330 2, nwires); 331 } 332 333 return syscon1 << 24; 334} 335 336void __init omap2_usbfs_init(struct omap_usb_config *pdata) 337{ 338 struct clk *ick; 339 340 if (!cpu_is_omap24xx()) 341 return; 342 343 ick = clk_get(NULL, "usb_l4_ick"); 344 if (IS_ERR(ick)) 345 return; 346 347 clk_enable(ick); 348 pdata->usb0_init = omap2_usb0_init; 349 pdata->usb1_init = omap2_usb1_init; 350 pdata->usb2_init = omap2_usb2_init; 351 udc_device_init(pdata); 352 ohci_device_init(pdata); 353 otg_device_init(pdata); 354 omap_otg_init(pdata); 355 clk_disable(ick); 356 clk_put(ick); 357} 358 359#endif 360