From e6c8a185e53337353e2f182b4625edf2d20542f7 Mon Sep 17 00:00:00 2001 From: Michael Sparmann Date: Sun, 11 Oct 2009 10:10:49 +0000 Subject: Implement NAND power management for iPod Nano 2G git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23099 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/arm/s5l8700/ata-nand-s5l8700.c | 4 ++ .../target/arm/s5l8700/ipodnano2g/nand-nano2g.c | 51 +++++++++++++++++++--- .../target/arm/s5l8700/ipodnano2g/nand-target.h | 8 ++-- firmware/target/arm/s5l8700/usb-s5l8700.c | 31 +++++-------- 4 files changed, 65 insertions(+), 29 deletions(-) (limited to 'firmware/target/arm') diff --git a/firmware/target/arm/s5l8700/ata-nand-s5l8700.c b/firmware/target/arm/s5l8700/ata-nand-s5l8700.c index 883c167c78..308f0a5e61 100644 --- a/firmware/target/arm/s5l8700/ata-nand-s5l8700.c +++ b/firmware/target/arm/s5l8700/ata-nand-s5l8700.c @@ -29,6 +29,7 @@ #include "panic.h" #include "usb.h" #include "ftl-target.h" +#include "nand-target.h" /* for compatibility */ long last_disk_activity = -1; @@ -62,14 +63,17 @@ void nand_spindown(int seconds) void nand_sleep(void) { + nand_power_down(); } void nand_sleepnow(void) { + nand_power_down(); } void nand_spin(void) { + nand_power_up(); } void nand_enable(bool on) diff --git a/firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c b/firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c index 795e489258..fe59fc5d2d 100644 --- a/firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c +++ b/firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c @@ -26,6 +26,7 @@ #include "cpu.h" #include "inttypes.h" #include "nand-target.h" +#include #include @@ -84,6 +85,7 @@ uint8_t nand_twp[4]; uint8_t nand_tunk2[4]; uint8_t nand_tunk3[4]; uint32_t nand_type[4]; +int nand_powered = 0; static struct mutex nand_mtx; static struct wakeup nand_wakeup; @@ -126,6 +128,45 @@ uint32_t nand_timeout(long timeout) } } +void nand_power_up(void) +{ + unsigned char powerup[2] = {0x15, 1}; + mutex_lock(&ecc_mtx); + PWRCONEXT &= ~0x40; + PWRCON &= ~0x100000; + PCON2 = 0x33333333; + PDAT2 = 0; + PCON3 = 0x11113333; + PDAT3 = 0; + PCON4 = 0x33333333; + PDAT4 = 0; + PCON5 = (PCON5 & ~0xF) | 3; + PUNK5 = 1; + pmu_write_multiple(0x35, 2, powerup); + sleep(HZ / 50); + nand_powered = 1; + mutex_unlock(&ecc_mtx); +} + +void nand_power_down(void) +{ + unsigned char powerdown[2] = {0x15, 0}; + mutex_lock(&ecc_mtx); + pmu_write_multiple(0x35, 2, powerdown); + PCON2 = 0x11111111; + PDAT2 = 0; + PCON3 = 0x11111111; + PDAT3 = 0; + PCON4 = 0x11111111; + PDAT4 = 0; + PCON5 = (PCON5 & ~0xF) | 1; + PUNK5 = 1; + PWRCONEXT |= 0x40; + PWRCON |= 0x100000; + nand_powered = 0; + mutex_unlock(&ecc_mtx); +} + uint32_t nand_wait_rbbdone(void) { long timeout = current_tick + HZ / 50; @@ -302,6 +343,7 @@ uint32_t nand_read_page(uint32_t bank, uint32_t page, void* databuffer, uint32_t checkempty) { mutex_lock(&nand_mtx); + if (!nand_powered) nand_power_up(); uint32_t rc, eccresult; nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA); if (nand_send_cmd(NAND_CMD_READ) != 0) return nand_unlock(1); @@ -351,6 +393,7 @@ uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer, void* sparebuffer, uint32_t doecc) { mutex_lock(&nand_mtx); + if (!nand_powered) nand_power_up(); if (sparebuffer != 0) memcpy(nand_uncached_spare, sparebuffer, 0x40); else memset(nand_uncached_spare, 0xFF, 0x40); if (doecc != 0) @@ -383,6 +426,7 @@ uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer, uint32_t nand_block_erase(uint32_t bank, uint32_t page) { mutex_lock(&nand_mtx); + if (!nand_powered) nand_power_up(); nand_set_fmctrl0(bank, 0); if (nand_send_cmd(NAND_CMD_BLOCKERASE) != 0) return nand_unlock(1); FMANUM = 2; @@ -410,12 +454,7 @@ uint32_t nand_device_init(void) uint32_t type; uint32_t i, j; - PCON2 = 0x33333333; - PDAT2 = 0; - PCON3 = 0x11113333; - PDAT3 = 0; - PCON4 = 0x33333333; - PDAT4 = 0; + if (!nand_powered) nand_power_up(); for (i = 0; i < 4; i++) { nand_tunk1[i] = 7; diff --git a/firmware/target/arm/s5l8700/ipodnano2g/nand-target.h b/firmware/target/arm/s5l8700/ipodnano2g/nand-target.h index bed94ee243..a1559e936c 100644 --- a/firmware/target/arm/s5l8700/ipodnano2g/nand-target.h +++ b/firmware/target/arm/s5l8700/ipodnano2g/nand-target.h @@ -19,8 +19,8 @@ * ****************************************************************************/ -#ifndef __NAND_H__ -#define __NAND_H__ +#ifndef __NAND_TARGET_H__ +#define __NAND_TARGET_H__ #include "config.h" #include "inttypes.h" @@ -30,7 +30,7 @@ struct nand_device_info_type { uint32_t id; uint16_t blocks; - uint32_t userblocks; + uint16_t userblocks; uint16_t pagesperblock; uint8_t blocksizeexponent; uint8_t tunk1; @@ -49,6 +49,8 @@ uint32_t nand_block_erase(uint32_t bank, uint32_t page); const struct nand_device_info_type* nand_get_device_type(uint32_t bank); uint32_t nand_reset(uint32_t bank); uint32_t nand_device_init(void); +void nand_power_up(void); +void nand_power_down(void); #endif diff --git a/firmware/target/arm/s5l8700/usb-s5l8700.c b/firmware/target/arm/s5l8700/usb-s5l8700.c index c0bf7a951b..6ad4dcea95 100644 --- a/firmware/target/arm/s5l8700/usb-s5l8700.c +++ b/firmware/target/arm/s5l8700/usb-s5l8700.c @@ -20,9 +20,6 @@ ****************************************************************************/ #include "config.h" #include "usb.h" -#include "cpu.h" -#include "system.h" -#include "string.h" void usb_init_device(void) { @@ -30,27 +27,21 @@ void usb_init_device(void) void usb_enable(bool on) { - /* This device specific code will eventually give way to proper USB - handling, which should be the same for all S5L870x targets. */ - if (on) - { -#ifdef IPOD_ARCH - /* For iPod, we can only do one thing with USB mode atm - reboot - into the flash-based disk-mode. This does not return. */ + (void)on; +} - memcpy((void *)0x0002bf00, "diskmodehotstuff\1\0\0\0", 20); +void usb_attach(void) +{ - system_reboot(); /* Reboot */ -#endif - } } -int usb_detect(void) +static bool usb_pin_state(void) { -#if defined(IPOD_NANO2G) - if ((PDAT14 & 0x8) == 0x0) - return USB_INSERTED; -#endif + return false; +} - return USB_EXTRACTED; +/* detect host or charger (INSERTED or EXTRACTED) */ +int usb_detect(void) +{ + return usb_pin_state() ? USB_INSERTED : USB_EXTRACTED; } -- cgit v1.2.3