/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id: powermgmt-sim.c 29543 2011-03-08 19:33:30Z thomasjfox $ * * Copyright (C) 2002 by Heikki Hannikainen, Uwe Freese * Revisions copyright (C) 2005 by Gerald Van Baren * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #include "config.h" #include "system.h" #include #include "kernel.h" #include "powermgmt.h" #include #define BATT_MINMVOLT 3500 /* minimum millivolts of battery */ #define BATT_MAXMVOLT 4200 /* maximum millivolts of battery */ #define BATT_MAXRUNTIME (10 * 60) /* maximum runtime with full battery in minutes */ #ifdef IZ2S #include #include #include #include #include #include #include #include unsigned char batlvl_calibration[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 5, 6, 7, 8, 9, 11, 13, 16, 20, 23, 29, 36, 42, 48, 54, 58, 62, 65, 68, 69, 71, 73, 77, 80,82, 83, 84, 85, 86, 88, 91, 92, 94, 94, 95, 95, 95, 95, 95, 96,96, 96, 97, 97, 98, 99, 99,100,100, }; #define MAP_SIZE 4096UL #define GPIO 0 /* AC Power */ #define GPIO_BASE 0x40E00000 /* PXA270 GPIO Register Base */ typedef unsigned long u32; static int regoffset(int gpio) { if (gpio < 32) return 0; if (gpio < 64) return 4; if (gpio < 96) return 8; return 0x100; } static int gpio_read(void *map_base, int gpio) { volatile u32 *reg = (u32*)((u32)map_base + regoffset(gpio)); return (*reg >> (gpio&31)) & 1; } #endif /* IZ2S */ extern void send_battery_level_event(void); extern int last_sent_battery_level; extern int battery_percent; static unsigned int battery_millivolts = BATT_MAXMVOLT; /* estimated remaining time in minutes */ static int powermgmt_est_runningtime_min = BATT_MAXRUNTIME; static void battery_status_update(void) { static time_t last_change = 0; static bool charging = false; time_t now; time(&now); #ifdef IZ2S /* Check once a second? */ if ((last_change) < now) { int fd; void *map_base; unsigned char res; static int tot, n = -1; static unsigned char lvl[64]; fd = open("/dev/mem", O_RDONLY | O_SYNC); if (fd < 0) return; map_base = mmap(0, MAP_SIZE, PROT_READ, MAP_SHARED, fd, GPIO_BASE); if(map_base == (void *) -1) return; if (gpio_read(map_base,GPIO) == 1) charging= true; /* mains */ else charging= false; /* battery(0) or error */ if(munmap(map_base, MAP_SIZE) == -1) return; close(fd); /* Open lpc915 controller via i2c */ if ( (fd = open("/dev/i2c-0",O_RDWR)) < 0) return; /* FORCE so we can look at registers even when a driver is also running */ if (ioctl(fd,I2C_SLAVE_FORCE,0x55) < 0) return; /* Take 64 readings, and give the average value. */ res = i2c_smbus_read_byte_data(fd, 0x02); /* batt chg level */ close(fd); if (n < 0) /* first time */ { n = 0; memset(lvl, res, 64); tot = res * 64; } tot -= lvl[n]; tot += res; lvl[n++] = res; n = n %64; battery_percent = batlvl_calibration[tot/64]; /* got charging and battery_percent */ #else /* NOT IZ2S */ /* Check once a minute? */ if ((last_change+60) < now) { int batteryTime = 0; int ac, charge, flag; char units[32]; FILE* fapm = fopen("/proc/apm", "r"); last_change = now; if (!fapm) return; fscanf(fapm, "%*s %*d.%*d %*x %x %x %x %d%% %d %s\n", &ac, &charge, &flag, &battery_percent, &batteryTime, units); fclose(fapm); if (charge) charging = true; else charging = false; #if 0 // BatteryTime not available on Zipit_Z2 yet. if ((flag & 0x80) == 0 && charge != 0xFF && ac != 1 && batteryTime != -1) { if (!strncmp(units, "min", 32)) powermgmt_est_runningtime_min = batteryTime *= 60; } #endif #endif /* NOT IZ2S, move onto ZIPIT_Z2 common code. */ powermgmt_est_runningtime_min = battery_percent * BATT_MAXRUNTIME / 100; battery_millivolts = battery_percent * (BATT_MAXMVOLT - BATT_MINMVOLT); battery_millivolts /= 100; battery_millivolts += BATT_MINMVOLT; send_battery_level_event(); } return; } void battery_read_info(int *voltage, int *level) { battery_status_update(); if (voltage) *voltage = battery_millivolts; if (level) *level = battery_percent; } unsigned int battery_voltage(void) { battery_status_update(); return battery_millivolts; } int battery_level(void) { battery_status_update(); return battery_percent; } int battery_time(void) { battery_status_update(); return powermgmt_est_runningtime_min; } bool battery_level_safe(void) { return battery_level() >= 10; } void set_battery_capacity(int capacity) { (void)capacity; } #if BATTERY_TYPES_COUNT > 1 void set_battery_type(int type) { (void)type; } #endif #ifdef HAVE_ACCESSORY_SUPPLY void accessory_supply_set(bool enable) { (void)enable; } #endif #ifdef HAVE_LINEOUT_POWEROFF void lineout_set(bool enable) { (void)enable; } #endif