summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorMichael Sparmann <theseven@rockbox.org>2009-10-11 10:10:49 +0000
committerMichael Sparmann <theseven@rockbox.org>2009-10-11 10:10:49 +0000
commite6c8a185e53337353e2f182b4625edf2d20542f7 (patch)
treec963036a9e72dd6b72ea37309bbd4d6280994d5c /firmware
parent0260b0ad5ad0dba0adaaab0626d135f3a40cab74 (diff)
Implement NAND power management for iPod Nano 2G
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23099 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/export/s5l8700.h1
-rw-r--r--firmware/target/arm/s5l8700/ata-nand-s5l8700.c4
-rw-r--r--firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c51
-rw-r--r--firmware/target/arm/s5l8700/ipodnano2g/nand-target.h8
-rw-r--r--firmware/target/arm/s5l8700/usb-s5l8700.c31
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 @@
#define PDAT4 (*(REG32_PTR_T)(0x3CF00044)) /* The data register for port 4 */
#define PCON5 (*(REG32_PTR_T)(0x3CF00050)) /* Configures the pins of port 5 */
#define PDAT5 (*(REG32_PTR_T)(0x3CF00054)) /* The data register for port 5 */
+#define PUNK5 (*(REG32_PTR_T)(0x3CF0005C)) /* Unknown thing for port 5 */
#define PCON6 (*(REG32_PTR_T)(0x3CF00060)) /* Configures the pins of port 6 */
#define PDAT6 (*(REG32_PTR_T)(0x3CF00064)) /* The data register for port 6 */
#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 @@
#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 <pmu-target.h>
#include <string.h>
@@ -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;
}