Merge branch 'for-anton' of git://git.linaro.org/people/ljones/linux-3.0-ux500
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / power / ab8500_btemp.c
index 20e2a7d3ef43c0f6877aae8e5b3cb9c08fc6a9ae..e1d28039ce7b0fdd4a636dfd0e6b5441bd9f41d4 100644 (file)
@@ -78,12 +78,13 @@ struct ab8500_btemp_ranges {
  * @parent:            Pointer to the struct ab8500
  * @gpadc:             Pointer to the struct gpadc
  * @fg:                        Pointer to the struct fg
- * @bat:               Pointer to the abx500_bm platform data
+ * @bm:                Platform specific battery management information
  * @btemp_psy:         Structure for BTEMP specific battery properties
  * @events:            Structure for information about events triggered
  * @btemp_ranges:      Battery temperature range structure
  * @btemp_wq:          Work queue for measuring the temperature periodically
  * @btemp_periodic_work:       Work for measuring the temperature periodically
+ * @initialized:       True if battery id read.
  */
 struct ab8500_btemp {
        struct device *dev;
@@ -94,12 +95,13 @@ struct ab8500_btemp {
        struct ab8500 *parent;
        struct ab8500_gpadc *gpadc;
        struct ab8500_fg *fg;
-       struct abx500_bm_data *bat;
+       struct abx500_bm_data *bm;
        struct power_supply btemp_psy;
        struct ab8500_btemp_events events;
        struct ab8500_btemp_ranges btemp_ranges;
        struct workqueue_struct *btemp_wq;
        struct delayed_work btemp_periodic_work;
+       bool initialized;
 };
 
 /* BTEMP power supply properties */
@@ -147,13 +149,13 @@ static int ab8500_btemp_batctrl_volt_to_res(struct ab8500_btemp *di,
                return (450000 * (v_batctrl)) / (1800 - v_batctrl);
        }
 
-       if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL) {
+       if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL) {
                /*
                 * If the battery has internal NTC, we use the current
                 * source to calculate the resistance, 7uA or 20uA
                 */
                rbs = (v_batctrl * 1000
-                      - di->bat->gnd_lift_resistance * inst_curr)
+                      - di->bm->gnd_lift_resistance * inst_curr)
                      / di->curr_source;
        } else {
                /*
@@ -209,7 +211,7 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di,
                return 0;
 
        /* Only do this for batteries with internal NTC */
-       if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && enable) {
+       if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && enable) {
                if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_7UA)
                        curr = BAT_CTRL_7U_ENA;
                else
@@ -241,7 +243,7 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di,
                                __func__);
                        goto disable_curr_source;
                }
-       } else if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && !enable) {
+       } else if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && !enable) {
                dev_dbg(di->dev, "Disable BATCTRL curr source\n");
 
                /* Write 0 to the curr bits */
@@ -457,9 +459,9 @@ static int ab8500_btemp_measure_temp(struct ab8500_btemp *di)
        int rbat, rntc, vntc;
        u8 id;
 
-       id = di->bat->batt_id;
+       id = di->bm->batt_id;
 
-       if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL &&
+       if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL &&
                        id != BATTERY_UNKNOWN) {
 
                rbat = ab8500_btemp_get_batctrl_res(di);
@@ -474,8 +476,8 @@ static int ab8500_btemp_measure_temp(struct ab8500_btemp *di)
                }
 
                temp = ab8500_btemp_res_to_temp(di,
-                       di->bat->bat_type[id].r_to_t_tbl,
-                       di->bat->bat_type[id].n_temp_tbl_elements, rbat);
+                       di->bm->bat_type[id].r_to_t_tbl,
+                       di->bm->bat_type[id].n_temp_tbl_elements, rbat);
        } else {
                vntc = ab8500_gpadc_convert(di->gpadc, BTEMP_BALL);
                if (vntc < 0) {
@@ -491,8 +493,8 @@ static int ab8500_btemp_measure_temp(struct ab8500_btemp *di)
                rntc = 230000 * vntc / (VTVOUT_V - vntc);
 
                temp = ab8500_btemp_res_to_temp(di,
-                       di->bat->bat_type[id].r_to_t_tbl,
-                       di->bat->bat_type[id].n_temp_tbl_elements, rntc);
+                       di->bm->bat_type[id].r_to_t_tbl,
+                       di->bm->bat_type[id].n_temp_tbl_elements, rntc);
                prev = temp;
        }
        dev_dbg(di->dev, "Battery temperature is %d\n", temp);
@@ -513,7 +515,7 @@ static int ab8500_btemp_id(struct ab8500_btemp *di)
        u8 i;
 
        di->curr_source = BTEMP_BATCTRL_CURR_SRC_7UA;
-       di->bat->batt_id = BATTERY_UNKNOWN;
+       di->bm->batt_id = BATTERY_UNKNOWN;
 
        res =  ab8500_btemp_get_batctrl_res(di);
        if (res < 0) {
@@ -522,23 +524,23 @@ static int ab8500_btemp_id(struct ab8500_btemp *di)
        }
 
        /* BATTERY_UNKNOWN is defined on position 0, skip it! */
