forked from len0rd/rockbox
Implement NAND power management for iPod Nano 2G
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23099 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
0260b0ad5a
commit
e6c8a185e5
5 changed files with 68 additions and 31 deletions
|
|
@ -545,6 +545,7 @@
|
||||||
#define PDAT4 (*(REG32_PTR_T)(0x3CF00044)) /* The data register for port 4 */
|
#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 PCON5 (*(REG32_PTR_T)(0x3CF00050)) /* Configures the pins of port 5 */
|
||||||
#define PDAT5 (*(REG32_PTR_T)(0x3CF00054)) /* The data register for 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 PCON6 (*(REG32_PTR_T)(0x3CF00060)) /* Configures the pins of port 6 */
|
||||||
#define PDAT6 (*(REG32_PTR_T)(0x3CF00064)) /* The data register for 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 */
|
#define PCON7 (*(REG32_PTR_T)(0x3CF00070)) /* Configures the pins of port 7 */
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
#include "panic.h"
|
#include "panic.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
#include "ftl-target.h"
|
#include "ftl-target.h"
|
||||||
|
#include "nand-target.h"
|
||||||
|
|
||||||
/* for compatibility */
|
/* for compatibility */
|
||||||
long last_disk_activity = -1;
|
long last_disk_activity = -1;
|
||||||
|
|
@ -62,14 +63,17 @@ void nand_spindown(int seconds)
|
||||||
|
|
||||||
void nand_sleep(void)
|
void nand_sleep(void)
|
||||||
{
|
{
|
||||||
|
nand_power_down();
|
||||||
}
|
}
|
||||||
|
|
||||||
void nand_sleepnow(void)
|
void nand_sleepnow(void)
|
||||||
{
|
{
|
||||||
|
nand_power_down();
|
||||||
}
|
}
|
||||||
|
|
||||||
void nand_spin(void)
|
void nand_spin(void)
|
||||||
{
|
{
|
||||||
|
nand_power_up();
|
||||||
}
|
}
|
||||||
|
|
||||||
void nand_enable(bool on)
|
void nand_enable(bool on)
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "inttypes.h"
|
#include "inttypes.h"
|
||||||
#include "nand-target.h"
|
#include "nand-target.h"
|
||||||
|
#include <pmu-target.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -84,6 +85,7 @@ uint8_t nand_twp[4];
|
||||||
uint8_t nand_tunk2[4];
|
uint8_t nand_tunk2[4];
|
||||||
uint8_t nand_tunk3[4];
|
uint8_t nand_tunk3[4];
|
||||||
uint32_t nand_type[4];
|
uint32_t nand_type[4];
|
||||||
|
int nand_powered = 0;
|
||||||
|
|
||||||
static struct mutex nand_mtx;
|
static struct mutex nand_mtx;
|
||||||
static struct wakeup nand_wakeup;
|
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)
|
uint32_t nand_wait_rbbdone(void)
|
||||||
{
|
{
|
||||||
long timeout = current_tick + HZ / 50;
|
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)
|
uint32_t checkempty)
|
||||||
{
|
{
|
||||||
mutex_lock(&nand_mtx);
|
mutex_lock(&nand_mtx);
|
||||||
|
if (!nand_powered) nand_power_up();
|
||||||
uint32_t rc, eccresult;
|
uint32_t rc, eccresult;
|
||||||
nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
|
nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
|
||||||
if (nand_send_cmd(NAND_CMD_READ) != 0) return nand_unlock(1);
|
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)
|
void* sparebuffer, uint32_t doecc)
|
||||||
{
|
{
|
||||||
mutex_lock(&nand_mtx);
|
mutex_lock(&nand_mtx);
|
||||||
|
if (!nand_powered) nand_power_up();
|
||||||
if (sparebuffer != 0) memcpy(nand_uncached_spare, sparebuffer, 0x40);
|
if (sparebuffer != 0) memcpy(nand_uncached_spare, sparebuffer, 0x40);
|
||||||
else memset(nand_uncached_spare, 0xFF, 0x40);
|
else memset(nand_uncached_spare, 0xFF, 0x40);
|
||||||
if (doecc != 0)
|
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)
|
uint32_t nand_block_erase(uint32_t bank, uint32_t page)
|
||||||
{
|
{
|
||||||
mutex_lock(&nand_mtx);
|
mutex_lock(&nand_mtx);
|
||||||
|
if (!nand_powered) nand_power_up();
|
||||||
nand_set_fmctrl0(bank, 0);
|
nand_set_fmctrl0(bank, 0);
|
||||||
if (nand_send_cmd(NAND_CMD_BLOCKERASE) != 0) return nand_unlock(1);
|
if (nand_send_cmd(NAND_CMD_BLOCKERASE) != 0) return nand_unlock(1);
|
||||||
FMANUM = 2;
|
FMANUM = 2;
|
||||||
|
|
@ -410,12 +454,7 @@ uint32_t nand_device_init(void)
|
||||||
|
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
uint32_t i, j;
|
uint32_t i, j;
|
||||||
PCON2 = 0x33333333;
|
if (!nand_powered) nand_power_up();
|
||||||
PDAT2 = 0;
|
|
||||||
PCON3 = 0x11113333;
|
|
||||||
PDAT3 = 0;
|
|
||||||
PCON4 = 0x33333333;
|
|
||||||
PDAT4 = 0;
|
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
nand_tunk1[i] = 7;
|
nand_tunk1[i] = 7;
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,8 @@
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifndef __NAND_H__
|
#ifndef __NAND_TARGET_H__
|
||||||
#define __NAND_H__
|
#define __NAND_TARGET_H__
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "inttypes.h"
|
#include "inttypes.h"
|
||||||
|
|
@ -30,7 +30,7 @@ struct nand_device_info_type
|
||||||
{
|
{
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
uint16_t blocks;
|
uint16_t blocks;
|
||||||
uint32_t userblocks;
|
uint16_t userblocks;
|
||||||
uint16_t pagesperblock;
|
uint16_t pagesperblock;
|
||||||
uint8_t blocksizeexponent;
|
uint8_t blocksizeexponent;
|
||||||
uint8_t tunk1;
|
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);
|
const struct nand_device_info_type* nand_get_device_type(uint32_t bank);
|
||||||
uint32_t nand_reset(uint32_t bank);
|
uint32_t nand_reset(uint32_t bank);
|
||||||
uint32_t nand_device_init(void);
|
uint32_t nand_device_init(void);
|
||||||
|
void nand_power_up(void);
|
||||||
|
void nand_power_down(void);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,6 @@
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
#include "cpu.h"
|
|
||||||
#include "system.h"
|
|
||||||
#include "string.h"
|
|
||||||
|
|
||||||
void usb_init_device(void)
|
void usb_init_device(void)
|
||||||
{
|
{
|
||||||
|
|
@ -30,27 +27,21 @@ void usb_init_device(void)
|
||||||
|
|
||||||
void usb_enable(bool on)
|
void usb_enable(bool on)
|
||||||
{
|
{
|
||||||
/* This device specific code will eventually give way to proper USB
|
(void)on;
|
||||||
handling, which should be the same for all S5L870x targets. */
|
}
|
||||||
if (on)
|
|
||||||
|
void usb_attach(void)
|
||||||
{
|
{
|
||||||
#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. */
|
|
||||||
|
|
||||||
memcpy((void *)0x0002bf00, "diskmodehotstuff\1\0\0\0", 20);
|
|
||||||
|
|
||||||
system_reboot(); /* Reboot */
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool usb_pin_state(void)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* detect host or charger (INSERTED or EXTRACTED) */
|
||||||
int usb_detect(void)
|
int usb_detect(void)
|
||||||
{
|
{
|
||||||
#if defined(IPOD_NANO2G)
|
return usb_pin_state() ? USB_INSERTED : USB_EXTRACTED;
|
||||||
if ((PDAT14 & 0x8) == 0x0)
|
|
||||||
return USB_INSERTED;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return USB_EXTRACTED;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue