| Index: apps/iloader/main.c | 
| — | — | @@ -188,7 +188,7 @@ | 
| 189 | 189 | break; | 
| 190 | 190 |  | 
| 191 | 191 | case 0x1: | 
| 192 |  | -                cputs(1, "iLoader terminated on user's behalf\n");
 | 
|  | 192 | +                cputs(1, "iLoader terminated on user's request\n"); | 
| 193 | 193 | return; | 
| 194 | 194 |  | 
| 195 | 195 | case 0x2: | 
| Index: embios/trunk/target/ipodnano2g/s5l8701.h | 
| — | — | @@ -79,6 +79,8 @@ | 
| 80 | 80 | #define PDAT10       (*((volatile uint32_t*)(0x3CF000A4))) | 
| 81 | 81 | #define PCON11       (*((volatile uint32_t*)(0x3CF000B0))) | 
| 82 | 82 | #define PDAT11       (*((volatile uint32_t*)(0x3CF000B4))) | 
|  | 83 | +#define PCON14       (*((volatile uint32_t*)(0x3CF000E0))) | 
|  | 84 | +#define PDAT14       (*((volatile uint32_t*)(0x3CF000E4))) | 
| 83 | 85 | #define PCON15       (*((volatile uint32_t*)(0x3CF000F0))) | 
| 84 | 86 | #define PUNK15       (*((volatile uint32_t*)(0x3CF000FC))) | 
| 85 | 87 |  | 
| Index: embios/trunk/target/ipodnano2g/power.c | 
| — | — | @@ -50,9 +50,19 @@ | 
| 51 | 51 | { | 
| 52 | 52 | pmu_init(); | 
| 53 | 53 | pmu_write(0x1e, 15);  /* Vcore = 1.000V */ | 
| 54 |  | -}
 | 
|  | 54 | +} | 
| 55 | 55 |  | 
| 56 | 56 | bool charging_state(void) | 
| 57 | 57 | { | 
| 58 | 58 | return (PDAT11 & 0x10) ? false : true; | 
| 59 | 59 | } | 
|  | 60 | + | 
|  | 61 | +bool external_power_state(void) | 
|  | 62 | +{ | 
|  | 63 | +    return (PDAT14 & 8) ? false : true; | 
|  | 64 | +} | 
|  | 65 | + | 
|  | 66 | +bool vbus_state(void) | 
|  | 67 | +{ | 
|  | 68 | +    return (PDAT14 & 8) ? false : true; | 
|  | 69 | +} | 
| Index: embios/trunk/target/ipodnano4g/power.c | 
| — | — | @@ -41,3 +41,13 @@ | 
| 42 | 42 | { | 
| 43 | 43 | return false; | 
| 44 | 44 | } | 
|  | 45 | + | 
|  | 46 | +bool external_power_state(void) | 
|  | 47 | +{ | 
|  | 48 | +    return true; | 
|  | 49 | +} | 
|  | 50 | + | 
|  | 51 | +bool vbus_state(void) | 
|  | 52 | +{ | 
|  | 53 | +    return true; | 
|  | 54 | +} | 
| Index: embios/trunk/power.h | 
| — | — | @@ -30,5 +30,8 @@ | 
| 31 | 31 | void power_off(void); | 
| 32 | 32 | void power_init(void); | 
| 33 | 33 | bool charging_state(void); | 
|  | 34 | +bool external_power_state(void); | 
|  | 35 | +bool vbus_state(void); | 
| 34 | 36 |  | 
|  | 37 | + | 
| 35 | 38 | #endif | 
| Index: embios/trunk/usb/synopsysotg.c | 
| — | — | @@ -33,6 +33,7 @@ | 
| 34 | 34 | #include "util.h" | 
| 35 | 35 | #include "interrupt.h" | 
| 36 | 36 | #include "clockgates.h" | 
|  | 37 | +#include "power.h" | 
| 37 | 38 |  | 
| 38 | 39 |  | 
| 39 | 40 | struct ep_type | 
| — | — | @@ -47,6 +48,7 @@ | 
| 48 | 49 |  | 
| 49 | 50 | static struct ep_type endpoints[5]; | 
| 50 | 51 | static struct usb_ctrlrequest ctrlreq CACHEALIGN_ATTR; | 
|  | 52 | +static uint32_t synopsysotg_stack[0x40] STACK_ATTR; | 
| 51 | 53 |  | 
| 52 | 54 | int usb_drv_port_speed(void) | 
| 53 | 55 | { | 
| — | — | @@ -351,6 +353,45 @@ | 
| 352 | 354 | } | 
| 353 | 355 | } | 
| 354 | 356 |  | 
|  | 357 | +void usb_drv_power_up(void) | 
|  | 358 | +{ | 
|  | 359 | +    /* Enable USB clock */ | 
|  | 360 | +    clockgate_enable(CLOCKGATE_USB_1, true); | 
|  | 361 | +    clockgate_enable(CLOCKGATE_USB_2, true); | 
|  | 362 | +    PCGCCTL = 0; | 
|  | 363 | + | 
|  | 364 | +    /* reset the beast */ | 
|  | 365 | +    usb_reset(); | 
|  | 366 | +} | 
|  | 367 | + | 
|  | 368 | +void usb_drv_power_down(void) | 
|  | 369 | +{ | 
|  | 370 | +    DCTL = 0x802;  /* Soft Disconnect */ | 
|  | 371 | + | 
|  | 372 | +    ORSTCON = 1;  /* Put the PHY into reset (needed to get current down) */ | 
|  | 373 | +    PCGCCTL = 1;  /* Shut down PHY clock */ | 
|  | 374 | +    OPHYPWR = 0xF;  /* PHY: Power down */ | 
|  | 375 | + | 
|  | 376 | +    clockgate_enable(CLOCKGATE_USB_1, false); | 
|  | 377 | +    clockgate_enable(CLOCKGATE_USB_2, false); | 
|  | 378 | +} | 
|  | 379 | + | 
|  | 380 | +void usb_check_vbus() | 
|  | 381 | +{ | 
|  | 382 | +    bool oldstate = false; | 
|  | 383 | +    while (true) | 
|  | 384 | +    { | 
|  | 385 | +        sleep(200000); | 
|  | 386 | +        bool newstate = vbus_state(); | 
|  | 387 | +        if (oldstate != newstate) | 
|  | 388 | +        { | 
|  | 389 | +            if (newstate) usb_drv_power_up(); | 
|  | 390 | +            else usb_drv_power_down(); | 
|  | 391 | +            oldstate = newstate; | 
|  | 392 | +        } | 
|  | 393 | +    } | 
|  | 394 | +} | 
|  | 395 | + | 
| 355 | 396 | void usb_drv_init(void) | 
| 356 | 397 | { | 
| 357 | 398 | unsigned int i; | 
| — | — | @@ -365,8 +406,10 @@ | 
| 366 | 407 | /* unmask irq */ | 
| 367 | 408 | interrupt_enable(IRQ_USB_FUNC, true); | 
| 368 | 409 |  | 
| 369 |  | -    /* reset the beast */
 | 
| 370 |  | -    usb_reset();
 | 
|  | 410 | +    thread_create("synopsysotg", usb_check_vbus, synopsysotg_stack, | 
|  | 411 | +                  sizeof(synopsysotg_stack), OS_THREAD, 63, true); | 
|  | 412 | + | 
|  | 413 | +    usb_drv_power_down(); | 
| 371 | 414 | } | 
| 372 | 415 |  | 
| 373 | 416 | int usb_drv_get_max_out_size() |