int pmu_read_adc(unsigned int adc) { int data = 0; mutex_lock(&pmu_adc_mutex); pmu_write(0x54, 5 | (adc << 4)); while ((data & 0x80) == 0) { yield(); data = pmu_read(0x57); } int value = (pmu_read(0x55) << 2) | (data & 3); mutex_unlock(&pmu_adc_mutex); return value; }
void pmu_ldo_on_in_standby(unsigned int ldo, int onoff) { if (ldo < 4) { unsigned char newval = pmu_read(0x3B) & ~(1 << (2 * ldo)); if (onoff) newval |= 1 << (2 * ldo); pmu_write(0x3B, newval); } else if (ldo < 8) { unsigned char newval = pmu_read(0x3C) & ~(1 << (2 * (ldo - 4))); if (onoff) newval |= 1 << (2 * (ldo - 4)); pmu_write(0x3C, newval); } }
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; } } }
static void pmu_read_inputs_ooc(void) { unsigned char oocstat = pmu_read(PCF5063X_REG_OOCSTAT); if (oocstat & PCF5063X_OOCSTAT_EXTON2) usb_insert_int(); else usb_remove_int(); #ifdef IPOD_ACCESSORY_PROTOCOL pmu_input_accessory = !(oocstat & PCF5063X_OOCSTAT_EXTON3); #endif }
bool_t pmu_init(void) { u8_t val; iic_init(); if(pmu_read(0x31, &val)) pmu_write(0x31, val & 0xf8); return TRUE; }
/* returns raw value, 8 or 10-bit resolution */ unsigned short pmu_read_adc(const struct pmu_adc_channel *ch) { mutex_lock(&pmu_adc_mutex); pmu_write(PCF5063X_REG_ADCC3, ch->adcc3); if (ch->bias_dly) sleep(ch->bias_dly); uint8_t buf[2] = { ch->adcc2, ch->adcc1 | PCF5063X_ADCC1_ADCSTART }; pmu_write_multiple(PCF5063X_REG_ADCC2, 2, buf); int adcs3 = 0; while (!(adcs3 & PCF5063X_ADCS3_ADCRDY)) { yield(); adcs3 = pmu_read(PCF5063X_REG_ADCS3); } int raw = pmu_read(PCF5063X_REG_ADCS1); if ((ch->adcc1 & PCF5063X_ADCC1_RES_MASK) == PCF5063X_ADCC1_RES_10BIT) raw = (raw << 2) | (adcs3 & PCF5063X_ADCS3_ADCDAT1L_MASK); mutex_unlock(&pmu_adc_mutex); return raw; }
/* 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); }
static inline void software_reset(void) { uint16_t pmucnt2; switch (current_cpu_type()) { case CPU_VR4122: case CPU_VR4131: case CPU_VR4133: pmucnt2 = pmu_read(PMUCNT2REG); pmucnt2 |= SOFTRST; pmu_write(PMUCNT2REG, pmucnt2); break; default: set_c0_status(ST0_BEV | ST0_ERL); change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); __flush_cache_all(); write_c0_wired(0); __asm__("jr %0"::"r"(0xbfc00000)); break; } }
static void pmu_read_inputs_gpio(void) { pmu_input_holdswitch = !(pmu_read(PCF50635_REG_GPIOSTAT) & PCF50635_GPIOSTAT_GPIO2); }
static void pmu_read_inputs_mbcs(void) { pmu_input_firewire = !!(pmu_read(PCF5063X_REG_MBCS1) & PCF5063X_MBCS1_ADAPTPRES); }
bool dbg_hw_info(void) { int line; int i; unsigned int state = 0; const unsigned int max_states=3; lcd_clear_display(); lcd_setfont(FONT_SYSFIXED); state=0; while(1) { lcd_clear_display(); line = 0; if(state == 0) { _DEBUG_PRINTF("CPU:"); _DEBUG_PRINTF("current_tick: %d", (unsigned int)current_tick); line++; _DEBUG_PRINTF("LCD type: %d", lcd_type); line++; } else if(state==1) { _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, pmu_read(0x2e + (i << 1))?" on":"off", 900 + pmu_read(0x2d + (i << 1))*100, device[i]); } _DEBUG_PRINTF("cpu voltage: %dmV",625 + pmu_read(0x1e)*25); _DEBUG_PRINTF("memory voltage: %dmV",625 + pmu_read(0x22)*25); line++; _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)); } else if(state==2) { _DEBUG_PRINTF("Audio DMA:"); _DEBUG_PRINTF(">%08X %08X %08X %08X %08X", DMAC0C0CONFIG, DMAC0C0SRCADDR, DMAC0C0DESTADDR, DMAC0C0NEXTLLI, DMAC0C0CONTROL); for(i = 0; i < PCM_LLICOUNT; i++) _DEBUG_PRINTF("%08X: %08X %08X %08X %08X", &pcm_lli[i], pcm_lli[i].srcaddr, pcm_lli[i].dstaddr, pcm_lli[i].nextlli, pcm_lli[i].control); _DEBUG_PRINTF("chunk: %08X %08X", pcm_chunksize, pcm_remaining); } else { state=0; } lcd_update(); switch(button_get_w_tmo(HZ/20)) { case BUTTON_SCROLL_BACK: if(state!=0) state--; break; case BUTTON_SCROLL_FWD: if(state!=max_states-1) { state++; } break; case DEBUG_CANCEL: case BUTTON_REL: lcd_setfont(FONT_UI); return false; } } lcd_setfont(FONT_UI); return false; }