diff options
author | Gary King <gking@nvidia.com> | 2009-12-11 15:02:59 -0800 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2009-12-11 15:02:59 -0800 |
commit | b86cbafbb7328f276b6540c1cec4491d4c2d342a (patch) | |
tree | 6274e0d4f7750629066e80f799bd324135c37fb2 | |
parent | e550e3fd26c036ec1fcb55928fd7606d7e1daedb (diff) |
power: add battery driver for NvEc batteries
Adds a battery driver for batteries connected to NVIDIA Tegra NvEc-compliant
embedded controllers
Change-Id: I5ab13902749fcf01df93efba13a010f45e9eea30
-rw-r--r-- | arch/arm/mach-tegra/include/nvodm_battery.h | 337 | ||||
-rw-r--r-- | drivers/power/Kconfig | 7 | ||||
-rw-r--r-- | drivers/power/Makefile | 2 | ||||
-rw-r--r-- | drivers/power/nvec_battery.c | 467 |
4 files changed, 813 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/include/nvodm_battery.h b/arch/arm/mach-tegra/include/nvodm_battery.h new file mode 100644 index 000000000000..ae4567169b05 --- /dev/null +++ b/arch/arm/mach-tegra/include/nvodm_battery.h @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * <b>NVIDIA Tegra ODM Kit: + * Battery Interface</b> + * + * @b Description: Defines the ODM adaptation interface for battery. + * + */ + +#ifndef INCLUDED_NVODM_BATTERY_H +#define INCLUDED_NVODM_BATTERY_H + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#include "nvodm_services.h" + +/** + * @defgroup nvodm_battery_group Battery Adaptation Interface + * + * @ingroup nvodm_adaptation + * @{ + */ + +/** + * Defines an opaque handle that exists for each battery device in the + * system, each of which is defined by the customer implementation. + */ +typedef struct NvOdmBatteryDeviceRec *NvOdmBatteryDeviceHandle; + +/** + * Defines the AC status. + */ +typedef enum +{ + /// Specifies AC is offline. + NvOdmBatteryAcLine_Offline, + + /// Specifies AC is online. + NvOdmBatteryAcLine_Online, + + /// Specifies backup power. + NvOdmBatteryAcLine_BackupPower, + + NvOdmBatteryAcLine_Num, + /// Ignore -- Forces compilers to make 32-bit enums. + NvOdmBatteryAcLine_Force32 = 0x7FFFFFFF +}NvOdmBatteryAcLineStatus; + +/** + * Defines the Battery events. + */ +typedef enum +{ + /// Specifies Battery Present State. + NvOdmBatteryEventType_Present, + + /// Specifies Charging State. + NvOdmBatteryEventType_Charging, + + /// Specifies Remaining Capacity Alarm. + NvOdmBatteryEventType_RemainingCapacityAlarm, + + NvOdmBatteryEventType_Num, + /// Ignore -- Forces compilers to make 32-bit enums. + NvOdmBatteryEventType_Force32 = 0x7FFFFFFF +}NvOdmBatteryEventType; + +/** @name Battery Status Defines */ +/*@{*/ + +#define NVODM_BATTERY_STATUS_HIGH 0x01 +#define NVODM_BATTERY_STATUS_LOW 0x02 +#define NVODM_BATTERY_STATUS_CRITICAL 0x04 +#define NVODM_BATTERY_STATUS_CHARGING 0x08 +#define NVODM_BATTERY_STATUS_NO_BATTERY 0x80 +#define NVODM_BATTERY_STATUS_UNKNOWN 0xFF + +/*@}*/ +/** @name Battery Data Defines */ +/*@{*/ +#define NVODM_BATTERY_DATA_UNKNOWN 0x7FFFFFFF + +/*@}*/ +/** + * Defines battery instances. + */ +typedef enum +{ + /// Specifies main battery. + NvOdmBatteryInst_Main, + + /// Specifies backup battery. + NvOdmBatteryInst_Backup, + + NvOdmBatteryInst_Num, + /// Ignore -- Forces compilers to make 32-bit enums. + NvOdmBatteryInst_Force32 = 0x7FFFFFFF + +}NvOdmBatteryInstance; + +/** + * Defines battery data. + */ +typedef struct NvOdmBatteryDataRec +{ + /// Specifies battery life percent. + NvU32 BatteryLifePercent; + + /// Specifies battery lifetime. + NvU32 BatteryLifeTime; + + /// Specifies voltage. + NvU32 BatteryVoltage; + + /// Specifies battery current. + NvS32 BatteryCurrent; + + /// Specifies battery average current. + NvS32 BatteryAverageCurrent; + + /// Specifies battery interval. + NvU32 BatteryAverageInterval; + + /// Specifies the mAH consumed. + NvU32 BatteryMahConsumed; + + /// Specifies battery temperature. + NvU32 BatteryTemperature; + + /// Specifies battery Remaining Capacity. + NvU32 BatteryRemainingCapacity; + + /// Specifies battery Last Charge Full Capacity. + NvU32 BatteryLastChargeFullCapacity; + + /// Specifies battery Critical Capacity. + NvU32 BatteryCriticalCapacity; + +}NvOdmBatteryData; + +/** + * Defines battery chemistry. + */ +typedef enum +{ + /// Specifies an alkaline battery. + NvOdmBatteryChemistry_Alkaline, + + /// Specifies a nickel-cadmium (NiCd) battery. + NvOdmBatteryChemistry_NICD, + + /// Specifies a nickel-metal hydride (NiMH) battery. + NvOdmBatteryChemistry_NIMH, + + /// Specifies a lithium-ion (Li-ion) battery. + NvOdmBatteryChemistry_LION, + + /// Specifies a lithium-ion polymer (Li-poly) battery. + NvOdmBatteryChemistry_LIPOLY, + + /// Specifies a zinc-air battery. + NvOdmBatteryChemistry_XINCAIR, + + NvOdmBatteryChemistry_Num, + /// Ignore -- Forces compilers to make 32-bit enums. + NvOdmBatteryChemistry_Force32 = 0x7FFFFFFF +}NvOdmBatteryChemistry; + +/** + * Opens the handle for battery ODM. + * + * @param hDevice A pointer to the handle to the battery ODM. + * @param hOdmSemaphore Battery events signals this registered semaphore. + * Can Pass NULL if events are not needed by client. + * @return NV_TRUE if successful, or NV_FALSE otherwise. + */ +NvBool NvOdmBatteryDeviceOpen(NvOdmBatteryDeviceHandle *hDevice, + NvOdmOsSemaphoreHandle *hOdmSemaphore); + +/** + * Closes the handle for battery ODM. + * + * @param hDevice A handle to the battery ODM. + */ +void NvOdmBatteryDeviceClose(NvOdmBatteryDeviceHandle hDevice); + +/** + * Gets the AC line status. + * + * @param hDevice A handle to the EC. + * @param pStatus A pointer to the AC line + * status returned by the ODM. + * + * @return NV_TRUE if successful, or NV_FALSE otherwise. + */ +NvBool NvOdmBatteryGetAcLineStatus( + NvOdmBatteryDeviceHandle hDevice, + NvOdmBatteryAcLineStatus *pStatus); + + +/** + * Gets the battery status. + * + * @param hDevice A handle to the EC. + * @param batteryInst The battery type. + * @param pStatus A pointer to the battery + * status returned by the ODM. + * + * @return NV_TRUE if successful, or NV_FALSE otherwise. + */ +NvBool NvOdmBatteryGetBatteryStatus( + NvOdmBatteryDeviceHandle hDevice, + NvOdmBatteryInstance batteryInst, + NvU8 *pStatus); + +/** + * Gets the battery data. + * + * @param hDevice A handle to the EC. + * @param batteryInst The battery type. + * @param pData A pointer to the battery + * data returned by the ODM. + * + * @return NV_TRUE if successful, or NV_FALSE otherwise. + */ +NvBool NvOdmBatteryGetBatteryData( + NvOdmBatteryDeviceHandle hDevice, + NvOdmBatteryInstance batteryInst, + NvOdmBatteryData *pData); + + +/** + * Gets the battery full lifetime. + * + * @param hDevice A handle to the EC. + * @param batteryInst The battery type. + * @param pLifeTime A pointer to the battery + * full lifetime returned by the ODM. + * + */ +void NvOdmBatteryGetBatteryFullLifeTime( + NvOdmBatteryDeviceHandle hDevice, + NvOdmBatteryInstance batteryInst, + NvU32 *pLifeTime); + +/** + * Gets the battery chemistry. + * + * @param hDevice A handle to the EC. + * @param batteryInst The battery type. + * @param pChemistry A pointer to the battery + * chemistry returned by the ODM. + * + */ +void NvOdmBatteryGetBatteryChemistry( + NvOdmBatteryDeviceHandle hDevice, + NvOdmBatteryInstance batteryInst, + NvOdmBatteryChemistry *pChemistry); + +/** + * Gets the battery event. + * + * @param hDevice A handle to the EC. + * @param pBatteryEvent Battery events + * + */ +void NvOdmBatteryGetEvent( + NvOdmBatteryDeviceHandle hDevice, + NvU8 *pBatteryEvent); + + +/** + * Gets the Battery Manufacturer. + * + * @param hDevice [IN] A handle to the EC. + * @param BatteryInst [IN] The battery type. + * @param pBatteryManufacturer [OUT] A pointer to the battery Manufacturer + */ +NvBool NvOdmBatteryGetManufacturer( + NvOdmBatteryDeviceHandle hDevice, + NvOdmBatteryInstance BatteryInst, + NvU8 *pBatteryManufacturer); + +/** + * Gets the Battery Model. + * + * @param hDevice [IN] A handle to the EC. + * @param BatteryInst [IN] The battery type. + * @param pBatteryModel [OUT] A pointer to the battery model + */ +NvBool NvOdmBatteryGetModel( + NvOdmBatteryDeviceHandle hDevice, + NvOdmBatteryInstance BatteryInst, + NvU8 *pBatteryModel); + +#if defined(__cplusplus) +} +#endif + +/** @} */ + +#endif // INCLUDED_NVODM_BATTERY_H diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index d14fde35e87b..20812689dd94 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -95,4 +95,11 @@ config BATTERY_TEGRA_ODM Say Y to enable battery support for Tegra using the NVIDIA ODM kit PMU adaptation interface +config TEGRA_BATTERY_NVEC + boolean "Battery connected to NVIDIA Tegra NvEc embedded controller" + depends on ARCH_TEGRA && TEGRA_NVEC + help + Say Y to include battery support for batteries connected to an + NVIDIA Tegra NvEc-compliant embedded controller + endif # POWER_SUPPLY diff --git a/drivers/power/Makefile b/drivers/power/Makefile index b5d57361f64b..777243b6ff40 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -27,3 +27,5 @@ obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o obj-$(CONFIG_BATTERY_TEGRA_ODM) += tegra_odm_battery.o +obj-$(CONFIG_TEGRA_BATTERY_NVEC) += nvec_battery.o + diff --git a/drivers/power/nvec_battery.c b/drivers/power/nvec_battery.c new file mode 100644 index 000000000000..f96007c27963 --- /dev/null +++ b/drivers/power/nvec_battery.c @@ -0,0 +1,467 @@ +/* + * drivers/power/nvec_battery.c + * + * Battery driver for batteries connected to NVIDIA NvEc-compliant embedded + * controller + * + * Copyright (c) 2009, NVIDIA Corporation. + * + * 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 program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +/* + * Copyright (c) 2009 NVIDIA Corporation. All rights reserved. + * + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/debugfs.h> +#include <linux/power_supply.h> +#include <linux/wakelock.h> + +#include "nvcommon.h" +#include "nvos.h" +#include "nvodm_battery.h" + +/* This defines the manufacturer name and model name length */ +#define BATTERY_INFO_NAME_LEN 30 + +#define GET_CHARGER_STATUS 0 + +typedef enum +{ + NvCharger_Type_Battery = 0, + NvCharger_Type_USB, + NvCharger_Type_AC, + NvCharger_Type_Num, + NvCharger_Type_Force32 = 0x7FFFFFFF +} NvCharger_Type; + +typedef enum +{ + NvCharge_Control_Charging_Disable = 0, + NvCharge_Control_Charging_Enable, + NvCharge_Control_Num, + NvCharge_Control_Force32 = 0x7FFFFFFF +} NvCharge_Control; + +static enum power_supply_property tegra_battery_properties[] = { + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_PRESENT, + POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_HEALTH, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_CURRENT_AVG, + POWER_SUPPLY_PROP_CHARGE_NOW, + POWER_SUPPLY_PROP_CHARGE_FULL, + POWER_SUPPLY_PROP_CHARGE_EMPTY, + POWER_SUPPLY_PROP_TEMP, +// POWER_SUPPLY_PROP_MODEL_NAME, +// POWER_SUPPLY_PROP_MANUFACTURER, + +}; + +static enum power_supply_property tegra_power_properties[] = { + POWER_SUPPLY_PROP_ONLINE, +}; + +static char *supply_list[] = { + "battery", +}; + +static int tegra_power_get_property(struct power_supply *psy, + enum power_supply_property psp, union power_supply_propval *val); + +static int tegra_battery_get_property(struct power_supply *psy, + enum power_supply_property psp, union power_supply_propval *val); + +static struct power_supply tegra_power_supplies[] = { + { + .name = "battery", + .type = POWER_SUPPLY_TYPE_BATTERY, + .properties = tegra_battery_properties, + .num_properties = ARRAY_SIZE(tegra_battery_properties), + .get_property = tegra_battery_get_property, + }, + { + .name = "usb", + .type = POWER_SUPPLY_TYPE_USB, + .supplied_to = supply_list, + .num_supplicants = ARRAY_SIZE(supply_list), + .properties = tegra_power_properties, + .num_properties = ARRAY_SIZE(tegra_power_properties), + .get_property = tegra_power_get_property, + }, + { + .name = "ac", + .type = POWER_SUPPLY_TYPE_MAINS, + .supplied_to = supply_list, + .num_supplicants = ARRAY_SIZE(supply_list), + .properties = tegra_power_properties, + .num_properties = ARRAY_SIZE(tegra_power_properties), + .get_property = tegra_power_get_property, + }, +}; + +/* This is the Battery context structure */ +struct tegra_battery_dev { + NvOdmBatteryDeviceHandle hOdmBattDev; + NvU32 batt_id; + NvU32 voltage; /* voltage */ + NvU32 temp; /* Temperature */ + NvU32 current; /* Battery current */ + NvU32 current_avg; /* average current */ + NvU32 charging_source; /* 0: no cable, 1:usb, 2:AC */ + NvU32 charging_enabled; /* 0: Disable, 1: Enable */ + NvU32 capacity; /* full capacity of battery (mAh) */ + NvU32 capacity_crit; /* critical capacity level */ + NvU32 capacity_remain; /* remaining battery capacity */ + NvU32 percent_remain; /* percentage of battery remaining */ + NvU32 lifetime; + NvU32 consumed; + NvBool ac_status; + NvBool present; +}; + +static struct tegra_battery_dev *batt_dev; + +static void tegra_get_battery_tech(int *val, NvOdmBatteryInstance inst) +{ + NvOdmBatteryChemistry chemistry = NvOdmBatteryChemistry_Num; + + NvOdmBatteryGetBatteryChemistry(batt_dev->hOdmBattDev, + inst, &chemistry); + + switch(chemistry) { + case NvOdmBatteryChemistry_NICD: + *val = POWER_SUPPLY_TECHNOLOGY_NiCd; + break; + + case NvOdmBatteryChemistry_NIMH: + *val = POWER_SUPPLY_TECHNOLOGY_NiMH; + break; + + case NvOdmBatteryChemistry_LION: + *val = POWER_SUPPLY_TECHNOLOGY_LION; + break; + + case NvOdmBatteryChemistry_LIPOLY: + *val = POWER_SUPPLY_TECHNOLOGY_LIPO; + break; + + case NvOdmBatteryChemistry_XINCAIR: + case NvOdmBatteryChemistry_Alkaline: + default: + *val = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; + break; + } +} + +static void tegra_battery_convert(NvOdmBatteryData *data) +{ + if (data->BatteryLifePercent == NVODM_BATTERY_DATA_UNKNOWN) + data->BatteryLifePercent = 0; + + if (data->BatteryLifeTime == NVODM_BATTERY_DATA_UNKNOWN) + data->BatteryLifeTime = 0; + + if (data->BatteryVoltage == NVODM_BATTERY_DATA_UNKNOWN) + data->BatteryVoltage = 0; + + if (data->BatteryCurrent == NVODM_BATTERY_DATA_UNKNOWN) + data->BatteryCurrent = 0; + + if (data->BatteryMahConsumed == NVODM_BATTERY_DATA_UNKNOWN) + data->BatteryMahConsumed = 0; + + if (data->BatteryTemperature == NVODM_BATTERY_DATA_UNKNOWN) + data->BatteryTemperature = 0; + + if (data->BatteryAverageCurrent == NVODM_BATTERY_DATA_UNKNOWN) + data->BatteryAverageCurrent = 0; + + if (data->BatteryLastChargeFullCapacity == NVODM_BATTERY_DATA_UNKNOWN) + data->BatteryLastChargeFullCapacity = 0; + + if (data->BatteryCriticalCapacity == NVODM_BATTERY_DATA_UNKNOWN) + data->BatteryCriticalCapacity = 0; + + if (data->BatteryRemainingCapacity == NVODM_BATTERY_DATA_UNKNOWN) + data->BatteryRemainingCapacity = 0; +} + +static NvBool tegra_battery_data(NvOdmBatteryInstance NvBatteryInst) +{ + NvOdmBatteryData data = {0}; + + if (!NvOdmBatteryGetBatteryData(batt_dev->hOdmBattDev, + NvBatteryInst, &data)) + return NV_FALSE; + + tegra_battery_convert(&data); + + if (NvBatteryInst == NvOdmBatteryInst_Main) { + batt_dev->voltage = data.BatteryVoltage; + batt_dev->current = data.BatteryCurrent; + batt_dev->current_avg = data.BatteryAverageCurrent; + batt_dev->temp = data.BatteryTemperature; + batt_dev->percent_remain = data.BatteryLifePercent; + batt_dev->lifetime = data.BatteryLifeTime; + batt_dev->consumed = data.BatteryMahConsumed; + batt_dev->capacity = data.BatteryLastChargeFullCapacity; + batt_dev->capacity_crit = data.BatteryCriticalCapacity; + batt_dev->capacity_remain = data.BatteryRemainingCapacity; + } + + return NV_TRUE; +} + +static int tegra_power_get_property(struct power_supply *psy, + enum power_supply_property psp, union power_supply_propval *val) +{ + NvCharger_Type charger = 0; + NvOdmBatteryAcLineStatus status = NvOdmBatteryAcLine_Offline; + + /* Need to find out the way which tell the charger source */ + + switch (psp) { + + case POWER_SUPPLY_PROP_ONLINE: + if (!NvOdmBatteryGetAcLineStatus(batt_dev->hOdmBattDev, + &status)) + return -ENODEV; + + if (status == NvOdmBatteryAcLine_Offline) { + batt_dev->ac_status = NV_FALSE; + } + else if (status == NvOdmBatteryAcLine_Online) { + batt_dev->ac_status = NV_TRUE; + charger = NvCharger_Type_AC; + } + else + batt_dev->ac_status = NV_FALSE; + + if (psy->type == POWER_SUPPLY_TYPE_MAINS) + val->intval = (charger == NvCharger_Type_AC); + else if (psy->type == POWER_SUPPLY_TYPE_USB) + val->intval = (charger == NvCharger_Type_USB); + else + val->intval = 0; + + break; + + default: + return -EINVAL; + } + return 0; +} + +static int tegra_battery_get_property(struct power_supply *psy, + enum power_supply_property psp, union power_supply_propval *val) +{ + NvU8 name[BATTERY_INFO_NAME_LEN] = {0}; + int technology = 0; + NvU8 state = 0; + + switch (psp) { + case POWER_SUPPLY_PROP_STATUS: + val->intval = POWER_SUPPLY_STATUS_UNKNOWN; + /* TODO:Get Charger status here */ +#if GET_CHARGER_STATUS + if (!NvOdmBatteryGetBatteryStatus(batt_dev->hOdmBattDev, + NvOdmBatteryInst_Main, &state)) + return -ENODEV; + + if (state == NVODM_BATTERY_STATUS_UNKNOWN) { + batt_dev->present = NV_FALSE; + val->intval = POWER_SUPPLY_STATUS_UNKNOWN; + } else if (state == NVODM_BATTERY_STATUS_NO_BATTERY) { + batt_dev->present = NV_FALSE; + val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; + } else if (state & NVODM_BATTERY_STATUS_CHARGING) { + batt_dev->present = NV_TRUE; + val->intval = POWER_SUPPLY_STATUS_CHARGING; + /* TODO:Get Charger status here */ + } else + val->intval = POWER_SUPPLY_STATUS_DISCHARGING; +#endif + /* Getting the battery info once here so for the other property + * requests there will not be lot of ec req */ + if (!tegra_battery_data(NvOdmBatteryInst_Main)) { + ; /* FIXME: return error? */ + } + break; + + case POWER_SUPPLY_PROP_HEALTH: + if (batt_dev->present) + val->intval = POWER_SUPPLY_HEALTH_GOOD; + else + val->intval = POWER_SUPPLY_HEALTH_UNKNOWN; + + break; + + case POWER_SUPPLY_PROP_PRESENT: + if (!NvOdmBatteryGetBatteryStatus(batt_dev->hOdmBattDev, + NvOdmBatteryInst_Main, &state)) + return -EINVAL; + + if (state == NVODM_BATTERY_STATUS_UNKNOWN) { + batt_dev->present = NV_FALSE; + val->intval = POWER_SUPPLY_STATUS_UNKNOWN; + } else { + if (state == NVODM_BATTERY_STATUS_NO_BATTERY) { + batt_dev->present = NV_FALSE; + val->intval = NV_FALSE; + } + if (state & (NVODM_BATTERY_STATUS_HIGH | + NVODM_BATTERY_STATUS_LOW | + NVODM_BATTERY_STATUS_CRITICAL | + NVODM_BATTERY_STATUS_CHARGING)) { + batt_dev->present = NV_TRUE; + val->intval = NV_TRUE; + } + } + break; + + case POWER_SUPPLY_PROP_TECHNOLOGY: + tegra_get_battery_tech(&technology, NvOdmBatteryInst_Main); + val->intval = technology; + break; + + case POWER_SUPPLY_PROP_CAPACITY: + val->intval = batt_dev->percent_remain; + break; + + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = batt_dev->voltage*1000; + break; + + case POWER_SUPPLY_PROP_CURRENT_NOW: + val->intval = batt_dev->current; + break; + + case POWER_SUPPLY_PROP_CURRENT_AVG: + val->intval = batt_dev->current_avg; + break; + + case POWER_SUPPLY_PROP_CHARGE_NOW: + val->intval = batt_dev->capacity_remain; + break; + + case POWER_SUPPLY_PROP_CHARGE_FULL: + val->intval = batt_dev->capacity; + break; + + case POWER_SUPPLY_PROP_CHARGE_EMPTY: + val->intval = batt_dev->capacity_crit; + break; + + case POWER_SUPPLY_PROP_TEMP: + /* returned value is degrees C * 10 */ + val->intval = batt_dev->temp/10; + break; + + case POWER_SUPPLY_PROP_MODEL_NAME: + if (!NvOdmBatteryGetModel(batt_dev->hOdmBattDev, + NvOdmBatteryInst_Main, name)) + return -EINVAL; + + strncpy((char *)val->strval, name, strlen(name)); + break; + + case POWER_SUPPLY_PROP_MANUFACTURER: + if (!NvOdmBatteryGetManufacturer(batt_dev->hOdmBattDev, + NvOdmBatteryInst_Main, name)) + return -EINVAL; + + strncpy((char *)val->strval, name, strlen(name)); + break; + + default: + return -EINVAL; + } + + return 0; +} + +static int tegra_battery_probe(struct platform_device *pdev) +{ + int i, rc; + NvBool result = NV_FALSE; + + batt_dev = kzalloc(sizeof(struct tegra_battery_dev), GFP_KERNEL); + if (!batt_dev) { + return -ENOMEM; + } + + result = NvOdmBatteryDeviceOpen(&(batt_dev->hOdmBattDev), NULL); + if (!result || !batt_dev->hOdmBattDev) { + kfree(batt_dev); + batt_dev = NULL; + return -1; + } + + for (i = 0; i < ARRAY_SIZE(tegra_power_supplies); i++) { + if (power_supply_register(&pdev->dev, &tegra_power_supplies[i])) + printk(KERN_ERR "Failed to register power supply\n"); + } + + return 0; +} + +static int tegra_battery_remove(struct platform_device *pdev) +{ + if (batt_dev) { + if (batt_dev->hOdmBattDev) { + NvOdmBatteryDeviceClose(batt_dev->hOdmBattDev); + batt_dev->hOdmBattDev = NULL; + } + + kfree(batt_dev); + batt_dev = NULL; + + } + return 0; +} + +static struct platform_driver tegra_battery_driver = { + .probe = tegra_battery_probe, + .remove = tegra_battery_remove, + .driver = { + .name = "tegra_battery", + .owner = THIS_MODULE, + }, +}; + +static int __init tegra_battery_init(void) +{ + platform_driver_register(&tegra_battery_driver); + return 0; +} + +static void __exit tegra_battery_exit(void) +{ + platform_driver_unregister(&tegra_battery_driver); +} + +module_init(tegra_battery_init); +module_exit(tegra_battery_exit); +MODULE_DESCRIPTION("TEGRA EC based Battery Driver"); + |