diff options
author | Michael Sparmann <theseven@rockbox.org> | 2009-10-11 10:10:49 +0000 |
---|---|---|
committer | Michael Sparmann <theseven@rockbox.org> | 2009-10-11 10:10:49 +0000 |
commit | e6c8a185e53337353e2f182b4625edf2d20542f7 (patch) | |
tree | c963036a9e72dd6b72ea37309bbd4d6280994d5c | |
parent | 0260b0ad5ad0dba0adaaab0626d135f3a40cab74 (diff) | |
download | rockbox-e6c8a185e53337353e2f182b4625edf2d20542f7.tar.gz rockbox-e6c8a185e53337353e2f182b4625edf2d20542f7.zip |
Implement NAND power management for iPod Nano 2G
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23099 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/export/s5l8700.h | 1 | ||||
-rw-r--r-- | firmware/target/arm/s5l8700/ata-nand-s5l8700.c | 4 | ||||
-rw-r--r-- | firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c | 51 | ||||
-rw-r--r-- | firmware/target/arm/s5l8700/ipodnano2g/nand-target.h | 8 | ||||
-rw-r--r-- | firmware/target/arm/s5l8700/usb-s5l8700.c | 31 |
5 files changed, 66 insertions, 29 deletions
diff --git a/firmware/export/s5l8700.h b/firmware/export/s5l8700.h index f9e015baff..e649b92c14 100644 --- a/firmware/export/s5l8700.h +++ b/firmware/export/s5l8700.h | |||
@@ -545,6 +545,7 @@ | |||
545 | #define PDAT4 (*(REG32_PTR_T)(0x3CF00044)) /* The data register for port 4 */ | 545 | #define PDAT4 (*(REG32_PTR_T)(0x3CF00044)) /* The data register for port 4 */ |
546 | #define PCON5 (*(REG32_PTR_T)(0x3CF00050)) /* Configures the pins of port 5 */ | 546 | #define PCON5 (*(REG32_PTR_T)(0x3CF00050)) /* Configures the pins of port 5 */ |
547 | #define PDAT5 (*(REG32_PTR_T)(0x3CF00054)) /* The data register for port 5 */ | 547 | #define PDAT5 (*(REG32_PTR_T)(0x3CF00054)) /* The data register for port 5 */ |
548 | #define PUNK5 (*(REG32_PTR_T)(0x3CF0005C)) /* Unknown thing for port 5 */ | ||
548 | #define PCON6 (*(REG32_PTR_T)(0x3CF00060)) /* Configures the pins of port 6 */ | 549 | #define PCON6 (*(REG32_PTR_T)(0x3CF00060)) /* Configures the pins of port 6 */ |
549 | #define PDAT6 (*(REG32_PTR_T)(0x3CF00064)) /* The data register for port 6 */ | 550 | #define PDAT6 (*(REG32_PTR_T)(0x3CF00064)) /* The data register for port 6 */ |
550 | #define PCON7 (*(REG32_PTR_T)(0x3CF00070)) /* Configures the pins of port 7 */ | 551 | #define PCON7 (*(REG32_PTR_T)(0x3CF00070)) /* Configures the pins of port 7 */ |
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 @@ | |||
29 | #include "panic.h" | 29 | #include "panic.h" |
30 | #include "usb.h" | 30 | #include "usb.h" |
31 | #include "ftl-target.h" | 31 | #include "ftl-target.h" |
32 | #include "nand-target.h" | ||
32 | 33 | ||
33 | /* for compatibility */ | 34 | /* for compatibility */ |
34 | long last_disk_activity = -1; | 35 | long last_disk_activity = -1; |
@@ -62,14 +63,17 @@ void nand_spindown(int seconds) | |||
62 | 63 | ||
63 | void nand_sleep(void) | 64 | void nand_sleep(void) |
64 | { | 65 | { |
66 | nand_power_down(); | ||
65 | } | 67 | } |
66 | 68 | ||
67 | void nand_sleepnow(void) | 69 | void nand_sleepnow(void) |
68 | { | 70 | { |
71 | nand_power_down(); | ||
69 | } | 72 | } |
70 | 73 | ||
71 | void nand_spin(void) | 74 | void nand_spin(void) |
72 | { | 75 | { |
76 | nand_power_up(); | ||
73 | } | 77 | } |
74 | 78 | ||
75 | void nand_enable(bool on) | 79 | 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 @@ | |||
26 | #include "cpu.h" | 26 | #include "cpu.h" |
27 | #include "inttypes.h" | 27 | #include "inttypes.h" |
28 | #include "nand-target.h" | 28 | #include "nand-target.h" |
29 | #include <pmu-target.h> | ||
29 | #include <string.h> | 30 | #include <string.h> |
30 | 31 | ||
31 | 32 | ||
@@ -84,6 +85,7 @@ uint8_t nand_twp[4]; | |||
84 | uint8_t nand_tunk2[4]; | 85 | uint8_t nand_tunk2[4]; |
85 | uint8_t nand_tunk3[4]; | 86 | uint8_t nand_tunk3[4]; |
86 | uint32_t nand_type[4]; | 87 | uint32_t nand_type[4]; |
88 | int nand_powered = 0; | ||
87 | 89 | ||
88 | static struct mutex nand_mtx; | 90 | static struct mutex nand_mtx; |
89 | static struct wakeup nand_wakeup; | 91 | static struct wakeup nand_wakeup; |
@@ -126,6 +128,45 @@ uint32_t nand_timeout(long timeout) | |||
126 | } | 128 | } |
127 | } | 129 | } |
128 | 130 | ||
131 | void nand_power_up(void) | ||
132 | { | ||
133 | unsigned char powerup[2] = {0x15, 1}; | ||
134 | mutex_lock(&ecc_mtx); | ||
135 | PWRCONEXT &= ~0x40; | ||
136 | PWRCON &= ~0x100000; | ||
137 | PCON2 = 0x33333333; | ||
138 | PDAT2 = 0; | ||
139 | PCON3 = 0x11113333; | ||
140 | PDAT3 = 0; | ||
141 | PCON4 = 0x33333333; | ||
142 | PDAT4 = 0; | ||
143 | PCON5 = (PCON5 & ~0xF) | 3; | ||
144 | PUNK5 = 1; | ||
145 | pmu_write_multiple(0x35, 2, powerup); | ||
146 | sleep(HZ / 50); | ||
147 | nand_powered = 1; | ||
148 | mutex_unlock(&ecc_mtx); | ||
149 | } | ||
150 | |||
151 | void nand_power_down(void) | ||
152 | { | ||
153 | unsigned char powerdown[2] = {0x15, 0}; | ||
154 | mutex_lock(&ecc_mtx); | ||
155 | pmu_write_multiple(0x35, 2, powerdown); | ||
156 | PCON2 = 0x11111111; | ||
157 | PDAT2 = 0; | ||
158 | PCON3 = 0x11111111; | ||
159 | PDAT3 = 0; | ||
160 | PCON4 = 0x11111111; | ||
161 | PDAT4 = 0; | ||
162 | PCON5 = (PCON5 & ~0xF) | 1; | ||
163 | PUNK5 = 1; | ||
164 | PWRCONEXT |= 0x40; | ||
165 | PWRCON |= 0x100000; | ||
166 | nand_powered = 0; | ||
167 | mutex_unlock(&ecc_mtx); | ||
168 | } | ||
169 | |||
129 | uint32_t nand_wait_rbbdone(void) | 170 | uint32_t nand_wait_rbbdone(void) |
130 | { | 171 | { |
131 | long timeout = current_tick + HZ / 50; | 172 | long timeout = current_tick + HZ / 50; |
@@ -302,6 +343,7 @@ uint32_t nand_read_page(uint32_t bank, uint32_t page, void* databuffer, | |||
302 | uint32_t checkempty) | 343 | uint32_t checkempty) |
303 | { | 344 | { |
304 | mutex_lock(&nand_mtx); | 345 | mutex_lock(&nand_mtx); |
346 | if (!nand_powered) nand_power_up(); | ||
305 | uint32_t rc, eccresult; | 347 | uint32_t rc, eccresult; |
306 | nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA); | 348 | nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA); |
307 | if (nand_send_cmd(NAND_CMD_READ) != 0) return nand_unlock(1); | 349 | 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, | |||
351 | void* sparebuffer, uint32_t doecc) | 393 | void* sparebuffer, uint32_t doecc) |
352 | { | 394 | { |
353 | mutex_lock(&nand_mtx); | 395 | mutex_lock(&nand_mtx); |
396 | if (!nand_powered) nand_power_up(); | ||
354 | if (sparebuffer != 0) memcpy(nand_uncached_spare, sparebuffer, 0x40); | 397 | if (sparebuffer != 0) memcpy(nand_uncached_spare, sparebuffer, 0x40); |
355 | else memset(nand_uncached_spare, 0xFF, 0x40); | 398 | else memset(nand_uncached_spare, 0xFF, 0x40); |
356 | if (doecc != 0) | 399 | if (doecc != 0) |
@@ -383,6 +426,7 @@ uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer, | |||
383 | uint32_t nand_block_erase(uint32_t bank, uint32_t page) | 426 | uint32_t nand_block_erase(uint32_t bank, uint32_t page) |
384 | { | 427 | { |
385 | mutex_lock(&nand_mtx); | 428 | mutex_lock(&nand_mtx); |
429 | if (!nand_powered) nand_power_up(); | ||
386 | nand_set_fmctrl0(bank, 0); | 430 | nand_set_fmctrl0(bank, 0); |
387 | if (nand_send_cmd(NAND_CMD_BLOCKERASE) != 0) return nand_unlock(1); | 431 | if (nand_send_cmd(NAND_CMD_BLOCKERASE) != 0) return nand_unlock(1); |
388 | FMANUM = 2; | 432 | FMANUM = 2; |
@@ -410,12 +454,7 @@ uint32_t nand_device_init(void) | |||
410 | 454 | ||
411 | uint32_t type; | 455 | uint32_t type; |
412 | uint32_t i, j; | 456 | uint32_t i, j; |
413 | PCON2 = 0x33333333; | 457 | if (!nand_powered) nand_power_up(); |
414 | PDAT2 = 0; | ||
415 | PCON3 = 0x11113333; | ||
416 | PDAT3 = 0; | ||
417 | PCON4 = 0x33333333; | ||
418 | PDAT4 = 0; | ||
419 | for (i = 0; i < 4; i++) | 458 | for (i = 0; i < 4; i++) |
420 | { | 459 | { |
421 | nand_tunk1[i] = 7; | 460 | 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 @@ | |||
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | 21 | ||
22 | #ifndef __NAND_H__ | 22 | #ifndef __NAND_TARGET_H__ |
23 | #define __NAND_H__ | 23 | #define __NAND_TARGET_H__ |
24 | 24 | ||
25 | #include "config.h" | 25 | #include "config.h" |
26 | #include "inttypes.h" | 26 | #include "inttypes.h" |
@@ -30,7 +30,7 @@ struct nand_device_info_type | |||
30 | { | 30 | { |
31 | uint32_t id; | 31 | uint32_t id; |
32 | uint16_t blocks; | 32 | uint16_t blocks; |
33 | uint32_t userblocks; | 33 | uint16_t userblocks; |
34 | uint16_t pagesperblock; | 34 | uint16_t pagesperblock; |
35 | uint8_t blocksizeexponent; | 35 | uint8_t blocksizeexponent; |
36 | uint8_t tunk1; | 36 | uint8_t tunk1; |
@@ -49,6 +49,8 @@ uint32_t nand_block_erase(uint32_t bank, uint32_t page); | |||
49 | const struct nand_device_info_type* nand_get_device_type(uint32_t bank); | 49 | const struct nand_device_info_type* nand_get_device_type(uint32_t bank); |
50 | uint32_t nand_reset(uint32_t bank); | 50 | uint32_t nand_reset(uint32_t bank); |
51 | uint32_t nand_device_init(void); | 51 | uint32_t nand_device_init(void); |
52 | void nand_power_up(void); | ||
53 | void nand_power_down(void); | ||
52 | 54 | ||
53 | 55 | ||
54 | #endif | 56 | #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 @@ | |||
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | #include "config.h" | 21 | #include "config.h" |
22 | #include "usb.h" | 22 | #include "usb.h" |
23 | #include "cpu.h" | ||
24 | #include "system.h" | ||
25 | #include "string.h" | ||
26 | 23 | ||
27 | void usb_init_device(void) | 24 | void usb_init_device(void) |
28 | { | 25 | { |
@@ -30,27 +27,21 @@ void usb_init_device(void) | |||
30 | 27 | ||
31 | void usb_enable(bool on) | 28 | void usb_enable(bool on) |
32 | { | 29 | { |
33 | /* This device specific code will eventually give way to proper USB | 30 | (void)on; |
34 | handling, which should be the same for all S5L870x targets. */ | 31 | } |
35 | if (on) | ||
36 | { | ||
37 | #ifdef IPOD_ARCH | ||
38 | /* For iPod, we can only do one thing with USB mode atm - reboot | ||
39 | into the flash-based disk-mode. This does not return. */ | ||
40 | 32 | ||
41 | memcpy((void *)0x0002bf00, "diskmodehotstuff\1\0\0\0", 20); | 33 | void usb_attach(void) |
34 | { | ||
42 | 35 | ||
43 | system_reboot(); /* Reboot */ | ||
44 | #endif | ||
45 | } | ||
46 | } | 36 | } |
47 | 37 | ||
48 | int usb_detect(void) | 38 | static bool usb_pin_state(void) |
49 | { | 39 | { |
50 | #if defined(IPOD_NANO2G) | 40 | return false; |
51 | if ((PDAT14 & 0x8) == 0x0) | 41 | } |
52 | return USB_INSERTED; | ||
53 | #endif | ||
54 | 42 | ||
55 | return USB_EXTRACTED; | 43 | /* detect host or charger (INSERTED or EXTRACTED) */ |
44 | int usb_detect(void) | ||
45 | { | ||
46 | return usb_pin_state() ? USB_INSERTED : USB_EXTRACTED; | ||
56 | } | 47 | } |