Barry Wardell | d4945dc | 2006-10-05 10:58:51 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * $Id$ |
| 9 | * |
| 10 | * Copyright (C) 2002 by Linus Nielsen Feltzing |
| 11 | * |
| 12 | * iPod driver based on code from the ipodlinux project - http://ipodlinux.org |
| 13 | * Adapted for Rockbox in January 2006 |
| 14 | * Original file: podzilla/usb.c |
| 15 | * Copyright (C) 2005 Adam Johnston |
| 16 | * |
| 17 | * All files in this archive are subject to the GNU General Public License. |
| 18 | * See the file COPYING in the source tree root for full license agreement. |
| 19 | * |
| 20 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 21 | * KIND, either express or implied. |
| 22 | * |
| 23 | ****************************************************************************/ |
| 24 | #include "config.h" |
Barry Wardell | d4945dc | 2006-10-05 10:58:51 +0000 | [diff] [blame] | 25 | #include "system.h" |
Barry Wardell | d4945dc | 2006-10-05 10:58:51 +0000 | [diff] [blame] | 26 | #include "usb.h" |
Christian Gmeiner | f286bde | 2007-08-27 16:26:56 +0000 | [diff] [blame] | 27 | #include "button.h" |
| 28 | #include "ata.h" |
Christian Gmeiner | 863ce44 | 2007-08-27 16:30:23 +0000 | [diff] [blame] | 29 | #include "string.h" |
Dave Chapman | a6d52a8 | 2007-08-27 21:59:57 +0000 | [diff] [blame] | 30 | #include "arcotg_udc.h" |
Dave Chapman | 4da04b7 | 2007-02-04 21:46:01 +0000 | [diff] [blame] | 31 | |
Christian Gmeiner | 8181a0c | 2007-08-27 16:04:32 +0000 | [diff] [blame] | 32 | #ifdef HAVE_USBSTACK |
| 33 | #include "usbstack.h" |
| 34 | #endif |
| 35 | |
Barry Wardell | d4945dc | 2006-10-05 10:58:51 +0000 | [diff] [blame] | 36 | void usb_init_device(void) |
| 37 | { |
Christian Gmeiner | 1a8f7c5 | 2007-09-05 15:52:49 +0000 | [diff] [blame] | 38 | int r0; |
Dave Chapman | 9551ae9 | 2007-08-27 18:21:05 +0000 | [diff] [blame] | 39 | outl(inl(0x70000084) | 0x200, 0x70000084); |
Christian Gmeiner | 1a8f7c5 | 2007-09-05 15:52:49 +0000 | [diff] [blame] | 40 | |
Dave Chapman | 9551ae9 | 2007-08-27 18:21:05 +0000 | [diff] [blame] | 41 | outl(inl(0x7000002C) | 0x3000000, 0x7000002C); |
Christian Gmeiner | 1a8f7c5 | 2007-09-05 15:52:49 +0000 | [diff] [blame] | 42 | DEV_EN |= DEV_USB; |
| 43 | |
Dave Chapman | 9551ae9 | 2007-08-27 18:21:05 +0000 | [diff] [blame] | 44 | DEV_RS |= DEV_USB; /* reset usb start */ |
| 45 | DEV_RS &=~DEV_USB;/* reset usb end */ |
Christian Gmeiner | 1a8f7c5 | 2007-09-05 15:52:49 +0000 | [diff] [blame] | 46 | |
| 47 | DEV_INIT |= INIT_USB; |
| 48 | while ((inl(0x70000028) & 0x80) == 0); |
| 49 | |
Dave Chapman | 9551ae9 | 2007-08-27 18:21:05 +0000 | [diff] [blame] | 50 | UDC_PORTSC1 |= PORTSCX_PORT_RESET; |
Christian Gmeiner | 1a8f7c5 | 2007-09-05 15:52:49 +0000 | [diff] [blame] | 51 | while ((UDC_PORTSC1 & PORTSCX_PORT_RESET) != 0); |
| 52 | |
| 53 | UDC_OTGSC |= 0x5F000000; |
Dave Chapman | 9551ae9 | 2007-08-27 18:21:05 +0000 | [diff] [blame] | 54 | if( (UDC_OTGSC & 0x100) == 0) { |
Christian Gmeiner | 1a8f7c5 | 2007-09-05 15:52:49 +0000 | [diff] [blame] | 55 | UDC_USBMODE &=~ USB_MODE_CTRL_MODE_HOST; |
| 56 | UDC_USBMODE |= USB_MODE_CTRL_MODE_DEVICE; |
| 57 | outl(inl(0x70000028) | 0x4000, 0x70000028); |
| 58 | outl(inl(0x70000028) | 0x2, 0x70000028); |
| 59 | } else { |
| 60 | UDC_USBMODE |= USB_MODE_CTRL_MODE_DEVICE; |
| 61 | outl(inl(0x70000028) &~0x4000, 0x70000028); |
| 62 | outl(inl(0x70000028) | 0x2, 0x70000028); |
| 63 | } |
| 64 | |
| 65 | |
| 66 | UDC_USBCMD |= USB_CMD_CTRL_RESET; |
| 67 | while((UDC_USBCMD & USB_CMD_CTRL_RESET) != 0); |
| 68 | |
| 69 | r0 = UDC_PORTSC1; |
| 70 | |
Dave Chapman | 9551ae9 | 2007-08-27 18:21:05 +0000 | [diff] [blame] | 71 | /* Note from IPL source (referring to next 5 lines of code: |
| 72 | THIS NEEDS TO BE CHANGED ONCE THERE IS KERNEL USB */ |
Christian Gmeiner | 1a8f7c5 | 2007-09-05 15:52:49 +0000 | [diff] [blame] | 73 | DEV_INIT |= INIT_USB; |
| 74 | DEV_EN |= DEV_USB; |
| 75 | while ((inl(0x70000028) & 0x80) == 0); |
| 76 | outl(inl(0x70000028) | 0x2, 0x70000028); |
Dave Chapman | 9551ae9 | 2007-08-27 18:21:05 +0000 | [diff] [blame] | 77 | |
Christian Gmeiner | 1a8f7c5 | 2007-09-05 15:52:49 +0000 | [diff] [blame] | 78 | udelay(0x186A0); |
| 79 | |
| 80 | #ifndef HAVE_USBSTACK |
Dave Chapman | 9551ae9 | 2007-08-27 18:21:05 +0000 | [diff] [blame] | 81 | dr_controller_setup(); |
| 82 | #endif |
Jens Arnold | cb896cd | 2007-08-01 22:44:02 +0000 | [diff] [blame] | 83 | |
| 84 | #if defined(IPOD_COLOR) || defined(IPOD_4G) \ |
| 85 | || defined(IPOD_MINI) || defined(IPOD_MINI2G) |
| 86 | /* GPIO C bit 1 is firewire detect */ |
| 87 | GPIOC_ENABLE |= 0x02; |
| 88 | GPIOC_OUTPUT_EN &= ~0x02; |
| 89 | #endif |
Barry Wardell | d4945dc | 2006-10-05 10:58:51 +0000 | [diff] [blame] | 90 | } |
| 91 | |
| 92 | void usb_enable(bool on) |
| 93 | { |
Peter D'Hoye | f2bf042 | 2007-08-28 21:32:28 +0000 | [diff] [blame] | 94 | #ifdef HAVE_USBSTACK |
Christian Gmeiner | 2c30bd9 | 2007-09-05 16:16:49 +0000 | [diff] [blame] | 95 | if (!on) { |
| 96 | usb_stack_stop(); |
| 97 | } |
Christian Gmeiner | 1a8f7c5 | 2007-09-05 15:52:49 +0000 | [diff] [blame] | 98 | #else |
Barry Wardell | 4b54302 | 2006-12-20 15:28:32 +0000 | [diff] [blame] | 99 | /* This device specific code will eventually give way to proper USB |
Jens Arnold | cb896cd | 2007-08-01 22:44:02 +0000 | [diff] [blame] | 100 | handling, which should be the same for all PP502x targets. */ |
Barry Wardell | d4945dc | 2006-10-05 10:58:51 +0000 | [diff] [blame] | 101 | if (on) |
| 102 | { |
Daniel Stenberg | 20a5926 | 2007-02-17 21:54:17 +0000 | [diff] [blame] | 103 | #if defined(IPOD_ARCH) || defined(IRIVER_H10) || defined (IRIVER_H10_5GB) |
Barry Wardell | 4b54302 | 2006-12-20 15:28:32 +0000 | [diff] [blame] | 104 | /* For the H10 and iPod, we can only do one thing with USB mode - reboot |
| 105 | into the flash-based disk-mode. This does not return. */ |
Barry Wardell | 4b54302 | 2006-12-20 15:28:32 +0000 | [diff] [blame] | 106 | |
| 107 | #if defined(IRIVER_H10) || defined (IRIVER_H10_5GB) |
| 108 | if(button_status()==BUTTON_RIGHT) |
Peter D'Hoye | f2bf042 | 2007-08-28 21:32:28 +0000 | [diff] [blame] | 109 | #endif /* defined(IRIVER_H10) || defined (IRIVER_H10_5GB) */ |
Barry Wardell | 4b54302 | 2006-12-20 15:28:32 +0000 | [diff] [blame] | 110 | { |
| 111 | ata_sleepnow(); /* Immediately spindown the disk. */ |
| 112 | sleep(HZ*2); |
Jens Arnold | cb896cd | 2007-08-01 22:44:02 +0000 | [diff] [blame] | 113 | |
| 114 | #ifdef IPOD_ARCH /* The following code is based on ipodlinux */ |
| 115 | #if CONFIG_CPU == PP5020 |
| 116 | memcpy((void *)0x40017f00, "diskmode\0\0hotstuff\0\0\1", 21); |
| 117 | #elif CONFIG_CPU == PP5022 |
| 118 | memcpy((void *)0x4001ff00, "diskmode\0\0hotstuff\0\0\1", 21); |
Peter D'Hoye | f2bf042 | 2007-08-28 21:32:28 +0000 | [diff] [blame] | 119 | #endif /* CONFIG_CPU */ |
| 120 | #endif /* IPOD_ARCH */ |
Jens Arnold | cb896cd | 2007-08-01 22:44:02 +0000 | [diff] [blame] | 121 | |
Barry Wardell | 4b54302 | 2006-12-20 15:28:32 +0000 | [diff] [blame] | 122 | system_reboot(); /* Reboot */ |
| 123 | } |
Peter D'Hoye | f2bf042 | 2007-08-28 21:32:28 +0000 | [diff] [blame] | 124 | #endif /*defined(IPOD_ARCH) || defined(IRIVER_H10) || defined (IRIVER_H10_5GB)*/ |
Barry Wardell | d4945dc | 2006-10-05 10:58:51 +0000 | [diff] [blame] | 125 | } |
Peter D'Hoye | f2bf042 | 2007-08-28 21:32:28 +0000 | [diff] [blame] | 126 | #endif /* !HAVE_USBSTACK */ |
Barry Wardell | d4945dc | 2006-10-05 10:58:51 +0000 | [diff] [blame] | 127 | } |
| 128 | |
Dave Chapman | 1672350 | 2007-09-04 08:03:07 +0000 | [diff] [blame] | 129 | int usb_detect(void) |
Barry Wardell | d4945dc | 2006-10-05 10:58:51 +0000 | [diff] [blame] | 130 | { |
Dave Chapman | 1672350 | 2007-09-04 08:03:07 +0000 | [diff] [blame] | 131 | static int countdown = 0; |
| 132 | static int status = USB_EXTRACTED; |
Dave Chapman | 4da04b7 | 2007-02-04 21:46:01 +0000 | [diff] [blame] | 133 | static bool prev_usbstatus1 = false; |
Dave Chapman | 1672350 | 2007-09-04 08:03:07 +0000 | [diff] [blame] | 134 | bool usbstatus1, usbstatus2; |
Barry Wardell | d4945dc | 2006-10-05 10:58:51 +0000 | [diff] [blame] | 135 | |
Jens Arnold | cb896cd | 2007-08-01 22:44:02 +0000 | [diff] [blame] | 136 | #if defined(IPOD_COLOR) || defined(IPOD_4G) \ |
| 137 | || defined(IPOD_MINI) || defined(IPOD_MINI2G) |
| 138 | /* GPIO C bit 1 is firewire detect */ |
| 139 | if (!(GPIOC_INPUT_VAL & 0x02)) |
Dave Chapman | 1672350 | 2007-09-04 08:03:07 +0000 | [diff] [blame] | 140 | return USB_INSERTED; |
Jens Arnold | cb896cd | 2007-08-01 22:44:02 +0000 | [diff] [blame] | 141 | #endif |
| 142 | |
Dave Chapman | 1672350 | 2007-09-04 08:03:07 +0000 | [diff] [blame] | 143 | if (countdown > 0) |
| 144 | { |
| 145 | countdown--; |
| 146 | |
| 147 | usbstatus2 = (UDC_PORTSC1 & PORTSCX_CURRENT_CONNECT_STATUS) ? true : false; |
| 148 | if ((countdown == 0) || usbstatus2) |
| 149 | { |
| 150 | countdown = 0; |
| 151 | status = usbstatus2 ? USB_INSERTED : USB_POWERED; |
Christian Gmeiner | e267bc7 | 2007-09-04 23:29:42 +0000 | [diff] [blame] | 152 | #ifndef HAVE_USBSTACK |
Dave Chapman | 1672350 | 2007-09-04 08:03:07 +0000 | [diff] [blame] | 153 | dr_controller_stop(); |
Dave Chapman | 1672350 | 2007-09-04 08:03:07 +0000 | [diff] [blame] | 154 | #endif |
| 155 | } |
| 156 | return status; |
| 157 | } |
| 158 | |
Barry Wardell | 3a6d479 | 2007-02-16 22:13:21 +0000 | [diff] [blame] | 159 | /* UDC_ID should have the bit format: |
Barry Wardell | 4b54302 | 2006-12-20 15:28:32 +0000 | [diff] [blame] | 160 | [31:24] = 0x0 |
| 161 | [23:16] = 0x22 (Revision number) |
| 162 | [15:14] = 0x3 (Reserved) |
| 163 | [13:8] = 0x3a (NID - 1's compliment of ID) |
| 164 | [7:6] = 0x0 (Reserved) |
| 165 | [5:0] = 0x05 (ID) */ |
Barry Wardell | 3a6d479 | 2007-02-16 22:13:21 +0000 | [diff] [blame] | 166 | if (UDC_ID != 0x22FA05) { |
Dave Chapman | 1672350 | 2007-09-04 08:03:07 +0000 | [diff] [blame] | 167 | /* This should never occur - do we even need to test? */ |
| 168 | return USB_EXTRACTED; |
Barry Wardell | d4945dc | 2006-10-05 10:58:51 +0000 | [diff] [blame] | 169 | } |
Dave Chapman | 4da04b7 | 2007-02-04 21:46:01 +0000 | [diff] [blame] | 170 | |
Barry Wardell | 3a6d479 | 2007-02-16 22:13:21 +0000 | [diff] [blame] | 171 | usbstatus1 = (UDC_OTGSC & 0x800) ? true : false; |
Dave Chapman | 4da04b7 | 2007-02-04 21:46:01 +0000 | [diff] [blame] | 172 | |
Dave Chapman | 1672350 | 2007-09-04 08:03:07 +0000 | [diff] [blame] | 173 | if (usbstatus1 == prev_usbstatus1) |
| 174 | { |
| 175 | /* Nothing has changed, so just return previous status */ |
| 176 | return status; |
Dave Chapman | 4da04b7 | 2007-02-04 21:46:01 +0000 | [diff] [blame] | 177 | } |
Dave Chapman | 1672350 | 2007-09-04 08:03:07 +0000 | [diff] [blame] | 178 | prev_usbstatus1 = usbstatus1; |
| 179 | |
| 180 | if (!usbstatus1) |
| 181 | { /* We have just been disconnected */ |
| 182 | status = USB_EXTRACTED; |
Dave Chapman | 1672350 | 2007-09-04 08:03:07 +0000 | [diff] [blame] | 183 | return status; |
| 184 | } |
| 185 | |
| 186 | /* We now know that we have just been connected to either a charger |
| 187 | or a computer */ |
| 188 | |
| 189 | if((button_status() & ~USBPOWER_BTN_IGNORE) == USBPOWER_BUTTON) |
| 190 | { |
| 191 | /* The user wants to charge, so it doesn't matter what we are |
| 192 | connected to. */ |
| 193 | |
| 194 | status = USB_POWERED; |
| 195 | return status; |
| 196 | } |
| 197 | |
| 198 | /* Run the USB controller for long enough to detect if we're connected |
| 199 | to a computer, then stop it again. */ |
| 200 | |
Christian Gmeiner | 1a8f7c5 | 2007-09-05 15:52:49 +0000 | [diff] [blame] | 201 | #ifndef HAVE_USBSTACK |
Dave Chapman | 1672350 | 2007-09-04 08:03:07 +0000 | [diff] [blame] | 202 | dr_controller_run(); |
Christian Gmeiner | 1a8f7c5 | 2007-09-05 15:52:49 +0000 | [diff] [blame] | 203 | #else |
| 204 | usb_stack_start(); |
Christian Gmeiner | e267bc7 | 2007-09-04 23:29:42 +0000 | [diff] [blame] | 205 | #endif |
Dave Chapman | 1672350 | 2007-09-04 08:03:07 +0000 | [diff] [blame] | 206 | |
| 207 | /* Wait for 50 ticks (500ms) before deciding there is no computer |
| 208 | attached. The required value varied a lot between different users |
| 209 | when this feature was being tested. */ |
| 210 | |
| 211 | countdown = 50; |
| 212 | |
| 213 | return status; |
Barry Wardell | d4945dc | 2006-10-05 10:58:51 +0000 | [diff] [blame] | 214 | } |