-       for (i = BATTERY_UNKNOWN + 1; i < di->bat->n_btypes; i++) {
-               if ((res <= di->bat->bat_type[i].resis_high) &&
-                       (res >= di->bat->bat_type[i].resis_low)) {
+       for (i = BATTERY_UNKNOWN + 1; i < di->bm->n_btypes; i++) {
+               if ((res <= di->bm->bat_type[i].resis_high) &&
+                       (res >= di->bm->bat_type[i].resis_low)) {
                        dev_dbg(di->dev, "Battery detected on %s"
                                " low %d < res %d < high: %d"
                                " index: %d\n",
-                               di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL ?
+                               di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL ?
                                "BATCTRL" : "BATTEMP",
-                               di->bat->bat_type[i].resis_low, res,
-                               di->bat->bat_type[i].resis_high, i);
+                               di->bm->bat_type[i].resis_low, res,
+                               di->bm->bat_type[i].resis_high, i);
 
-                       di->bat->batt_id = i;
+                       di->bm->batt_id = i;
                        break;
                }
        }
 
-       if (di->bat->batt_id == BATTERY_UNKNOWN) {
+       if (di->bm->batt_id == BATTERY_UNKNOWN) {
                dev_warn(di->dev, "Battery identified as unknown"
                        ", resistance %d Ohm\n", res);
                return -ENXIO;
@@ -548,13 +550,13 @@ static int ab8500_btemp_id(struct ab8500_btemp *di)
         * We only have to change current source if the
         * detected type is Type 1, else we use the 7uA source
         */
-       if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL &&
-                       di->bat->batt_id == 1) {
+       if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL &&
+                       di->bm->batt_id == 1) {
                dev_dbg(di->dev, "Set BATCTRL current source to 20uA\n");
                di->curr_source = BTEMP_BATCTRL_CURR_SRC_20UA;
        }
 
-       return di->bat->batt_id;
+       return di->bm->batt_id;
 }
 
 /**
@@ -569,6 +571,13 @@ static void ab8500_btemp_periodic_work(struct work_struct *work)
        struct ab8500_btemp *di = container_of(work,
                struct ab8500_btemp, btemp_periodic_work.work);
 
+       if (!di->initialized) {
+               di->initialized = true;
+               /* Identify the battery */
+               if (ab8500_btemp_id(di) < 0)
+                       dev_warn(di->dev, "failed to identify the battery\n");
+       }
+
        di->bat_temp = ab8500_btemp_measure_temp(di);
 
        if (di->bat_temp != di->prev_bat_temp) {
@@ -577,9 +586,9 @@ static void ab8500_btemp_periodic_work(struct work_struct *work)
        }
 
        if (di->events.ac_conn || di->events.usb_conn)
-               interval = di->bat->temp_interval_chg;
+               interval = di->bm->temp_interval_chg;
        else
-               interval = di->bat->temp_interval_nochg;
+               interval = di->bm->temp_interval_nochg;
 
        /* Schedule a new measurement */
        queue_delayed_work(di->btemp_wq,
@@ -806,7 +815,7 @@ static int ab8500_btemp_get_property(struct power_supply *psy,
                        val->intval = 1;
                break;
        case POWER_SUPPLY_PROP_TECHNOLOGY:
-               val->intval = di->bat->bat_type[di->bat->batt_id].name;
+               val->intval = di->bm->bat_type[di->bm->batt_id].name;
                break;
        case POWER_SUPPLY_PROP_TEMP:
                val->intval = ab8500_btemp_get_temp(di);
@@ -967,6 +976,7 @@ static char *supply_interface[] = {
 static int ab8500_btemp_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
+       struct abx500_bm_data *plat = pdev->dev.platform_data;
        struct ab8500_btemp *di;
        int irq, i, ret = 0;
        u8 val;
@@ -976,21 +986,19 @@ static int ab8500_btemp_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "%s no mem for ab8500_btemp\n", __func__);
                return -ENOMEM;
        }
-       di->bat = pdev->mfd_cell->platform_data;
-       if (!di->bat) {
-               if (np) {
-                       ret = bmdevs_of_probe(&pdev->dev, np, &di->bat);
-                       if (ret) {
-                               dev_err(&pdev->dev,
-                                       "failed to get battery information\n");
-                               return ret;
-                       }
-               } else {
-                       dev_err(&pdev->dev, "missing dt node for ab8500_btemp\n");
-                       return -EINVAL;
+
+       if (!plat) {
+               dev_err(&pdev->dev, "no battery management data supplied\n");
+               return -EINVAL;
+       }
+       di->bm = plat;
+
+       if (np) {
+               ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm);
+               if (ret) {
+                       dev_err(&pdev->dev, "failed to get battery information\n");
+                       return ret;
                }
-       } else {
-               dev_info(&pdev->dev, "falling back to legacy platform data\n");
        }
 
        /* get parent data */
@@ -998,6 +1006,8 @@ static int ab8500_btemp_probe(struct platform_device *pdev)
        di->parent = dev_get_drvdata(pdev->dev.parent);
        di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
 
+       di->initialized = false;
+
        /* BTEMP supply */
        di->btemp_psy.name = "ab8500_btemp";
        di->btemp_psy.type = POWER_SUPPLY_TYPE_BATTERY;
@@ -1022,10 +1032,6 @@ static int ab8500_btemp_probe(struct platform_device *pdev)
        INIT_DEFERRABLE_WORK(&di->btemp_periodic_work,
                ab8500_btemp_periodic_work);
 
-       /* Identify the battery */
-       if (ab8500_btemp_id(di) < 0)
-               dev_warn(di->dev, "failed to identify the battery\n");
-
        /* Set BTEMP thermal limits. Low and Med are fixed */
        di->btemp_ranges.btemp_low_limit = BTEMP_THERMAL_LOW_LIMIT;
        di->btemp_ranges.btemp_med_limit = BTEMP_THERMAL_MED_LIMIT;