summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/export/pcf5063x.h11
-rw-r--r--firmware/target/arm/s5l8702/debug-s5l8702.c29
-rw-r--r--firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c162
-rw-r--r--firmware/target/arm/s5l8702/ipod6g/pmu-target.h25
-rw-r--r--firmware/target/arm/s5l8702/ipod6g/power-ipod6g.c2
-rw-r--r--firmware/target/arm/s5l8702/system-s5l8702.c1
6 files changed, 214 insertions, 16 deletions
diff --git a/firmware/export/pcf5063x.h b/firmware/export/pcf5063x.h
index 164417f..f5f177a 100644
--- a/firmware/export/pcf5063x.h
+++ b/firmware/export/pcf5063x.h
@@ -159,6 +159,17 @@ enum pcf5063X_reg_oocwake {
PCF5063X_OOCWAKE_ADP = 0x80,
};
+enum pcf5063X_reg_oocstat {
+ PCF5063X_OOCSTAT_ONKEY = 0x01,
+ PCF5063X_OOCSTAT_EXTON1 = 0x02,
+ PCF5063X_OOCSTAT_EXTON2 = 0x04,
+ PCF5063X_OOCSTAT_EXTON3 = 0x08,
+ PCF5063X_OOCSTAT_BUBPRES = 0x10,
+ PCF5063X_OOCSTAT_SYSOK = 0x20,
+ PCF5063X_OOCSTAT_BATOK = 0x40,
+ PCF5063X_OOCSTAT_TMPOK = 0x80,
+};
+
enum pcf5063X_reg_mbcc1 {
PCF5063X_MBCC1_CHGENA = 0x01, /* Charger enable */
PCF5063X_MBCC1_AUTOSTOP = 0x02,
diff --git a/firmware/target/arm/s5l8702/debug-s5l8702.c b/firmware/target/arm/s5l8702/debug-s5l8702.c
index 614019b..48a20a9 100644
--- a/firmware/target/arm/s5l8702/debug-s5l8702.c
+++ b/firmware/target/arm/s5l8702/debug-s5l8702.c
@@ -102,14 +102,14 @@ bool dbg_hw_info(void)
_DEBUG_PRINTF("PMU:");
for(i=0;i<7;i++)
{
- char *device[] = {"(unknown)",
- "(unknown)",
- "(unknown)",
- "(unknown)",
- "(unknown)",
- "(unknown)",
- "(unknown)"};
- _DEBUG_PRINTF("ldo%d %s: %dmV %s",i,
+ char *device[] = {"unknown",
+ "unknown",
+ "LCD",
+ "AUDIO",
+ "unknown",
+ "CLICKWHEEL",
+ "ACCESSORY"};
+ _DEBUG_PRINTF("ldo%d %s: %dmV (%s)",i,
pmu_read(0x2e + (i << 1))?" on":"off",
900 + pmu_read(0x2d + (i << 1))*100,
device[i]);
@@ -120,6 +120,19 @@ bool dbg_hw_info(void)
_DEBUG_PRINTF("charging: %s", charging_state() ? "true" : "false");
_DEBUG_PRINTF("backlight: %s", pmu_read(0x29) ? "on" : "off");
_DEBUG_PRINTF("brightness value: %d", pmu_read(0x28));
+ line++;
+ _DEBUG_PRINTF("USB present: %s",
+ pmu_usb_present() ? "true" : "false");
+#if CONFIG_CHARGING
+ _DEBUG_PRINTF("FW present: %s",
+ pmu_firewire_present() ? "true" : "false");
+#endif
+ _DEBUG_PRINTF("holdswitch locked: %s",
+ pmu_holdswitch_locked() ? "true" : "false");
+#ifdef IPOD_ACCESSORY_PROTOCOL
+ _DEBUG_PRINTF("accessory present: %s",
+ pmu_accessory_present() ? "true" : "false");
+#endif
}
#ifdef UC870X_DEBUG
else if(state==2)
diff --git a/firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c b/firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c
index 920c93a..4200308 100644
--- a/firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c
+++ b/firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c
@@ -21,8 +21,12 @@
#include "config.h"
#include "kernel.h"
-#include "i2c-s5l8702.h"
+#include "thread.h"
+
#include "pmu-target.h"
+#include "i2c-s5l8702.h"
+#include "gpio-s5l8702.h"
+
static struct mutex pmu_adc_mutex;
@@ -50,11 +54,6 @@ int pmu_write(int address, unsigned char val)
return pmu_write_multiple(address, 1, &val);
}
-void pmu_init(void)
-{
- mutex_init(&pmu_adc_mutex);
-}
-
int pmu_read_adc(unsigned int adc)
{
int data = 0;
@@ -144,6 +143,157 @@ void pmu_write_rtc(unsigned char* buffer)
}
/*
+ * eINT
+ */
+#define Q_EINT 0
+
+static char pmu_thread_stack[DEFAULT_STACK_SIZE/4];
+static struct event_queue pmu_queue;
+static unsigned char ints_msk[6];
+
+static void pmu_eint_isr(struct eint_handler*);
+
+static struct eint_handler pmu_eint = {
+ .gpio_n = GPIO_EINT_PMU,
+ .type = EIC_INTTYPE_LEVEL,
+ .level = EIC_INTLEVEL_LOW,
+ .isr = pmu_eint_isr,
+};
+
+static int pmu_input_holdswitch;
+static int pmu_input_usb;
+
+int pmu_holdswitch_locked(void)
+{
+ return pmu_input_holdswitch;
+}
+
+int pmu_usb_present(void)
+{
+ return pmu_input_usb;
+}
+
+#ifdef IPOD_ACCESSORY_PROTOCOL
+static int pmu_input_accessory;
+
+int pmu_accessory_present(void)
+{
+ return pmu_input_accessory;
+}
+#endif
+
+#if CONFIG_CHARGING
+static int pmu_input_firewire;
+
+int pmu_firewire_present(void)
+{
+ return pmu_input_firewire;
+}
+
+static void pmu_read_inputs_mbcs(void)
+{
+ pmu_input_firewire = !!(pmu_read(PCF5063X_REG_MBCS1)
+ & PCF5063X_MBCS1_ADAPTPRES);
+}
+#endif
+
+static void pmu_read_inputs_gpio(void)
+{
+ pmu_input_holdswitch = !(pmu_read(PCF50635_REG_GPIOSTAT)
+ & PCF50635_GPIOSTAT_GPIO2);
+}
+
+static void pmu_read_inputs_ooc(void)
+{
+ unsigned char oocstat = pmu_read(PCF5063X_REG_OOCSTAT);
+ pmu_input_usb = !!(oocstat & PCF5063X_OOCSTAT_EXTON2);
+#ifdef IPOD_ACCESSORY_PROTOCOL
+ pmu_input_accessory = !(oocstat & PCF5063X_OOCSTAT_EXTON3);
+#endif
+}
+
+static void pmu_eint_isr(struct eint_handler *h)
+{
+ eint_unregister(h);
+ queue_post(&pmu_queue, Q_EINT, 0);
+}
+
+static void NORETURN_ATTR pmu_thread(void)
+{
+ struct queue_event ev;
+ unsigned char ints[6];
+
+ while (true)
+ {
+ queue_wait_w_tmo(&pmu_queue, &ev, TIMEOUT_BLOCK);
+ switch (ev.id)
+ {
+ case Q_EINT:
+ /* read (clear) PMU interrupts, this will also
+ raise the PMU IRQ pin */
+ pmu_read_multiple(PCF5063X_REG_INT1, 2, ints);
+ ints[5] = pmu_read(PCF50635_REG_INT6);
+
+#if CONFIG_CHARGING
+ if (ints[0] & ~ints_msk[0]) pmu_read_inputs_mbcs();
+#endif
+ if (ints[1] & ~ints_msk[1]) pmu_read_inputs_ooc();
+ if (ints[5] & ~ints_msk[5]) pmu_read_inputs_gpio();
+
+ eint_register(&pmu_eint);
+ break;
+
+ case SYS_TIMEOUT:
+ break;
+ }
+ }
+}
+
+/* main init */
+void pmu_init(void)
+{
+ mutex_init(&pmu_adc_mutex);
+ queue_init(&pmu_queue, false);
+
+ create_thread(pmu_thread,
+ pmu_thread_stack, sizeof(pmu_thread_stack), 0,
+ "PMU" IF_PRIO(, PRIORITY_SYSTEM) IF_COP(, CPU));
+
+ /* configure PMU interrutps */
+ for (int i = 0; i < 6; i++)
+ ints_msk[i] = 0xff;
+
+#if CONFIG_CHARGING
+ ints_msk[0] &= ~PCF5063X_INT1_ADPINS & /* FireWire */
+ ~PCF5063X_INT1_ADPREM;
+#endif
+ ints_msk[1] &= ~PCF5063X_INT2_EXTON2R & /* USB */
+ ~PCF5063X_INT2_EXTON2F;
+#ifdef IPOD_ACCESSORY_PROTOCOL
+ ints_msk[1] &= ~PCF5063X_INT2_EXTON3R & /* Accessory */
+ ~PCF5063X_INT2_EXTON3F;
+#endif
+ ints_msk[5] &= ~PCF50635_INT6_GPIO2; /* Holdswitch */
+
+ pmu_write_multiple(PCF5063X_REG_INT1M, 5, ints_msk);
+ pmu_write(PCF50635_REG_INT6M, ints_msk[5]);
+
+ /* clear all */
+ unsigned char ints[5];
+ pmu_read_multiple(PCF5063X_REG_INT1, 5, ints);
+ pmu_read(PCF50635_REG_INT6);
+
+ /* get initial values */
+#if CONFIG_CHARGING
+ pmu_read_inputs_mbcs();
+#endif
+ pmu_read_inputs_ooc();
+ pmu_read_inputs_gpio();
+
+ eint_register(&pmu_eint);
+}
+
+/*
* preinit
*/
int pmu_rd_multiple(int address, int count, unsigned char* buffer)
diff --git a/firmware/target/arm/s5l8702/ipod6g/pmu-target.h b/firmware/target/arm/s5l8702/ipod6g/pmu-target.h
index d090f72..2274b40 100644
--- a/firmware/target/arm/s5l8702/ipod6g/pmu-target.h
+++ b/firmware/target/arm/s5l8702/ipod6g/pmu-target.h
@@ -30,7 +30,21 @@
/* undocummented PMU registers */
#define PCF50635_REG_INT6 0x85
#define PCF50635_REG_INT6M 0x86
-#define PCF50635_REG_GPIOSTAT 0x87 /* bit1: GPIO2 status (TBC) */
+#define PCF50635_REG_GPIOSTAT 0x87
+
+enum pcf50635_reg_int6 {
+ PCF50635_INT6_GPIO1 = 0x01, /* TBC */
+ PCF50635_INT6_GPIO2 = 0x02,
+};
+
+enum pcf50635_reg_gpiostat {
+ PCF50635_GPIOSTAT_GPIO1 = 0x01, /* TBC */
+ PCF50635_GPIOSTAT_GPIO2 = 0x02,
+};
+
+
+/* GPIO for external PMU interrupt */
+#define GPIO_EINT_PMU 0x7b
/* LDOs */
#define LDO_UNK1 1 /* TBC: SoC voltage (USB) */
@@ -77,6 +91,15 @@ void pmu_read_rtc(unsigned char* buffer);
void pmu_write_rtc(unsigned char* buffer);
void pmu_hdd_power(bool on);
+int pmu_holdswitch_locked(void);
+int pmu_usb_present(void);
+#if CONFIG_CHARGING
+int pmu_firewire_present(void);
+#endif
+#ifdef IPOD_ACCESSORY_PROTOCOL
+int pmu_accessory_present(void);
+#endif
+
void pmu_preinit(void);
#ifdef BOOTLOADER
unsigned char pmu_rd(int address);
diff --git a/firmware/target/arm/s5l8702/ipod6g/power-ipod6g.c b/firmware/target/arm/s5l8702/ipod6g/power-ipod6g.c
index 57358b8..d3224d2 100644
--- a/firmware/target/arm/s5l8702/ipod6g/power-ipod6g.c
+++ b/firmware/target/arm/s5l8702/ipod6g/power-ipod6g.c
@@ -41,6 +41,8 @@ void power_off(void)
void power_init(void)
{
+ pmu_init();
+
idepowered = false;
/* DOWN1CTL: CPU DVM step time = 30us (default: no DVM) */
diff --git a/firmware/target/arm/s5l8702/system-s5l8702.c b/firmware/target/arm/s5l8702/system-s5l8702.c
index cbe8bfc..459f4c3 100644
--- a/firmware/target/arm/s5l8702/system-s5l8702.c
+++ b/firmware/target/arm/s5l8702/system-s5l8702.c
@@ -207,7 +207,6 @@ void system_init(void)
#endif
gpio_init();
eint_init();
- pmu_init();
dma_init();
#ifdef HAVE_SERIAL
uart_init();