EM/Battery: Read battery profile and config
authorAmar Shankar <amarx.shankar@intel.com>
Thu, 12 Apr 2012 06:00:51 +0000 (11:30 +0530)
committerbuildbot <buildbot@intel.com>
Tue, 24 Apr 2012 20:31:34 +0000 (13:31 -0700)
BZ: 15399

Read battery charge profile and battery config from
platfrom layer

Change-Id: I465f153c4335271fb282dc5b8d45959196d95d7d
Signed-off-by: Amar Shankar <amarx.shankar@intel.com>
Reviewed-on: http://android.intel.com:8080/43228
Reviewed-by: Pujol, BenjaminX <benjaminx.pujol@intel.com>
Reviewed-by: Tc, Jenny <jenny.tc@intel.com>
Tested-by: P, Eshwar N <eshwar.n.p@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
arch/x86/platform/intel-mid/mrfl.c
drivers/power/basin_cove_charger.c
drivers/power/basin_cove_charger.h
include/linux/power/intel_mid_powersupply.h [new file with mode: 0644]
include/linux/sfi.h

index 082bca1..41a5c24 100644 (file)
@@ -19,6 +19,8 @@
 #include <asm/setup.h>
 #include <asm/intel-mid.h>
 #include <asm/processor.h>
+#include <linux/power/intel_mid_powersupply.h>
+#include <asm/intel_scu_ipc.h>
 
 unsigned long __init intel_mid_calibrate_tsc(void)
 {
@@ -45,3 +47,68 @@ static int __init set_simulation_platform(char *str)
        return -EINVAL;
 }
 early_param("mrfld_simulation", set_simulation_platform);
+
+struct plat_battery_config  *plat_batt_config;
+EXPORT_SYMBOL(plat_batt_config);
+
+static int __init get_plat_batt_config(void)
+{
+       int ret;
+       plat_batt_config = kzalloc(sizeof(struct plat_battery_config),
+                               GFP_KERNEL);
+       if (!plat_batt_config) {
+               pr_err("%s : Error in allocating"
+                               "plat_battery_config\n", __func__);
+               return -ENOMEM;
+       }
+       ret = intel_scu_ipc_read_mip((u8 *) plat_batt_config,
+               sizeof(struct plat_battery_config), BATT_SMIP_BASE_OFFSET, 1);
+       if (ret) {
+               pr_err("%s(): Error in reading platform battery"
+                       " configuration\n", __func__);
+               kfree(plat_batt_config);
+               plat_batt_config = NULL;
+       }
+       return ret;
+}
+/* FIXME: SMIP access is failing. So disabling the SMIP read */
+/*rootfs_initcall(get_plat_batt_config); */
+
+struct batt_charging_profile *batt_chrg_profile;
+EXPORT_SYMBOL(batt_chrg_profile);
+
+static int __init sfi_parse_batt(struct sfi_table_header *table)
+{
+       struct sfi_table_simple *sb;
+       struct batt_charging_profile *pentry;
+       int totentrs = 0, totlen = 0;
+
+       sb = (struct sfi_table_simple *)table;
+       totentrs = SFI_GET_NUM_ENTRIES(sb, struct batt_charging_profile);
+       if (totentrs) {
+               batt_chrg_profile = kzalloc(
+                       sizeof(struct batt_charging_profile), GFP_KERNEL);
+               if (!batt_chrg_profile) {
+                       pr_info("%s(): Error in kzalloc\n", __func__);
+                       return -ENOMEM;
+               }
+               pentry = (struct batt_charging_profile *)sb->pentry;
+               totlen = totentrs * sizeof(*pentry);
+               if (totlen <= sizeof(batt_chrg_profile))
+                       memcpy(batt_chrg_profile, pentry, totlen);
+               else {
+                       pr_err("%s: Error in copying batt charge profile\n");
+                       kfree(batt_chrg_profile);
+                       return -ENOMEM;
+               }
+       }
+       return 0;
+
+}
+
+static int __init mrfl_platform_init(void)
+{
+       sfi_table_parse(SFI_SIG_OEM0, NULL, NULL, sfi_parse_batt);
+       return 0;
+}
+arch_initcall(mrfl_platform_init);
index 75ae343..27155ad 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/wakelock.h>
 #include <linux/async.h>
 #include <linux/reboot.h>
