summaryrefslogtreecommitdiff
path: root/drivers/battery/sec_dt_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/battery/sec_dt_init.c')
-rw-r--r--drivers/battery/sec_dt_init.c1154
1 files changed, 1154 insertions, 0 deletions
diff --git a/drivers/battery/sec_dt_init.c b/drivers/battery/sec_dt_init.c
new file mode 100644
index 00000000..70559605
--- /dev/null
+++ b/drivers/battery/sec_dt_init.c
@@ -0,0 +1,1154 @@
+/*
+ * sec_dt_init.c
+ * Samsung battery data parsing from device tree
+ *
+ * Copyright (C) 2014 Samsung Electronics
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/of_irq.h>
+#include <soc/sprd/adc.h>
+#include <linux/battery/sec_battery.h>
+
+#include <soc/sprd/sci_glb_regs.h>
+#include <soc/sprd/sci.h>
+#include <soc/sprd/adi.h>
+#include <soc/sprd/arch_misc.h>
+#include <soc/sprd/hardware.h>
+#include <linux/delay.h>
+
+#ifdef CONFIG_MFD_RT8973
+#include <linux/mfd/rt8973.h>
+#endif
+#ifdef CONFIG_SM5502_MUIC
+#include <linux/mfd/sm5502-muic.h>
+#endif
+#ifdef CONFIG_MFD_SM5504
+#include <linux/mfd/sm5504.h>
+#endif
+#ifdef CONFIG_FUELGAUGE_SPRD4SAMSUNG27X3
+#include <linux/battery/fuelgauge/sprd27x3_fuelgauge4samsung.h>
+#endif
+
+#define BATT_DET_CURRENT 313
+
+static int current_cable_type = POWER_SUPPLY_TYPE_BATTERY;
+static u8 attached_cable;
+static bool is_jig_on;
+/* static unsigned int lpcharge; */
+/* EXPORT_SYMBOL(lpcharge); */
+unsigned int lpcharge;
+EXPORT_SYMBOL(lpcharge);
+static unsigned chg_irq;
+static int gpio_vbat_detect;
+
+#if defined(CONFIG_INPUT_TOUCHSCREEN)
+void (*tsp_charger_status_cb)(int);
+EXPORT_SYMBOL(tsp_charger_status_cb);
+#endif
+
+static bool sec_fg_gpio_init(void)
+{
+ return true;
+}
+
+static bool sec_fg_fuelalert_process(bool is_fuel_alerted) { return true; }
+
+static bool sec_bat_adc_none_init(struct platform_device *pdev) { return true; }
+static bool sec_bat_adc_none_exit(void) { return true; }
+static int sec_bat_adc_none_read(unsigned int channel) { return 0; }
+
+static bool sec_bat_adc_ap_init(struct platform_device *pdev) { return true; }
+static bool sec_bat_adc_ap_exit(void) { return true; }
+
+static bool sec_bat_adc_ic_init(struct platform_device *pdev) { return true; }
+static bool sec_bat_adc_ic_exit(void) { return true; }
+static int sec_bat_adc_ic_read(unsigned int channel) { return 0; }
+
+static sec_bat_adc_api_t adc_api[SEC_BATTERY_ADC_TYPE_NUM] = {
+ {
+ .init = sec_bat_adc_none_init,
+ .exit = sec_bat_adc_none_exit,
+ .read = sec_bat_adc_none_read
+ },
+ {
+ .init = sec_bat_adc_ap_init,
+ .exit = sec_bat_adc_ap_exit,
+ },
+ {
+ .init = sec_bat_adc_ic_init,
+ .exit = sec_bat_adc_ic_exit,
+ .read = sec_bat_adc_ic_read
+ }
+};
+
+static bool sec_chg_gpio_init(void)
+{
+ return true;
+}
+
+bool sec_bat_check_cable_result_callback(int cable_type)
+{
+ bool ret = true;
+ current_cable_type = cable_type;
+
+ switch (cable_type) {
+ case POWER_SUPPLY_TYPE_USB:
+ pr_info("%s set vbus applied\n",
+ __func__);
+ break;
+ case POWER_SUPPLY_TYPE_BATTERY:
+ pr_info("%s set vbus cut\n",
+ __func__);
+ break;
+ case POWER_SUPPLY_TYPE_MAINS:
+ break;
+ default:
+ pr_err("%s cable type (%d)\n",
+ __func__, cable_type);
+ ret = false;
+ break;
+ }
+
+ return ret;
+}
+
+static bool sec_bat_ovp_uvlo_result_callback(int health)
+{
+ return true;
+}
+
+/* Get LP charging mode state */
+static int sec_bat_is_lpm_check(char *str)
+{
+ if (strncmp(str, "charger", 7) == 0)
+ lpcharge = 1;
+
+ pr_info("%s: Low power charging mode: %d\n", __func__, lpcharge);
+
+ return lpcharge;
+}
+__setup("androidboot.mode=", sec_bat_is_lpm_check);
+
+bool sec_bat_is_lpm(void)
+{
+ return lpcharge == 1 ? true : false;
+}
+/*
+ * val.intval : temperature
+ */
+static bool sec_bat_get_temperature_callback(
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ return true;
+}
+
+void check_jig_status(int status)
+{
+ if (status) {
+ pr_info("%s: JIG On so reset fuel gauge capacity\n", __func__);
+ is_jig_on = true;
+ }
+
+}
+
+bool sec_bat_check_jig_status(void)
+{
+ return is_jig_on;
+}
+
+//int sec_bat_check_cable_callback(void)
+int sec_bat_check_cable_callback(struct sec_battery_info *battery)
+{
+ int ta_nconnected;
+ union power_supply_propval value;
+ struct power_supply *psy = power_supply_get_by_name("battery");
+
+ ta_nconnected = gpio_get_value(chg_irq);
+
+ pr_info("%s : ta_nconnected : %d\n", __func__, ta_nconnected);
+
+ if (ta_nconnected)
+ current_cable_type = POWER_SUPPLY_TYPE_BATTERY;
+ else
+ current_cable_type = POWER_SUPPLY_TYPE_MAINS;
+
+#ifdef CONFIG_MFD_RT8973
+ if (attached_cable == MUIC_RT8973_CABLE_TYPE_0x1A) {
+ if (ta_nconnected)
+ current_cable_type = POWER_SUPPLY_TYPE_BATTERY;
+ else
+ current_cable_type = POWER_SUPPLY_TYPE_MISC;
+ } else
+ return current_cable_type;
+#endif
+
+#ifdef CONFIG_MFD_SM5504
+ if (attached_cable == MUIC_SM5504_CABLE_TYPE_0x1A) {
+ if (ta_nconnected)
+ current_cable_type = POWER_SUPPLY_TYPE_BATTERY;
+ else
+ current_cable_type = POWER_SUPPLY_TYPE_MISC;
+ } else
+ return current_cable_type;
+#endif
+ if (!psy || !psy->set_property)
+ pr_err("%s: fail to get battery psy\n", __func__);
+ else {
+ value.intval = current_cable_type;
+ psy->set_property(psy, POWER_SUPPLY_PROP_ONLINE, &value);
+ }
+
+ return current_cable_type;
+}
+
+void sec_bat_initial_check(void)
+{
+ union power_supply_propval value;
+
+ if (POWER_SUPPLY_TYPE_BATTERY < current_cable_type) {
+ value.intval = current_cable_type;
+ psy_do_property("battery", set,
+ POWER_SUPPLY_PROP_ONLINE, value);
+ } else {
+ psy_do_property("sec-charger", get,
+ POWER_SUPPLY_PROP_ONLINE, value);
+ if (value.intval == POWER_SUPPLY_TYPE_WPC) {
+ value.intval = POWER_SUPPLY_TYPE_WPC;
+ psy_do_property("battery", set,
+ POWER_SUPPLY_PROP_ONLINE, value);
+ }
+#if 0
+ else {
+ value.intval = POWER_SUPPLY_TYPE_BATTERY;
+ psy_do_property("sec-charger", set,
+ POWER_SUPPLY_PROP_ONLINE, value);
+ }
+#endif
+ }
+}
+
+static bool sec_bat_gpio_init(void)
+{
+ return true;
+}
+
+//static bool sec_bat_check_callback(void) { return true; }
+extern bool sec_bat_check_callback(struct sec_battery_info *battery){return true; }
+static bool sec_bat_check_result_callback(void) { return true; }
+
+/* callback for OVP/UVLO check
+ * return : int
+ * battery health
+ */
+static int sec_bat_ovp_uvlo_callback(void)
+{
+ int health;
+ health = POWER_SUPPLY_HEALTH_GOOD;
+
+ return health;
+}
+
+#if defined(CONFIG_SENSORS_GRIP_SX9500) && defined(CONFIG_MACH_DEGAS)
+extern void charger_status_cb(int status);
+#endif
+
+#ifdef CONFIG_MFD_RT8973
+void sec_charger_cb(u8 cable_type)
+{
+ union power_supply_propval value;
+ struct power_supply *psy = power_supply_get_by_name("battery");
+
+ pr_info("%s: cable type (0x%02x)\n", __func__, cable_type);
+
+ attached_cable = cable_type;
+
+ switch (cable_type) {
+ case MUIC_RT8973_CABLE_TYPE_NONE:
+ case MUIC_RT8973_CABLE_TYPE_JIG_UART_OFF:
+ current_cable_type = POWER_SUPPLY_TYPE_BATTERY;
+ break;
+ case MUIC_RT8973_CABLE_TYPE_USB:
+ case MUIC_RT8973_CABLE_TYPE_L_USB:
+ case MUIC_RT8973_CABLE_TYPE_CDP:
+ case MUIC_RT8973_CABLE_TYPE_JIG_USB_ON:
+ case MUIC_RT8973_CABLE_TYPE_JIG_USB_OFF:
+ current_cable_type = POWER_SUPPLY_TYPE_USB;
+ break;
+ case MUIC_RT8973_CABLE_TYPE_REGULAR_TA:
+ case MUIC_RT8973_CABLE_TYPE_ATT_TA:
+ case MUIC_RT8973_CABLE_TYPE_JIG_UART_OFF_WITH_VBUS:
+ case MUIC_RT8973_CABLE_TYPE_JIG_UART_ON_WITH_VBUS:
+ case MUIC_RT8973_CABLE_TYPE_TYPE1_CHARGER:
+ current_cable_type = POWER_SUPPLY_TYPE_MAINS;
+ break;
+ case MUIC_RT8973_CABLE_TYPE_OTG:
+ goto skip;
+ case MUIC_RT8973_CABLE_TYPE_0x15:
+ case MUIC_RT8973_CABLE_TYPE_0x1A:
+ //case MUIC_RT8973_CABLE_TYPE_0x1A_VBUS:
+ current_cable_type = POWER_SUPPLY_TYPE_MISC;
+ break;
+ default:
+ pr_err("%s: invalid type for charger:%d\n",
+ __func__, cable_type);
+ current_cable_type = POWER_SUPPLY_TYPE_UNKNOWN;
+ goto skip;
+ }
+
+ if (!psy || !psy->set_property)
+ pr_err("%s: fail to get battery psy\n", __func__);
+ else {
+ value.intval = current_cable_type;
+ psy->set_property(psy, POWER_SUPPLY_PROP_ONLINE, &value);
+
+#if defined(CONFIG_INPUT_TOUCHSCREEN)
+ /* for changing of tsp operation mode */
+ if (tsp_charger_status_cb)
+ tsp_charger_status_cb(current_cable_type);
+#endif
+ }
+
+skip:
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_SM5502_MUIC
+void sec_charger_cb(u8 cable_type)
+{
+
+ union power_supply_propval value;
+ struct power_supply *psy = power_supply_get_by_name("battery");
+
+ pr_info("%s: cable type (0x%02x)\n", __func__, cable_type);
+
+ attached_cable = cable_type;
+ is_jig_on = false;
+
+ switch (cable_type) {
+ case CABLE_TYPE_NONE_MUIC:
+ case CABLE_TYPE2_DESKDOCK_MUIC:
+ current_cable_type = POWER_SUPPLY_TYPE_BATTERY;
+ break;
+ case CABLE_TYPE1_USB_MUIC:
+ current_cable_type = POWER_SUPPLY_TYPE_USB;
+ break;
+ case CABLE_TYPE1_TA_MUIC:
+ case CABLE_TYPE3_U200CHG_MUIC:
+ case CABLE_TYPE3_NONSTD_SDP_MUIC:
+ pr_info("%s: VBUS Online\n", __func__);
+ current_cable_type = POWER_SUPPLY_TYPE_MAINS;
+ break;
+ case CABLE_TYPE2_JIG_UART_OFF_VB_MUIC:
+ case CABLE_TYPE2_JIG_UART_ON_VB_MUIC:
+ is_jig_on = true;
+ current_cable_type = POWER_SUPPLY_TYPE_MAINS;
+ break;
+ case CABLE_TYPE1_OTG_MUIC:
+ goto skip;
+ case CABLE_TYPE2_JIG_UART_OFF_MUIC:
+ is_jig_on = true;
+ current_cable_type = POWER_SUPPLY_TYPE_BATTERY;
+ break;
+ case CABLE_TYPE2_JIG_USB_ON_MUIC:
+ case CABLE_TYPE2_JIG_USB_OFF_MUIC:
+ is_jig_on = true;
+ current_cable_type = POWER_SUPPLY_TYPE_USB;
+ break;
+ case CABLE_TYPE1_CARKIT_T1OR2_MUIC:
+ current_cable_type = POWER_SUPPLY_TYPE_USB;
+ break;
+ case CABLE_TYPE3_DESKDOCK_VB_MUIC:
+ current_cable_type = POWER_SUPPLY_TYPE_MISC;
+ break;
+ default:
+ pr_err("%s: invalid type for charger:%d\n",
+ __func__, cable_type);
+ current_cable_type = POWER_SUPPLY_TYPE_UNKNOWN;
+ goto skip;
+ }
+
+ if (!psy || !psy->set_property)
+ pr_err("%s: fail to get battery psy\n", __func__);
+ else {
+ value.intval = current_cable_type;
+ psy->set_property(psy, POWER_SUPPLY_PROP_ONLINE, &value);
+
+#if defined(CONFIG_INPUT_TOUCHSCREEN)
+ /* for changing of tsp operation mode */
+ if (tsp_charger_status_cb)
+ tsp_charger_status_cb(current_cable_type);
+#endif
+ }
+#if defined(CONFIG_SENSORS_GRIP_SX9500) && defined(CONFIG_MACH_DEGAS)
+ /* for grip sensor threshold change at TA/USB status - sx9500.c */
+ charger_status_cb(current_cable_type);
+#endif
+
+skip:
+ return;
+}
+#endif /* CONFIG_SM5502_MUIC */
+
+
+#ifdef CONFIG_MFD_SM5504
+void sec_charger_cb(u8 cable_type)
+{
+ union power_supply_propval value;
+ struct power_supply *psy = power_supply_get_by_name("battery");
+
+ pr_info("%s: cable type (0x%02x)\n", __func__, cable_type);
+
+ attached_cable = cable_type;
+
+ switch (cable_type) {
+ case MUIC_SM5504_CABLE_TYPE_NONE:
+ case MUIC_SM5504_CABLE_TYPE_JIG_UART_ON:
+ case MUIC_SM5504_CABLE_TYPE_JIG_UART_OFF:
+ case MUIC_SM5504_CABLE_TYPE_JIG_UART_ON_WITH_VBUS:
+ current_cable_type = POWER_SUPPLY_TYPE_BATTERY;
+ break;
+ case MUIC_SM5504_CABLE_TYPE_USB:
+ case MUIC_SM5504_CABLE_TYPE_CDP:
+ case MUIC_SM5504_CABLE_TYPE_L_USB:
+ case MUIC_SM5504_CABLE_TYPE_JIG_USB_ON:
+ case MUIC_SM5504_CABLE_TYPE_JIG_USB_OFF:
+ current_cable_type = POWER_SUPPLY_TYPE_USB;
+ break;
+ case MUIC_SM5504_CABLE_TYPE_REGULAR_TA:
+ case MUIC_SM5504_CABLE_TYPE_ATT_TA:
+ case MUIC_SM5504_CABLE_TYPE_JIG_UART_OFF_WITH_VBUS:
+ case MUIC_SM5504_CABLE_TYPE_TYPE1_CHARGER:
+ current_cable_type = POWER_SUPPLY_TYPE_MAINS;
+ break;
+ case MUIC_SM5504_CABLE_TYPE_UART:
+ current_cable_type = POWER_SUPPLY_TYPE_UNKNOWN;
+ break;
+ case MUIC_SM5504_CABLE_TYPE_OTG:
+ case MUIC_SM5504_CABLE_TYPE_OTG_WITH_VBUS:
+ current_cable_type = POWER_SUPPLY_TYPE_OTG;
+ break;
+ case MUIC_SM5504_CABLE_TYPE_0x15:
+ case MUIC_SM5504_CABLE_TYPE_0x1A:
+// case MUIC_SM5504_CABLE_TYPE_0x1A_VBUS:
+ current_cable_type = POWER_SUPPLY_TYPE_MISC;
+ break;
+ default:
+ pr_err("%s: invalid type for charger:%d\n",
+ __func__, cable_type);
+ current_cable_type = POWER_SUPPLY_TYPE_UNKNOWN;
+ goto skip;
+ }
+
+ if (!psy || !psy->set_property)
+ pr_err("%s: fail to get battery psy\n", __func__);
+ else {
+ value.intval = current_cable_type;
+ psy->set_property(psy, POWER_SUPPLY_PROP_ONLINE, &value);
+
+#if defined(CONFIG_INPUT_TOUCHSCREEN)
+ /* for changing of tsp operation mode */
+ if (tsp_charger_status_cb)
+ tsp_charger_status_cb(current_cable_type);
+#endif
+ }
+
+skip:
+ return 0;
+
+}
+#endif /* CONFIG_MFD_SM5504 */
+
+int sec_vf_adc_current_check(void)
+{
+ int battery_on = 0;
+
+ sci_adi_set(ANA_REG_GLB_AUXAD_CTL,
+ (BIT_AUXAD_CURRENTSEN_EN | BITS_AUXAD_CURRENT_IBS(0x6)));
+ sci_adi_set(ANA_REG_GLB_BATDET_CUR_CTRL,
+ (BIT_BATDET_CUR_EN | BITS_BATDET_CUR_I(0x4)));
+ mdelay(5);
+
+ if (gpio_get_value(gpio_vbat_detect))
+ {
+ printk("%s : vbat good!\n", __func__);
+ battery_on = 1;
+ }
+ else
+ {
+ printk("%s : vbat is not connected!\n", __func__);
+ battery_on = 0;
+ }
+
+ sci_adi_clr(ANA_REG_GLB_AUXAD_CTL, BIT_AUXAD_CURRENTSEN_EN);
+ sci_adi_clr(ANA_REG_GLB_BATDET_CUR_CTRL, BIT_BATDET_CUR_EN);
+
+ return battery_on;
+}
+
+/* vf adc check, only for MUIC & young2dtv */
+int sec_vf_adc_check(void)
+{
+ int adc = 0;
+
+ adc = sci_adc_get_value(0, false);
+ pr_info("%s, vf adc : %d", __func__, adc);
+
+ if (adc > 500)
+ return 0;
+ else
+ return 1;
+}
+
+int sec_bat_dt_init(struct device_node *np,
+ struct device *dev,
+ sec_battery_platform_data_t *pdata)
+{
+ int ret, i, len;
+ unsigned int bat_irq_attr;
+ const u32 *p;
+
+ ret = of_property_read_string(np,
+ "battery,vendor", (char const **)&pdata->vendor);
+ if (ret)
+ pr_info("%s: Vendor is Empty\n", __func__);
+
+ ret = of_property_read_string(np,
+ "battery,charger_name", (char const **)&pdata->charger_name);
+ if (ret)
+ pr_info("%s: charger_name is Empty\n", __func__);
+
+ ret = of_property_read_string(np,
+ "battery,fuelgauge_name", (char const **)&pdata->fuelgauge_name);
+ if (ret)
+ pr_info("%s: fuelguage_name is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,technology",
+ &pdata->technology);
+ if (ret)
+ pr_info("%s : technology is Empty\n", __func__);
+
+ p = of_get_property(np, "battery,polling_time", &len);
+ if (!p)
+ return 1;
+
+ len = len / sizeof(u32);
+ pdata->polling_time = kzalloc(sizeof(*pdata->polling_time) * len, GFP_KERNEL);
+ ret = of_property_read_u32_array(np, "battery,polling_time",
+ pdata->polling_time, len);
+
+ p = of_get_property(np, "battery,temp_table_adc", &len);
+ if (!p)
+ return 1;
+
+ len = len / sizeof(u32);
+
+ pdata->temp_adc_table_size = len;
+ pdata->temp_amb_adc_table_size = len;
+
+ pdata->temp_adc_table =
+ kzalloc(sizeof(sec_bat_adc_table_data_t) *
+ pdata->temp_adc_table_size, GFP_KERNEL);
+ pdata->temp_amb_adc_table =
+ kzalloc(sizeof(sec_bat_adc_table_data_t) *
+ pdata->temp_adc_table_size, GFP_KERNEL);
+
+ for(i = 0; i < pdata->temp_adc_table_size; i++) {
+ ret = of_property_read_u32_index(np,
+ "battery,temp_table_adc", i,
+ &pdata->temp_adc_table[i].adc);
+ if (ret)
+ pr_info("%s : Temp_adc_table(adc) is Empty\n",
+ __func__);
+
+ ret = of_property_read_u32_index(np,
+ "battery,temp_table_data", i,
+ &pdata->temp_adc_table[i].temperature);
+ if (ret)
+ pr_info("%s : Temp_adc_table(data) is Empty\n",
+ __func__);
+
+ ret = of_property_read_u32_index(np,
+ "battery,temp_table_adc", i,
+ &pdata->temp_amb_adc_table[i].adc);
+ if (ret)
+ pr_info("%s : Temp_amb_adc_table(adc) is Empty\n",
+ __func__);
+
+ ret = of_property_read_u32_index(np,
+ "battery,temp_table_data", i,
+ &pdata->temp_amb_adc_table[i].temperature);
+ if (ret)
+ pr_info("%s : Temp_amb_adc_table(data) is Empty\n",
+ __func__);
+ }
+
+ p = of_get_property(np, "battery,input_current_limit", &len);
+ if (!p)
+ return 1;
+
+ len = len / sizeof(u32);
+
+ pdata->charging_current =
+ kzalloc(sizeof(sec_charging_current_t) * len,
+ GFP_KERNEL);
+
+ for(i = 0; i < len; i++) {
+ ret = of_property_read_u32_index(np,
+ "battery,input_current_limit", i,
+ &pdata->charging_current[i].input_current_limit);
+ if (ret)
+ pr_info("%s : Input_current_limit is Empty\n",
+ __func__);
+
+ ret = of_property_read_u32_index(np,
+ "battery,fast_charging_current", i,
+ &pdata->charging_current[i].fast_charging_current);
+ if (ret)
+ pr_info("%s : Fast charging current is Empty\n",
+ __func__);
+
+ ret = of_property_read_u32_index(np,
+ "battery,full_check_current_1st", i,
+ &pdata->charging_current[i].full_check_current_1st);
+ if (ret)
+ pr_info("%s : Full check current 1st is Empty\n",
+ __func__);
+
+ ret = of_property_read_u32_index(np,
+ "battery,full_check_current_2nd", i,
+ &pdata->charging_current[i].full_check_current_2nd);
+ if (ret)
+ pr_info("%s : Full check current 2nd is Empty\n",
+ __func__);
+ }
+
+ ret = of_property_read_u32(np, "battery,adc_check_count",
+ &pdata->adc_check_count);
+ if (ret)
+ pr_info("%s : Adc check count is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,cable_check_type",
+ &pdata->cable_check_type);
+ if (ret)
+ pr_info("%s : Cable check type is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,cable_source_type",
+ &pdata->cable_source_type);
+ if (ret)
+ pr_info("%s : Cable source type is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,event_waiting_time",
+ &pdata->event_waiting_time);
+ if (ret)
+ pr_info("%s : Event waiting time is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,polling_type",
+ &pdata->polling_type);
+ if (ret)
+ pr_info("%s : Polling type is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,monitor_initial_count",
+ &pdata->monitor_initial_count);
+ if (ret)
+ pr_info("%s : Monitor initial count is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,battery_check_type",
+ &pdata->battery_check_type);
+ if (ret)
+ pr_info("%s : Battery check type is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,check_count",
+ &pdata->check_count);
+
+ if (ret)
+ pr_info("%s : Check count is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,check_adc_max",
+ &pdata->check_adc_max);
+ if (ret)
+ pr_info("%s : Check adc max is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,check_adc_min",
+ &pdata->check_adc_min);
+ if (ret)
+ pr_info("%s : Check adc min is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,ovp_uvlo_check_type",
+ &pdata->ovp_uvlo_check_type);
+ if (ret)
+ pr_info("%s : Ovp Uvlo check type is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,thermal_source",
+ &pdata->thermal_source);
+ if (ret)
+ pr_info("%s : Thermal source is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,temp_check_type",
+ &pdata->temp_check_type);
+ if (ret)
+ pr_info("%s : Temp check type is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,temp_check_count",
+ &pdata->temp_check_count);
+ if (ret)
+ pr_info("%s : Temp check count is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,temp_high_recovery_event",
+ &pdata->temp_high_recovery_event);
+ if (ret)
+ pr_info("%s : Temp high recovery event is Empty\n", __func__);
+
+#if defined(CONFIG_MACH_DEGAS_USA)
+ pdata->temp_high_threshold_event = 550;
+ pdata->temp_high_recovery_event = 480;
+ pdata->temp_low_threshold_event = 20;
+ pdata->temp_low_recovery_event = 50;
+ pdata->temp_high_threshold_normal = 550;
+ pdata->temp_high_recovery_normal = 480;
+ pdata->temp_low_threshold_normal = 20;
+ pdata->temp_low_recovery_normal = 50;
+ pdata->temp_high_threshold_lpm = 550;
+ pdata->temp_high_recovery_lpm = 480;
+ pdata->temp_low_threshold_lpm = 20;
+ pdata->temp_low_recovery_lpm = 50;
+#elif defined(CONFIG_MACH_DEGAS_BMW)
+ pdata->temp_high_threshold_event = 450;
+ pdata->temp_high_recovery_event = 400;
+ pdata->temp_low_threshold_event = 0;
+ pdata->temp_low_recovery_event = 50;
+ pdata->temp_high_threshold_normal = 450;
+ pdata->temp_high_recovery_normal = 400;
+ pdata->temp_low_threshold_normal = 0;
+ pdata->temp_low_recovery_normal = 50;
+ pdata->temp_high_threshold_lpm = 450;
+ pdata->temp_high_recovery_lpm = 400;
+ pdata->temp_low_threshold_lpm = 0;
+ pdata->temp_low_recovery_lpm = 50;
+#else
+ ret = of_property_read_u32(np, "battery,temp_highlimit_threshold_event",
+ &pdata->temp_highlimit_threshold_event);
+ if (ret)
+ pr_info("%s : Temp highlimit threshold event is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,battery,temp_highlimit_recovery_event",
+ &pdata->temp_highlimit_recovery_event);
+ if (ret)
+ pr_info("%s : Temp highlimit threshold event recovery is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,temp_highlimit_threshold_normal",
+ &pdata->temp_highlimit_threshold_normal);
+ if (ret)
+ pr_info("%s : Temp highlimit threshold normal is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,temp_highlimit_recovery_normal",
+ &pdata->temp_highlimit_recovery_normal);
+ if (ret)
+ pr_info("%s : Temp highlimit threshold normal recovery is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,temp_highlimit_threshold_lpm",
+ &pdata->temp_highlimit_threshold_lpm);
+ if (ret)
+ pr_info("%s : Temp highlimit threshold lpm is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,temp_highlimit_recovery_lpm",
+ &pdata->temp_highlimit_recovery_lpm);
+ if (ret)
+ pr_info("%s : Temp highlimit threshold lpm recovery is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,temp_high_threshold_event",
+ &pdata->temp_high_threshold_event);
+ if (ret)
+ pr_info("%s : Temp high threshold event is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,temp_low_threshold_event",
+ &pdata->temp_low_threshold_event);
+ if (ret)
+ pr_info("%s : Temp low threshold event is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,temp_low_recovery_event",
+ &pdata->temp_low_recovery_event);
+ if (ret)
+ pr_info("%s : Temp low recovery event is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,temp_high_threshold_normal",
+ &pdata->temp_high_threshold_normal);
+ if (ret)
+ pr_info("%s : Temp high threshold normal is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,temp_high_recovery_normal",
+ &pdata->temp_high_recovery_normal);
+ if (ret)
+ pr_info("%s : Temp high recovery normal is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,temp_low_threshold_normal",
+ &pdata->temp_low_threshold_normal);
+ if (ret)
+ pr_info("%s : Temp low threshold normal is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,temp_low_recovery_normal",
+ &pdata->temp_low_recovery_normal);
+
+ if (ret)
+ pr_info("%s : Temp low recovery normal is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,temp_high_threshold_lpm",
+ &pdata->temp_high_threshold_lpm);
+ if (ret)
+ pr_info("%s : Temp high threshold lpm is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,temp_high_recovery_lpm",
+ &pdata->temp_high_recovery_lpm);
+ if (ret)
+ pr_info("%s : Temp high recovery lpm is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,temp_low_threshold_lpm",
+ &pdata->temp_low_threshold_lpm);
+ if (ret)
+ pr_info("%s : Temp low threshold lpm is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,temp_low_recovery_lpm",
+ &pdata->temp_low_recovery_lpm);
+ if (ret)
+ pr_info("%s : Temp low recovery lpm is Empty\n", __func__);
+#endif
+
+ ret = of_property_read_u32(np, "battery,full_check_type",
+ &pdata->full_check_type);
+ if (ret)
+ pr_info("%s : Full check type is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,full_check_type_2nd",
+ &pdata->full_check_type_2nd);
+ if (ret)
+ pr_info("%s : Full check type 2nd is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,full_check_count",
+ &pdata->full_check_count);
+ if (ret)
+ pr_info("%s : Full check count is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,chg_gpio_full_check",
+ &pdata->chg_gpio_full_check);
+ if (ret)
+ pr_info("%s : Chg gpio full check is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,chg_polarity_full_check",
+ &pdata->chg_polarity_full_check);
+ if (ret)
+ pr_info("%s : Chg polarity full check is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,full_condition_type",
+ &pdata->full_condition_type);
+ if (ret)
+ pr_info("%s : Full condition type is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,full_condition_soc",
+ &pdata->full_condition_soc);
+ if (ret)
+ pr_info("%s : Full condition soc is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,full_condition_vcell",
+ &pdata->full_condition_vcell);
+ if (ret)
+ pr_info("%s : Full condition vcell is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,recharge_check_count",
+ &pdata->recharge_check_count);
+ if (ret)
+ pr_info("%s : Recharge check count is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,recharge_condition_type",
+ &pdata->recharge_condition_type);
+ if (ret)
+ pr_info("%s : Recharge condition type is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,recharge_condition_soc",
+ &pdata->recharge_condition_soc);
+ if (ret)
+ pr_info("%s : Recharge condition soc is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,recharge_condition_vcell",
+ &pdata->recharge_condition_vcell);
+ if (ret)
+ pr_info("%s : Recharge condition vcell is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,recharge_condition_avgvcell",
+ &pdata->recharge_condition_avgvcell);
+ if (ret)
+ pr_info("%s : Recharge condition avgvcell is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,charging_total_time",
+ (unsigned int *)&pdata->charging_total_time);
+ if (ret)
+ pr_info("%s : Charging total time is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,recharging_total_time",
+ (unsigned int *)&pdata->recharging_total_time);
+ if (ret)
+ pr_info("%s : Recharging total time is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,charging_reset_time",
+ (unsigned int *)&pdata->charging_reset_time);
+ if (ret)
+ pr_info("%s : Charging reset time is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,charging_reset_time",
+ (unsigned int *)&pdata->charging_reset_time);
+ if (ret)
+ pr_info("%s : Charging reset time is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,bat-irq-attr", &bat_irq_attr);
+ if (ret)
+ pr_info("%s : Battery irq is Empty\n", __func__);
+
+ pdata->bat_gpio_init = sec_bat_gpio_init;
+ pdata->check_battery_callback = sec_bat_check_callback;
+ pdata->check_battery_result_callback = sec_bat_check_result_callback;
+ pdata->check_cable_callback = sec_bat_check_cable_callback;
+ pdata->check_cable_result_callback =
+ sec_bat_check_cable_result_callback;
+ pdata->get_temperature_callback = sec_bat_get_temperature_callback;
+ pdata->initial_check = sec_bat_initial_check;
+ pdata->is_lpm = sec_bat_is_lpm;
+ pdata->ovp_uvlo_callback = sec_bat_ovp_uvlo_callback;
+ pdata->ovp_uvlo_result_callback = sec_bat_ovp_uvlo_result_callback;
+ pdata->check_jig_status = sec_bat_check_jig_status;
+
+ for (i = 0; i < SEC_BATTERY_ADC_TYPE_NUM; i++)
+ pdata->adc_api[i] = adc_api[i];
+
+ return 0;
+}
+
+int sec_chg_dt_init(struct device_node *np,
+ struct device *dev,
+ sec_battery_platform_data_t *pdata)
+{
+ int ret = 0, len = 0;
+ unsigned int chg_irq_attr = 0;
+ int chg_gpio_en = 0;
+ int chg_irq_gpio = 0;
+
+ if (!np)
+ return -EINVAL;
+
+ chg_gpio_en = of_get_named_gpio(np, "chgen-gpio", 0);
+ if (chg_gpio_en < 0) {
+ pr_err("%s: of_get_named_gpio failed: %d\n", __func__,
+ chg_gpio_en);
+ return chg_gpio_en;
+ }
+
+ ret = of_property_read_u32(np, "chg-irq-attr",
+ &chg_irq_attr);
+ if (ret) {
+ pr_info("%s chg_irq_attr request failed: %d\n", __func__, chg_irq_attr);
+ }
+
+ ret = gpio_request(chg_gpio_en, "chgen-gpio");
+ if (ret) {
+ pr_err("%s gpio_request failed: %d\n", __func__, chg_gpio_en);
+ return ret;
+ }
+
+ chg_irq_gpio = of_get_named_gpio(np, "chgirq-gpio", 0);
+ if (chg_irq_gpio < 0)
+ pr_err("%s: chgirq gpio get failed: %d\n", __func__, chg_irq_gpio);
+
+ ret = gpio_request(chg_irq_gpio, "chgirq-gpio");
+ if (ret)
+ pr_err("%s gpio_request failed: %d\n", __func__, chg_irq_gpio);
+
+ ret = of_property_read_u32(np, "chg-float-voltage",
+ &pdata->chg_float_voltage);
+ if (ret)
+ return ret;
+
+ np = of_find_node_by_name(NULL, "sec-battery");
+ if (!np) {
+ pr_err("%s np NULL\n", __func__);
+ }
+ else {
+ int i = 0;
+ const u32 *p;
+ p = of_get_property(np, "battery,input_current_limit", &len);
+ if (!p){
+
+ pr_err("%s charger,input_current_limit is Empty\n", __func__);
+ // return 1;
+ }
+ else{
+
+ len = len / sizeof(u32);
+
+ pdata->charging_current = kzalloc(sizeof(sec_charging_current_t) * len,
+ GFP_KERNEL);
+
+ for(i = 0; i < len; i++) {
+ ret = of_property_read_u32_index(np,
+ "battery,input_current_limit", i,
+ &pdata->charging_current[i].input_current_limit);
+ if (ret)
+ pr_info("%s : Input_current_limit is Empty\n",
+ __func__);
+
+ ret = of_property_read_u32_index(np,
+ "battery,fast_charging_current", i,
+ &pdata->charging_current[i].fast_charging_current);
+ if (ret)
+ pr_info("%s : Fast charging current is Empty\n",
+ __func__);
+
+ ret = of_property_read_u32_index(np,
+ "battery,full_check_current_1st", i,
+ &pdata->charging_current[i].full_check_current_1st);
+ if (ret)
+ pr_info("%s : Full check current 1st is Empty\n",
+ __func__);
+
+ ret = of_property_read_u32_index(np,
+ "battery,full_check_current_2nd", i,
+ &pdata->charging_current[i].full_check_current_2nd);
+ if (ret)
+ pr_info("%s : Full check current 2nd is Empty\n",
+ __func__);
+ }
+ }
+ }
+
+ ret = of_property_read_u32(np, "battery,ovp_uvlo_check_type",
+ &pdata->ovp_uvlo_check_type);
+ if (ret)
+ pr_info("%s : Ovp Uvlo check type is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,full_check_type",
+ &pdata->full_check_type);
+ if (ret)
+ pr_info("%s : Full check type is Empty\n", __func__);
+
+ ret = of_property_read_u32(np, "battery,full_check_type_2nd",
+ &pdata->full_check_type_2nd);
+ if (ret)
+ pr_info("%s : Full check type 2nd is Empty\n", __func__);
+
+#if defined(CONFIG_MACH_PIKEAYOUNG2DTV)
+ gpio_vbat_detect = BATT_DET_CURRENT;
+
+ if (!gpio_is_valid(gpio_vbat_detect)) {
+ printk("%s: battery detect gpio %d failed\n", __func__, gpio_vbat_detect);
+ return 1;
+ }
+ gpio_request(gpio_vbat_detect, "battery-detect");
+ gpio_direction_input(gpio_vbat_detect);
+ printk("%s: battery detect gpio %d\n", __func__, gpio_vbat_detect);
+#endif
+
+ if (chg_irq_gpio > 0) {
+ pdata->chg_irq_attr = chg_irq_attr;
+ pdata->chg_irq = gpio_to_irq(chg_irq_gpio);
+ }
+ pdata->chg_gpio_en = chg_gpio_en;
+ pdata->chg_gpio_init = sec_chg_gpio_init;
+ pdata->check_cable_result_callback =
+ sec_bat_check_cable_result_callback;
+
+ return 0;
+}
+
+#ifdef CONFIG_FUELGAUGE_SPRD4SAMSUNG27X3
+struct battery_data_t bat_data;
+#endif
+
+int sec_fg_dt_init(struct device_node *np,
+ struct device *dev,
+ sec_battery_platform_data_t *pdata)
+{
+ int ret;
+ unsigned int fg_irq_attr;
+
+ ret = of_property_read_u32(np, "capacity-max", &pdata->capacity_max);
+ if (ret)
+ return ret;
+ ret = of_property_read_u32(np, "capacity-max-margin",
+ &pdata->capacity_max_margin);
+ if (ret)
+ return ret;
+ ret = of_property_read_u32(np, "capacity-min", &pdata->capacity_min);
+ if (ret)
+ return ret;
+ ret = of_property_read_u32(np, "fg-irq-attr", &fg_irq_attr);
+ if (ret)
+ return ret;
+ ret = of_property_read_u32(np, "fuel-alert-soc",
+ &pdata->fuel_alert_soc);
+ if (ret)
+ return ret;
+ if (of_find_property(np, "repeated-fuelalert", NULL))
+ pdata->repeated_fuelalert = true;
+
+ ret = of_property_read_u32(np, "temp_adc_channel",
+ &pdata->temp_adc_channel);
+ if (ret)
+ return ret;
+
+#ifdef CONFIG_FUELGAUGE_SPRD4SAMSUNG27X3
+ {
+ struct sprd_battery_platform_data *battery_data;
+ int len, i;
+ uint32_t cell_value;
+ struct device_node *temp_np = NULL;
+
+ battery_data = devm_kzalloc(dev, sizeof(*battery_data), GFP_KERNEL);
+ temp_np = of_get_child_by_name(np, "sprd_fgu");
+ if (!temp_np) {
+ return ERR_PTR(-EINVAL);
+ }
+ battery_data->irq_fgu = irq_of_parse_and_map(temp_np, 0);
+ of_property_read_u32(np, "chg_bat_safety_vol", &battery_data->chg_bat_safety_vol);
+ of_property_read_u32(np, "soft_vbat_uvlo", &battery_data->soft_vbat_uvlo);
+ of_property_read_u32(np, "vmod", &battery_data->fgu_mode);
+ of_property_read_u32(np, "alm_soc", &battery_data->alm_soc);
+ of_property_read_u32(np, "alm_vbat", &battery_data->alm_vol);
+ of_property_read_u32(np, "rint", &battery_data->rint);
+ of_property_read_u32(np, "cnom", &battery_data->cnom);
+ of_property_read_u32(np, "rsense_real", &battery_data->rsense_real);
+ of_property_read_u32(np, "rsense_spec", &battery_data->rsense_spec);
+ of_property_read_u32(np, "relax_current", &battery_data->relax_current);
+ of_property_read_u32(np, "cal_ajust", &battery_data->fgu_cal_ajust);
+ of_get_property(np, "ocv_table", &len);
+ len /= sizeof(u32);
+ battery_data->ocv_tab_size = len >> 1;
+ battery_data->ocv_tab = kzalloc(sizeof(struct sprdbat_table_data) *
+ battery_data->ocv_tab_size, GFP_KERNEL);
+ for (i = 0; i < len; i++) {
+ of_property_read_u32_index(np, "ocv_table", i, &cell_value);
+ if(i&0x1) {
+ battery_data->ocv_tab[i >> 1].y = cell_value;
+ } else {
+ battery_data->ocv_tab[i >> 1].x = cell_value;
+ }
+ }
+ bat_data.pdata = battery_data;
+ pdata->battery_data = &bat_data;
+ }
+#endif
+
+ pdata->fg_irq_attr = fg_irq_attr;
+ pdata->fuelalert_process = sec_fg_fuelalert_process;
+ pdata->fg_gpio_init = sec_fg_gpio_init;
+ pdata->capacity_calculation_type =
+ SEC_FUELGAUGE_CAPACITY_TYPE_RAW;
+ pdata->check_jig_status = sec_bat_check_jig_status;
+
+ return 0;
+}