summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary King <gking@nvidia.com>2009-12-11 15:02:59 -0800
committerGary King <gking@nvidia.com>2009-12-11 15:02:59 -0800
commitb86cbafbb7328f276b6540c1cec4491d4c2d342a (patch)
tree6274e0d4f7750629066e80f799bd324135c37fb2
parente550e3fd26c036ec1fcb55928fd7606d7e1daedb (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.h337
-rw-r--r--drivers/power/Kconfig7
-rw-r--r--drivers/power/Makefile2
-rw-r--r--drivers/power/nvec_battery.c467
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");
+