int rtc_write_datetime(const struct tm *tm) { unsigned int i; int rc, oldlevel; unsigned char buf[7]; buf[0] = tm->tm_sec; buf[1] = tm->tm_min; buf[2] = tm->tm_hour; buf[3] = tm->tm_wday; buf[4] = tm->tm_mday; buf[5] = tm->tm_mon + 1; buf[6] = tm->tm_year - 100; for (i = 0; i < sizeof(buf); i++) buf[i] = DEC2BCD(buf[i]); oldlevel = disable_irq_save(); if (get_pmu_type() == PCF50606) rc = pcf50606_write_multiple(PCF5060X_RTCSC, buf, sizeof(buf)); else rc = pcf50635_write_multiple(PCF5063X_REG_RTCSC, buf, sizeof(buf)); restore_irq(oldlevel); return rc; }
int rtc_read_datetime(struct tm *tm) { unsigned int i; int rc, oldlevel; unsigned char buf[7]; oldlevel = disable_irq_save(); if (get_pmu_type() == PCF50606) rc = pcf50606_read_multiple(PCF5060X_RTCSC, buf, sizeof(buf)); else rc = pcf50635_read_multiple(PCF5063X_REG_RTCSC, buf, sizeof(buf)); restore_irq(oldlevel); for (i = 0; i < sizeof(buf); i++) buf[i] = BCD2DEC(buf[i]); tm->tm_sec = buf[0]; tm->tm_min = buf[1]; tm->tm_hour = buf[2]; tm->tm_wday = buf[3]; tm->tm_mday = buf[4]; tm->tm_mon = buf[5] - 1; tm->tm_year = buf[6] + 100; return rc; }
unsigned int power_input_status(void) { /* Players with a PCF50606 can use GPIOs to determine whether AC is inserted and whether charging is taking place. Newer players re-use C26 for the touchscreen, so we need to monitor PCF50635 USB/adapter IRQs for this. */ if (get_pmu_type() == PCF50606) { /* Check AC adapter */ if (GPIOD & (1<<23)) return POWER_INPUT_MAIN_CHARGER; /* C26 indicates charging, without AC connected it implies USB power */ if ((GPIOC & (1<<26)) == 0) return POWER_INPUT_USB_CHARGER; } else { /* pcf50635 power input status can be obtained from MBCS1 register */ int mbcs1 = pcf50635_read(PCF5063X_REG_MBCS1); /* Check AC adapter presence*/ if (mbcs1 & PCF5063X_MBCS1_ADAPTPRES) return POWER_INPUT_MAIN_CHARGER; /* Check USB presence */ if (mbcs1 & PCF5063X_MBCS1_USBPRES) return POWER_INPUT_USB_CHARGER; } return POWER_INPUT_NONE; }
void _backlight_off(void) { if (get_pmu_type() == PCF50606) { GPIOA_CLEAR = (1<<6); } else { int level = disable_irq_save(); pcf50635_write(PCF5063X_REG_LEDENA, 0); restore_irq(level); } }
/* Returns battery voltage from ADC [millivolts] */ unsigned int battery_adc_voltage(void) { static unsigned last_tick = 0; if (TIME_BEFORE(last_tick+HZ, current_tick)) { short adc_val; if (get_pmu_type() == PCF50606) pcf50606_read_adc(PCF5060X_ADC_BATVOLT_RES, &adc_val, NULL); else pcf50635_read_adc(PCF5063X_ADCC1_MUX_BATSNS_RES, &adc_val, NULL); current_voltage = (adc_val * BATTERY_SCALE_FACTOR) >> 10; last_tick = current_tick; }
void _backlight_set_brightness(int brightness) { int level = disable_irq_save(); if (get_pmu_type() == PCF50606) { pcf50606_write(PCF5060X_PWMC1, 0xe1 | (MAX_BRIGHTNESS_SETTING-brightness)<<1); pcf50606_write(PCF5060X_GPOC1, 0x3); } else { static const int brightness_lookup[MAX_BRIGHTNESS_SETTING+1] = {0x1, 0x8, 0xa, 0xe, 0x12, 0x16, 0x19, 0x1b, 0x1e, 0x21, 0x24, 0x26, 0x28, 0x2a, 0x2c}; pcf50635_write(PCF5063X_REG_LEDOUT, brightness_lookup[brightness]); } restore_irq(level); }
void EXT3(void) { if (get_pmu_type() == PCF50606) { unsigned char data[3]; /* 0 = INT1, 1 = INT2, 2 = INT3 */ /* Clear pending interrupts from pcf50606 */ pcf50606_read_multiple(0x02, data, 3); if (data[0] & 0x04) { /* ONKEY1S */ if (!charger_inserted()) sys_poweroff(); else pcf50606_reset_timeout(); } if (data[2] & 0x08) { /* Touchscreen event, do something about it */ touchscreen_handle_device_irq(); } } else { unsigned char data[5]; /* 0 = INT1, 1 = INT2, 2 = INT3, ... 4 = INT5 */ /* Clear pending interrupts from pcf50635 */ pcf50635_read_multiple(PCF5063X_REG_INT1, data, 5); if (data[2] & PCF5063X_INT3_ONKEY1S) { if (!charger_inserted()) sys_poweroff(); } } }