diff options
-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 | } | ||