+#include <linux/power/intel_mid_powersupply.h>
 /*TODO remove this below header file once tangier_otg.h is available*/
 #include <linux/usb/penwell_otg.h>
 #include <asm/intel_basincove_gpadc.h>
@@ -258,60 +259,9 @@ static void init_charger_ps_context(struct bc_chrgr_drv_context *chrgr_drv_cxt)
        chrgr_drv_cxt->chrgr_props_cxt.vbus_vol = 4200;
 }
 
-static int get_charging_profile(struct charging_profile *chrg_profile)
-{
-       /*
-        * TODO: Get battery profile from platfrom layer. Using hardcoded sample
-        * value till this is done.
-        */
-
-       memcpy(chrg_profile->batt_id, "UNKNOWN", sizeof("UNKNOWN"));
-       chrg_profile->voltage_max = 4200;
-       chrg_profile->capacity = 1500;
-       chrg_profile->battery_type = 2; /* POWER_SUPPLY_TECHNOLOGY_LION */
-       chrg_profile->temp_mon_ranges = 4;
-
-       chrg_profile->temp_mon_range[0].temp_low_lim = 45;
-       chrg_profile->temp_mon_range[0].temp_up_lim = 60;
-       chrg_profile->temp_mon_range[0].rbatt = 120;
-       chrg_profile->temp_mon_range[0].full_chrg_cur = 950;
-       chrg_profile->temp_mon_range[0].full_chrg_vol = 4100;
-       chrg_profile->temp_mon_range[0].maint_chrg_cur = 950;
-       chrg_profile->temp_mon_range[0].maint_chrg_vol_ll = 4000;
-       chrg_profile->temp_mon_range[0].maint_chrg_vol_ul = 4050;
-
-       chrg_profile->temp_mon_range[1].temp_low_lim = 10;
-       chrg_profile->temp_mon_range[1].temp_up_lim = 45;
-       chrg_profile->temp_mon_range[1].rbatt = 120;
-       chrg_profile->temp_mon_range[1].full_chrg_cur = 950;
-       chrg_profile->temp_mon_range[1].full_chrg_vol = 4200;
-       chrg_profile->temp_mon_range[1].maint_chrg_cur = 950;
-       chrg_profile->temp_mon_range[1].maint_chrg_vol_ll = 4100;
-       chrg_profile->temp_mon_range[1].maint_chrg_vol_ul = 4150;
-
-       chrg_profile->temp_mon_range[2].temp_low_lim = 0;
-       chrg_profile->temp_mon_range[2].temp_up_lim = 10;
-       chrg_profile->temp_mon_range[2].rbatt = 120;
-       chrg_profile->temp_mon_range[2].full_chrg_cur = 950;
-       chrg_profile->temp_mon_range[2].full_chrg_vol = 4100;
-       chrg_profile->temp_mon_range[2].maint_chrg_cur = 950;
-       chrg_profile->temp_mon_range[2].maint_chrg_vol_ll = 4000;
-       chrg_profile->temp_mon_range[2].maint_chrg_vol_ul = 4050;
-
-       chrg_profile->temp_mon_range[3].temp_low_lim = -10;
-       chrg_profile->temp_mon_range[3].temp_up_lim = 0;
-       chrg_profile->temp_mon_range[3].rbatt = 120;
-       chrg_profile->temp_mon_range[3].full_chrg_cur = 950;
-       chrg_profile->temp_mon_range[3].full_chrg_vol = 3900;
-       chrg_profile->temp_mon_range[3].maint_chrg_cur = 950;
-       chrg_profile->temp_mon_range[3].maint_chrg_vol_ll = 3950;
-       chrg_profile->temp_mon_range[3].maint_chrg_vol_ul = 3950;
-
-       return 0;
 
-}
-
-static void populate_invalid_chrg_profile(struct charging_profile *chrg_profile)
+static void populate_invalid_chrg_profile
+       (struct batt_charging_profile *chrg_profile)
 {
 
        /*
@@ -325,7 +275,8 @@ static void populate_invalid_chrg_profile(struct charging_profile *chrg_profile)
 
 }
 
-static int get_batt_config(struct battery_config *batt_config)
+static void populate_default_battery_config(
+               struct plat_battery_config *batt_config)
 {
 
        /*TODO: Get battery configuration from platfrom layer.Using default
@@ -339,13 +290,6 @@ static int get_batt_config(struct battery_config *batt_config)
        return 0;
 }
 
-static void populate_default_battery_config(struct battery_config *batt_config)
-{
-       batt_config->vbatt_sh_min = BATT_DEAD_CUTOFF_VOLT;
-       batt_config->vbatt_crit = BATT_CRIT_CUTOFF_VOLT;
-       batt_config->temp_high = MSIC_BATT_TEMP_MAX;
-       batt_config->temp_low = MSIC_BATT_TEMP_MIN;
-}
 
 /*TO BE FIXED : event handler stub*/
 static int pmic_bc_event_handler(void *arg, int event, struct otg_bc_cap *cap)
@@ -519,7 +463,7 @@ static int bc_chrgr_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
        chrgr_drv_cxt->chrg_profile =
-           kzalloc(sizeof(struct charging_profile), GFP_KERNEL);
+           kzalloc(sizeof(struct batt_charging_profile), GFP_KERNEL);
        if (!chrgr_drv_cxt->chrg_profile) {
 
                dev_err(&pdev->dev, "%s(): memory allocation failed: Unable to"
@@ -529,7 +473,7 @@ static int bc_chrgr_probe(struct platform_device *pdev)
        }
 
        chrgr_drv_cxt->batt_config =
-           kzalloc(sizeof(struct battery_config), GFP_KERNEL);
+           kzalloc(sizeof(struct plat_battery_config), GFP_KERNEL);
        if (!chrgr_drv_cxt->batt_config) {
 
                dev_err(&pdev->dev, "%s(): memory allocation failed: Unable to"
@@ -548,7 +492,7 @@ static int bc_chrgr_probe(struct platform_device *pdev)
        INIT_DELAYED_WORK(&chrgr_drv_cxt->chrg_callback_dwrk,
                                bc_chrg_callback_worker);
 
-       if (get_charging_profile(chrgr_drv_cxt->chrg_profile)) {
+       if (get_batt_charging_profile(chrgr_drv_cxt->chrg_profile)) {
                dev_err(&pdev->dev, "%s() :Failed to get battery properties\n",
                        __func__);
                populate_invalid_chrg_profile(chrgr_drv_cxt->chrg_profile);
index 44271ba..fc4c9f9 100644 (file)
 #define SCHGRIRQ1_ADDR         0x4F
 #define BATT_PRESENT           1
 #define BATT_NOT_PRESENT       0
-#define BATT_STRING_MAX                8
-#define BATTID_STR_LEN         8
-#define BATT_PROF_MAX_TEMP_NR_RNG      6
 
 #define CHARGER_PRESENT                1
 #define CHARGER_NOT_PRESENT    0
 
 /* Bit definitions */
 
-/* Temperature Monitoring Table */
-struct temp_mon_table {
-       short int temp_up_lim;
-       short int temp_low_lim;
-       short int rbatt;
-       short int full_chrg_vol;
-       short int full_chrg_cur;
-       short int maint_chrg_vol_ll;
-       short int maint_chrg_vol_ul;
-       short int maint_chrg_cur;
-} __packed;
-
-/*Battery properties */
-struct charging_profile {
-       char batt_id[BATTID_STR_LEN];
-       unsigned short int voltage_max;
-       unsigned int capacity;
-       u8 battery_type;
-       u8 temp_mon_ranges;
-       struct temp_mon_table temp_mon_range[BATT_PROF_MAX_TEMP_NR_RNG];
-} __packed;
 
 struct bc_batt_props_cxt {
        unsigned int status;
        unsigned int health;
        bool present;
 };
-
 struct bc_charger_props_cxt {
        unsigned int charging_mode;
        unsigned int charger_present;
@@ -216,26 +191,6 @@ struct bc_charger_props_cxt {
        char charger_vender[BATT_STRING_MAX];
 };
 
-/* Battery Settings info from platfrom layer*/
-struct battery_config {
-       u8 smip_rev;
-       u8 fpo;                 /* fixed implementation options */
-       u8 fpo1;                /* fixed implementation options1 */
-       u8 rsys;                /* System Resistance for Fuel gauging */
-
-       /* Minimum voltage necessary to
-        * be able to safely shut down */
-       short int vbatt_sh_min;
-
-       /* Voltage at which the battery driver
-        * should report the LEVEL as CRITICAL */
-       short int vbatt_crit;
-
-       short int itc;          /* Charge termination current */
-       short int temp_high;    /* Safe Temp Upper Limit */
-       short int temp_low;     /* Safe Temp lower Limit */
-       u8 brd_id;              /* Unique Board ID */
-} __packed;
 
 /*
  * basinc cove charger driver info
@@ -245,9 +200,8 @@ struct bc_chrgr_drv_context {
        struct platform_device *pdev;
        bool invalid_batt;
        bool is_batt_present;
-
-       struct charging_profile *chrg_profile;
-       struct battery_config *batt_config;
+       struct batt_charging_profile *chrg_profile;
+       struct plat_battery_config *batt_config;
 
        /* lock to protect the charger properties
         * locking is applied wherever read or write
diff --git a/include/linux/power/intel_mid_powersupply.h b/include/linux/power/intel_mid_powersupply.h
new file mode 100644 (file)
index 0000000..c45fe41
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * intel_mid_powersupply.h - Intel MID Power Supply header file
+ *
+ * Copyright (C) 2011 Intel 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; version 2 of the License.
+ *
+ * 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * Author: Jenny TC <jenny.tc@intel.com>
+ */
+
+#ifndef __INTEL_MID_POWERSUPPLY_H_
+#define __INTEL_MID_POWERSUPPLY_H_
+
+
+/* Battery data Offset range in SMIP */
+#define BATT_SMIP_BASE_OFFSET          0x314
+
+#define BATT_STRING_MAX                8
+#define BATTID_STR_LEN         8
+#define BATT_PROF_MAX_TEMP_NR_RNG      6
+/* Temperature Monitoring Table */
+
+struct temp_mon_table {
+       short int temp_up_lim;
+       short int temp_low_lim;
+       short int rbatt;
+       short int full_chrg_vol;
+       short int full_chrg_cur;
+       short int maint_chrg_vol_ll;
+       short int maint_chrg_vol_ul;
+       short int maint_chrg_cur;
+} __packed;
+
+/* Charging Profile */
+/* FIXME: make the batt_chargig profile generic */
+struct batt_charging_profile {
+       char batt_id[BATTID_STR_LEN];
+       unsigned short int voltage_max;
+       unsigned int capacity;
+       u8 battery_type;
+       u8 temp_mon_ranges;
+       struct temp_mon_table temp_mon_range[BATT_PROF_MAX_TEMP_NR_RNG];
+} __packed;
+
+/* Battery Configuration info */
+struct plat_battery_config {
+       u8 smip_rev;
+       u8 fpo;                 /* fixed implementation options */
+       u8 fpo1;                /* fixed implementation options1 */
+       u8 rsys;                /* System Resistance for Fuel gauging */
+
+       /* Minimum voltage necessary to
+        * be able to safely shut down */
+       short int vbatt_sh_min;
+
+       /* Voltage at which the battery driver
+        * should report the LEVEL as CRITICAL */
+       short int vbatt_crit;
+
+       short int itc;          /* Charge termination current */
+       short int temp_high;    /* Safe Temp Upper Limit */
+       short int temp_low;     /* Safe Temp lower Limit */
+       u8 brd_id;              /* Unique Board ID */
+} __packed;
+
+
+extern struct batt_charging_profile *batt_chrg_profile;
+
+extern struct plat_battery_config  *plat_batt_config;
+
+static inline int get_batt_charging_profile
+       (struct batt_charging_profile *chrg_profile)
+{
+
+       if (batt_chrg_profile) {
+               memcpy(chrg_profile, batt_chrg_profile,
+                               sizeof(struct batt_charging_profile));
+               return 0;
+       }
+       return -EINVAL;
+}
+static inline int get_batt_config(struct plat_battery_config *batt_config)
+{
+       if (plat_batt_config) {
+               memcpy(batt_config, plat_batt_config,
+                               sizeof(struct plat_battery_config));
+               return 0;
+       }
+       return -EINVAL;
+}
+
+#endif
index 4ff445b..f928c68 100644 (file)
@@ -73,6 +73,7 @@
 #define SFI_SIG_DEVS           "DEVS"
 #define SFI_SIG_GPIO           "GPIO"
 #define SFI_SIG_OEMB           "OEMB"
+#define SFI_SIG_OEM0           "OEM0"
 
 #define SFI_SIGNATURE_SIZE     4
 #define SFI_OEM_ID_SIZE                6