diff options
| author | David VomLehn <dvomlehn@cisco.com> | 2010-08-02 21:40:58 -0400 |
|---|---|---|
| committer | Ralf Baechle <ralf@linux-mips.org> | 2010-08-05 08:26:34 -0400 |
| commit | 0d365753d0b7c26043fdfa97790411606fb40112 (patch) | |
| tree | 8ad3a06bf6c5299151a611d55c7e5b2a5d63fec6 | |
| parent | 5089ca9d31b0250f42ccd0e0a41b3547f22a20a0 (diff) | |
MIPS: PowerTV: Separate PowerTV USB support from non-USB code
Separate USB code into a file separate from asic/asic_devices.
Separating the USB code from everything else in asic/asic_devices.c goes
a long way toward reducing the use of that file as a dumping ground for
everything that didn't seem to fit anywhere else.
Signed-off-by: David VomLehn <dvomlehn@cisco.com>
To: linux-mips@linux-mips.org
Cc: greg@kroah.com
Cc: linux-usb@vger.kernel.org
Patchwork: http://patchwork.linux-mips.org/patch/1522/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
| -rw-r--r-- | arch/mips/include/asm/mach-powertv/asic.h | 17 | ||||
| -rw-r--r-- | arch/mips/include/asm/mach-powertv/asic_regs.h | 1 | ||||
| -rw-r--r-- | arch/mips/powertv/Makefile | 2 | ||||
| -rw-r--r-- | arch/mips/powertv/asic/asic_devices.c | 238 | ||||
| -rw-r--r-- | arch/mips/powertv/powertv-usb.c | 403 |
5 files changed, 432 insertions, 229 deletions
diff --git a/arch/mips/include/asm/mach-powertv/asic.h b/arch/mips/include/asm/mach-powertv/asic.h index df33d93e4f56..c7077a64b9a7 100644 --- a/arch/mips/include/asm/mach-powertv/asic.h +++ b/arch/mips/include/asm/mach-powertv/asic.h | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #define _ASM_MACH_POWERTV_ASIC_H | 20 | #define _ASM_MACH_POWERTV_ASIC_H |
| 21 | 21 | ||
| 22 | #include <linux/ioport.h> | 22 | #include <linux/ioport.h> |
| 23 | #include <linux/platform_device.h> | ||
| 23 | #include <asm/mach-powertv/asic_regs.h> | 24 | #include <asm/mach-powertv/asic_regs.h> |
| 24 | 25 | ||
| 25 | #define DVR_CAPABLE (1<<0) | 26 | #define DVR_CAPABLE (1<<0) |
| @@ -71,16 +72,24 @@ extern int platform_supports_ffs(void); | |||
| 71 | extern int platform_supports_pcie(void); | 72 | extern int platform_supports_pcie(void); |
| 72 | extern int platform_supports_display(void); | 73 | extern int platform_supports_display(void); |
| 73 | extern void configure_platform(void); | 74 | extern void configure_platform(void); |
| 74 | extern void platform_configure_usb_ehci(void); | ||
| 75 | extern void platform_unconfigure_usb_ehci(void); | ||
| 76 | extern void platform_configure_usb_ohci(void); | ||
| 77 | extern void platform_unconfigure_usb_ohci(void); | ||
| 78 | 75 | ||
| 79 | /* Platform Resources */ | 76 | /* Platform Resources */ |
| 80 | #define ASIC_RESOURCE_GET_EXISTS 1 | 77 | #define ASIC_RESOURCE_GET_EXISTS 1 |
| 81 | extern struct resource *asic_resource_get(const char *name); | 78 | extern struct resource *asic_resource_get(const char *name); |
| 82 | extern void platform_release_memory(void *baddr, int size); | 79 | extern void platform_release_memory(void *baddr, int size); |
| 83 | 80 | ||
| 81 | /* USB configuration */ | ||
| 82 | struct usb_hcd; /* Forward reference */ | ||
| 83 | extern void platform_configure_usb_ehci(void); | ||
| 84 | extern void platform_unconfigure_usb_ehci(void); | ||
| 85 | extern void platform_configure_usb_ohci(void); | ||
| 86 | extern void platform_unconfigure_usb_ohci(void); | ||
| 87 | |||
| 88 | /* Resource for ASIC registers */ | ||
| 89 | extern struct resource asic_resource; | ||
| 90 | extern int platform_usb_devices_init(struct platform_device **echi_dev, | ||
| 91 | struct platform_device **ohci_dev); | ||
| 92 | |||
| 84 | /* Reboot Cause */ | 93 | /* Reboot Cause */ |
| 85 | extern void set_reboot_cause(char code, unsigned int data, unsigned int data2); | 94 | extern void set_reboot_cause(char code, unsigned int data, unsigned int data2); |
| 86 | extern void set_locked_reboot_cause(char code, unsigned int data, | 95 | extern void set_locked_reboot_cause(char code, unsigned int data, |
diff --git a/arch/mips/include/asm/mach-powertv/asic_regs.h b/arch/mips/include/asm/mach-powertv/asic_regs.h index 2657ae6a7ec7..deecb26a077e 100644 --- a/arch/mips/include/asm/mach-powertv/asic_regs.h +++ b/arch/mips/include/asm/mach-powertv/asic_regs.h | |||
| @@ -101,6 +101,7 @@ static inline void register_map_virtualize(struct register_map *map) | |||
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | extern struct register_map _asic_register_map; | 103 | extern struct register_map _asic_register_map; |
| 104 | extern unsigned long asic_phy_base; | ||
| 104 | 105 | ||
| 105 | /* | 106 | /* |
| 106 | * Macros to interface to registers through their ioremapped address | 107 | * Macros to interface to registers through their ioremapped address |
diff --git a/arch/mips/powertv/Makefile b/arch/mips/powertv/Makefile index 506c4ca9d44a..baf6e9092a9f 100644 --- a/arch/mips/powertv/Makefile +++ b/arch/mips/powertv/Makefile | |||
| @@ -26,4 +26,6 @@ | |||
| 26 | obj-y += init.o ioremap.o memory.o powertv_setup.o reset.o time.o \ | 26 | obj-y += init.o ioremap.o memory.o powertv_setup.o reset.o time.o \ |
| 27 | asic/ pci/ | 27 | asic/ pci/ |
| 28 | 28 | ||
| 29 | obj-$(CONFIG_USB) += powertv-usb.o | ||
| 30 | |||
| 29 | EXTRA_CFLAGS += -Wall | 31 | EXTRA_CFLAGS += -Wall |
diff --git a/arch/mips/powertv/asic/asic_devices.c b/arch/mips/powertv/asic/asic_devices.c index 095a887df39c..e56fa61b3991 100644 --- a/arch/mips/powertv/asic/asic_devices.c +++ b/arch/mips/powertv/asic/asic_devices.c | |||
| @@ -33,7 +33,6 @@ | |||
| 33 | #include <linux/mm.h> | 33 | #include <linux/mm.h> |
| 34 | #include <linux/platform_device.h> | 34 | #include <linux/platform_device.h> |
| 35 | #include <linux/module.h> | 35 | #include <linux/module.h> |
| 36 | #include <linux/gfp.h> | ||
| 37 | #include <asm/page.h> | 36 | #include <asm/page.h> |
| 38 | #include <linux/swap.h> | 37 | #include <linux/swap.h> |
| 39 | #include <linux/highmem.h> | 38 | #include <linux/highmem.h> |
| @@ -68,7 +67,6 @@ unsigned long asic_phy_base; | |||
| 68 | unsigned long asic_base; | 67 | unsigned long asic_base; |
| 69 | EXPORT_SYMBOL(asic_base); /* Exported for testing */ | 68 | EXPORT_SYMBOL(asic_base); /* Exported for testing */ |
| 70 | struct resource *gp_resources; | 69 | struct resource *gp_resources; |
| 71 | static bool usb_configured; | ||
| 72 | 70 | ||
| 73 | /* | 71 | /* |
| 74 | * Don't recommend to use it directly, it is usually used by kernel internally. | 72 | * Don't recommend to use it directly, it is usually used by kernel internally. |
| @@ -91,101 +89,19 @@ struct resource asic_resource = { | |||
| 91 | }; | 89 | }; |
| 92 | 90 | ||
| 93 | /* | 91 | /* |
| 94 | * | ||
| 95 | * USB Host Resource Definition | ||
| 96 | * | ||
| 97 | */ | ||
| 98 | |||
| 99 | static struct resource ehci_resources[] = { | ||
| 100 | { | ||
| 101 | .parent = &asic_resource, | ||
| 102 | .start = 0, | ||
| 103 | .end = 0xff, | ||
| 104 | .flags = IORESOURCE_MEM, | ||
| 105 | }, | ||
| 106 | { | ||
| 107 | .start = irq_usbehci, | ||
| 108 | .end = irq_usbehci, | ||
| 109 | .flags = IORESOURCE_IRQ, | ||
| 110 | }, | ||
| 111 | }; | ||
| 112 | |||
| 113 | static u64 ehci_dmamask = DMA_BIT_MASK(32); | ||
| 114 | |||
| 115 | static struct platform_device ehci_device = { | ||
| 116 | .name = "powertv-ehci", | ||
| 117 | .id = 0, | ||
| 118 | .num_resources = 2, | ||
| 119 | .resource = ehci_resources, | ||
| 120 | .dev = { | ||
| 121 | .dma_mask = &ehci_dmamask, | ||
| 122 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
| 123 | }, | ||
| 124 | }; | ||
| 125 | |||
| 126 | static struct resource ohci_resources[] = { | ||
| 127 | { | ||
| 128 | .parent = &asic_resource, | ||
| 129 | .start = 0, | ||
| 130 | .end = 0xff, | ||
| 131 | .flags = IORESOURCE_MEM, | ||
| 132 | }, | ||
| 133 | { | ||
| 134 | .start = irq_usbohci, | ||
| 135 | .end = irq_usbohci, | ||
| 136 | .flags = IORESOURCE_IRQ, | ||
| 137 | }, | ||
| 138 | }; | ||
| 139 | |||
| 140 | static u64 ohci_dmamask = DMA_BIT_MASK(32); | ||
| 141 | |||
| 142 | static struct platform_device ohci_device = { | ||
| 143 | .name = "powertv-ohci", | ||
| 144 | .id = 0, | ||
| 145 | .num_resources = 2, | ||
| 146 | .resource = ohci_resources, | ||
| 147 | .dev = { | ||
| 148 | .dma_mask = &ohci_dmamask, | ||
| 149 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
| 150 | }, | ||
| 151 | }; | ||
| 152 | |||
| 153 | static struct platform_device *platform_devices[] = { | ||
| 154 | &ehci_device, | ||
| 155 | &ohci_device, | ||
| 156 | }; | ||
| 157 | |||
| 158 | /* | ||
| 159 | * | ||
| 160 | * Platform Configuration and Device Initialization | ||
| 161 | * | ||
| 162 | */ | ||
| 163 | static void __init fs_update(int pe, int md, int sdiv, int disable_div_by_3) | ||
| 164 | { | ||
| 165 | int en_prg, byp, pwr, nsb, val; | ||
| 166 | int sout; | ||
| 167 | |||
| 168 | sout = 1; | ||
| 169 | en_prg = 1; | ||
| 170 | byp = 0; | ||
| 171 | nsb = 1; | ||
| 172 | pwr = 1; | ||
| 173 | |||
| 174 | val = ((sdiv << 29) | (md << 24) | (pe<<8) | (sout<<3) | (byp<<2) | | ||
| 175 | (nsb<<1) | (disable_div_by_3<<5)); | ||
| 176 | |||
| 177 | asic_write(val, fs432x4b4_usb_ctl); | ||
| 178 | asic_write(val | (en_prg<<4), fs432x4b4_usb_ctl); | ||
| 179 | asic_write(val | (en_prg<<4) | pwr, fs432x4b4_usb_ctl); | ||
| 180 | } | ||
| 181 | |||
| 182 | /* | ||
| 183 | * Allow override of bootloader-specified model | 92 | * Allow override of bootloader-specified model |
| 93 | * Returns zero on success, a negative errno value on failure. This parameter | ||
| 94 | * allows overriding of the bootloader-specified model. | ||
| 184 | */ | 95 | */ |
| 185 | static char __initdata cmdline[COMMAND_LINE_SIZE]; | 96 | static char __initdata cmdline[COMMAND_LINE_SIZE]; |
| 186 | 97 | ||
| 187 | #define FORCEFAMILY_PARAM "forcefamily" | 98 | #define FORCEFAMILY_PARAM "forcefamily" |
| 188 | 99 | ||
| 100 | /* | ||
| 101 | * check_forcefamily - check for, and parse, forcefamily command line parameter | ||
| 102 | * @forced_family: Pointer to two-character array in which to store the | ||
| 103 | * value of the forcedfamily parameter, if any. | ||
| 104 | */ | ||
| 189 | static __init int check_forcefamily(unsigned char forced_family[2]) | 105 | static __init int check_forcefamily(unsigned char forced_family[2]) |
| 190 | { | 106 | { |
| 191 | const char *p; | 107 | const char *p; |
| @@ -225,14 +141,10 @@ static __init int check_forcefamily(unsigned char forced_family[2]) | |||
| 225 | */ | 141 | */ |
| 226 | static __init noinline void platform_set_family(void) | 142 | static __init noinline void platform_set_family(void) |
| 227 | { | 143 | { |
| 228 | #define BOOTLDRFAMILY(byte1, byte0) (((byte1) << 8) | (byte0)) | ||
| 229 | |||
| 230 | unsigned char forced_family[2]; | 144 | unsigned char forced_family[2]; |
| 231 | unsigned short bootldr_family; | 145 | unsigned short bootldr_family; |
| 232 | 146 | ||
| 233 | check_forcefamily(forced_family); | 147 | if (check_forcefamily(forced_family) == 0) |
| 234 | |||
| 235 | if (forced_family[0] != '\0' && forced_family[1] != '\0') | ||
| 236 | bootldr_family = BOOTLDRFAMILY(forced_family[0], | 148 | bootldr_family = BOOTLDRFAMILY(forced_family[0], |
| 237 | forced_family[1]); | 149 | forced_family[1]); |
| 238 | else { | 150 | else { |
| @@ -298,24 +210,9 @@ unsigned int platform_get_family(void) | |||
| 298 | EXPORT_SYMBOL(platform_get_family); | 210 | EXPORT_SYMBOL(platform_get_family); |
| 299 | 211 | ||
| 300 | /* | 212 | /* |
| 301 | * \brief usb_eye_configure() for optimizing the USB eye on Calliope. | ||
| 302 | * | ||
| 303 | * \param unsigned int value saved to the register. | ||
| 304 | * | ||
| 305 | * \return none | ||
| 306 | * | ||
| 307 | */ | ||
| 308 | static void __init usb_eye_configure(unsigned int value) | ||
| 309 | { | ||
| 310 | asic_write(asic_read(crt_spare) | value, crt_spare); | ||
| 311 | } | ||
| 312 | |||
| 313 | /* | ||
| 314 | * platform_get_asic - determine the ASIC type. | 213 | * platform_get_asic - determine the ASIC type. |
| 315 | * | 214 | * |
| 316 | * \param none | 215 | * Returns the ASIC type, or ASIC_UNKNOWN if unknown |
| 317 | * | ||
| 318 | * \return ASIC type; ASIC_UNKNOWN if none | ||
| 319 | * | 216 | * |
| 320 | */ | 217 | */ |
| 321 | enum asic_type platform_get_asic(void) | 218 | enum asic_type platform_get_asic(void) |
| @@ -325,93 +222,10 @@ enum asic_type platform_get_asic(void) | |||
| 325 | EXPORT_SYMBOL(platform_get_asic); | 222 | EXPORT_SYMBOL(platform_get_asic); |
| 326 | 223 | ||
| 327 | /* | 224 | /* |
| 328 | * platform_configure_usb - usb configuration based on platform type. | 225 | * set_register_map - set ASIC register configuration |
| 329 | * @bcm1_usb2_ctl: value for the BCM1_USB2_CTL register, which is | 226 | * @phys_base: Physical address of the base of the ASIC registers |
| 330 | * quirky | 227 | * @map: Description of key ASIC registers |
| 331 | */ | ||
| 332 | static void __init platform_configure_usb(void) | ||
| 333 | { | ||
| 334 | u32 bcm1_usb2_ctl; | ||
| 335 | |||
| 336 | if (usb_configured) | ||
| 337 | return; | ||
| 338 | |||
| 339 | switch (asic) { | ||
| 340 | case ASIC_ZEUS: | ||
| 341 | case ASIC_CRONUS: | ||
| 342 | case ASIC_CRONUSLITE: | ||
| 343 | fs_update(0x0000, 0x11, 0x02, 0); | ||
| 344 | bcm1_usb2_ctl = 0x803; | ||
| 345 | break; | ||
| 346 | |||
| 347 | case ASIC_CALLIOPE: | ||
| 348 | fs_update(0x0000, 0x11, 0x02, 1); | ||
| 349 | |||
| 350 | switch (platform_family) { | ||
| 351 | case FAMILY_1500VZE: | ||
| 352 | break; | ||
| 353 | |||
| 354 | case FAMILY_1500VZF: | ||
| 355 | usb_eye_configure(0x003c0000); | ||
| 356 | break; | ||
| 357 | |||
| 358 | default: | ||
| 359 | usb_eye_configure(0x00300000); | ||
| 360 | break; | ||
| 361 | } | ||
| 362 | |||
| 363 | bcm1_usb2_ctl = 0x803; | ||
| 364 | break; | ||
| 365 | |||
| 366 | default: | ||
| 367 | pr_err("Unknown ASIC type: %d\n", asic); | ||
| 368 | break; | ||
| 369 | } | ||
| 370 | |||
| 371 | /* turn on USB power */ | ||
| 372 | asic_write(0, usb2_strap); | ||
| 373 | /* Enable all OHCI interrupts */ | ||
| 374 | asic_write(bcm1_usb2_ctl, usb2_control); | ||
| 375 | /* USB2_STBUS_OBC store32/load32 */ | ||
| 376 | asic_write(3, usb2_stbus_obc); | ||
| 377 | /* USB2_STBUS_MESS_SIZE 2 packets */ | ||
| 378 | asic_write(1, usb2_stbus_mess_size); | ||
| 379 | /* USB2_STBUS_CHUNK_SIZE 2 packets */ | ||
| 380 | asic_write(1, usb2_stbus_chunk_size); | ||
| 381 | |||
| 382 | usb_configured = true; | ||
| 383 | } | ||
| 384 | |||
| 385 | /* | ||
| 386 | * Set up the USB EHCI interface | ||
| 387 | */ | ||
| 388 | void platform_configure_usb_ehci() | ||
| 389 | { | ||
| 390 | platform_configure_usb(); | ||
| 391 | } | ||
| 392 | |||
| 393 | /* | ||
| 394 | * Set up the USB OHCI interface | ||
| 395 | */ | ||
| 396 | void platform_configure_usb_ohci() | ||
| 397 | { | ||
| 398 | platform_configure_usb(); | ||
| 399 | } | ||
| 400 | |||
| 401 | /* | ||
| 402 | * Shut the USB EHCI interface down--currently a NOP | ||
| 403 | */ | 228 | */ |
| 404 | void platform_unconfigure_usb_ehci() | ||
| 405 | { | ||
| 406 | } | ||
| 407 | |||
| 408 | /* | ||
| 409 | * Shut the USB OHCI interface down--currently a NOP | ||
| 410 | */ | ||
| 411 | void platform_unconfigure_usb_ohci() | ||
| 412 | { | ||
| 413 | } | ||
| 414 | |||
| 415 | static void __init set_register_map(unsigned long phys_base, | 229 | static void __init set_register_map(unsigned long phys_base, |
| 416 | const struct register_map *map) | 230 | const struct register_map *map) |
| 417 | { | 231 | { |
| @@ -560,34 +374,8 @@ void __init configure_platform(void) | |||
| 560 | } | 374 | } |
| 561 | } | 375 | } |
| 562 | 376 | ||
| 563 | /** | ||
| 564 | * platform_devices_init - sets up USB device resourse. | ||
| 565 | */ | ||
| 566 | static int __init platform_devices_init(void) | ||
| 567 | { | ||
| 568 | pr_notice("%s: ----- Initializing USB resources -----\n", __func__); | ||
| 569 | |||
| 570 | asic_resource.start = asic_phy_base; | ||
| 571 | asic_resource.end += asic_resource.start; | ||
| 572 | |||
| 573 | ehci_resources[0].start = asic_reg_phys_addr(ehci_hcapbase); | ||
| 574 | ehci_resources[0].end += ehci_resources[0].start; | ||
| 575 | |||
| 576 | ohci_resources[0].start = asic_reg_phys_addr(ohci_hc_revision); | ||
| 577 | ohci_resources[0].end += ohci_resources[0].start; | ||
| 578 | |||
| 579 | set_io_port_base(0); | ||
| 580 | |||
| 581 | platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); | ||
| 582 | |||
| 583 | return 0; | ||
| 584 | } | ||
| 585 | |||
| 586 | arch_initcall(platform_devices_init); | ||
| 587 | |||
| 588 | /* | 377 | /* |
| 589 | * | 378 | * RESOURCE ALLOCATION |
| 590 | * BOOTMEM ALLOCATION | ||
| 591 | * | 379 | * |
| 592 | */ | 380 | */ |
| 593 | /* | 381 | /* |
diff --git a/arch/mips/powertv/powertv-usb.c b/arch/mips/powertv/powertv-usb.c new file mode 100644 index 000000000000..6ac85cf7aa20 --- /dev/null +++ b/arch/mips/powertv/powertv-usb.c | |||
| @@ -0,0 +1,403 @@ | |||
| 1 | /* | ||
| 2 | * powertv-usb.c | ||
| 3 | * | ||
| 4 | * Description: ASIC-specific USB device setup and shutdown | ||
| 5 | * | ||
| 6 | * Copyright (C) 2005-2009 Scientific-Atlanta, Inc. | ||
| 7 | * Copyright (C) 2009 Cisco Systems, Inc. | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License as published by | ||
| 11 | * the Free Software Foundation; either version 2 of the License, or | ||
| 12 | * (at your option) any later version. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License | ||
| 20 | * along with this program; if not, write to the Free Software | ||
| 21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 22 | * | ||
| 23 | * Author: Ken Eppinett | ||
| 24 | * David Schleef <ds@schleef.org> | ||
| 25 | * | ||
| 26 | * NOTE: The bootloader allocates persistent memory at an address which is | ||
| 27 | * 16 MiB below the end of the highest address in KSEG0. All fixed | ||
| 28 | * address memory reservations must avoid this region. | ||
| 29 | */ | ||
| 30 | |||
| 31 | #include <linux/kernel.h> | ||
| 32 | #include <linux/ioport.h> | ||
| 33 | #include <linux/platform_device.h> | ||
| 34 | #include <asm/mach-powertv/asic.h> | ||
| 35 | #include <asm/mach-powertv/interrupts.h> | ||
| 36 | |||
| 37 | /* misc_clk_ctl1 values */ | ||
| 38 | #define MCC1_30MHZ_POWERUP_SELECT (1 << 14) | ||
| 39 | #define MCC1_DIV9 (1 << 13) | ||
| 40 | #define MCC1_ETHMIPS_POWERUP_SELECT (1 << 11) | ||
| 41 | #define MCC1_USB_POWERUP_SELECT (1 << 1) | ||
| 42 | #define MCC1_CLOCK108_POWERUP_SELECT (1 << 0) | ||
| 43 | |||
| 44 | /* Possible values for clock select */ | ||
| 45 | #define MCC1_USB_CLOCK_HIGH_Z (0 << 4) | ||
| 46 | #define MCC1_USB_CLOCK_48MHZ (1 << 4) | ||
| 47 | #define MCC1_USB_CLOCK_24MHZ (2 << 4) | ||
| 48 | #define MCC1_USB_CLOCK_6MHZ (3 << 4) | ||
| 49 | |||
| 50 | #define MCC1_CONFIG (MCC1_30MHZ_POWERUP_SELECT | \ | ||
| 51 | MCC1_DIV9 | \ | ||
| 52 | MCC1_ETHMIPS_POWERUP_SELECT | \ | ||
| 53 | MCC1_USB_POWERUP_SELECT | \ | ||
| 54 | MCC1_CLOCK108_POWERUP_SELECT) | ||
| 55 | |||
| 56 | /* misc_clk_ctl2 values */ | ||
| 57 | #define MCC2_GMII_GCLK_TO_PAD (1 << 31) | ||
| 58 | #define MCC2_ETHER125_0_CLOCK_SELECT (1 << 29) | ||
| 59 | #define MCC2_RMII_0_CLOCK_SELECT (1 << 28) | ||
| 60 | #define MCC2_GMII_TX0_CLOCK_SELECT (1 << 27) | ||
| 61 | #define MCC2_GMII_RX0_CLOCK_SELECT (1 << 26) | ||
| 62 | #define MCC2_ETHER125_1_CLOCK_SELECT (1 << 24) | ||
| 63 | #define MCC2_RMII_1_CLOCK_SELECT (1 << 23) | ||
| 64 | #define MCC2_GMII_TX1_CLOCK_SELECT (1 << 22) | ||
| 65 | #define MCC2_GMII_RX1_CLOCK_SELECT (1 << 21) | ||
| 66 | #define MCC2_ETHER125_2_CLOCK_SELECT (1 << 19) | ||
| 67 | #define MCC2_RMII_2_CLOCK_SELECT (1 << 18) | ||
| 68 | #define MCC2_GMII_TX2_CLOCK_SELECT (1 << 17) | ||
| 69 | #define MCC2_GMII_RX2_CLOCK_SELECT (1 << 16) | ||
| 70 | |||
| 71 | #define ETHER_CLK_CONFIG (MCC2_GMII_GCLK_TO_PAD | \ | ||
| 72 | MCC2_ETHER125_0_CLOCK_SELECT | \ | ||
| 73 | MCC2_RMII_0_CLOCK_SELECT | \ | ||
| 74 | MCC2_GMII_TX0_CLOCK_SELECT | \ | ||
| 75 | MCC2_GMII_RX0_CLOCK_SELECT | \ | ||
| 76 | MCC2_ETHER125_1_CLOCK_SELECT | \ | ||
| 77 | MCC2_RMII_1_CLOCK_SELECT | \ | ||
| 78 | MCC2_GMII_TX1_CLOCK_SELECT | \ | ||
| 79 | MCC2_GMII_RX1_CLOCK_SELECT | \ | ||
| 80 | MCC2_ETHER125_2_CLOCK_SELECT | \ | ||
| 81 | MCC2_RMII_2_CLOCK_SELECT | \ | ||
| 82 | MCC2_GMII_TX2_CLOCK_SELECT | \ | ||
| 83 | MCC2_GMII_RX2_CLOCK_SELECT) | ||
| 84 | |||
| 85 | /* misc_clk_ctl2 definitions for Gaia */ | ||
| 86 | #define FSX4A_REF_SELECT (1 << 16) | ||
| 87 | #define FSX4B_REF_SELECT (1 << 17) | ||
| 88 | #define FSX4C_REF_SELECT (1 << 18) | ||
| 89 | #define DDR_PLL_REF_SELECT (1 << 19) | ||
| 90 | #define MIPS_PLL_REF_SELECT (1 << 20) | ||
| 91 | |||
| 92 | /* Definitions for the QAM frequency select register FS432X4A4_QAM_CTL */ | ||
| 93 | #define QAM_FS_SDIV_SHIFT 29 | ||
| 94 | #define QAM_FS_MD_SHIFT 24 | ||
| 95 | #define QAM_FS_MD_MASK 0x1f /* Cut down to 5 bits */ | ||
| 96 | #define QAM_FS_PE_SHIFT 8 | ||
| 97 | |||
| 98 | #define QAM_FS_DISABLE_DIVIDE_BY_3 (1 << 5) | ||
| 99 | #define QAM_FS_ENABLE_PROGRAM (1 << 4) | ||
| 100 | #define QAM_FS_ENABLE_OUTPUT (1 << 3) | ||
| 101 | #define QAM_FS_SELECT_TEST_BYPASS (1 << 2) | ||
| 102 | #define QAM_FS_DISABLE_DIGITAL_STANDBY (1 << 1) | ||
| 103 | #define QAM_FS_CHOOSE_FS (1 << 0) | ||
| 104 | |||
| 105 | /* Definitions for fs432x4a_ctl register */ | ||
| 106 | #define QAM_FS_NSDIV_54MHZ (1 << 2) | ||
| 107 | |||
| 108 | /* Definitions for bcm1_usb2_ctl register */ | ||
| 109 | #define BCM1_USB2_CTL_BISTOK (1 << 11) | ||
| 110 | #define BCM1_USB2_CTL_PORT2_SHIFT_JK (1 << 7) | ||
| 111 | #define BCM1_USB2_CTL_PORT1_SHIFT_JK (1 << 6) | ||
| 112 | #define BCM1_USB2_CTL_PORT2_FAST_EDGE (1 << 5) | ||
| 113 | #define BCM1_USB2_CTL_PORT1_FAST_EDGE (1 << 4) | ||
| 114 | #define BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH (1 << 1) | ||
| 115 | #define BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH (1 << 0) | ||
| 116 | |||
| 117 | /* Definitions for crt_spare register */ | ||
| 118 | #define CRT_SPARE_PORT2_SHIFT_JK (1 << 21) | ||
| 119 | #define CRT_SPARE_PORT1_SHIFT_JK (1 << 20) | ||
| 120 | #define CRT_SPARE_PORT2_FAST_EDGE (1 << 19) | ||
| 121 | #define CRT_SPARE_PORT1_FAST_EDGE (1 << 18) | ||
| 122 | #define CRT_SPARE_DIVIDE_BY_9_FROM_432 (1 << 17) | ||
| 123 | #define CRT_SPARE_USB_DIVIDE_BY_9 (1 << 16) | ||
| 124 | |||
| 125 | /* Definitions for usb2_stbus_obc register */ | ||
| 126 | #define USB_STBUS_OBC_STORE32_LOAD32 0x3 | ||
| 127 | |||
| 128 | /* Definitions for usb2_stbus_mess_size register */ | ||
| 129 | #define USB2_STBUS_MESS_SIZE_2 0x1 /* 2 packets */ | ||
| 130 | |||
| 131 | /* Definitions for usb2_stbus_chunk_size register */ | ||
| 132 | #define USB2_STBUS_CHUNK_SIZE_2 0x1 /* 2 packets */ | ||
| 133 | |||
| 134 | /* Definitions for usb2_strap register */ | ||
| 135 | #define USB2_STRAP_HFREQ_SELECT 0x1 | ||
| 136 | |||
| 137 | /* | ||
| 138 | * USB Host Resource Definition | ||
| 139 | */ | ||
| 140 | |||
| 141 | static struct resource ehci_resources[] = { | ||
| 142 | { | ||
| 143 | .parent = &asic_resource, | ||
| 144 | .start = 0, | ||
| 145 | .end = 0xff, | ||
| 146 | .flags = IORESOURCE_MEM, | ||
| 147 | }, | ||
| 148 | { | ||
| 149 | .start = irq_usbehci, | ||
| 150 | .end = irq_usbehci, | ||
| 151 | .flags = IORESOURCE_IRQ, | ||
| 152 | }, | ||
| 153 | }; | ||
| 154 | |||
| 155 | static u64 ehci_dmamask = 0xffffffffULL; | ||
| 156 | |||
| 157 | static struct platform_device ehci_device = { | ||
| 158 | .name = "powertv-ehci", | ||
| 159 | .id = 0, | ||
| 160 | .num_resources = 2, | ||
| 161 | .resource = ehci_resources, | ||
| 162 | .dev = { | ||
| 163 | .dma_mask = &ehci_dmamask, | ||
| 164 | .coherent_dma_mask = 0xffffffff, | ||
| 165 | }, | ||
| 166 | }; | ||
| 167 | |||
| 168 | static struct resource ohci_resources[] = { | ||
| 169 | { | ||
| 170 | .parent = &asic_resource, | ||
| 171 | .start = 0, | ||
| 172 | .end = 0xff, | ||
| 173 | .flags = IORESOURCE_MEM, | ||
| 174 | }, | ||
| 175 | { | ||
| 176 | .start = irq_usbohci, | ||
| 177 | .end = irq_usbohci, | ||
| 178 | .flags = IORESOURCE_IRQ, | ||
| 179 | }, | ||
| 180 | }; | ||
| 181 | |||
| 182 | static u64 ohci_dmamask = 0xffffffffULL; | ||
| 183 | |||
| 184 | static struct platform_device ohci_device = { | ||
| 185 | .name = "powertv-ohci", | ||
| 186 | .id = 0, | ||
| 187 | .num_resources = 2, | ||
| 188 | .resource = ohci_resources, | ||
| 189 | .dev = { | ||
| 190 | .dma_mask = &ohci_dmamask, | ||
| 191 | .coherent_dma_mask = 0xffffffff, | ||
| 192 | }, | ||
| 193 | }; | ||
| 194 | |||
| 195 | static unsigned usb_users; | ||
| 196 | static DEFINE_SPINLOCK(usb_regs_lock); | ||
| 197 | |||
| 198 | /* | ||
| 199 | * | ||
| 200 | * fs_update - set frequency synthesizer for USB | ||
| 201 | * @pe_bits Phase tap setting | ||
| 202 | * @md_bits Coarse selector bus for algorithm of phase tap | ||
| 203 | * @sdiv_bits Output divider setting | ||
| 204 | * @disable_div_by_3 Either QAM_FS_DISABLE_DIVIDE_BY_3 or zero | ||
| 205 | * @standby Either QAM_FS_DISABLE_DIGITAL_STANDBY or zero | ||
| 206 | * | ||
| 207 | * QAM frequency selection code, which affects the frequency at which USB | ||
| 208 | * runs. The frequency is calculated as: | ||
| 209 | * 2^15 * ndiv * Fin | ||
| 210 | * Fout = ------------------------------------------------------------ | ||
| 211 | * (sdiv * (ipe * (1 + md/32) - (ipe - 2^15)*(1 + (md + 1)/32))) | ||
| 212 | * where: | ||
| 213 | * Fin 54 MHz | ||
| 214 | * ndiv QAM_FS_NSDIV_54MHZ ? 8 : 16 | ||
| 215 | * sdiv 1 << (sdiv_bits + 1) | ||
| 216 | * ipe Same as pe_bits | ||
| 217 | * md A five-bit, two's-complement integer (range [-16, 15]), which | ||
| 218 | * is the lower 5 bits of md_bits. | ||
| 219 | */ | ||
| 220 | static void fs_update(u32 pe_bits, int md_bits, u32 sdiv_bits, | ||
| 221 | u32 disable_div_by_3, u32 standby) | ||
| 222 | { | ||
| 223 | u32 val; | ||
| 224 | |||
| 225 | val = ((sdiv_bits << QAM_FS_SDIV_SHIFT) | | ||
| 226 | ((md_bits & QAM_FS_MD_MASK) << QAM_FS_MD_SHIFT) | | ||
| 227 | (pe_bits << QAM_FS_PE_SHIFT) | | ||
| 228 | QAM_FS_ENABLE_OUTPUT | | ||
| 229 | standby | | ||
| 230 | disable_div_by_3); | ||
| 231 | asic_write(val, fs432x4b4_usb_ctl); | ||
| 232 | asic_write(val | QAM_FS_ENABLE_PROGRAM, fs432x4b4_usb_ctl); | ||
| 233 | asic_write(val | QAM_FS_ENABLE_PROGRAM | QAM_FS_CHOOSE_FS, | ||
| 234 | fs432x4b4_usb_ctl); | ||
| 235 | } | ||
| 236 | |||
| 237 | /* | ||
| 238 | * usb_eye_configure - for optimizing the shape USB eye waveform | ||
| 239 | * @set: Bits to set in the register | ||
| 240 | * @clear: Bits to clear in the register; each bit with a one will | ||
| 241 | * be set in the register, zero bits will not be modified | ||
| 242 | */ | ||
| 243 | static void usb_eye_configure(u32 set, u32 clear) | ||
| 244 | { | ||
| 245 | u32 old; | ||
| 246 | |||
| 247 | old = asic_read(crt_spare); | ||
| 248 | old |= set; | ||
| 249 | old &= ~clear; | ||
| 250 | asic_write(old, crt_spare); | ||
| 251 | } | ||
| 252 | |||
| 253 | /* | ||
| 254 | * platform_configure_usb - usb configuration based on platform type. | ||
| 255 | */ | ||
| 256 | static void platform_configure_usb(void) | ||
| 257 | { | ||
| 258 | u32 bcm1_usb2_ctl_value; | ||
| 259 | enum asic_type asic_type; | ||
| 260 | unsigned long flags; | ||
| 261 | |||
| 262 | spin_lock_irqsave(&usb_regs_lock, flags); | ||
| 263 | usb_users++; | ||
| 264 | |||
| 265 | if (usb_users != 1) { | ||
| 266 | spin_unlock_irqrestore(&usb_regs_lock, flags); | ||
| 267 | return; | ||
| 268 | } | ||
| 269 | |||
| 270 | asic_type = platform_get_asic(); | ||
| 271 | |||
| 272 | switch (asic_type) { | ||
| 273 | case ASIC_ZEUS: | ||
| 274 | fs_update(0x0000, -15, 0x02, 0, 0); | ||
| 275 | bcm1_usb2_ctl_value = BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH | | ||
| 276 | BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH; | ||
| 277 | break; | ||
| 278 | |||
| 279 | case ASIC_CRONUS: | ||
| 280 | case ASIC_CRONUSLITE: | ||
| 281 | usb_eye_configure(0, CRT_SPARE_USB_DIVIDE_BY_9); | ||
| 282 | fs_update(0x8000, -14, 0x03, QAM_FS_DISABLE_DIVIDE_BY_3, | ||
| 283 | QAM_FS_DISABLE_DIGITAL_STANDBY); | ||
| 284 | bcm1_usb2_ctl_value = BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH | | ||
| 285 | BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH; | ||
| 286 | break; | ||
| 287 | |||
| 288 | case ASIC_CALLIOPE: | ||
| 289 | fs_update(0x0000, -15, 0x02, QAM_FS_DISABLE_DIVIDE_BY_3, | ||
| 290 | QAM_FS_DISABLE_DIGITAL_STANDBY); | ||
| 291 | |||
| 292 | switch (platform_get_family()) { | ||
| 293 | case FAMILY_1500VZE: | ||
| 294 | break; | ||
| 295 | |||
| 296 | case FAMILY_1500VZF: | ||
| 297 | usb_eye_configure(CRT_SPARE_PORT2_SHIFT_JK | | ||
| 298 | CRT_SPARE_PORT1_SHIFT_JK | | ||
| 299 | CRT_SPARE_PORT2_FAST_EDGE | | ||
| 300 | CRT_SPARE_PORT1_FAST_EDGE, 0); | ||
| 301 | break; | ||
| 302 | |||
| 303 | default: | ||
| 304 | usb_eye_configure(CRT_SPARE_PORT2_SHIFT_JK | | ||
| 305 | CRT_SPARE_PORT1_SHIFT_JK, 0); | ||
| 306 | break; | ||
| 307 | } | ||
| 308 | |||
| 309 | bcm1_usb2_ctl_value = BCM1_USB2_CTL_BISTOK | | ||
| 310 | BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH | | ||
| 311 | BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH; | ||
| 312 | break; | ||
| 313 | |||
| 314 | case ASIC_GAIA: | ||
| 315 | fs_update(0x8000, -14, 0x03, QAM_FS_DISABLE_DIVIDE_BY_3, | ||
| 316 | QAM_FS_DISABLE_DIGITAL_STANDBY); | ||
| 317 | bcm1_usb2_ctl_value = BCM1_USB2_CTL_BISTOK | | ||
| 318 | BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH | | ||
| 319 | BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH; | ||
| 320 | break; | ||
| 321 | |||
| 322 | default: | ||
| 323 | pr_err("Unknown ASIC type: %d\n", asic_type); | ||
| 324 | bcm1_usb2_ctl_value = 0; | ||
| 325 | break; | ||
| 326 | } | ||
| 327 | |||
| 328 | /* turn on USB power */ | ||
| 329 | asic_write(0, usb2_strap); | ||
| 330 | /* Enable all OHCI interrupts */ | ||
| 331 | asic_write(bcm1_usb2_ctl_value, usb2_control); | ||
| 332 | /* usb2_stbus_obc store32/load32 */ | ||
| 333 | asic_write(USB_STBUS_OBC_STORE32_LOAD32, usb2_stbus_obc); | ||
| 334 | /* usb2_stbus_mess_size 2 packets */ | ||
| 335 | asic_write(USB2_STBUS_MESS_SIZE_2, usb2_stbus_mess_size); | ||
| 336 | /* usb2_stbus_chunk_size 2 packets */ | ||
| 337 | asic_write(USB2_STBUS_CHUNK_SIZE_2, usb2_stbus_chunk_size); | ||
| 338 | spin_unlock_irqrestore(&usb_regs_lock, flags); | ||
| 339 | } | ||
| 340 | |||
| 341 | static void platform_unconfigure_usb(void) | ||
| 342 | { | ||
| 343 | unsigned long flags; | ||
| 344 | |||
| 345 | spin_lock_irqsave(&usb_regs_lock, flags); | ||
| 346 | usb_users--; | ||
| 347 | if (usb_users == 0) | ||
| 348 | asic_write(USB2_STRAP_HFREQ_SELECT, usb2_strap); | ||
| 349 | spin_unlock_irqrestore(&usb_regs_lock, flags); | ||
| 350 | } | ||
| 351 | |||
| 352 | /* | ||
| 353 | * Set up the USB EHCI interface | ||
| 354 | */ | ||
| 355 | void platform_configure_usb_ehci() | ||
| 356 | { | ||
| 357 | platform_configure_usb(); | ||
| 358 | } | ||
| 359 | EXPORT_SYMBOL(platform_configure_usb_ehci); | ||
| 360 | |||
| 361 | /* | ||
| 362 | * Set up the USB OHCI interface | ||
| 363 | */ | ||
| 364 | void platform_configure_usb_ohci() | ||
| 365 | { | ||
| 366 | platform_configure_usb(); | ||
| 367 | } | ||
| 368 | EXPORT_SYMBOL(platform_configure_usb_ohci); | ||
| 369 | |||
| 370 | /* | ||
| 371 | * Shut the USB EHCI interface down | ||
| 372 | */ | ||
| 373 | void platform_unconfigure_usb_ehci() | ||
| 374 | { | ||
| 375 | platform_unconfigure_usb(); | ||
| 376 | } | ||
| 377 | EXPORT_SYMBOL(platform_unconfigure_usb_ehci); | ||
| 378 | |||
| 379 | /* | ||
| 380 | * Shut the USB OHCI interface down | ||
| 381 | */ | ||
| 382 | void platform_unconfigure_usb_ohci() | ||
| 383 | { | ||
| 384 | platform_unconfigure_usb(); | ||
| 385 | } | ||
| 386 | EXPORT_SYMBOL(platform_unconfigure_usb_ohci); | ||
| 387 | |||
| 388 | /** | ||
| 389 | * platform_devices_init - sets up USB device resourse. | ||
| 390 | */ | ||
| 391 | int __init platform_usb_devices_init(struct platform_device **ehci_dev, | ||
| 392 | struct platform_device **ohci_dev) | ||
| 393 | { | ||
| 394 | *ehci_dev = &ehci_device; | ||
| 395 | ehci_resources[0].start = asic_reg_phys_addr(ehci_hcapbase); | ||
| 396 | ehci_resources[0].end += ehci_resources[0].start; | ||
| 397 | |||
| 398 | *ohci_dev = &ohci_device; | ||
| 399 | ohci_resources[0].start = asic_reg_phys_addr(ohci_hc_revision); | ||
| 400 | ohci_resources[0].end += ohci_resources[0].start; | ||
| 401 | |||
| 402 | return 0; | ||
| 403 | } | ||
