[PATCH 1/4] mfd: ab8500: add devicetree support for fuelgauge
Rajanikanth HV
rajanikanth.hv at stericsson.com
Mon Oct 1 05:59:45 EDT 2012
did you have a look at arnd and anton comments regarding
'supplied-to' and boolean property
On Monday 01 October 2012 03:19 PM, Lee Jones wrote:
> On Mon, 01 Oct 2012, Rajanikanth H.V wrote:
>
>> From: "Rajanikanth H.V" <rajanikanth.hv at stericsson.com>
>>
>> - This patch adds device tree support for fuelguage driver
>> - optimize bm devices platform_data usage and of_probe(...)
>> Note: of_probe() routine for battery managed devices is made
>> common across all bm drivers.
>>
>> Signed-off-by: Rajanikanth H.V <rajanikanth.hv at stericsson.com>
>> ---
>> Documentation/devicetree/bindings/mfd/ab8500.txt | 8 +-
>> .../devicetree/bindings/power_supply/ab8500/fg.txt | 86 +++
>> arch/arm/boot/dts/dbx5x0.dtsi | 22 +-
>> drivers/mfd/ab8500-core.c | 1 +
>> drivers/power/Makefile | 2 +-
>> drivers/power/ab8500_bmdata.c | 549 ++++++++++++++++++++
>> drivers/power/ab8500_btemp.c | 4 +-
>> drivers/power/ab8500_charger.c | 4 +-
>> drivers/power/ab8500_fg.c | 76 ++-
>> drivers/power/abx500_chargalg.c | 4 +-
>> include/linux/mfd/abx500.h | 37 +-
>> include/linux/mfd/abx500/ab8500-bm.h | 7 +
>> 12 files changed, 744 insertions(+), 56 deletions(-)
>> create mode 100644 Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
>> create mode 100644 drivers/power/ab8500_bmdata.c
>>
>> diff --git a/Documentation/devicetree/bindings/mfd/ab8500.txt b/Documentation/devicetree/bindings/mfd/ab8500.txt
>> index ce83c8d..762dc11 100644
>> --- a/Documentation/devicetree/bindings/mfd/ab8500.txt
>> +++ b/Documentation/devicetree/bindings/mfd/ab8500.txt
>> @@ -24,7 +24,13 @@ ab8500-bm : : : Battery Manager
>> ab8500-btemp : : : Battery Temperature
>> ab8500-charger : : : Battery Charger
>> ab8500-codec : : : Audio Codec
>> -ab8500-fg : : : Fuel Gauge
>> +ab8500-fg : : vddadc : Fuel Gauge
>> + : NCONV_ACCU : : Accumulate N Sample Conversion
>> + : BATT_OVV : : Battery Over Voltage
>> + : LOW_BAT_F : : LOW threshold battery voltage
>> + : CC_INT_CALIB : : Counter Counter Internal Calibration
>
> I think you mean: Coulomb Counter.
>
>> + : CCEOC : : Coulomb Counter End of Conversion
>> + : : :
>
> Random empty entry.
>
>> ab8500-gpadc : HW_CONV_END : vddadc : Analogue to Digital Converter
>> SW_CONV_END : :
>> ab8500-gpio : : : GPIO Controller
>> diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt b/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
>> new file mode 100644
>> index 0000000..caa33b0
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
>> @@ -0,0 +1,86 @@
>> +=== AB8500 Fuel Gauge Driver ===
>> +
>> +AB8500 is a mixed signal multimedia and power management
>> +device comprising: power and energy-management-module,
>> +wall-charger, usb-charger, audio codec, general purpose adc,
>> +tvout, clock management and sim card interface.
>> +
>> +Fuel-guage support is part of energy-management-module, the other
>
> Spelling.
>
>> +components of this module are:
>> +main-charger, usb-combo-charger and Battery temperature monitoring.
>> +
>> +The properties below describes the node for fuel guage driver.
>
> Spelling.
>
>> +
>> +Required Properties:
>> +- compatible = "stericsson,ab8500-fg"
>> +- interface-name:
>> + Name of the controller/driver which is part of energy-management-module
>> +- supplied-to:
>
> Still not sure about this property, or your justification for use.
>
>> + This property shall have dependent nodes which represent other
>> + energy-management-module.
>
> Plural?
>
>> + This is a logical binding w.r.t power supply events
>
> Proper English please, no slang.
>
>> + across energy-management-module drivers where-in, the
>
> Ill placed comma?
>
>> + runtime battery properties are shared along with uevent
>> + notification.
>
> Plural?
>
>> + ref: di->fg.external_power_changed =
>> + ab8500_fg_external_power_changed;
>> + ab8500_fg.c
>> +
>> + Need for this property:
>> + energy-management-module driver updates power-supply properties
>> + which are subset of events listed in 'enum power_supply_property',
>> + ref: power_supply.h file
>> + Event handler invokes power supply change notifier
>> + which in-turn invokes registered power supply class call-back
>> + based on the 'supplied-to' string.
>> + ref:
>> + power_supply_changed_work(..) ./drivers/power/power_supply_core.c
>> + di->fg_psy.external_power_changed
>> +
>> + example:
>> + ab8500-fg {
>> + /* dependent energy management modules */
>> + supplied-to = <&ab8500_chargalg &ab8500_usb>;
>> + };
>> +
>> + ab8500_battery_info: ab8500_bat_type {
>> + battery-type = <2>;
>> + thermistor-on-batctrl = <1>;
>
> You have this as a bool here, and ...
>> + };
>> +
>> +Other dependent node for fuel-gauge is:
>> + ab8500_battery_info: ab8500_bat_type {
>> + };
>> + This node will provide information on 'thermistor interface' and
>> + 'battery technology type' used.
>> +
>> +Properties of this node are:
>> +thermistor-on-batctrl:
>> + A boolean value indicating thermistor interface to battery
>> +
>> + Note:
>> + 'btemp' and 'batctrl' are the pins interfaced for battery temperature
>> + measurement, 'btemp' signal is used when NTC(negative temperature
>> + coefficient) resister is interfaced external to battery whereas
>> + 'batctrl' pin is used when NTC resister is internal to battery.
>> +
>> + e.g:
>> + ab8500_battery_info: ab8500_bat_type {
>> + thermistor-on-batctrl;
>
> ... a standard property here. I suggest you drop the bool value.
>
>> + };
>> + indiactes: NTC resister is internal to battery, 'batctrl' is used
>> + for thermal measurement.
>> +
>> + The absence of property 'thermal-on-batctrl' indicates
>> + NTC resister is external to battery and 'btemp' signal is used
>> + for thermal measurement.
>> +
>> +battery-type:
>> + This shall be the battery manufacturing technology type,
>> + allowed types are:
>> + "UNKNOWN" "NiMH" "LION" "LIPO" "LiFe" "NiCd" "LiMn"
>> + e.g:
>> + ab8500_battery_info: ab8500_bat_type {
>> + battery-name = "LION";
>> + }
>> +
>> diff --git a/arch/arm/boot/dts/dbx5x0.dtsi b/arch/arm/boot/dts/dbx5x0.dtsi
>> index 748ba7a..bd22c56 100644
>> --- a/arch/arm/boot/dts/dbx5x0.dtsi
>> +++ b/arch/arm/boot/dts/dbx5x0.dtsi
>> @@ -352,8 +352,28 @@
>> vddadc-supply = <&ab8500_ldo_tvout_reg>;
>> };
>>
>> - ab8500-usb {
>> + ab8500_battery_info: ab8500_bat_type {
>> + battery-name = "LION";
>
> All new properties have to be documented.
>
> Vendor specific properties should be prepended with the vendor name, so
> either write a generic binding document for all to use or prefix with
> 'stericsson,".
>
>> + thermistor-on-batctrl;
>> + };
>> +
>> + ab8500_chargalg: ab8500_chalg {
>> + compatible = "stericsson,ab8500-chargalg";
>> + interface-name = "ab8500_chargalg";
>
> Same with all of your new properties (I'll stop mentioning them now).
>
>> + battery-info = <&ab8500_battery_info>;
>> + supplied-to = <&ab8500_fuel_gauge>;
>
> Weren't you going to reverse this logic to be more inline with how
> the reset of Device Tree works?
>
>> + };
>> +
>> + ab8500_fuel_gauge: ab8500_fg {
>> + compatible = "stericsson,ab8500-fg";
>> + interface-name = "ab8500_fg";
>> + battery-info = <&ab8500_battery_info>;
>> + supplied-to = <&ab8500_chargalg &ab8500_usb>;
>
> As above.
>
>> + };
>> +
>> + ab8500_usb: ab8500_usb_if {
>
> What does 'if' mean?
>
>> compatible = "stericsson,ab8500-usb";
>> + interface-name = "ab8500_usb";
>
> Why is this required?
>
>> interrupts = < 90 0x4
>> 96 0x4
>> 14 0x4
>> diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
>> index 1667c77..6c3d7c2 100644
>> --- a/drivers/mfd/ab8500-core.c
>> +++ b/drivers/mfd/ab8500-core.c
>> @@ -1051,6 +1051,7 @@ static struct mfd_cell __devinitdata ab8500_bm_devs[] = {
>> },
>> {
>> .name = "ab8500-fg",
>> + .of_compatible = "stericsson,ab8500-fg",
>> .num_resources = ARRAY_SIZE(ab8500_fg_resources),
>> .resources = ab8500_fg_resources,
>> },
>> diff --git a/drivers/power/Makefile b/drivers/power/Makefile
>> index ee58afb..2c58d4e 100644
>> --- a/drivers/power/Makefile
>> +++ b/drivers/power/Makefile
>> @@ -34,7 +34,7 @@ obj-$(CONFIG_BATTERY_S3C_ADC) += s3c_adc_battery.o
>> obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o
>> obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o
>> obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o
>> -obj-$(CONFIG_AB8500_BM) += ab8500_charger.o ab8500_btemp.o ab8500_fg.o abx500_chargalg.o
>> +obj-$(CONFIG_AB8500_BM) += ab8500_bmdata.o ab8500_charger.o ab8500_fg.o ab8500_btemp.o abx500_chargalg.o
>> obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o
>> obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o
>> obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o
>> diff --git a/drivers/power/ab8500_bmdata.c b/drivers/power/ab8500_bmdata.c
>> new file mode 100644
>> index 0000000..d0def3b
>> --- /dev/null
>> +++ b/drivers/power/ab8500_bmdata.c
>> @@ -0,0 +1,549 @@
>> +#include <linux/export.h>
>> +#include <linux/power_supply.h>
>> +#include <linux/of.h>
>> +#include <linux/mfd/abx500.h>
>> +#include <linux/mfd/abx500/ab8500.h>
>> +#include <linux/mfd/abx500/ab8500-bm.h>
>> +
>> +/*
>> + * These are the defined batteries that uses a NTC and ID resistor placed
>> + * inside of the battery pack.
>> + * Note that the res_to_temp table must be strictly sorted by falling resistance
>> + * values to work.
>> + */
>> +static struct abx500_res_to_temp temp_tbl_A_thermistor[] = {
>> + {-5, 53407},
>> + { 0, 48594},
>> + { 5, 43804},
>> + {10, 39188},
>> + {15, 34870},
>> + {20, 30933},
>> + {25, 27422},
>> + {30, 24347},
>> + {35, 21694},
>> + {40, 19431},
>> + {45, 17517},
>> + {50, 15908},
>> + {55, 14561},
>> + {60, 13437},
>> + {65, 12500},
>> +};
>> +static struct abx500_res_to_temp temp_tbl_B_thermistor[] = {
>> + {-5, 165418},
>> + { 0, 159024},
>> + { 5, 151921},
>> + {10, 144300},
>> + {15, 136424},
>> + {20, 128565},
>> + {25, 120978},
>> + {30, 113875},
>> + {35, 107397},
>> + {40, 101629},
>> + {45, 96592},
>> + {50, 92253},
>> + {55, 88569},
>> + {60, 85461},
>> + {65, 82869},
>> +};
>> +static struct abx500_v_to_cap cap_tbl_A_thermistor[] = {
>> + {4171, 100},
>> + {4114, 95},
>> + {4009, 83},
>> + {3947, 74},
>> + {3907, 67},
>> + {3863, 59},
>> + {3830, 56},
>> + {3813, 53},
>> + {3791, 46},
>> + {3771, 33},
>> + {3754, 25},
>> + {3735, 20},
>> + {3717, 17},
>> + {3681, 13},
>> + {3664, 8},
>> + {3651, 6},
>> + {3635, 5},
>> + {3560, 3},
>> + {3408, 1},
>> + {3247, 0},
>> +};
>> +static struct abx500_v_to_cap cap_tbl_B_thermistor[] = {
>> + {4161, 100},
>> + {4124, 98},
>> + {4044, 90},
>> + {4003, 85},
>> + {3966, 80},
>> + {3933, 75},
>> + {3888, 67},
>> + {3849, 60},
>> + {3813, 55},
>> + {3787, 47},
>> + {3772, 30},
>> + {3751, 25},
>> + {3718, 20},
>> + {3681, 16},
>> + {3660, 14},
>> + {3589, 10},
>> + {3546, 7},
>> + {3495, 4},
>> + {3404, 2},
>> + {3250, 0},
>> +};
>> +
>> +static struct abx500_v_to_cap cap_tbl[] = {
>> + {4186, 100},
>> + {4163, 99},
>> + {4114, 95},
>> + {4068, 90},
>> + {3990, 80},
>> + {3926, 70},
>> + {3898, 65},
>> + {3866, 60},
>> + {3833, 55},
>> + {3812, 50},
>> + {3787, 40},
>> + {3768, 30},
>> + {3747, 25},
>> + {3730, 20},
>> + {3705, 15},
>> + {3699, 14},
>> + {3684, 12},
>> + {3672, 9},
>> + {3657, 7},
>> + {3638, 6},
>> + {3556, 4},
>> + {3424, 2},
>> + {3317, 1},
>> + {3094, 0},
>> +};
>> +
>> +/*
>> + * Note that the res_to_temp table must be strictly sorted by falling
>> + * resistance values to work.
>> + */
>> +static struct abx500_res_to_temp temp_tbl[] = {
>> + {-5, 214834},
>> + { 0, 162943},
>> + { 5, 124820},
>> + {10, 96520},
>> + {15, 75306},
>> + {20, 59254},
>> + {25, 47000},
>> + {30, 37566},
>> + {35, 30245},
>> + {40, 24520},
>> + {45, 20010},
>> + {50, 16432},
>> + {55, 13576},
>> + {60, 11280},
>> + {65, 9425},
>> +};
>> +
>> +/*
>> + * Note that the batres_vs_temp table must be strictly sorted by falling
>> + * temperature values to work.
>> + */
>> +struct batres_vs_temp temp_to_batres_tbl_thermistor[] = {
>> + { 40, 120},
>> + { 30, 135},
>> + { 20, 165},
>> + { 10, 230},
>> + { 00, 325},
>> + {-10, 445},
>> + {-20, 595},
>> +};
>> +
>> +/*
>> + * Note that the batres_vs_temp table must be strictly sorted by falling
>> + * temperature values to work.
>> + */
>> +struct batres_vs_temp temp_to_batres_tbl_ext_thermistor[] = {
>> + { 60, 300},
>> + { 30, 300},
>> + { 20, 300},
>> + { 10, 300},
>> + { 00, 300},
>> + {-10, 300},
>> + {-20, 300},
>> +};
>> +
>> +/* battery resistance table for LI ION 9100 battery */
>> +struct batres_vs_temp temp_to_batres_tbl_9100[] = {
>> + { 60, 180},
>> + { 30, 180},
>> + { 20, 180},
>> + { 10, 180},
>> + { 00, 180},
>> + {-10, 180},
>> + {-20, 180},
>> +};
>> +
>> +struct abx500_battery_type bat_type_thermistor[] = {
>> +[BATTERY_UNKNOWN] = {
>> + /* First element always represent the UNKNOWN battery */
>> + .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN,
>> + .resis_high = 0,
>> + .resis_low = 0,
>> + .battery_resistance = 300,
>> + .charge_full_design = 612,
>> + .nominal_voltage = 3700,
>> + .termination_vol = 4050,
>> + .termination_curr = 200,
>> + .recharge_vol = 3990,
>> + .normal_cur_lvl = 400,
>> + .normal_vol_lvl = 4100,
>> + .maint_a_cur_lvl = 400,
>> + .maint_a_vol_lvl = 4050,
>> + .maint_a_chg_timer_h = 60,
>> + .maint_b_cur_lvl = 400,
>> + .maint_b_vol_lvl = 4000,
>> + .maint_b_chg_timer_h = 200,
>> + .low_high_cur_lvl = 300,
>> + .low_high_vol_lvl = 4000,
>> + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
>> + .r_to_t_tbl = temp_tbl,
>> + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
>> + .v_to_cap_tbl = cap_tbl,
>> + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
>> + .batres_tbl = temp_to_batres_tbl_thermistor,
>> +},
>> +{
>> + .name = POWER_SUPPLY_TECHNOLOGY_LIPO,
>> + .resis_high = 53407,
>> + .resis_low = 12500,
>> + .battery_resistance = 300,
>> + .charge_full_design = 900,
>> + .nominal_voltage = 3600,
>> + .termination_vol = 4150,
>> + .termination_curr = 80,
>> + .recharge_vol = 4130,
>> + .normal_cur_lvl = 700,
>> + .normal_vol_lvl = 4200,
>> + .maint_a_cur_lvl = 600,
>> + .maint_a_vol_lvl = 4150,
>> + .maint_a_chg_timer_h = 60,
>> + .maint_b_cur_lvl = 600,
>> + .maint_b_vol_lvl = 4100,
>> + .maint_b_chg_timer_h = 200,
>> + .low_high_cur_lvl = 300,
>> + .low_high_vol_lvl = 4000,
>> + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_A_thermistor),
>> + .r_to_t_tbl = temp_tbl_A_thermistor,
>> + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_A_thermistor),
>> + .v_to_cap_tbl = cap_tbl_A_thermistor,
>> + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
>> + .batres_tbl = temp_to_batres_tbl_thermistor,
>> +
>> +},
>> +{
>> + .name = POWER_SUPPLY_TECHNOLOGY_LIPO,
>> + .resis_high = 165418,
>> + .resis_low = 82869,
>> + .battery_resistance = 300,
>> + .charge_full_design = 900,
>> + .nominal_voltage = 3600,
>> + .termination_vol = 4150,
>> + .termination_curr = 80,
>> + .recharge_vol = 4130,
>> + .normal_cur_lvl = 700,
>> + .normal_vol_lvl = 4200,
>> + .maint_a_cur_lvl = 600,
>> + .maint_a_vol_lvl = 4150,
>> + .maint_a_chg_timer_h = 60,
>> + .maint_b_cur_lvl = 600,
>> + .maint_b_vol_lvl = 4100,
>> + .maint_b_chg_timer_h = 200,
>> + .low_high_cur_lvl = 300,
>> + .low_high_vol_lvl = 4000,
>> + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_B_thermistor),
>> + .r_to_t_tbl = temp_tbl_B_thermistor,
>> + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_B_thermistor),
>> + .v_to_cap_tbl = cap_tbl_B_thermistor,
>> + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
>> + .batres_tbl = temp_to_batres_tbl_thermistor,
>> +},
>> +};
>> +
>> +struct abx500_battery_type bat_type_ext_thermistor[] = {
>> +[BATTERY_UNKNOWN] = {
>> + /* First element always represent the UNKNOWN battery */
>> + .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN,
>> + .resis_high = 0,
>> + .resis_low = 0,
>> + .battery_resistance = 300,
>> + .charge_full_design = 612,
>> + .nominal_voltage = 3700,
>> + .termination_vol = 4050,
>> + .termination_curr = 200,
>> + .recharge_vol = 3990,
>> + .normal_cur_lvl = 400,
>> + .normal_vol_lvl = 4100,
>> + .maint_a_cur_lvl = 400,
>> + .maint_a_vol_lvl = 4050,
>> + .maint_a_chg_timer_h = 60,
>> + .maint_b_cur_lvl = 400,
>> + .maint_b_vol_lvl = 4000,
>> + .maint_b_chg_timer_h = 200,
>> + .low_high_cur_lvl = 300,
>> + .low_high_vol_lvl = 4000,
>> + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
>> + .r_to_t_tbl = temp_tbl,
>> + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
>> + .v_to_cap_tbl = cap_tbl,
>> + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
>> + .batres_tbl = temp_to_batres_tbl_thermistor,
>> +},
>> +/*
>> + * These are the batteries that doesn't have an internal NTC resistor to measure
>> + * its temperature. The temperature in this case is measure with a NTC placed
>> + * near the battery but on the PCB.
>> + */
>> +{
>> + .name = POWER_SUPPLY_TECHNOLOGY_LIPO,
>> + .resis_high = 76000,
>> + .resis_low = 53000,
>> + .battery_resistance = 300,
>> + .charge_full_design = 900,
>> + .nominal_voltage = 3700,
>> + .termination_vol = 4150,
>> + .termination_curr = 100,
>> + .recharge_vol = 4130,
>> + .normal_cur_lvl = 700,
>> + .normal_vol_lvl = 4200,
>> + .maint_a_cur_lvl = 600,
>> + .maint_a_vol_lvl = 4150,
>> + .maint_a_chg_timer_h = 60,
>> + .maint_b_cur_lvl = 600,
>> + .maint_b_vol_lvl = 4100,
>> + .maint_b_chg_timer_h = 200,
>> + .low_high_cur_lvl = 300,
>> + .low_high_vol_lvl = 4000,
>> + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
>> + .r_to_t_tbl = temp_tbl,
>> + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
>> + .v_to_cap_tbl = cap_tbl,
>> + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
>> + .batres_tbl = temp_to_batres_tbl_thermistor,
>> +},
>> +{
>> + .name = POWER_SUPPLY_TECHNOLOGY_LION,
>> + .resis_high = 30000,
>> + .resis_low = 10000,
>> + .battery_resistance = 300,
>> + .charge_full_design = 950,
>> + .nominal_voltage = 3700,
>> + .termination_vol = 4150,
>> + .termination_curr = 100,
>> + .recharge_vol = 4130,
>> + .normal_cur_lvl = 700,
>> + .normal_vol_lvl = 4200,
>> + .maint_a_cur_lvl = 600,
>> + .maint_a_vol_lvl = 4150,
>> + .maint_a_chg_timer_h = 60,
>> + .maint_b_cur_lvl = 600,
>> + .maint_b_vol_lvl = 4100,
>> + .maint_b_chg_timer_h = 200,
>> + .low_high_cur_lvl = 300,
>> + .low_high_vol_lvl = 4000,
>> + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
>> + .r_to_t_tbl = temp_tbl,
>> + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
>> + .v_to_cap_tbl = cap_tbl,
>> + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
>> + .batres_tbl = temp_to_batres_tbl_thermistor,
>> +},
>> +{
>> + .name = POWER_SUPPLY_TECHNOLOGY_LION,
>> + .resis_high = 95000,
>> + .resis_low = 76001,
>> + .battery_resistance = 300,
>> + .charge_full_design = 950,
>> + .nominal_voltage = 3700,
>> + .termination_vol = 4150,
>> + .termination_curr = 100,
>> + .recharge_vol = 4130,
>> + .normal_cur_lvl = 700,
>> + .normal_vol_lvl = 4200,
>> + .maint_a_cur_lvl = 600,
>> + .maint_a_vol_lvl = 4150,
>> + .maint_a_chg_timer_h = 60,
>> + .maint_b_cur_lvl = 600,
>> + .maint_b_vol_lvl = 4100,
>> + .maint_b_chg_timer_h = 200,
>> + .low_high_cur_lvl = 300,
>> + .low_high_vol_lvl = 4000,
>> + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
>> + .r_to_t_tbl = temp_tbl,
>> + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
>> + .v_to_cap_tbl = cap_tbl,
>> + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
>> + .batres_tbl = temp_to_batres_tbl_thermistor,
>> +},
>> +};
>> +
>> +static const struct abx500_bm_capacity_levels cap_levels = {
>> + .critical = 2,
>> + .low = 10,
>> + .normal = 70,
>> + .high = 95,
>> + .full = 100,
>> +};
>> +
>> +static const struct abx500_fg_parameters fg = {
>> + .recovery_sleep_timer = 10,
>> + .recovery_total_time = 100,
>> + .init_timer = 1,
>> + .init_discard_time = 5,
>> + .init_total_time = 40,
>> + .high_curr_time = 60,
>> + .accu_charging = 30,
>> + .accu_high_curr = 30,
>> + .high_curr_threshold = 50,
>> + .lowbat_threshold = 3100,
>> + .battok_falling_th_sel0 = 2860,
>> + .battok_raising_th_sel1 = 2860,
>> + .user_cap_limit = 15,
>> + .maint_thres = 97,
>> +};
>> +
>> +static const struct abx500_maxim_parameters maxi_params = {
>> + .ena_maxi = true,
>> + .chg_curr = 910,
>> + .wait_cycles = 10,
>> + .charger_curr_step = 100,
>> +};
>> +
>> +static const struct abx500_bm_charger_parameters chg = {
>> + .usb_volt_max = 5500,
>> + .usb_curr_max = 1500,
>> + .ac_volt_max = 7500,
>> + .ac_curr_max = 1500,
>> +};
>> +
>> +struct abx500_bm_data ab8500_bm_data = {
>> + .temp_under = 3,
>> + .temp_low = 8,
>> + .temp_high = 43,
>> + .temp_over = 48,
>> + .main_safety_tmr_h = 4,
>> + .temp_interval_chg = 20,
>> + .temp_interval_nochg = 120,
>> + .usb_safety_tmr_h = 4,
>> + .bkup_bat_v = BUP_VCH_SEL_2P6V,
>> + .bkup_bat_i = BUP_ICH_SEL_150UA,
>> + .no_maintenance = false,
>> + .adc_therm = ABx500_ADC_THERM_BATCTRL,
>> + .chg_unknown_bat = false,
>> + .enable_overshoot = false,
>> + .fg_res = 100,
>> + .cap_levels = &cap_levels,
>> + .bat_type = bat_type_thermistor,
>> + .n_btypes = 3,
>> + .batt_id = 0,
>> + .interval_charging = 5,
>> + .interval_not_charging = 120,
>> + .temp_hysteresis = 3,
>> + .gnd_lift_resistance = 34,
>> + .maxi = &maxi_params,
>> + .chg_params = &chg,
>> + .fg_params = &fg,
>> +};
>> +
>> +int __devinit
>> +bmdevs_of_probe(struct device *dev,
>> + struct device_node *np,
>> + struct abx500_bm_plat_data *pdata)
>> +{
>> + int i, ret = 0, thermistor = NTC_INTERNAL;
>> + const __be32 *ph;
>> + const char *bat_tech;
>> + struct abx500_bm_data *bat;
>> + struct abx500_battery_type *btype;
>> + struct device_node *np_bat_supply;
>> + struct abx500_bmdevs_plat_data *plat_data = pdata->bmdev_pdata;
>
> <nit>
>
> This spacing is uncharacteristic of Linux drivers.
>
> Usually, struct declarations come first.
>
> </nit>
>
>> + /* get phandle to 'supplied-to' node */
>
> I thought you were going to reverse this?
>
>> + ph = of_get_property(np, "supplied-to", &plat_data->num_supplicants);
>> + if (ph == NULL) {
>
> if (!ph) {
>
>> + dev_err(dev, "no supplied_to property specified\n");
>> + return -EINVAL;
>> + }
>> + plat_data->num_supplicants /= sizeof(int);
>> + plat_data->supplied_to =
>> + devm_kzalloc(dev, plat_data->num_supplicants *
>> + sizeof(const char *), GFP_KERNEL);
>> + if (plat_data->supplied_to == NULL) {
>> + dev_err(dev, "%s no mem for supplied-to\n", __func__);
>> + return -ENOMEM;
>> + }
>> + for (i = 0; i < plat_data->num_supplicants; ++i) {
>> + np_bat_supply = of_find_node_by_phandle(be32_to_cpup(ph) + i);
>
> Use: of_parse_phandle(np, "supplied-to", i) instead.
>
>> + if (np_bat_supply == NULL) {
>
> if (!np_bat_supply) {
>
>> + dev_err(dev, "invalid supplied_to property\n");
>> + return -EINVAL;
>> + }
>> + ret = of_property_read_string(np_bat_supply, "interface-name",
>> + (const char **)(plat_data->supplied_to + i));
>> + if (ret < 0) {
>> + of_node_put(np_bat_supply);
>> + dev_err(dev, "supply/interface name not found\n");
>> + return ret;
>> + }
>> + dev_dbg(dev, "%s power supply interface_name:%s\n",
>> + __func__, *(plat_data->supplied_to + i));
>> + }
>
> <remove>
>
>> + /* get phandle to 'battery-info' node */
>> + ph = of_get_property(np, "battery-info", NULL);
>> + if (ph == NULL) {
>> + dev_err(dev, "missing property battery-info\n");
>> + return -EINVAL;
>> + }
>> + np_bat_supply = of_find_node_by_phandle(be32_to_cpup(ph));
>
> </remove>
>
> ... and replace with: np_bat_supply = of_parse_phandle(np, "battery-info", 0) instead.
>
>> + if (np_bat_supply == NULL) {
>
> if (!np_bat_supply) {
>
> I'll not mention this again.
>
>> + dev_err(dev, "invalid battery-info node\n");
>> + return -EINVAL;
>> + }
>> + if (of_property_read_bool(np_bat_supply,
>> + "thermistor-on-batctrl") == false){
>
> Replace with:
> if (of_get_property(np_bat_supply, "thermistor-on-batctr", NULL))
> np_bat_supply = true;
>
> <remove>
>
>> + dev_warn(dev, "missing property thermistor-on-batctrl\n");
>> + thermistor = NTC_EXTERNAL;
>> + }
>
> </remove>
>
>> + pdata->battery = &ab8500_bm_data;
>> + bat = pdata->battery;
>
> Why not: bat = &ab8500_bm_data
>
> Or just use ab8500_bm_data in its own right?
>
>> + if (thermistor == NTC_EXTERNAL) {
>> + bat->n_btypes = 4;
>> + bat->bat_type = bat_type_ext_thermistor;
>> + bat->adc_therm = ABx500_ADC_THERM_BATTEMP;
>> + }
>> + ret = of_property_read_string(np_bat_supply, "battery-name", &bat_tech);
>> + if (ret < 0) {
>> + dev_warn(dev, "missing property battery-name/type\n");
>> + bat_tech = "UNKNOWN";
>> + }
>> + of_node_put(np_bat_supply);
>> + if (strcmp(bat_tech, "LION") == 0) {
>> + bat->no_maintenance = true;
>> + bat->chg_unknown_bat = true;
>> + bat->bat_type[BATTERY_UNKNOWN].charge_full_design = 2600;
>> + bat->bat_type[BATTERY_UNKNOWN].termination_vol = 4150;
>> + bat->bat_type[BATTERY_UNKNOWN].recharge_vol = 4130;
>> + bat->bat_type[BATTERY_UNKNOWN].normal_cur_lvl = 520;
>> + bat->bat_type[BATTERY_UNKNOWN].normal_vol_lvl = 4200;
>> + }
>> + /* select the battery resolution table */
>> + for (i = 0; i < bat->n_btypes; ++i) {
>> + btype = (bat->bat_type + i);
>> + if (thermistor == NTC_EXTERNAL) {
>> + btype->batres_tbl =
>> + temp_to_batres_tbl_ext_thermistor;
>> + } else if (strcmp(bat_tech, "LION") == 0) {
>
> Isn't strncmp safer, since you know the size of the comparison?
>
>> + btype->batres_tbl =
>> + temp_to_batres_tbl_9100;
>> + } else {
>> + btype->batres_tbl =
>> + temp_to_batres_tbl_thermistor;
>> + }
>> + }
>> + return 0;
>> +}
>> +EXPORT_SYMBOL(bmdevs_of_probe);
>
> Why are you exporting?
>
>> diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
>> index bba3cca..8e427e7 100644
>> --- a/drivers/power/ab8500_btemp.c
>> +++ b/drivers/power/ab8500_btemp.c
>> @@ -93,7 +93,7 @@ struct ab8500_btemp {
>> struct ab8500 *parent;
>> struct ab8500_gpadc *gpadc;
>> struct ab8500_fg *fg;
>> - struct abx500_btemp_platform_data *pdata;
>> + struct abx500_bmdevs_plat_data *pdata;
>> struct abx500_bm_data *bat;
>> struct power_supply btemp_psy;
>> struct ab8500_btemp_events events;
>> @@ -982,7 +982,7 @@ static int __devinit ab8500_btemp_probe(struct platform_device *pdev)
>> di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
>>
>> /* get btemp specific platform data */
>> - di->pdata = plat_data->btemp;
>> + di->pdata = plat_data->bmdev_pdata;
>> if (!di->pdata) {
>> dev_err(di->dev, "no btemp platform data supplied\n");
>> ret = -EINVAL;
>> diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
>> index d4f0c98..5ff0d83 100644
>> --- a/drivers/power/ab8500_charger.c
>> +++ b/drivers/power/ab8500_charger.c
>> @@ -220,7 +220,7 @@ struct ab8500_charger {
>> bool autopower;
>> struct ab8500 *parent;
>> struct ab8500_gpadc *gpadc;
>> - struct abx500_charger_platform_data *pdata;
>> + struct abx500_bmdevs_plat_data *pdata;
>> struct abx500_bm_data *bat;
>> struct ab8500_charger_event_flags flags;
>> struct ab8500_charger_usb_state usb_state;
>> @@ -2555,7 +2555,7 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev)
>> spin_lock_init(&di->usb_state.usb_lock);
>>
>> /* get charger specific platform data */
>> - di->pdata = plat_data->charger;
>> + di->pdata = plat_data->bmdev_pdata;
>> if (!di->pdata) {
>> dev_err(di->dev, "no charger platform data supplied\n");
>> ret = -EINVAL;
>> diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
>> index bf02225..96741b8 100644
>> --- a/drivers/power/ab8500_fg.c
>> +++ b/drivers/power/ab8500_fg.c
>> @@ -22,15 +22,14 @@
>> #include <linux/platform_device.h>
>> #include <linux/power_supply.h>
>> #include <linux/kobject.h>
>> -#include <linux/mfd/abx500/ab8500.h>
>> -#include <linux/mfd/abx500.h>
>> #include <linux/slab.h>
>> -#include <linux/mfd/abx500/ab8500-bm.h>
>> #include <linux/delay.h>
>> -#include <linux/mfd/abx500/ab8500-gpadc.h>
>> -#include <linux/mfd/abx500.h>
>> #include <linux/time.h>
>> #include <linux/completion.h>
>> +#include <linux/mfd/abx500.h>
>> +#include <linux/mfd/abx500/ab8500.h>
>> +#include <linux/mfd/abx500/ab8500-bm.h>
>> +#include <linux/mfd/abx500/ab8500-gpadc.h>
>>
>> #define MILLI_TO_MICRO 1000
>> #define FG_LSB_IN_MA 1627
>> @@ -212,7 +211,7 @@ struct ab8500_fg {
>> struct ab8500_fg_avg_cap avg_cap;
>> struct ab8500 *parent;
>> struct ab8500_gpadc *gpadc;
>> - struct abx500_fg_platform_data *pdata;
>> + struct abx500_bmdevs_plat_data *pdata;
>> struct abx500_bm_data *bat;
>> struct power_supply fg_psy;
>> struct workqueue_struct *fg_wq;
>> @@ -544,14 +543,14 @@ cc_err:
>> ret = abx500_set_register_interruptible(di->dev,
>> AB8500_GAS_GAUGE, AB8500_GASG_CC_NCOV_ACCU,
>> SEC_TO_SAMPLE(10));
>> - if (ret)
>> + if (ret < 0)
>
> I don't 'think' this change is required. abx500_set_register_interruptible
> will only return !0 on error.
>
>> goto fail;
>>
>> /* Start the CC */
>> ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
>> AB8500_RTC_CC_CONF_REG,
>> (CC_DEEP_SLEEP_ENA | CC_PWR_UP_ENA));
>> - if (ret)
>> + if (ret < 0)
>> goto fail;
>> } else {
>> di->turn_off_fg = false;
>> @@ -2429,7 +2428,6 @@ static int __devexit ab8500_fg_remove(struct platform_device *pdev)
>> flush_scheduled_work();
>> power_supply_unregister(&di->fg_psy);
>> platform_set_drvdata(pdev, NULL);
>> - kfree(di);
>> return ret;
>> }
>>
>> @@ -2446,18 +2444,47 @@ static int __devinit ab8500_fg_probe(struct platform_device *pdev)
>> {
>> int i, irq;
>> int ret = 0;
>> - struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
>> + struct abx500_bm_plat_data *plat_data
>> + = pdev->dev.platform_data;
>> + struct device_node *np = pdev->dev.of_node;
>> struct ab8500_fg *di;
>>
>> + di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
>> + if (!di) {
>> + dev_err(&pdev->dev, "%s no mem for ab8500_fg\n", __func__);
>> + return -ENOMEM;
>> + }
>> + if (np) {
>> + if (!plat_data) {
>
> Change these around.
>
> if (!plat_data) {
> if (np) {
> <snip>
> } else {
> <ERROR>
> }
> }
>
>> + plat_data =
>> + devm_kzalloc(&pdev->dev, sizeof(*plat_data),
>> + GFP_KERNEL);
>> + if (!plat_data) {
>> + dev_err(&pdev->dev,
>> + "%s no mem for plat_data\n", __func__);
>> + return -ENOMEM;
>> + }
>> + plat_data->bmdev_pdata = devm_kzalloc(&pdev->dev,
>> + sizeof(*plat_data->bmdev_pdata), GFP_KERNEL);
>> + if (!plat_data->bmdev_pdata) {
>> + dev_err(&pdev->dev,
>> + "%s no mem for pdata->fg\n",
>> + __func__);
>> + return -ENOMEM;
>> + }
>> + }
>> + ret = bmdevs_of_probe(&pdev->dev, np, plat_data);
>> + if (ret < 0) {
>> + dev_err(&pdev->dev, "failed to get platform data\n");
>> + return ret;
>> + }
>> + }
>
> <remove>
>
>> if (!plat_data) {
>> - dev_err(&pdev->dev, "No platform data\n");
>> + dev_err(&pdev->dev,
>> + "%s no fg platform data found\n", __func__);
>> return -EINVAL;
>> }
> </remove>
>
>> - di = kzalloc(sizeof(*di), GFP_KERNEL);
>> - if (!di)
>> - return -ENOMEM;
>> -
>> mutex_init(&di->cc_lock);
>>
>> /* get parent data */
>> @@ -2466,19 +2493,17 @@ static int __devinit ab8500_fg_probe(struct platform_device *pdev)
>> di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
>>
>> /* get fg specific platform data */
>> - di->pdata = plat_data->fg;
>> + di->pdata = plat_data->bmdev_pdata;
>> if (!di->pdata) {
>> dev_err(di->dev, "no fg platform data supplied\n");
>> - ret = -EINVAL;
>> - goto free_device_info;
>> + return -EINVAL;
>> }
>>
>> /* get battery specific platform data */
>> di->bat = plat_data->battery;
>> if (!di->bat) {
>> dev_err(di->dev, "no battery platform data supplied\n");
>> - ret = -EINVAL;
>> - goto free_device_info;
>> + return -EINVAL;
>> }
>>
>> di->fg_psy.name = "ab8500_fg";
>> @@ -2506,7 +2531,7 @@ static int __devinit ab8500_fg_probe(struct platform_device *pdev)
>> di->fg_wq = create_singlethread_workqueue("ab8500_fg_wq");
>> if (di->fg_wq == NULL) {
>> dev_err(di->dev, "failed to create work queue\n");
>> - goto free_device_info;
>> + return -ENOMEM;
>> }
>>
>> /* Init work for running the fg algorithm instantly */
>> @@ -2605,12 +2630,14 @@ free_irq:
>> }
>> free_inst_curr_wq:
>> destroy_workqueue(di->fg_wq);
>> -free_device_info:
>> - kfree(di);
>> -
>> return ret;
>> }
>>
>> +static const struct of_device_id ab8500_fg_match[] = {
>> + {.compatible = "stericsson,ab8500-fg",},
>
> <nit>
>
> Spaces:
>
> { .compatible = "stericsson,ab8500-fg", },
>
> </nit>
>
>> + {},
>> +};
>> +
>> static struct platform_driver ab8500_fg_driver = {
>> .probe = ab8500_fg_probe,
>> .remove = __devexit_p(ab8500_fg_remove),
>> @@ -2619,6 +2646,7 @@ static struct platform_driver ab8500_fg_driver = {
>> .driver = {
>> .name = "ab8500-fg",
>> .owner = THIS_MODULE,
>> + .of_match_table = ab8500_fg_match,
>> },
>> };
>>
>> diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
>> index 804b88c..ba548e4 100644
>> --- a/drivers/power/abx500_chargalg.c
>> +++ b/drivers/power/abx500_chargalg.c
>> @@ -231,7 +231,7 @@ struct abx500_chargalg {
>> struct abx500_chargalg_charger_info chg_info;
>> struct abx500_chargalg_battery_data batt_data;
>> struct abx500_chargalg_suspension_status susp_status;
>> - struct abx500_chargalg_platform_data *pdata;
>> + struct abx500_bmdevs_plat_data *pdata;
>> struct abx500_bm_data *bat;
>> struct power_supply chargalg_psy;
>> struct ux500_charger *ac_chg;
>> @@ -1814,7 +1814,7 @@ static int __devinit abx500_chargalg_probe(struct platform_device *pdev)
>> di->dev = &pdev->dev;
>>
>> plat_data = pdev->dev.platform_data;
>> - di->pdata = plat_data->chargalg;
>> + di->pdata = plat_data->bmdev_pdata;
>> di->bat = plat_data->battery;
>>
>> /* chargalg supply */
>> diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h
>> index 1318ca6..286f8ac 100644
>> --- a/include/linux/mfd/abx500.h
>> +++ b/include/linux/mfd/abx500.h
>> @@ -382,39 +382,30 @@ struct abx500_bm_data {
>> int gnd_lift_resistance;
>> const struct abx500_maxim_parameters *maxi;
>> const struct abx500_bm_capacity_levels *cap_levels;
>> - const struct abx500_battery_type *bat_type;
>> + struct abx500_battery_type *bat_type;
>> const struct abx500_bm_charger_parameters *chg_params;
>> const struct abx500_fg_parameters *fg_params;
>> };
>>
>> -struct abx500_chargalg_platform_data {
>> - char **supplied_to;
>> - size_t num_supplicants;
>> +struct abx500_bmdevs_plat_data {
>> + char **supplied_to;
>> + size_t num_supplicants;
>> + bool autopower_cfg;
>> };
>>
>> -struct abx500_charger_platform_data {
>> - char **supplied_to;
>> - size_t num_supplicants;
>> - bool autopower_cfg;
>> -};
>> -
>> -struct abx500_btemp_platform_data {
>> - char **supplied_to;
>> - size_t num_supplicants;
>> +struct abx500_bm_plat_data {
>> + struct abx500_bm_data *battery;
>> + struct abx500_bmdevs_plat_data *bmdev_pdata;
>> };
>>
>> -struct abx500_fg_platform_data {
>> - char **supplied_to;
>> - size_t num_supplicants;
>> +enum {
>> + NTC_EXTERNAL = 0,
>> + NTC_INTERNAL,
>> };
>>
>> -struct abx500_bm_plat_data {
>> - struct abx500_bm_data *battery;
>> - struct abx500_charger_platform_data *charger;
>> - struct abx500_btemp_platform_data *btemp;
>> - struct abx500_fg_platform_data *fg;
>> - struct abx500_chargalg_platform_data *chargalg;
>> -};
>> +int bmdevs_of_probe(struct device *dev,
>> + struct device_node *np,
>> + struct abx500_bm_plat_data *pdata);
>>
>> int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg,
>> u8 value);
>> diff --git a/include/linux/mfd/abx500/ab8500-bm.h b/include/linux/mfd/abx500/ab8500-bm.h
>> index 44310c9..d15b7f1 100644
>> --- a/include/linux/mfd/abx500/ab8500-bm.h
>> +++ b/include/linux/mfd/abx500/ab8500-bm.h
>> @@ -422,6 +422,13 @@ struct ab8500_chargalg_platform_data {
>> struct ab8500_btemp;
>> struct ab8500_gpadc;
>> struct ab8500_fg;
>> +
>> +extern struct abx500_bm_data ab8500_bm_data;
>> +extern struct abx500_battery_type bat_type_ext_thermistor[];
>> +extern struct batres_vs_temp temp_to_batres_tbl_ext_thermistor[];
>> +extern struct batres_vs_temp temp_to_batres_tbl_9100[];
>> +extern struct batres_vs_temp temp_to_batres_tbl_thermistor[];
>> +
>> #ifdef CONFIG_AB8500_BM
>> void ab8500_fg_reinit(void);
>> void ab8500_charger_usb_state_changed(u8 bm_usb_state, u16 mA);
>> --
>> 1.7.9.5
>>
>
> --
> Lee Jones
> Linaro ST-Ericsson Landing Team Lead
> Linaro.org │ Open source software for ARM SoCs
> Follow Linaro: Facebook | Twitter | Blog
>
More information about the linux-arm-kernel
mailing list